/** * */ package vroom.trsp.datamodel; import java.util.Iterator; import vroom.common.modeling.dataModel.Depot; /** * <code>TRSPSolutionChecker</code> is an implementation of {@link TRSPSolutionCheckerBase} that checks the feasibility * of a solution regarding the base definition of the TRSP. * <p> * Creation date: Jun 15, 2011 - 10:22:15 AM * * @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 class TRSPSolutionChecker extends TRSPSolutionCheckerBase { public static final TRSPSolutionChecker INSTANCE = new TRSPSolutionChecker(); /** * Creates a new <code>TRSPSolutionChecker</code> */ public TRSPSolutionChecker() { super(); } /** * Creates a new <code>TRSPSolutionChecker</code> * * @param checkUnserved */ public TRSPSolutionChecker(boolean checkUnserved) { super(checkUnserved); } /* * (non-Javadoc) * @see vroom.trsp.datamodel.TRSPSolutionCheckerBase#checkTour(vroom.trsp.datamodel.TRSPTour) */ @Override public String checkTour(ITRSPTour tour) { if (tour.length() == 0) return ""; TRSPInstance instance = tour.getInstance(); Technician tech = instance.getFleet().getVehicle(tour.getTechnicianId()); StringBuilder err = new StringBuilder(); // --------------------------------------------------------------- // Check if the tour starts and end at the technician home Depot home = tech.getHome(); if (!instance.isDynamic() && (tour.getFirstNode() != home.getID() || tour.getLastNode() != instance .getHomeDuplicate(home.getID()))) err.append("Tour does not start/end at the technician home"); // --------------------------------------------------------------- if (tour.length() < 2) return err.toString(); int[] spare = tech.getSpareParts(); Iterator<Integer> it = tour.iterator(); // Iterate over the tour double time = tech.getHome().getTimeWindow().startAsDouble(); int pred = it.next(); boolean checkSPT = true; while (it.hasNext()) { int node = it.next(); // Update current time time = instance.getTimeWindow(pred).getEarliestStartOfService(time); time += instance.getServiceTime(pred); time += instance.getCostDelegate().getTravelTime(pred, node, tech); // Time windows if (!instance.getTimeWindow(node).isFeasible(time)) { append(err, "TW violated at node %s (%.4f@%s)", node, time, instance.getTimeWindow(node)); } // Visit to main depot if (instance.isMainDepot(node)) { if (!instance.isMainDepotTripAllowed()) append(err, "Trips to main depot are not allowed"); else checkSPT = false; // We assume that SP and T constraints will be satisfied } // The node is a request, check skills, tools, and spare parts if (instance.isRequest(node)) { final TRSPRequest req = instance.getRequest(node); // Skills for (int s : req.getSkillSet()) { if (!tech.getSkillSet().hasAttribute(s)) append(err, "SkillCtr violated at node %s (skill:%s)", node, s); } if (checkSPT) { // Tools for (int t : req.getToolSet()) { if (!tech.getToolSet().hasAttribute(t)) append(err, "ToolCtr violated at node %s (tool:%s)", node, t); } // Spare parts for (int s = 0; s < spare.length; s++) { spare[s] -= req.getSparePartRequirement(s); if (spare[s] < 0) append(err, "SpareCtr violated at node %s (part:%s rem:%s)", node, s, spare[s]); } } } pred = node; } return err.toString(); } }