package vroom.trsp.optimization.constructive;
import vroom.common.heuristics.ProcedureStatus;
import vroom.trsp.datamodel.TRSPInstance;
import vroom.trsp.datamodel.TRSPSolution;
import vroom.trsp.datamodel.TRSPTour;
import vroom.trsp.datamodel.costDelegates.TRSPCostDelegate;
import vroom.trsp.optimization.TRSPHeuristic;
import vroom.trsp.optimization.constraints.TourConstraintHandler;
import vroom.trsp.optimization.mpa.DTRSPSolution;
import vroom.trsp.sim.TRSPSimulator;
import vroom.trsp.util.TRSPGlobalParameters;
public abstract class TRSPConstructiveHeuristic extends TRSPHeuristic {
/** the current solution **/
private TRSPSolution mSolution;
/**
* Getter for the current solution
*
* @return the current solution
*/
public TRSPSolution getSolution() {
return this.mSolution;
}
/**
* Setter for the current solution
*
* @param solution
* the value to be set for the current solution
*/
protected void setSolution(TRSPSolution solution) {
this.mSolution = solution;
}
/**
* Creates a new <code>TRSPConstructiveHeuristic</code> with the given constraint handler
*
* @param constraintHandler
* the constraint handler to use in this heuristic
* @param costDelegate
* the cost delegate used in this heuristic
*/
public TRSPConstructiveHeuristic(TRSPInstance instance, TRSPGlobalParameters parameters,
TourConstraintHandler constraintHandler, TRSPCostDelegate costDelegate) {
super(instance, parameters, constraintHandler, costDelegate);
}
/**
* This method will add empty tours for each technician starting and ending at the technician's home
*
* @param sol
* the solution for which empty tours will be created
*/
private void addEmptyTours(TRSPSolution sol) {
// Create empty tours
for (TRSPTour tour : sol) {
if (tour.length() == 0) {
tour.appendNode(tour.getTechnician().getHome().getID());
tour.appendNode(getInstance().getHomeDuplicate(
tour.getTechnician().getHome().getID()));
}
}
}
/**
* Builds an initial solution
* <p>
* This method will check if a {@linkplain TRSPSimulator#getCurrentSolution() current solution} is defined and use
* it as a starting point.
* </p>
*
* @param solution
* the solution to be initialized
* @see TRSPSimulator#getCurrentSolution()
*/
public final void initializeSolution(TRSPSolution solution) {
// Initialize from current solution
if (solution.getInstance().getSimulator() != null
&& !solution.getInstance().getSimulator().isStaticSetting()) {
DTRSPSolution current = solution.getInstance().getSimulator().getCurrentSolution();
if (current != null) {
solution.importSolution(current);
((DTRSPSolution) solution).unfreeze();
}
for (TRSPTour t : solution) {
t.setAutoUpdated(true);
int home = t.getTechnician().getHome().getID();
int homeD = solution.getInstance().getHomeDuplicate(home);
if (t.length() == 0)
t.appendNode(home);
if (t.getLastNode() != homeD)
t.appendNode(homeD);
}
} else {
addEmptyTours(getSolution());
}
initializeSolutionInternal(solution);
}
/**
* Finish the initialization of the solution, this method is called by {@link #initializeSolution(TRSPSolution)}
*
* @param sol
*/
protected abstract void initializeSolutionInternal(TRSPSolution sol);
@Override
public ProcedureStatus call() {
setStatus(ProcedureStatus.RUNNING);
// Instantiate a dynamic instance when needed
if (getInstance().getSimulator() != null && !getInstance().getSimulator().isStaticSetting())
setSolution(new DTRSPSolution(getInstance(), getCostDelegate()));
else
setSolution(new TRSPSolution(getInstance(), getCostDelegate()));
initializeSolution(getSolution());
if (getSolution().getUnservedCount() == 0)
setStatus(ProcedureStatus.TERMINATED);
else
setStatus(ProcedureStatus.INFEASIBLE_SOLUTION);
return getStatus();
}
}