/** * */ package vroom.trsp.optimization.alns; import java.util.ArrayList; import java.util.Collections; import java.util.ConcurrentModificationException; import java.util.List; import java.util.Set; import vroom.common.heuristics.alns.IDestroy; import vroom.common.utilities.optimization.IParameters; import vroom.trsp.datamodel.TRSPInstance; import vroom.trsp.datamodel.TRSPSolution; import vroom.trsp.datamodel.TRSPTour; /** * <code>DestroyTRSP</code> is the base class for <em>destroy</em> procedures used within an ALNS for the TRSP. * <p> * It provides common processes such as the removal of unnecessary depot trips * </p> * <p> * Creation date: May 24, 2011 - 10:34:22 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 abstract class DestroyTRSP implements IDestroy<TRSPSolution> { /** * Creates a new <code>DestroyTRSP</code> * * @param simulator */ public DestroyTRSP() { } private boolean mRunning = false; @Override public final IDestroyResult<TRSPSolution> destroy(TRSPSolution solution, IParameters parameters, double size) { if (mRunning) throw new ConcurrentModificationException( "This destroy procedure is already used by another thread"); mRunning = true; ArrayList<Integer> removable = new ArrayList<>(solution.getInstance() .getUnservedReleasedRequests().size()); for (int i : solution.getInstance().getUnservedReleasedRequests()) { if (canBeRemoved(solution, i)) removable.add(i); } Set<Integer> remRequests; if (!removable.isEmpty()) { int numReq = (int) (size * removable.size()); remRequests = doDestroy(solution, parameters, removable, numReq); // Remove unnecessary trips to depot for (TRSPTour t : solution) { if (t.isMainDepotVisited() && !t.isVisitToMainDepotRequired() && !solution.getInstance().isServedOrAssignedOrRejected(t.getMainDepotId())) t.removeNode(t.getMainDepotId()); } } else { remRequests = Collections.emptySet(); } mRunning = false; return new TRSPDestroyResult(remRequests); } /** * Remove <code>size*{@link TRSPInstance#getRequestCount() requestCount}</code> requests from <code>solution</code> * and return them in a set. * <p> * Implementations do no need to remove depot trips, nor to add removed requests to the * {@link TRSPSolution#getUnservedRequests() unserved pool}. * </p> * * @param solution * the solution * @param parameters * the parameters * @param removableReq * the ids of the requests that can be removed * @param numReq * the number of requests to be removed * @return a set containing the removed requests * @see #destroy(TRSPSolution, IParameters, double) */ protected abstract Set<Integer> doDestroy(TRSPSolution solution, IParameters parameters, List<Integer> removableReq, int numReq); /** * Check if a request can be removed from the current solution. The method will return {@code false} for requests * that are already {@linkplain TRSPSolution#getUnservedRequests() unserved}, and in the dynamic case this method * will return {@code false} for requests that have already been served, or assigned, or rejected. * * @param request * the request id * @return {@code true} if the request can be removed, {@code false} otherwise */ private boolean canBeRemoved(TRSPSolution solution, int request) { return !solution.getInstance().isServedOrAssignedOrRejected(request) && !solution.getUnservedRequests().contains(request); } /** * Remove a request from the solution * * @param solution * the solution in which the request will be removed * @param request * the request to be removed * @return the tour in which the request was, or <code>null</code> if the request was not found */ public TRSPTour removeRequest(TRSPSolution solution, int request) { TRSPTour tour = solution.getVisitingTour(request); if (tour != null) { tour.removeNode(request); solution.markAsUnserved(request); } return tour; } @Override public void dispose() { // Do nothing } @Override public abstract DestroyTRSP clone(); /** * Store the evaluation of a request */ protected static class Evaluation implements Comparable<Evaluation> { final int request; final TRSPTour tour; double eval; /** * Creates a new <code>Relatedness</code> * * @param request * @param tour * @param eval */ public Evaluation(int request, TRSPTour tour, double eval) { this.request = request; this.eval = eval; this.tour = tour; } @Override public int compareTo(Evaluation o) { return Double.compare(this.eval, o.eval); } @Override public String toString() { return String.format("r%s(%s)", request, eval); } } }