// Path: src/main/java/org/avmframework/objective/NumericObjectiveValue.java
// public class NumericObjectiveValue extends ObjectiveValue<NumericObjectiveValue> {
// 
//   protected double value;
//   protected boolean higherIsBetter;
// 
//   protected boolean haveOptimum = false;
//   protected double optimum;
// 
//   public NumericObjectiveValue(double value, boolean higherIsBetter) {
//     this.value = value;
//     this.higherIsBetter = higherIsBetter;
//   }
// 
//   public NumericObjectiveValue(double value, boolean higherIsBetter, double optimum) {
//     this(value, higherIsBetter);
//     this.haveOptimum = true;
//     this.optimum = optimum;
//   }
// 
//   public double getValue() {
//     return value;
//   }
// 
//   @Override
//   public boolean isOptimal() {
//     if (!haveOptimum) {
//       return false;
//     }
// 
//     if (higherIsBetter) {
//       return value >= optimum;
//     } else {
//       return value <= optimum;
//     }
//   }
// 
//   @Override
//   public int compareTo(NumericObjectiveValue other) {
//     if (value == other.value) {
//       return 0;
//     } else if (value < other.value) {
//       return higherIsBetter ? -1 : 1;
//     } else {
//       return higherIsBetter ? 1 : -1;
//     }
//   }
// 
//   @Override
//   public String toString() {
//     return "" + getValue();
//   }
// 
//   public static NumericObjectiveValue higherIsBetterObjectiveValue(double value) {
//     return new NumericObjectiveValue(value, true);
//   }
// 
//   public static NumericObjectiveValue higherIsBetterObjectiveValue(double value, double optimum) {
//     return new NumericObjectiveValue(value, true, optimum);
//   }
// 
//   public static NumericObjectiveValue lowerIsBetterObjectiveValue(double value) {
//     return new NumericObjectiveValue(value, false);
//   }
// 
//   public static NumericObjectiveValue lowerIsBetterObjectiveValue(double value, double optimum) {
//     return new NumericObjectiveValue(value, false, optimum);
//   }
// }
// 
// Path: src/main/java/org/avmframework/objective/ObjectiveFunction.java
// public abstract class ObjectiveFunction {
// 
//   public static final boolean USE_CACHE_DEFAULT = true;
// 
//   protected boolean useCache = USE_CACHE_DEFAULT;
//   protected Map<Vector, ObjectiveValue> previousVals = new HashMap<>();
//   protected Monitor monitor;
// 
//   public void setMonitor(Monitor monitor) {
//     this.monitor = monitor;
//   }
// 
//   public ObjectiveValue evaluate(Vector vector) throws TerminationException {
//     monitor.observeVector();
// 
//     if (useCache && previousVals.containsKey(vector)) {
//       return previousVals.get(vector);
//     }
// 
//     ObjectiveValue objVal = computeObjectiveValue(vector);
// 
//     if (useCache) {
//       previousVals.put(vector.deepCopy(), objVal);
//     }
// 
//     if (monitor != null) {
//       monitor.observePreviouslyUnseenVector(vector, objVal);
//     }
// 
//     return objVal;
//   }
// 
//   protected abstract ObjectiveValue computeObjectiveValue(Vector vector);
// }
// 
// Path: src/main/java/org/avmframework/objective/ObjectiveValue.java
// public abstract class ObjectiveValue<T extends ObjectiveValue> implements Comparable<T> {
// 
//   public abstract boolean isOptimal();
// 
//   public boolean betterThan(T other) {
//     return compareTo(other) > 0;
//   }
// 
//   public boolean sameAs(T other) {
//     return compareTo(other) == 0;
//   }
// 
//   public boolean worseThan(T other) {
//     return compareTo(other) < 0;
//   }
// }
// 
// Path: src/main/java/org/avmframework/variable/IntegerVariable.java
// public class IntegerVariable extends AtomicVariable {
// 
//   public IntegerVariable(int initialValue, int min, int max) {
//     super(initialValue, min, max);
//     if (min > max) {
//       throw new MinGreaterThanMaxException(min, max);
//     }
//     setValueToInitial();
//   }
// 
//   public int asInt() {
//     return value;
//   }
// 
//   @Override
//   public IntegerVariable deepCopy() {
//     IntegerVariable copy = new IntegerVariable(initialValue, min, max);
//     copy.value = value;
//     return copy;
//   }
// 
//   @Override
//   public String toString() {
//     return "" + asInt();
//   }
// }
// 
// Path: src/main/java/org/avmframework/variable/Variable.java
// public interface Variable {
// 
//   void setValueToInitial();
// 
//   void setValueToRandom(RandomGenerator randomGenerator);
// 
//   Variable deepCopy();
// }


import org.avmframework.objective.NumericObjectiveValue;
import org.avmframework.objective.ObjectiveFunction;
import org.avmframework.objective.ObjectiveValue;
import org.avmframework.variable.IntegerVariable;
import org.avmframework.variable.Variable;
package org.avmframework;


public class ObjectiveFunctions {

  public static ObjectiveFunction flat() {
    ObjectiveFunction objFun =
        new ObjectiveFunction() {
          @Override
          protected ObjectiveValue computeObjectiveValue(Vector vector) {
            return NumericObjectiveValue.higherIsBetterObjectiveValue(1.0);
          }
        };
    return objFun;
  }

  public static ObjectiveFunction allZeros() {
    return new ObjectiveFunction() {
// Path: src/main/java/org/avmframework/objective/NumericObjectiveValue.java
// public class NumericObjectiveValue extends ObjectiveValue<NumericObjectiveValue> {
// 
//   protected double value;
//   protected boolean higherIsBetter;
// 
//   protected boolean haveOptimum = false;
//   protected double optimum;
// 
//   public NumericObjectiveValue(double value, boolean higherIsBetter) {
//     this.value = value;
//     this.higherIsBetter = higherIsBetter;
//   }
// 
//   public NumericObjectiveValue(double value, boolean higherIsBetter, double optimum) {
//     this(value, higherIsBetter);
//     this.haveOptimum = true;
//     this.optimum = optimum;
//   }
// 
//   public double getValue() {
//     return value;
//   }
// 
//   @Override
//   public boolean isOptimal() {
//     if (!haveOptimum) {
//       return false;
//     }
// 
//     if (higherIsBetter) {
//       return value >= optimum;
//     } else {
//       return value <= optimum;
//     }
//   }
// 
//   @Override
//   public int compareTo(NumericObjectiveValue other) {
//     if (value == other.value) {
//       return 0;
//     } else if (value < other.value) {
//       return higherIsBetter ? -1 : 1;
//     } else {
//       return higherIsBetter ? 1 : -1;
//     }
//   }
// 
//   @Override
//   public String toString() {
//     return "" + getValue();
//   }
// 
//   public static NumericObjectiveValue higherIsBetterObjectiveValue(double value) {
//     return new NumericObjectiveValue(value, true);
//   }
// 
//   public static NumericObjectiveValue higherIsBetterObjectiveValue(double value, double optimum) {
//     return new NumericObjectiveValue(value, true, optimum);
//   }
// 
//   public static NumericObjectiveValue lowerIsBetterObjectiveValue(double value) {
//     return new NumericObjectiveValue(value, false);
//   }
// 
//   public static NumericObjectiveValue lowerIsBetterObjectiveValue(double value, double optimum) {
//     return new NumericObjectiveValue(value, false, optimum);
//   }
// }
// 
// Path: src/main/java/org/avmframework/objective/ObjectiveFunction.java
// public abstract class ObjectiveFunction {
// 
//   public static final boolean USE_CACHE_DEFAULT = true;
// 
//   protected boolean useCache = USE_CACHE_DEFAULT;
//   protected Map<Vector, ObjectiveValue> previousVals = new HashMap<>();
//   protected Monitor monitor;
// 
//   public void setMonitor(Monitor monitor) {
//     this.monitor = monitor;
//   }
// 
//   public ObjectiveValue evaluate(Vector vector) throws TerminationException {
//     monitor.observeVector();
// 
//     if (useCache && previousVals.containsKey(vector)) {
//       return previousVals.get(vector);
//     }
// 
//     ObjectiveValue objVal = computeObjectiveValue(vector);
// 
//     if (useCache) {
//       previousVals.put(vector.deepCopy(), objVal);
//     }
// 
//     if (monitor != null) {
//       monitor.observePreviouslyUnseenVector(vector, objVal);
//     }
// 
//     return objVal;
//   }
// 
//   protected abstract ObjectiveValue computeObjectiveValue(Vector vector);
// }
// 
// Path: src/main/java/org/avmframework/objective/ObjectiveValue.java
// public abstract class ObjectiveValue<T extends ObjectiveValue> implements Comparable<T> {
// 
//   public abstract boolean isOptimal();
// 
//   public boolean betterThan(T other) {
//     return compareTo(other) > 0;
//   }
// 
//   public boolean sameAs(T other) {
//     return compareTo(other) == 0;
//   }
// 
//   public boolean worseThan(T other) {
//     return compareTo(other) < 0;
//   }
// }
// 
// Path: src/main/java/org/avmframework/variable/IntegerVariable.java
// public class IntegerVariable extends AtomicVariable {
// 
//   public IntegerVariable(int initialValue, int min, int max) {
//     super(initialValue, min, max);
//     if (min > max) {
//       throw new MinGreaterThanMaxException(min, max);
//     }
//     setValueToInitial();
//   }
// 
//   public int asInt() {
//     return value;
//   }
// 
//   @Override
//   public IntegerVariable deepCopy() {
//     IntegerVariable copy = new IntegerVariable(initialValue, min, max);
//     copy.value = value;
//     return copy;
//   }
// 
//   @Override
//   public String toString() {
//     return "" + asInt();
//   }
// }
// 
// Path: src/main/java/org/avmframework/variable/Variable.java
// public interface Variable {
// 
//   void setValueToInitial();
// 
//   void setValueToRandom(RandomGenerator randomGenerator);
// 
//   Variable deepCopy();
// }


// Path: src/test/java/org/avmframework/ObjectiveFunctions.java
import org.avmframework.objective.NumericObjectiveValue;
import org.avmframework.objective.ObjectiveFunction;
import org.avmframework.objective.ObjectiveValue;
import org.avmframework.variable.IntegerVariable;
import org.avmframework.variable.Variable;

package org.avmframework;


public class ObjectiveFunctions {

  public static ObjectiveFunction flat() {
    ObjectiveFunction objFun =
        new ObjectiveFunction() {
          @Override
          protected ObjectiveValue computeObjectiveValue(Vector vector) {
            return NumericObjectiveValue.higherIsBetterObjectiveValue(1.0);
          }
        };
    return objFun;
  }

  public static ObjectiveFunction allZeros() {
    return new ObjectiveFunction() {
      @Override