// 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/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.ObjectiveFunction;
import org.avmframework.objective.ObjectiveValue;
package org.avmframework.examples.inputdatageneration;


public abstract class BranchTargetObjectiveFunction extends ObjectiveFunction {

  protected Branch target;
  protected ControlDependenceChain controlDependenceChain;
  protected ExecutionTrace trace;

  public BranchTargetObjectiveFunction(Branch target) {
    this.target = target;
    this.controlDependenceChain = getControlDependenceChainForTarget();
  }

  protected abstract ControlDependenceChain getControlDependenceChainForTarget();

  protected ObjectiveValue computeObjectiveValue(Vector vector) {
    trace = new ExecutionTrace();
    executeTestObject(vector);
    DivergencePoint divergencePoint = controlDependenceChain.getDivergencePoint(trace);

    int approachLevel = 0;
    double distance = 0;
    if (divergencePoint != null) {
      approachLevel = divergencePoint.chainIndex;
      distance = trace.getBranchExecution(divergencePoint.traceIndex).getDistanceToAlternative();
    }
    return new BranchTargetObjectiveValue(approachLevel, distance);
  }

// 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/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/inputdatageneration/BranchTargetObjectiveFunction.java
import org.avmframework.Vector;
import org.avmframework.objective.ObjectiveFunction;
import org.avmframework.objective.ObjectiveValue;

package org.avmframework.examples.inputdatageneration;


public abstract class BranchTargetObjectiveFunction extends ObjectiveFunction {

  protected Branch target;
  protected ControlDependenceChain controlDependenceChain;
  protected ExecutionTrace trace;

  public BranchTargetObjectiveFunction(Branch target) {
    this.target = target;
    this.controlDependenceChain = getControlDependenceChainForTarget();
  }

  protected abstract ControlDependenceChain getControlDependenceChainForTarget();

  protected ObjectiveValue computeObjectiveValue(Vector vector) {
    trace = new ExecutionTrace();
    executeTestObject(vector);
    DivergencePoint divergencePoint = controlDependenceChain.getDivergencePoint(trace);

    int approachLevel = 0;
    double distance = 0;
    if (divergencePoint != null) {
      approachLevel = divergencePoint.chainIndex;
      distance = trace.getBranchExecution(divergencePoint.traceIndex).getDistanceToAlternative();
    }
    return new BranchTargetObjectiveValue(approachLevel, distance);
  }

  protected abstract void executeTestObject(Vector vector);