// Path: src/main/java/org/avmframework/Vector.java
// public class Vector extends AbstractVector {
// 
//   public void addVariable(Variable variable) {
//     variables.add(variable);
//   }
// 
//   public List<Variable> getVariables() {
//     return new ArrayList<>(variables);
//   }
// 
//   public void setVariablesToInitial() {
//     for (Variable var : variables) {
//       var.setValueToInitial();
//     }
//   }
// 
//   public void setVariablesToRandom(RandomGenerator rg) {
//     for (Variable var : variables) {
//       var.setValueToRandom(rg);
//     }
//   }
// 
//   public Vector deepCopy() {
//     Vector copy = new Vector();
//     deepCopyVariables(copy);
//     return copy;
//   }
// }
// 
// 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;
//   }
// }


import org.avmframework.Vector;
import org.avmframework.objective.NumericObjectiveValue;
import org.avmframework.objective.ObjectiveFunction;
import org.avmframework.objective.ObjectiveValue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
        coveredCoverageSet.addAll(testCase.getApiCovered());
        // to get the number of unique apis covered by this test case
        int afterCoverage = coveredCoverageSet.size() - beforeCoverage;

        coverageCal +=
            ((double) (afterCoverage))
                * ((double) (orderedTestSuite.size() - i) / orderedTestSuite.size());
        fdcCal +=
            ((double) (testCase.getFaultDetection()))
                * ((double) (orderedTestSuite.size() - i) / orderedTestSuite.size());
        timeCalc +=
            ((double) (testCase.getTime()))
                * ((double) (orderedTestSuite.size() - i) / orderedTestSuite.size());
      }
    }
    double objCoverage;
    double objFaultDetectionCoverage;
    double objTime;

    // divide by maximum of all the test cases in the test suite
    objCoverage = coverageCal / transitionStateCoverage.getCoverage().size();
    objFaultDetectionCoverage = fdcCal / transitionStateCoverage.getFaultDetection();
    objTime = timeCalc / transitionStateCoverage.getExecutionTime();

    // subtract 1 for minimization, 1 is not subtracted for objTime because minimum time is better
    double fitness =
        (1 - objCoverage) * this.weightCoverage
            + (1 - objFaultDetectionCoverage) * this.weightFaultDetection
            + objTime * this.weightTime;

// Path: src/main/java/org/avmframework/Vector.java
// public class Vector extends AbstractVector {
// 
//   public void addVariable(Variable variable) {
//     variables.add(variable);
//   }
// 
//   public List<Variable> getVariables() {
//     return new ArrayList<>(variables);
//   }
// 
//   public void setVariablesToInitial() {
//     for (Variable var : variables) {
//       var.setValueToInitial();
//     }
//   }
// 
//   public void setVariablesToRandom(RandomGenerator rg) {
//     for (Variable var : variables) {
//       var.setValueToRandom(rg);
//     }
//   }
// 
//   public Vector deepCopy() {
//     Vector copy = new Vector();
//     deepCopyVariables(copy);
//     return copy;
//   }
// }
// 
// 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/examples/testoptimization/PrioritizationObjectiveFunction.java
import org.avmframework.Vector;
import org.avmframework.objective.NumericObjectiveValue;
import org.avmframework.objective.ObjectiveFunction;
import org.avmframework.objective.ObjectiveValue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

        coveredCoverageSet.addAll(testCase.getApiCovered());
        // to get the number of unique apis covered by this test case
        int afterCoverage = coveredCoverageSet.size() - beforeCoverage;

        coverageCal +=
            ((double) (afterCoverage))
                * ((double) (orderedTestSuite.size() - i) / orderedTestSuite.size());
        fdcCal +=
            ((double) (testCase.getFaultDetection()))
                * ((double) (orderedTestSuite.size() - i) / orderedTestSuite.size());
        timeCalc +=
            ((double) (testCase.getTime()))
                * ((double) (orderedTestSuite.size() - i) / orderedTestSuite.size());
      }
    }
    double objCoverage;
    double objFaultDetectionCoverage;
    double objTime;

    // divide by maximum of all the test cases in the test suite
    objCoverage = coverageCal / transitionStateCoverage.getCoverage().size();
    objFaultDetectionCoverage = fdcCal / transitionStateCoverage.getFaultDetection();
    objTime = timeCalc / transitionStateCoverage.getExecutionTime();

    // subtract 1 for minimization, 1 is not subtracted for objTime because minimum time is better
    double fitness =
        (1 - objCoverage) * this.weightCoverage
            + (1 - objFaultDetectionCoverage) * this.weightFaultDetection
            + objTime * this.weightTime;

    return NumericObjectiveValue.lowerIsBetterObjectiveValue(fitness, 0);