/**
*
*/
package vroom.trsp.optimization.mpa;
import java.util.LinkedList;
import java.util.List;
import vroom.optimization.online.jmsa.IActualRequest;
import vroom.optimization.online.jmsa.IMSARequest;
import vroom.optimization.online.jmsa.IScenario;
import vroom.optimization.online.jmsa.components.ComponentManager;
import vroom.optimization.online.jmsa.components.ScenarioUpdaterBase;
import vroom.trsp.MPASolver;
import vroom.trsp.datamodel.ITRSPNode;
import vroom.trsp.datamodel.ITRSPTour;
import vroom.trsp.datamodel.TRSPRequest;
import vroom.trsp.datamodel.TRSPTour;
import vroom.trsp.datamodel.TRSPTour.TRSPTourIterator;
import vroom.trsp.optimization.InsertionMove;
import vroom.trsp.optimization.alns.RepairRegret;
import vroom.trsp.optimization.mpa.DTRSPSolution.DTRSPTour;
/**
* <code>DTRSPScenarioUpdater</code>
* <p>
* Creation date: Feb 7, 2012 - 11:33:52 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 DTRSPScenarioUpdater extends ScenarioUpdaterBase {
private final MPASolver mSolver;
private final RepairRegret mRepairRegret;
public DTRSPScenarioUpdater(ComponentManager<?, ?> componentManager) {
super(componentManager);
mSolver = getMSAProxy().getParameters().get(MPASolver.TRSP_MPA_SOLVER);
mRepairRegret = new RepairRegret(mSolver.getParams(), mSolver.getTourCtrHandler(), 3, false);
}
@Override
public boolean insertRequest(IScenario scenario, IMSARequest request) {
DTRSPSolution scen = (DTRSPSolution) scenario;
TRSPRequest req = (TRSPRequest) request;
InsertionMove mve = InsertionMove.findInsertion(req.getID(), scen, scen.getCostDelegate(),
mSolver.getTourCtrHandler(), true, true);
if (mve != null && mve.isFeasible()) {
InsertionMove.executeMove(mve);
scen.markAsServed(req.getID());
return true;
} else {
scen.markAsUnserved(req.getID());
return false;
}
}
/**
* Schedule a decision: check all scenarios and set the earliest departure time of {@code node} to {@code time}
* <p>
* The goal is to fix the earliest departure time until the assignment decision is reevaluated.
* </p>
*
* @param node
* the node that will be visited next by {@code technician}
* @param technician
* the technician that is expected to visit {@code node}
* @param time
* the time at which the assignment decision will be reevaluated
*/
public void scheduleDecision(ITRSPNode node, int technician, double time) {
LinkedList<IScenario> outdatedScen = new LinkedList<>();
for (IScenario scen : getMSAProxy().getScenarioPool()) {
DTRSPSolution sol = (DTRSPSolution) scen;
boolean feasible = enforceDecision(scen, node, technician);
if (feasible) {
DTRSPTour tour = sol.getTour(technician);
// We freeze the node and update the earliest departure time
sol.freeze(node.getID(), tour.getEarliestArrivalTime(node.getID()), time);
} else {
outdatedScen.add(scen);
}
}
getMSAProxy().getScenarioPool().removeScenarios(outdatedScen);
}
@Override
public boolean enforceDecision(IScenario scenario, IActualRequest request, int resourceId) {
DTRSPSolution scen = (DTRSPSolution) scenario;
ITRSPNode node = (ITRSPNode) request;
int nodeId = node.getID();
TRSPTour visitingTour = scen.getVisitingTour(nodeId);
int current = mSolver.getInstance().getSimulator().getCurrentNode(resourceId).getID();
TRSPTour targetTour = scen.getTour(resourceId);
if (nodeId == scen.getInstance().getHomeDuplicate(
targetTour.getTechnician().getHome().getID())) {
// The node is the technician home, remove all unserved requests
TRSPTourIterator it = targetTour.iterator();
while (it.hasNext()) {
int n = it.next();
if (!scen.getInstance().isServedOrAssignedOrRejected(n)) {
it.remove();
scen.markAsUnserved(n);
}
}
if (targetTour.getLastNode() != nodeId)
targetTour.appendNode(nodeId, node.getArrivalTime());
} else if (visitingTour != targetTour || current != visitingTour.getPred(nodeId)) {
if (visitingTour != null)
visitingTour.removeNode(nodeId);
targetTour.insertAfter(current, nodeId);
}
scen.markAsServed(nodeId);
// Freeze the node
scen.freeze(nodeId, node.getArrivalTime(),
targetTour.getTimeWindow(nodeId).getEarliestStartOfService(node.getArrivalTime())
+ targetTour.getServiceTime(nodeId));
fixTour(scen, targetTour);
return mSolver.getSolCtrHandler().isFeasible(scen);
}
/**
* Check if a tour is feasible, and if not attempt to fix it
*
* @param scenario
* @param tour
* @return {@code true} if the tour was repaired, {@code false} if some requests were left unserved
*/
public boolean fixTour(DTRSPSolution scenario, TRSPTour tour) {
int infeasNode = mSolver.getSolCtrHandler().getTourConstraintHandler()
.firstInfeasibleNode(tour);
// Attempt to repair the solution if it is not feasible
if (infeasNode != ITRSPTour.UNDEFINED && !scenario.getInstance().isMainDepot(infeasNode)) {// [12/08/03] ignore
// the main depot
// Incrementally check the feasibility of targetTour, remove infeasible requests when detected, attempt to
// reinsert them
List<Integer> removedNodes = tour.truncate(tour.getPred(infeasNode));
for (Integer n : removedNodes)
scenario.markAsUnserved(n);
return mRepairRegret.repair(scenario, null, null);
} else {
return true;
}
}
@Override
public boolean startServicingUpdate(IScenario scenario, int resourceId) {
// Nothing to do
return true;
}
@Override
public boolean stopServicingUpdate(IScenario scenario, int resourceId) {
// Nothing to do
return true;
}
@Override
public boolean startOfServiceUpdate(IScenario scenario, int resourceId, IActualRequest request) {
// Nothing to do
return true;
}
@Override
public boolean endOfServiceUpdate(IScenario scenario, int resourceId,
IActualRequest servedRequest) {
// Nothing to do
return true;
}
}