/**
*
*/
package vroom.trsp.optimization.constraints;
import vroom.common.utilities.optimization.IMove;
import vroom.trsp.datamodel.ITRSPTour;
import vroom.trsp.optimization.InsertionMove;
import vroom.trsp.optimization.localSearch.TRSPShift.TRSPShiftMove;
import vroom.trsp.optimization.localSearch.TRSPTwoOpt.TRSPTwoOptMove;
/**
* The class <code>TourConstraintBase</code> contains common logic for implementations of the {@link ITourConstraint}
* interface.
* <p>
* Creation date: Sep 27, 2011 - 1:39:45 PM
*
* @author Victor Pillac, <a href="http://uniandes.edu.co">Universidad de Los Andes</a>-<a
* href="http://copa.uniandes.edu.co">Copa</a> <a href="http://www.emn.fr">Ecole des Mines de Nantes</a>-<a
* href="http://www.irccyn.ec-nantes.fr/irccyn/d/en/equipes/Slp">SLP</a>
* @version 1.0
*/
public abstract class TourConstraintBase implements ITourConstraint {
/*
* (non-Javadoc)
* @see vroom.common.utilities.optimization.IConstraint#isFeasible(java.lang.Object)
*/
@Override
public boolean isFeasible(ITRSPTour tour) {
return checkFeasibility(tour).isFeasible();
}
@Override
public int firstInfeasibleNode(ITRSPTour tour) {
return checkFeasibility(tour).getInfeasibleNode();
}
@Override
public final String getInfeasibilityExplanation(ITRSPTour tour) {
return checkFeasibility(tour).getInfeasibility();
}
/**
* Checks the feasibility of a tour
*
* @param tour
* the tour to be checked
* @return an object describing the feasibility of {@code tour}
*/
protected abstract FeasibilityState checkFeasibility(ITRSPTour tour);
@Override
public boolean isFeasible(ITRSPTour tour, IMove move) {
// We assume that the tour data is updated and coherent
if (move instanceof InsertionMove) {
return isInsFeasible(tour, (InsertionMove) move);
} else if (move instanceof TRSPShiftMove) {
return isShiftFeasible(tour, (TRSPShiftMove) move);
} else if (move instanceof TRSPTwoOptMove) {
return isTwoOptFeasible(tour, (TRSPTwoOptMove) move);
} else {
throw new UnsupportedOperationException(String.format("Unsupported move: %s", move));
}
}
/*
* (non-Javadoc)
* @see vroom.common.utilities.optimization.IConstraint#getInfeasibilityExplanation(java.lang.Object,
* vroom.common.utilities.optimization.IMove)
*/
@Override
public String getInfeasibilityExplanation(ITRSPTour solution, IMove move) {
if (!isFeasible(solution, move))
return this.getClass().getSimpleName() + ":infeasible";
else
return this.getClass().getSimpleName() + ":feasible";
}
protected abstract boolean isTwoOptFeasible(ITRSPTour tour, TRSPTwoOptMove move);
protected abstract boolean isShiftFeasible(ITRSPTour tour, TRSPShiftMove move);
protected abstract boolean isInsFeasible(ITRSPTour tour, InsertionMove move);
@Override
public abstract int checkFeasibility(ITRSPTour tour, IMove move);
/**
* The class <code>FeasibilityState</code> is used to reduce overhead when checking the feasibility of a solution or
* move.
* <p>
* Creation date: Oct 5, 2011 - 1:57:27 PM
*
* @author Victor Pillac, <a href="http://uniandes.edu.co">Universidad de Los Andes</a>-<a
* href="http://copa.uniandes.edu.co">Copa</a> <a href="http://www.emn.fr">Ecole des Mines de Nantes</a>-<a
* href="http://www.irccyn.ec-nantes.fr/irccyn/d/en/equipes/Slp">SLP</a>
* @version 1.0
*/
protected static class FeasibilityState {
private final String mFormat;
private final int mInfeasibleNode;
private final Object[] mArgs;
private final boolean mFeasible;
/**
* Creates a new <code>FeasibilityState</code>
*
* @param infeasibleNode
* the node at which the tour becomes infeasible (optional)
* @param format
* the format string for the infeasibility explanation, if <code>null</code> the state is assumed to
* be feasible
* @param args
* arguments for the format string
*/
protected FeasibilityState(int infeasibleNode, String format, Object... args) {
mFormat = format;
mInfeasibleNode = infeasibleNode;
mArgs = args;
mFeasible = format == null;
}
/**
* Creates a new <code>FeasibilityState</code> representing a feasible state
*/
protected FeasibilityState() {
this(ITRSPTour.UNDEFINED, null, (Object[]) null);
}
/**
* Returns <code>true</code> if this instance corresponds to a feasible state, <code>false</code> otherwise
*
* @return <code>true</code> if this instance corresponds to a feasible state, <code>false</code> otherwise
*/
protected boolean isFeasible() {
return mFeasible;
}
/**
* Returns the infeasibility explanation for this state, or <code>null</code> if the state is feasible
*
* @return the infeasibility explanation for this state, or <code>null</code> if the state is feasible
*/
protected String getInfeasibility() {
return mFeasible ? null : String.format(mFormat, mArgs);
}
/**
* Returns the first node at which the tour becomes infeasible
*
* @return the first node at which the tour becomes infeasible
*/
public int getInfeasibleNode() {
return mInfeasibleNode;
}
}
}