@Override
 public Set<ValueRequirement> getRequirements(
     final FunctionCompilationContext context,
     final ComputationTarget target,
     final ValueRequirement desiredValue) {
   final ValueProperties constraints = desiredValue.getConstraints();
   Set<String> values = constraints.getValues(VALUE_PROPERTY_NAME);
   final String inputValue;
   if ((values == null) || values.isEmpty()) {
     inputValue = DEFAULT_VALUE_NAME;
   } else if (values.size() == 1) {
     inputValue = values.iterator().next();
   } else {
     return null;
   }
   // Propogate the desired value constraints onto the requirements, removing those specific to
   // this function and adding a unit homogeneity clause
   final ValueProperties.Builder requirementConstraintsBuilder =
       constraints.copy().withoutAny(VALUE_PROPERTY_NAME);
   for (String unit : UnitProperties.unitPropertyNames()) {
     values = constraints.getValues(unit);
     if (values == null) {
       // Unit was not specified on the output, but we specify it on the inputs so we can check
       // homogeneity to ensure the division is valid
       requirementConstraintsBuilder.withOptional(unit);
     }
   }
   // Request value on the value and parent
   final ValueProperties requirementConstraints = requirementConstraintsBuilder.get();
   return ImmutableSet.of(
       new ValueRequirement(inputValue, getValueTarget(target), requirementConstraints),
       new ValueRequirement(inputValue, getParentTarget(target), requirementConstraints));
 }
 @Override
 public Set<ValueSpecification> getResults(
     final FunctionCompilationContext context,
     final ComputationTarget target,
     final Map<ValueSpecification, ValueRequirement> inputs) {
   ValueSpecification inputValue = null;
   ValueSpecification inputParent = null;
   final UniqueId value = target.getUniqueId();
   for (ValueSpecification input : inputs.keySet()) {
     if (value.equals(input.getTargetSpecification().getUniqueId())) {
       assert inputValue == null;
       inputValue = input;
     } else {
       assert inputParent == null;
       inputParent = input;
     }
   }
   final ValueProperties rawResultProperties =
       inputValue.getProperties().intersect(inputParent.getProperties());
   final ValueProperties.Builder resultPropertiesBuilder = rawResultProperties.copy();
   for (String unit : UnitProperties.unitPropertyNames()) {
     final Set<String> valueUnits = inputValue.getProperties().getValues(unit);
     final Set<String> parentUnits = inputParent.getProperties().getValues(unit);
     if (valueUnits != null) {
       if (parentUnits != null) {
         if (rawResultProperties.getValues(unit) != null) {
           // The operation is a division, so there are no units on the result
           resultPropertiesBuilder.withoutAny(unit);
         } else {
           // No common intersection between parent and value properties for this unit
           return null;
         }
       } else {
         // Parent did not include the same units as the value
         return null;
       }
     } else {
       if (parentUnits != null) {
         // Value did not include the same units as the parent
         return null;
       }
     }
   }
   resultPropertiesBuilder
       .withoutAny(VALUE_PROPERTY_NAME)
       .with(VALUE_PROPERTY_NAME, inputValue.getValueName());
   resultPropertiesBuilder
       .withoutAny(ValuePropertyNames.FUNCTION)
       .with(ValuePropertyNames.FUNCTION, getUniqueId());
   return Collections.singleton(
       new ValueSpecification(
           ValueRequirementNames.WEIGHT, target.toSpecification(), resultPropertiesBuilder.get()));
 }