diff --git a/jsprit-analysis/src/main/java/jsprit/analysis/toolbox/SolutionPrinter.java b/jsprit-analysis/src/main/java/jsprit/analysis/toolbox/SolutionPrinter.java index fa92732e..741e3f79 100644 --- a/jsprit-analysis/src/main/java/jsprit/analysis/toolbox/SolutionPrinter.java +++ b/jsprit-analysis/src/main/java/jsprit/analysis/toolbox/SolutionPrinter.java @@ -30,8 +30,10 @@ import jsprit.core.problem.vehicle.PenaltyVehicleType; * Printer to print the details of a vehicle-routing-problem solution. * * @author stefan schroeder + * @deprecated use jsprit.core.reporting.SolutionPrinter instead * */ +@Deprecated public class SolutionPrinter { /** @@ -93,6 +95,7 @@ public class SolutionPrinter { System.out.format("+---------------+------------------------------------------+%n"); System.out.format(leftAlignSolution, "costs",solution.getCost()); System.out.format(leftAlignSolution, "nVehicles",solution.getRoutes().size()); + System.out.format(leftAlignSolution, "unassignedJobs", solution.getUnassignedJobs().size()); System.out.format("+----------------------------------------------------------+%n"); if(print.equals(Print.VERBOSE)){ @@ -130,6 +133,10 @@ public class SolutionPrinter { } System.out.format("+*:=PenaltyVehicle+%n"); System.out.format("+--------------------------------------------------------------------------------------------------------------------------------+%n"); + System.out.format("+*:=badJobs+%n"); + for(Job j : solution.getUnassignedJobs()){ + System.out.println(j.getId()); + } } private static String getVehicleString(VehicleRoute route) { diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/InsertionInitialSolutionFactory.java b/jsprit-core/src/main/java/jsprit/core/algorithm/InsertionInitialSolutionFactory.java index dd2f59e7..9435513e 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/InsertionInitialSolutionFactory.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/InsertionInitialSolutionFactory.java @@ -29,6 +29,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.ArrayList; +import java.util.Collection; import java.util.List; @@ -51,8 +52,8 @@ public final class InsertionInitialSolutionFactory implements InitialSolutionFac logger.info("create initial solution."); List vehicleRoutes = new ArrayList(); vehicleRoutes.addAll(vrp.getInitialVehicleRoutes()); - insertion.insertJobs(vehicleRoutes, getUnassignedJobs(vrp)); - VehicleRoutingProblemSolution solution = new VehicleRoutingProblemSolution(vehicleRoutes, Double.MAX_VALUE); + Collection badJobs = insertion.insertJobs(vehicleRoutes, getUnassignedJobs(vrp)); + VehicleRoutingProblemSolution solution = new VehicleRoutingProblemSolution(vehicleRoutes, badJobs, Double.MAX_VALUE); double costs = solutionCostsCalculator.getCosts(solution); solution.setCost(costs); logger.info("creation done"); diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/NeighborhoodThresholdInitialiser.java b/jsprit-core/src/main/java/jsprit/core/algorithm/NeighborhoodThresholdInitialiser.java deleted file mode 100644 index 183a659d..00000000 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/NeighborhoodThresholdInitialiser.java +++ /dev/null @@ -1,125 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - ******************************************************************************/ -package jsprit.core.algorithm; - -import jsprit.core.algorithm.io.VehicleRoutingAlgorithms; -import jsprit.core.algorithm.listener.AlgorithmStartsListener; -import jsprit.core.problem.VehicleRoutingProblem; -import jsprit.core.problem.solution.VehicleRoutingProblemSolution; -import jsprit.core.problem.solution.route.VehicleRoute; -import jsprit.core.problem.solution.route.activity.TourActivity; -import jsprit.core.util.*; -import org.apache.commons.math.stat.descriptive.moment.Mean; -import org.apache.commons.math.stat.descriptive.moment.StandardDeviation; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.Collection; - - -class NeighborhoodThresholdInitialiser implements AlgorithmStartsListener{ - - private static Logger log = LogManager.getLogger(NeighborhoodThresholdInitialiser.class); - - private NeighborhoodImpl neighborhood; - - private VehicleRoutingAlgorithmFactory routingAlgorithmFactory = new VehicleRoutingAlgorithmFactory() { - - @Override - public VehicleRoutingAlgorithm createAlgorithm(VehicleRoutingProblem vrp) { - VehicleRoutingAlgorithm algorithm = VehicleRoutingAlgorithms.readAndCreateAlgorithm(vrp, "resources/config.xml"); - return algorithm; - } - }; - - private int crowFlySpeed = 20; - - public NeighborhoodThresholdInitialiser(NeighborhoodImpl neighborhood) { - this.neighborhood = neighborhood; - } - - - /** - * @param crowFlySpeed the crowFlySpeed to set - */ - public void setCrowFlySpeed(int crowFlySpeed) { - this.crowFlySpeed = crowFlySpeed; - } - - - /** - * @param routingAlgorithmFactory the routingAlgorithm to set - */ - public void setRoutingAlgorithmFactory(VehicleRoutingAlgorithmFactory routingAlgorithmFactory) { - this.routingAlgorithmFactory = routingAlgorithmFactory; - } - - public void initialise(VehicleRoutingProblem problem){ - informAlgorithmStarts(problem, null, null); - } - - @Override - public void informAlgorithmStarts(VehicleRoutingProblem problem, VehicleRoutingAlgorithm algorithm, Collection solutions) { - VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance(); - builder.addAllJobs(problem.getJobs().values()); - builder.addAllVehicles(problem.getVehicles()); - CrowFlyCosts crowFly = new CrowFlyCosts(builder.getLocations()); - crowFly.speed = crowFlySpeed; - builder.setRoutingCost(crowFly); - VehicleRoutingProblem pblm = builder.build(); - - VehicleRoutingAlgorithm algo = routingAlgorithmFactory.createAlgorithm(pblm); - Collection mySolutions = algo.searchSolutions(); - - double threshold = determineThreshold(pblm,builder.getLocations(), mySolutions); - neighborhood.setThreshold(threshold); - neighborhood.initialise(); - } - - private double determineThreshold(VehicleRoutingProblem pblm, Locations locations, Collection mySolutions) { - VehicleRoutingProblemSolution bestSolution = Solutions.bestOf(mySolutions); - double[] distances = new double[bestSolution.getRoutes().size()+pblm.getJobs().size()]; - getDistances(distances,bestSolution,locations); - Mean mean = new Mean(); - double meanValue = mean.evaluate(distances); - StandardDeviation dev = new StandardDeviation(); - double devValue = dev.evaluate(distances, meanValue); - log.info("mean="+meanValue+", dev="+devValue); - return meanValue + devValue; -// + 2*devValue; -// return Double.MAX_VALUE; - } - - private void getDistances(double[] distances, VehicleRoutingProblemSolution bestSolution, Locations locations) { - int index = 0; - for(VehicleRoute route : bestSolution.getRoutes()){ - TourActivity prev = null; - for(TourActivity act : route.getTourActivities().getActivities()){ - if(prev == null){ prev = act; continue; } - double dist = EuclideanDistanceCalculator.calculateDistance(locations.getCoord(prev.getLocationId()), locations.getCoord(act.getLocationId())); -// log.info("dist="+dist); - distances[index] = dist; - index++; - prev = act; - } -// double dist = EuclideanDistanceCalculator.calculateDistance(locations.getCoord(prev.getLocationId()), locations.getCoord(route.getEnd().getLocationId())); -// distances[index] = dist; -// index++; - } - } - -} diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/SearchStrategy.java b/jsprit-core/src/main/java/jsprit/core/algorithm/SearchStrategy.java index dc0bdb6f..6a13beab 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/SearchStrategy.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/SearchStrategy.java @@ -117,7 +117,8 @@ public class SearchStrategy { * @param vrp the underlying vehicle routing problem * @param solutions which will be modified * @return discoveredSolution - */ + * @throws java.lang.IllegalStateException if selector cannot select any solution + */ @SuppressWarnings("UnusedParameters") public DiscoveredSolution run(VehicleRoutingProblem vrp, Collection solutions){ VehicleRoutingProblemSolution solution = solutionSelector.selectSolution(solutions); diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/SearchStrategyManager.java b/jsprit-core/src/main/java/jsprit/core/algorithm/SearchStrategyManager.java index 1bd8d0c1..fb38c740 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/SearchStrategyManager.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/SearchStrategyManager.java @@ -16,15 +16,15 @@ ******************************************************************************/ package jsprit.core.algorithm; +import jsprit.core.algorithm.listener.SearchStrategyListener; +import jsprit.core.algorithm.listener.SearchStrategyModuleListener; +import jsprit.core.util.RandomNumberGeneration; + import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Random; -import jsprit.core.algorithm.listener.SearchStrategyListener; -import jsprit.core.algorithm.listener.SearchStrategyModuleListener; -import jsprit.core.util.RandomNumberGeneration; - public class SearchStrategyManager { @@ -55,8 +55,9 @@ public class SearchStrategyManager { /** * adds a new search strategy. the probability must be within [0,1]. - * @param strategy - * @param probability + * @param strategy strategy to be added + * @param probability probability of corresponding strategy to be added + * @throws java.lang.IllegalStateException if strategy is null OR prob > 1. OR prob < 0. */ public void addStrategy(SearchStrategy strategy, double probability){ if(strategy == null){ @@ -76,6 +77,12 @@ public class SearchStrategyManager { } } + /** + * Returns search strategy that has been randomly selected. + * + * @return selected search strategy + * @throws java.lang.IllegalStateException if randomNumberGenerator is null OR no search strategy can be found + */ public SearchStrategy getRandomStrategy() { if(random == null) throw new IllegalStateException("randomizer is null. make sure you set random object correctly"); double randomFig = random.nextDouble(); diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/VariablePlusFixedSolutionCostCalculatorFactory.java b/jsprit-core/src/main/java/jsprit/core/algorithm/VariablePlusFixedSolutionCostCalculatorFactory.java index 7dca0685..5e02b6f0 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/VariablePlusFixedSolutionCostCalculatorFactory.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/VariablePlusFixedSolutionCostCalculatorFactory.java @@ -23,6 +23,7 @@ import jsprit.core.problem.solution.SolutionCostCalculator; import jsprit.core.problem.solution.VehicleRoutingProblemSolution; import jsprit.core.problem.solution.route.VehicleRoute; import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter; +import jsprit.core.problem.vehicle.Vehicle; /** * Default objective function which is the sum of all fixed vehicle and variable @@ -43,16 +44,23 @@ public class VariablePlusFixedSolutionCostCalculatorFactory { public SolutionCostCalculator createCalculator(){ return new SolutionCostCalculator() { - + @Override public double getCosts(VehicleRoutingProblemSolution solution) { double c = 0.0; - for(VehicleRoute r : solution.getRoutes()){ - c += stateManager.getRouteState(r, InternalStates.COSTS,Double.class); - c += r.getVehicle().getType().getVehicleCostParams().fix; + for(VehicleRoute r : solution.getRoutes()){ + c += stateManager.getRouteState(r, InternalStates.COSTS, Double.class); + c += getFixedCosts(r.getVehicle()); } + c += solution.getUnassignedJobs().size() * c * .1; return c; } + + private double getFixedCosts(Vehicle vehicle) { + if(vehicle == null) return 0.0; + if(vehicle.getType() == null) return 0.0; + return vehicle.getType().getVehicleCostParams().fix; + } }; } diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/acceptor/GreedyAcceptance.java b/jsprit-core/src/main/java/jsprit/core/algorithm/acceptor/GreedyAcceptance.java index 1f896697..b892d145 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/acceptor/GreedyAcceptance.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/acceptor/GreedyAcceptance.java @@ -16,10 +16,10 @@ ******************************************************************************/ package jsprit.core.algorithm.acceptor; -import java.util.Collection; - import jsprit.core.problem.solution.VehicleRoutingProblemSolution; +import java.util.Collection; + public class GreedyAcceptance implements SolutionAcceptor{ @@ -48,12 +48,6 @@ public class GreedyAcceptance implements SolutionAcceptor{ if (worstSolution == null) worstSolution = s; else if (s.getCost() > worstSolution.getCost()) worstSolution = s; } -// if(newSolution.getRoutes().size() < worstSolution.getRoutes().size()){ -// solutions.remove(worstSolution); -// solutions.add(newSolution); -// solutionAccepted = true; -// } -// else if(newSolution.getCost() < worstSolution.getCost()){ solutions.remove(worstSolution); solutions.add(newSolution); diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/io/VehicleRoutingAlgorithms.java b/jsprit-core/src/main/java/jsprit/core/algorithm/io/VehicleRoutingAlgorithms.java index 1854df27..4ce8fb42 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/io/VehicleRoutingAlgorithms.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/io/VehicleRoutingAlgorithms.java @@ -620,25 +620,8 @@ public class VehicleRoutingAlgorithms { } private static SolutionCostCalculator getDefaultCostCalculator(final StateManager stateManager) { - SolutionCostCalculator calc = new SolutionCostCalculator() { - - @Override - public double getCosts(VehicleRoutingProblemSolution solution) { - double costs = 0.0; - for(VehicleRoute route : solution.getRoutes()){ - costs += stateManager.getRouteState(route, InternalStates.COSTS, Double.class) + getFixedCosts(route.getVehicle()); - } - return costs; - } - - private double getFixedCosts(Vehicle vehicle) { - if(vehicle == null) return 0.0; - if(vehicle.getType() == null) return 0.0; - return vehicle.getType().getVehicleCostParams().fix; - } - }; - return calc; - } + return new VariablePlusFixedSolutionCostCalculatorFactory(stateManager).createCalculator(); + } private static VehicleFleetManager createFleetManager(final VehicleRoutingProblem vrp) { if(vrp.getFleetSize().equals(FleetSize.INFINITE)){ diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/module/RuinAndRecreateModule.java b/jsprit-core/src/main/java/jsprit/core/algorithm/module/RuinAndRecreateModule.java index 29f79a1e..9aca39d7 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/module/RuinAndRecreateModule.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/module/RuinAndRecreateModule.java @@ -16,8 +16,6 @@ ******************************************************************************/ package jsprit.core.algorithm.module; -import java.util.Collection; - import jsprit.core.algorithm.SearchStrategyModule; import jsprit.core.algorithm.listener.SearchStrategyModuleListener; import jsprit.core.algorithm.recreate.InsertionStrategy; @@ -27,6 +25,10 @@ import jsprit.core.algorithm.ruin.listener.RuinListener; import jsprit.core.problem.job.Job; import jsprit.core.problem.solution.VehicleRoutingProblemSolution; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + public class RuinAndRecreateModule implements SearchStrategyModule{ @@ -46,7 +48,12 @@ public class RuinAndRecreateModule implements SearchStrategyModule{ @Override public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) { Collection ruinedJobs = ruin.ruin(vrpSolution.getRoutes()); - insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobs); + Set ruinedJobSet = new HashSet(); + ruinedJobSet.addAll(ruinedJobs); + ruinedJobSet.addAll(vrpSolution.getUnassignedJobs()); + Collection unassignedJobs = insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobSet); + vrpSolution.getUnassignedJobs().clear(); + vrpSolution.getUnassignedJobs().addAll(unassignedJobs); return vrpSolution; } diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/BestInsertion.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/BestInsertion.java index 15f9fd26..29cff38a 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/BestInsertion.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/BestInsertion.java @@ -34,11 +34,11 @@ import java.util.*; /** - * + * Best insertion that insert the job where additional costs are minimal. + * * @author stefan schroeder * */ - final class BestInsertion implements InsertionStrategy{ class Insertion { @@ -79,8 +79,6 @@ final class BestInsertion implements InsertionStrategy{ private JobInsertionCostsCalculator bestInsertionCostCalculator; - private boolean minVehiclesFirst = false; - public void setRandom(Random random) { this.random = random; } @@ -99,9 +97,10 @@ final class BestInsertion implements InsertionStrategy{ } @Override - public void insertJobs(Collection vehicleRoutes, Collection unassignedJobs) { + public Collection insertJobs(Collection vehicleRoutes, Collection unassignedJobs) { insertionsListeners.informInsertionStarts(vehicleRoutes,unassignedJobs); - List unassignedJobList = new ArrayList(unassignedJobs); + List badJobs = new ArrayList(unassignedJobs.size()); + List unassignedJobList = new ArrayList(unassignedJobs); Collections.shuffle(unassignedJobList, random); for(Job unassignedJob : unassignedJobList){ Insertion bestInsertion = null; @@ -116,41 +115,20 @@ final class BestInsertion implements InsertionStrategy{ bestInsertionCost = iData.getInsertionCost(); } } - if(!minVehiclesFirst){ - VehicleRoute newRoute = VehicleRoute.emptyRoute(); - InsertionData newIData = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost); - if(newIData.getInsertionCost() < bestInsertionCost){ - bestInsertion = new Insertion(newRoute,newIData); - vehicleRoutes.add(newRoute); - } - } - if(bestInsertion == null){ - VehicleRoute newRoute = VehicleRoute.emptyRoute(); - InsertionData bestI = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE); - if(bestI instanceof InsertionData.NoInsertionFound){ - throw new NoSolutionFoundException(getErrorMsg(unassignedJob)); - } - else{ - bestInsertion = new Insertion(newRoute,bestI); - vehicleRoutes.add(newRoute); - } - } -// logger.info("insert " + unassignedJob + " pickup@" + bestInsertion.getInsertionData().getPickupInsertionIndex() + " delivery@" + bestInsertion.getInsertionData().getDeliveryInsertionIndex()); - inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute()); - } + VehicleRoute newRoute = VehicleRoute.emptyRoute(); + InsertionData newIData = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost); + if(newIData.getInsertionCost() < bestInsertionCost){ + bestInsertion = new Insertion(newRoute,newIData); + vehicleRoutes.add(newRoute); + } + if(bestInsertion == null) badJobs.add(unassignedJob); + else inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute()); + } insertionsListeners.informInsertionEndsListeners(vehicleRoutes); + return badJobs; } - private String getErrorMsg(Job unassignedJob) { - return "given the vehicles, could not insert job\n" + - "\t" + unassignedJob + - "\n\tthis might have the following reasons:\n" + - "\t- no vehicle has the capacity to transport the job [check whether there is at least one vehicle that is capable to transport the job]\n" + - "\t- the time-window cannot be met, even in a commuter tour the time-window is missed [check whether it is possible to reach the time-window on the shortest path or make hard time-windows soft]\n" + - "\t- if you deal with finite vehicles, and the available vehicles are already fully employed, no vehicle can be found anymore to transport the job [add penalty-vehicles]"; - } - - @Override + @Override public void removeListener(InsertionListener insertionListener) { insertionsListeners.removeListener(insertionListener); } diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/BestInsertionConcurrent.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/BestInsertionConcurrent.java index ac981be3..e993eb79 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/BestInsertionConcurrent.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/BestInsertionConcurrent.java @@ -85,12 +85,8 @@ final class BestInsertionConcurrent implements InsertionStrategy{ private JobInsertionCostsCalculator bestInsertionCostCalculator; - private boolean minVehiclesFirst = false; - private int nuOfBatches; - - private ExecutorService executor; - + private ExecutorCompletionService completionService; public void setRandom(Random random) { @@ -100,11 +96,10 @@ final class BestInsertionConcurrent implements InsertionStrategy{ public BestInsertionConcurrent(JobInsertionCostsCalculator jobInsertionCalculator, ExecutorService executorService, int nuOfBatches, VehicleRoutingProblem vehicleRoutingProblem) { super(); this.insertionsListeners = new InsertionListeners(); - this.executor = executorService; this.nuOfBatches = nuOfBatches; inserter = new Inserter(insertionsListeners, vehicleRoutingProblem); bestInsertionCostCalculator = jobInsertionCalculator; - completionService = new ExecutorCompletionService(executor); + completionService = new ExecutorCompletionService(executorService); logger.info("initialise " + this); } @@ -114,19 +109,16 @@ final class BestInsertionConcurrent implements InsertionStrategy{ } @Override - public void insertJobs(Collection vehicleRoutes, Collection unassignedJobs) { + public Collection insertJobs(Collection vehicleRoutes, Collection unassignedJobs) { insertionsListeners.informInsertionStarts(vehicleRoutes,unassignedJobs); - List unassignedJobList = new ArrayList(unassignedJobs); + List badJobs = new ArrayList(unassignedJobs.size()); + List unassignedJobList = new ArrayList(unassignedJobs); Collections.shuffle(unassignedJobList, random); - - List batches = distributeRoutes(vehicleRoutes,nuOfBatches); - - for(final Job unassignedJob : unassignedJobList){ - - Insertion bestInsertion = null; + List batches = distributeRoutes(vehicleRoutes,nuOfBatches); + for(final Job unassignedJob : unassignedJobList){ + Insertion bestInsertion = null; double bestInsertionCost = Double.MAX_VALUE; - - for(final Batch batch : batches){ + for(final Batch batch : batches){ completionService.submit(new Callable() { @Override @@ -135,21 +127,18 @@ final class BestInsertionConcurrent implements InsertionStrategy{ } }); - - } - - try{ - for(int i=0;i futureIData = completionService.take(); - Insertion insertion = futureIData.get(); - if(insertion == null) continue; - if(insertion.getInsertionData().getInsertionCost() < bestInsertionCost){ - bestInsertion = insertion; - bestInsertionCost = insertion.getInsertionData().getInsertionCost(); - } - } - } - catch(InterruptedException e){ + } + try { + for (int i = 0; i < batches.size(); i++) { + Future futureIData = completionService.take(); + Insertion insertion = futureIData.get(); + if (insertion == null) continue; + if (insertion.getInsertionData().getInsertionCost() < bestInsertionCost) { + bestInsertion = insertion; + bestInsertionCost = insertion.getInsertionData().getInsertionCost(); + } + } + } catch(InterruptedException e){ Thread.currentThread().interrupt(); } catch (ExecutionException e) { @@ -157,42 +146,18 @@ final class BestInsertionConcurrent implements InsertionStrategy{ logger.error(e.getCause().toString()); System.exit(1); } - - if(!minVehiclesFirst){ - VehicleRoute newRoute = VehicleRoute.emptyRoute(); - InsertionData newIData = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost); - if(newIData.getInsertionCost() < bestInsertionCost){ - bestInsertion = new Insertion(newRoute,newIData); - bestInsertionCost = newIData.getInsertionCost(); - vehicleRoutes.add(newRoute); - batches.get(random.nextInt(batches.size())).routes.add(newRoute); - } - } - - if(bestInsertion == null){ - VehicleRoute newRoute = VehicleRoute.emptyRoute(); - InsertionData bestI = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE); - if(bestI instanceof InsertionData.NoInsertionFound){ - throw new IllegalStateException(getErrorMsg(unassignedJob)); - } - else{ - bestInsertion = new Insertion(newRoute,bestI); - vehicleRoutes.add(newRoute); - } - } -// logger.info("insert " + unassignedJob + " pickup@" + bestInsertion.getInsertionData().getPickupInsertionIndex() + " delivery@" + bestInsertion.getInsertionData().getDeliveryInsertionIndex()); - inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute()); + VehicleRoute newRoute = VehicleRoute.emptyRoute(); + InsertionData newIData = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost); + if(newIData.getInsertionCost() < bestInsertionCost){ + bestInsertion = new Insertion(newRoute,newIData); + vehicleRoutes.add(newRoute); + batches.get(random.nextInt(batches.size())).routes.add(newRoute); + } + if(bestInsertion == null) badJobs.add(unassignedJob); + else inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute()); } insertionsListeners.informInsertionEndsListeners(vehicleRoutes); - } - - private String getErrorMsg(Job unassignedJob) { - return "given the vehicles, could not insert job\n" + - "\t" + unassignedJob + - "\n\tthis might have the following reasons:\n" + - "\t- no vehicle has the capacity to transport the job [check whether there is at least one vehicle that is capable to transport the job]\n" + - "\t- the time-window cannot be met, even in a commuter tour the time-window is missed [check whether it is possible to reach the time-window on the shortest path or make hard time-windows soft]\n" + - "\t- if you deal with finite vehicles, and the available vehicles are already fully employed, no vehicle can be found anymore to transport the job [add penalty-vehicles]"; + return badJobs; } @Override diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/InsertionStrategy.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/InsertionStrategy.java index b7f77521..8d0bc264 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/InsertionStrategy.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/InsertionStrategy.java @@ -16,18 +16,17 @@ ******************************************************************************/ package jsprit.core.algorithm.recreate; -import java.util.Collection; - import jsprit.core.algorithm.recreate.listener.InsertionListener; import jsprit.core.problem.job.Job; import jsprit.core.problem.solution.route.VehicleRoute; - +import java.util.Collection; /** - * + * Basic interface for insertion strategies + * * @author stefan schroeder * */ @@ -35,14 +34,13 @@ import jsprit.core.problem.solution.route.VehicleRoute; public interface InsertionStrategy { /** - * Assigns the unassigned jobs to service-providers - * - * @param vehicleRoutes - * @param unassignedJobs - */ - public void insertJobs(Collection vehicleRoutes, Collection unassignedJobs); - - public void addListener(InsertionListener insertionListener); + * Inserts unassigned jobs into vehicle routes. + * @param vehicleRoutes existing vehicle routes + * @param unassignedJobs jobs to be inserted + */ + public Collection insertJobs(Collection vehicleRoutes, Collection unassignedJobs); + + public void addListener(InsertionListener insertionListener); public void removeListener(InsertionListener insertionListener); diff --git a/jsprit-core/src/main/java/jsprit/core/problem/VehicleRoutingProblem.java b/jsprit-core/src/main/java/jsprit/core/problem/VehicleRoutingProblem.java index f4404433..ee48759b 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/VehicleRoutingProblem.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/VehicleRoutingProblem.java @@ -526,7 +526,9 @@ public class VehicleRoutingProblem { * * @param penaltyFactor penaltyFactor of penaltyVehicle * @return this builder + * @deprecated since 1.3.2-SNAPSHOT bad job list replaces penalty vehicles */ + @Deprecated public Builder addPenaltyVehicles(double penaltyFactor){ this.addPenaltyVehicles = true; this.penaltyFactor = penaltyFactor; @@ -543,7 +545,9 @@ public class VehicleRoutingProblem { * @param penaltyFactor the penaltyFactor of penaltyVehicle * @param penaltyFixedCosts which is an absolute penaltyValue (in contrary to penaltyFactor) * @return this builder + * @deprecated since 1.3.2-SNAPSHOT bad job list replaces penalty vehicles */ + @Deprecated public Builder addPenaltyVehicles(double penaltyFactor, double penaltyFixedCosts){ this.addPenaltyVehicles = true; this.penaltyFactor = penaltyFactor; diff --git a/jsprit-core/src/main/java/jsprit/core/problem/io/VrpXMLReader.java b/jsprit-core/src/main/java/jsprit/core/problem/io/VrpXMLReader.java index 76ca436a..1284c596 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/io/VrpXMLReader.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/io/VrpXMLReader.java @@ -20,10 +20,7 @@ import jsprit.core.problem.VehicleRoutingProblem; import jsprit.core.problem.VehicleRoutingProblem.FleetSize; import jsprit.core.problem.driver.Driver; import jsprit.core.problem.driver.DriverImpl; -import jsprit.core.problem.job.Delivery; -import jsprit.core.problem.job.Pickup; -import jsprit.core.problem.job.Service; -import jsprit.core.problem.job.Shipment; +import jsprit.core.problem.job.*; import jsprit.core.problem.solution.VehicleRoutingProblemSolution; import jsprit.core.problem.solution.route.VehicleRoute; import jsprit.core.problem.solution.route.activity.TimeWindow; @@ -304,7 +301,16 @@ public class VrpXMLReader{ } routes.add(routeBuilder.build()); } - VehicleRoutingProblemSolution solution = new VehicleRoutingProblemSolution(routes, cost); + VehicleRoutingProblemSolution solution = new VehicleRoutingProblemSolution(routes, cost); + List unassignedJobConfigs = solutionConfig.configurationsAt("unassignedJobs.job"); + for(HierarchicalConfiguration unassignedJobConfig : unassignedJobConfigs){ + String jobId = unassignedJobConfig.getString("[@id]"); + Job job = getShipment(jobId); + if(job == null) job = getService(jobId); + if(job == null) throw new IllegalStateException("cannot find unassignedJob with id " + jobId); + solution.getUnassignedJobs().add(job); + } + solutions.add(solution); } } diff --git a/jsprit-core/src/main/java/jsprit/core/problem/io/VrpXMLWriter.java b/jsprit-core/src/main/java/jsprit/core/problem/io/VrpXMLWriter.java index 93216615..e2cd8196 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/io/VrpXMLWriter.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/io/VrpXMLWriter.java @@ -203,6 +203,11 @@ public class VrpXMLWriter { xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").end", route.getEnd().getArrTime()); routeCounter++; } + int unassignedJobCounter = 0; + for(Job unassignedJob : solution.getUnassignedJobs()){ + xmlConfig.setProperty(solutionPath + "(" + counter + ").unassignedJobs.job(" + unassignedJobCounter + ")[@id]", unassignedJob.getId()); + unassignedJobCounter++; + } counter++; } } diff --git a/jsprit-core/src/main/java/jsprit/core/problem/solution/VehicleRoutingProblemSolution.java b/jsprit-core/src/main/java/jsprit/core/problem/solution/VehicleRoutingProblemSolution.java index 63302c94..68f1e621 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/solution/VehicleRoutingProblemSolution.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/solution/VehicleRoutingProblemSolution.java @@ -16,11 +16,12 @@ ******************************************************************************/ package jsprit.core.problem.solution; +import jsprit.core.problem.job.Job; +import jsprit.core.problem.solution.route.VehicleRoute; + import java.util.ArrayList; import java.util.Collection; -import jsprit.core.problem.solution.route.VehicleRoute; - /** * Contains the solution of a vehicle routing problem and its corresponding costs. @@ -29,14 +30,12 @@ import jsprit.core.problem.solution.route.VehicleRoute; * */ public class VehicleRoutingProblemSolution { - - public static double NO_COST_YET = -9999.0; - + /** * Makes a deep copy of the solution to be copied. * - * @param solution2copy - * @return + * @param solution2copy solution to be copied + * @return solution */ public static VehicleRoutingProblemSolution copyOf(VehicleRoutingProblemSolution solution2copy){ return new VehicleRoutingProblemSolution(solution2copy); @@ -44,6 +43,8 @@ public class VehicleRoutingProblemSolution { private final Collection routes; + private Collection unassignedJobs = new ArrayList(); + private double cost; private VehicleRoutingProblemSolution(VehicleRoutingProblemSolution solution){ @@ -53,13 +54,14 @@ public class VehicleRoutingProblemSolution { routes.add(route); } this.cost = solution.getCost(); + unassignedJobs.addAll(solution.getUnassignedJobs()); } /** * Constructs a solution with a number of {@link VehicleRoute}s and their corresponding aggregate cost value. * - * @param routes - * @param cost + * @param routes routes being part of the solution + * @param cost total costs of solution */ public VehicleRoutingProblemSolution(Collection routes, double cost) { super(); @@ -67,6 +69,21 @@ public class VehicleRoutingProblemSolution { this.cost = cost; } + /** + * Constructs a solution with a number of {@link VehicleRoute}s, bad jobs and their corresponding aggregate cost value. + * + * @param routes routes being part of the solution + * @param unassignedJobs jobs that could not be assigned to any vehicle + * @param cost total costs of solution + * + */ + public VehicleRoutingProblemSolution(Collection routes, Collection unassignedJobs, double cost) { + super(); + this.routes = routes; + this.unassignedJobs = unassignedJobs; + this.cost = cost; + } + /** * Returns a collection of vehicle-routes. * @@ -88,10 +105,19 @@ public class VehicleRoutingProblemSolution { /** * Sets the costs of this solution. * - * @param cost + * @param cost the cost to assigned to this solution */ public void setCost(double cost){ this.cost = cost; } + /** + * Returns bad jobs, i.e. jobs that are not assigned to any vehicle route. + * + * @return bad jobs + */ + public Collection getUnassignedJobs(){ + return unassignedJobs; + } + } diff --git a/jsprit-core/src/main/java/jsprit/core/reporting/SolutionPrinter.java b/jsprit-core/src/main/java/jsprit/core/reporting/SolutionPrinter.java index 22abcc1b..6efd27a2 100644 --- a/jsprit-core/src/main/java/jsprit/core/reporting/SolutionPrinter.java +++ b/jsprit-core/src/main/java/jsprit/core/reporting/SolutionPrinter.java @@ -77,10 +77,10 @@ public class SolutionPrinter { System.out.printf("| indicator | value |%n"); System.out.format("+---------------+----------+%n"); - System.out.format(leftAlign, "nJobs", problem.getJobs().values().size()); + System.out.format(leftAlign, "noJobs", problem.getJobs().values().size()); Jobs jobs = getNuOfJobs(problem); - System.out.format(leftAlign, "nServices",jobs.nServices); - System.out.format(leftAlign, "nShipments",jobs.nShipments); + System.out.format(leftAlign, "noServices",jobs.nServices); + System.out.format(leftAlign, "noShipments",jobs.nShipments); System.out.format(leftAlign, "fleetsize",problem.getFleetSize().toString()); System.out.format("+--------------------------+%n"); @@ -92,7 +92,8 @@ public class SolutionPrinter { System.out.printf("| indicator | value |%n"); System.out.format("+---------------+------------------------------------------+%n"); System.out.format(leftAlignSolution, "costs",solution.getCost()); - System.out.format(leftAlignSolution, "nVehicles",solution.getRoutes().size()); + System.out.format(leftAlignSolution, "noVehicles",solution.getRoutes().size()); + System.out.format(leftAlignSolution, "unassgndJobs", solution.getUnassignedJobs().size()); System.out.format("+----------------------------------------------------------+%n"); if(print.equals(Print.VERBOSE)){ @@ -130,6 +131,14 @@ public class SolutionPrinter { } System.out.format("+*:=PenaltyVehicle+%n"); System.out.format("+--------------------------------------------------------------------------------------------------------------------------------+%n"); + System.out.format("+----------------+%n"); + System.out.format("| unassignedJobs |%n"); + System.out.format("+----------------+%n"); + String unassignedJobAlgin = "| %-14s |%n"; + for(Job j : solution.getUnassignedJobs()){ + System.out.format(unassignedJobAlgin,j.getId()); + } + System.out.format("+----------------+%n"); } private static String getVehicleString(VehicleRoute route) { diff --git a/jsprit-core/src/main/resources/vrp_xml_schema.xsd b/jsprit-core/src/main/resources/vrp_xml_schema.xsd index 2eeefe9f..5161871b 100644 --- a/jsprit-core/src/main/resources/vrp_xml_schema.xsd +++ b/jsprit-core/src/main/resources/vrp_xml_schema.xsd @@ -281,7 +281,18 @@ - + + + + + + + + + + + + diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/UnassignedJobListTest.java b/jsprit-core/src/test/java/jsprit/core/algorithm/UnassignedJobListTest.java new file mode 100644 index 00000000..a22f3064 --- /dev/null +++ b/jsprit-core/src/test/java/jsprit/core/algorithm/UnassignedJobListTest.java @@ -0,0 +1,57 @@ +package jsprit.core.algorithm; + +import jsprit.core.algorithm.box.GreedySchrimpfFactory; +import jsprit.core.problem.VehicleRoutingProblem; +import jsprit.core.problem.job.Service; +import jsprit.core.problem.solution.VehicleRoutingProblemSolution; +import jsprit.core.problem.solution.route.activity.TimeWindow; +import jsprit.core.problem.vehicle.VehicleImpl; +import jsprit.core.util.Coordinate; +import jsprit.core.util.Solutions; +import org.junit.Test; + +import java.util.Collection; + +import static org.junit.Assert.assertTrue; + +public class UnassignedJobListTest { + + @Test + public void job2ShouldBeInBadJobList_dueToTimeWindow(){ + VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance(); + builder.addVehicle(VehicleImpl.Builder.newInstance("v1").setEarliestStart(0).setLatestArrival(12).setStartLocationCoordinate(Coordinate.newInstance(1, 1)).build()); + Service job1 = Service.Builder.newInstance("job1").setCoord(Coordinate.newInstance(0, 0)).setTimeWindow(TimeWindow.newInstance(0, 12)).setServiceTime(1).build(); + builder.addJob(job1); + Service job2 = Service.Builder.newInstance("job2").setCoord(Coordinate.newInstance(2, 2)).setTimeWindow(TimeWindow.newInstance(12, 24)).setServiceTime(1).build(); + builder.addJob(job2); + + VehicleRoutingProblem vrp = builder.build(); + VehicleRoutingAlgorithm algorithm = new GreedySchrimpfFactory().createAlgorithm(vrp); + algorithm.setMaxIterations(10); + Collection solutions = algorithm.searchSolutions(); + + VehicleRoutingProblemSolution solution = Solutions.bestOf(solutions); + assertTrue(!solution.getUnassignedJobs().contains(job1)); + assertTrue(solution.getUnassignedJobs().contains(job2)); + } + + @Test + public void job2ShouldBeInBadJobList_dueToSize(){ + VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance(); + builder.addVehicle(VehicleImpl.Builder.newInstance("v1").setEarliestStart(0).setLatestArrival(12).setStartLocationCoordinate(Coordinate.newInstance(1, 1)).build()); + Service job1 = Service.Builder.newInstance("job1").setCoord(Coordinate.newInstance(0, 0)).setTimeWindow(TimeWindow.newInstance(0, 12)).setServiceTime(1).build(); + builder.addJob(job1); + Service job2 = Service.Builder.newInstance("job2").setCoord(Coordinate.newInstance(2, 2)).addSizeDimension(0,10).setTimeWindow(TimeWindow.newInstance(0, 12)).setServiceTime(1).build(); + builder.addJob(job2); + + VehicleRoutingProblem vrp = builder.build(); + VehicleRoutingAlgorithm algorithm = new GreedySchrimpfFactory().createAlgorithm(vrp); + algorithm.setMaxIterations(10); + Collection solutions = algorithm.searchSolutions(); + + VehicleRoutingProblemSolution solution = Solutions.bestOf(solutions); + assertTrue(!solution.getUnassignedJobs().contains(job1)); + assertTrue(solution.getUnassignedJobs().contains(job2)); + } + +} diff --git a/jsprit-core/src/test/java/jsprit/core/algorithm/io/TestAlgorithmReader.java b/jsprit-core/src/test/java/jsprit/core/algorithm/io/TestAlgorithmReader.java index b282e69b..262a01f4 100644 --- a/jsprit-core/src/test/java/jsprit/core/algorithm/io/TestAlgorithmReader.java +++ b/jsprit-core/src/test/java/jsprit/core/algorithm/io/TestAlgorithmReader.java @@ -16,12 +16,6 @@ ******************************************************************************/ package jsprit.core.algorithm.io; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.Collection; - import jsprit.core.algorithm.SearchStrategy; import jsprit.core.algorithm.SearchStrategyModule; import jsprit.core.algorithm.VehicleRoutingAlgorithm; @@ -42,11 +36,16 @@ import jsprit.core.problem.io.VrpXMLReader; import jsprit.core.problem.job.Job; import jsprit.core.problem.solution.VehicleRoutingProblemSolution; import jsprit.core.problem.solution.route.VehicleRoute; - import org.apache.commons.configuration.ConfigurationException; import org.junit.Before; import org.junit.Test; +import java.util.ArrayList; +import java.util.Collection; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + public class TestAlgorithmReader { @@ -242,5 +241,19 @@ public class TestAlgorithmReader { } assertEquals(3, nOfModules); } + + @Test + public void readerTest_whenReadingAlgoWithSchemaValidation_itReadsCorrectly(){ + AlgorithmConfig algoConfig = new AlgorithmConfig(); + new AlgorithmConfigXmlReader(algoConfig).read("src/test/resources/algorithmConfig.xml"); + + } + + @Test + public void readerTest_whenReadingAlgoWithSchemaValidationWithoutIterations_itReadsCorrectly(){ + AlgorithmConfig algoConfig = new AlgorithmConfig(); + new AlgorithmConfigXmlReader(algoConfig).read("src/test/resources/algorithmConfig_withoutIterations.xml"); + + } } diff --git a/jsprit-core/src/test/java/jsprit/core/problem/io/AlgorithmReaderTest.java b/jsprit-core/src/test/java/jsprit/core/problem/io/AlgorithmReaderTest.java deleted file mode 100644 index 24beca4b..00000000 --- a/jsprit-core/src/test/java/jsprit/core/problem/io/AlgorithmReaderTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - ******************************************************************************/ -package jsprit.core.problem.io; - -import jsprit.core.algorithm.io.AlgorithmConfig; -import jsprit.core.algorithm.io.AlgorithmConfigXmlReader; - -import org.junit.Test; - -public class AlgorithmReaderTest { - - @Test - public void readerTest_whenReadingAlgoWithSchemaValidation_itReadsCorrectly(){ - AlgorithmConfig algoConfig = new AlgorithmConfig(); - new AlgorithmConfigXmlReader(algoConfig).read("src/test/resources/algorithmConfig.xml"); - - } - - @Test - public void readerTest_whenReadingAlgoWithSchemaValidationWithoutIterations_itReadsCorrectly(){ - AlgorithmConfig algoConfig = new AlgorithmConfig(); - new AlgorithmConfigXmlReader(algoConfig).read("src/test/resources/algorithmConfig_withoutIterations.xml"); - - } - -} diff --git a/jsprit-core/src/test/java/jsprit/core/problem/io/ReaderTest.java b/jsprit-core/src/test/java/jsprit/core/problem/io/ReaderTest.java deleted file mode 100644 index a9d1fb06..00000000 --- a/jsprit-core/src/test/java/jsprit/core/problem/io/ReaderTest.java +++ /dev/null @@ -1,63 +0,0 @@ -/******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3.0 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - ******************************************************************************/ -package jsprit.core.problem.io; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; -import java.util.List; - -import jsprit.core.problem.VehicleRoutingProblem; -import jsprit.core.problem.VehicleRoutingProblem.Builder; -import jsprit.core.problem.io.VrpXMLReader; -import jsprit.core.problem.solution.VehicleRoutingProblemSolution; -import jsprit.core.problem.solution.route.activity.DeliverShipment; -import jsprit.core.problem.solution.route.activity.PickupService; -import jsprit.core.problem.solution.route.activity.PickupShipment; -import jsprit.core.problem.solution.route.activity.TourActivity; - -import org.junit.Test; - - -public class ReaderTest { - - - @Test - public void testRead_ifReaderIsCalled_itReadsSuccessfully(){ - new VrpXMLReader(VehicleRoutingProblem.Builder.newInstance(), new ArrayList()).read("src/test/resources/lui-shen-solution.xml"); - } - - @Test - public void testRead_ifReaderIsCalled_itReadsSuccessfullyV2(){ - Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance(); - ArrayList solutions = new ArrayList(); - new VrpXMLReader(vrpBuilder, solutions).read("src/test/resources/finiteVrpWithShipmentsAndSolution.xml"); - VehicleRoutingProblem vrp = vrpBuilder.build(); - assertEquals(3,vrp.getJobs().size()); - assertEquals(1,solutions.size()); - - assertEquals(1,solutions.get(0).getRoutes().size()); - List activities = solutions.get(0).getRoutes().iterator().next().getTourActivities().getActivities(); - assertEquals(4,activities.size()); - assertTrue(activities.get(0) instanceof PickupService); - assertTrue(activities.get(1) instanceof PickupService); - assertTrue(activities.get(2) instanceof PickupShipment); - assertTrue(activities.get(3) instanceof DeliverShipment); - } - -} diff --git a/jsprit-core/src/test/java/jsprit/core/problem/io/VrpXMLReaderTest.java b/jsprit-core/src/test/java/jsprit/core/problem/io/VrpXMLReaderTest.java index 67bd1266..3fbabf8c 100644 --- a/jsprit-core/src/test/java/jsprit/core/problem/io/VrpXMLReaderTest.java +++ b/jsprit-core/src/test/java/jsprit/core/problem/io/VrpXMLReaderTest.java @@ -1,16 +1,16 @@ /******************************************************************************* - * Copyright (C) 2013 Stefan Schroeder - * + * Copyright (C) 2014 Stefan Schroeder + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either + * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. - * + * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . ******************************************************************************/ @@ -21,7 +21,13 @@ import jsprit.core.problem.VehicleRoutingProblem.FleetSize; import jsprit.core.problem.job.Job; import jsprit.core.problem.job.Service; import jsprit.core.problem.job.Shipment; +import jsprit.core.problem.solution.VehicleRoutingProblemSolution; +import jsprit.core.problem.solution.route.activity.DeliverShipment; +import jsprit.core.problem.solution.route.activity.PickupService; +import jsprit.core.problem.solution.route.activity.PickupShipment; +import jsprit.core.problem.solution.route.activity.TourActivity; import jsprit.core.problem.vehicle.Vehicle; +import jsprit.core.util.Solutions; import org.junit.Before; import org.junit.Test; @@ -570,5 +576,47 @@ public class VrpXMLReaderTest { assertEquals(2,vrp.getInitialVehicleRoutes().iterator().next().getActivities().size()); } + @Test + public void testRead_ifReaderIsCalled_itReadsSuccessfullyV2(){ + VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance(); + ArrayList solutions = new ArrayList(); + new VrpXMLReader(vrpBuilder, solutions).read("src/test/resources/finiteVrpWithShipmentsAndSolution.xml"); + VehicleRoutingProblem vrp = vrpBuilder.build(); + assertEquals(4,vrp.getJobs().size()); + assertEquals(1,solutions.size()); + assertEquals(1,solutions.get(0).getRoutes().size()); + List activities = solutions.get(0).getRoutes().iterator().next().getTourActivities().getActivities(); + assertEquals(4,activities.size()); + assertTrue(activities.get(0) instanceof PickupService); + assertTrue(activities.get(1) instanceof PickupService); + assertTrue(activities.get(2) instanceof PickupShipment); + assertTrue(activities.get(3) instanceof DeliverShipment); + } + + @Test + public void testRead_ifReaderIsCalled_itReadsSuccessfully(){ + new VrpXMLReader(VehicleRoutingProblem.Builder.newInstance(), new ArrayList()).read("src/test/resources/lui-shen-solution.xml"); + assertTrue(true); + } + + + @Test + public void unassignedJobShouldBeRead(){ + VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance(); + ArrayList solutions = new ArrayList(); + new VrpXMLReader(vrpBuilder, solutions).read("src/test/resources/finiteVrpWithShipmentsAndSolution.xml"); + + VehicleRoutingProblemSolution solution = Solutions.bestOf(solutions); + assertEquals(1,solution.getUnassignedJobs().size()); + assertEquals("4",solution.getUnassignedJobs().iterator().next().getId()); + } + +// @Test +// public void solutionListShouldBeEmpty(){ +// VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance(); +// ArrayList solutions = new ArrayList(); +// new VrpXMLReader(vrpBuilder, solutions).read("src/test/resources/finiteVrpforReaderTest.xml"); +// assertTrue(solutions.isEmpty()); +// } } diff --git a/jsprit-core/src/test/java/jsprit/core/problem/io/VrpXMLWriterTest.java b/jsprit-core/src/test/java/jsprit/core/problem/io/VrpXMLWriterTest.java index 7f8be992..e17a5ef1 100644 --- a/jsprit-core/src/test/java/jsprit/core/problem/io/VrpXMLWriterTest.java +++ b/jsprit-core/src/test/java/jsprit/core/problem/io/VrpXMLWriterTest.java @@ -21,15 +21,20 @@ import jsprit.core.problem.VehicleRoutingProblem.Builder; import jsprit.core.problem.VehicleRoutingProblem.FleetSize; import jsprit.core.problem.job.Service; import jsprit.core.problem.job.Shipment; +import jsprit.core.problem.solution.VehicleRoutingProblemSolution; +import jsprit.core.problem.solution.route.VehicleRoute; import jsprit.core.problem.solution.route.activity.TimeWindow; import jsprit.core.problem.vehicle.Vehicle; import jsprit.core.problem.vehicle.VehicleImpl; import jsprit.core.problem.vehicle.VehicleTypeImpl; import jsprit.core.util.Coordinate; +import jsprit.core.util.Solutions; import org.junit.Before; import org.junit.Test; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import static org.junit.Assert.*; @@ -865,4 +870,68 @@ public class VrpXMLWriterTest { assertEquals(2,newVrp.getInitialVehicleRoutes().iterator().next().getActivities().size()); } + @Test + public void solutionWithoutUnassignedJobsShouldBeWrittenCorrectly(){ + Builder builder = VehicleRoutingProblem.Builder.newInstance(); + + VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build(); + VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setStartLocationId("loc").setType(type1).build(); + builder.addVehicle(v1); + + Service s1 = Service.Builder.newInstance("1").addSizeDimension(0, 1).setLocationId("loc").setServiceTime(2.0).build(); + Service s2 = Service.Builder.newInstance("2").addSizeDimension(0, 1).setLocationId("loc2").setServiceTime(4.0).build(); + + VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build(); + + VehicleRoute route = VehicleRoute.Builder.newInstance(v1).addService(s1).addService(s2).build(); + List routes = new ArrayList(); + routes.add(route); + VehicleRoutingProblemSolution solution = new VehicleRoutingProblemSolution(routes,10.); + List solutions = new ArrayList(); + solutions.add(solution); + + new VrpXMLWriter(vrp, solutions).write(infileName); + + VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance(); + List solutionsToRead = new ArrayList(); + new VrpXMLReader(vrpToReadBuilder, solutionsToRead).read(infileName); + + assertEquals(1, solutionsToRead.size()); + assertEquals(10., Solutions.bestOf(solutionsToRead).getCost(),0.01); + assertTrue(Solutions.bestOf(solutionsToRead).getUnassignedJobs().isEmpty()); + } + + @Test + public void solutionWithUnassignedJobsShouldBeWrittenCorrectly(){ + Builder builder = VehicleRoutingProblem.Builder.newInstance(); + + VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("vehType").addCapacityDimension(0, 20).build(); + VehicleImpl v1 = VehicleImpl.Builder.newInstance("v1").setStartLocationId("loc").setType(type1).build(); + builder.addVehicle(v1); + + Service s1 = Service.Builder.newInstance("1").addSizeDimension(0, 1).setLocationId("loc").setServiceTime(2.0).build(); + Service s2 = Service.Builder.newInstance("2").addSizeDimension(0, 1).setLocationId("loc2").setServiceTime(4.0).build(); + + VehicleRoutingProblem vrp = builder.addJob(s1).addJob(s2).build(); + + VehicleRoute route = VehicleRoute.Builder.newInstance(v1).addService(s1).build(); + List routes = new ArrayList(); + routes.add(route); + VehicleRoutingProblemSolution solution = new VehicleRoutingProblemSolution(routes,10.); + solution.getUnassignedJobs().add(s2); + List solutions = new ArrayList(); + solutions.add(solution); + + new VrpXMLWriter(vrp, solutions).write(infileName); + + VehicleRoutingProblem.Builder vrpToReadBuilder = VehicleRoutingProblem.Builder.newInstance(); + List solutionsToRead = new ArrayList(); + new VrpXMLReader(vrpToReadBuilder, solutionsToRead).read(infileName); + + assertEquals(1, solutionsToRead.size()); + assertEquals(10., Solutions.bestOf(solutionsToRead).getCost(),0.01); + assertEquals(1, Solutions.bestOf(solutionsToRead).getUnassignedJobs().size()); + assertEquals("2", Solutions.bestOf(solutionsToRead).getUnassignedJobs().iterator().next().getId()); + } + } diff --git a/jsprit-core/src/test/java/jsprit/core/problem/solution/VehicleRoutingProblemSolutionTest.java b/jsprit-core/src/test/java/jsprit/core/problem/solution/VehicleRoutingProblemSolutionTest.java index 4d55c600..81e21ac4 100644 --- a/jsprit-core/src/test/java/jsprit/core/problem/solution/VehicleRoutingProblemSolutionTest.java +++ b/jsprit-core/src/test/java/jsprit/core/problem/solution/VehicleRoutingProblemSolutionTest.java @@ -18,14 +18,17 @@ ******************************************************************************/ package jsprit.core.problem.solution; +import jsprit.core.problem.job.Job; +import jsprit.core.problem.solution.route.VehicleRoute; +import org.junit.Test; + +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.List; -import jsprit.core.problem.solution.route.VehicleRoute; - -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; -import org.junit.Test; public class VehicleRoutingProblemSolutionTest { @@ -51,4 +54,42 @@ public class VehicleRoutingProblemSolutionTest { assertEquals(20.0,sol.getCost(),0.01); } + @Test + public void sizeOfBadJobsShouldBeCorrect(){ + Job badJob = mock(Job.class); + List badJobs = new ArrayList(); + badJobs.add(badJob); + VehicleRoutingProblemSolution sol = new VehicleRoutingProblemSolution(Collections.emptyList(), badJobs, 10.0); + assertEquals(1,sol.getUnassignedJobs().size()); + } + + @Test + public void sizeOfBadJobsShouldBeCorrect_2(){ + Job badJob = mock(Job.class); + List badJobs = new ArrayList(); + badJobs.add(badJob); + VehicleRoutingProblemSolution sol = new VehicleRoutingProblemSolution(Collections.emptyList(), 10.0); + sol.getUnassignedJobs().addAll(badJobs); + assertEquals(1, sol.getUnassignedJobs().size()); + } + + @Test + public void badJobsShouldBeCorrect(){ + Job badJob = mock(Job.class); + List badJobs = new ArrayList(); + badJobs.add(badJob); + VehicleRoutingProblemSolution sol = new VehicleRoutingProblemSolution(Collections.emptyList(), badJobs, 10.0); + assertEquals(badJob,sol.getUnassignedJobs().iterator().next()); + } + + @Test + public void badJobsShouldBeCorrect_2() { + Job badJob = mock(Job.class); + List badJobs = new ArrayList(); + badJobs.add(badJob); + VehicleRoutingProblemSolution sol = new VehicleRoutingProblemSolution(Collections.emptyList(), 10.0); + sol.getUnassignedJobs().addAll(badJobs); + assertEquals(badJob, sol.getUnassignedJobs().iterator().next()); + } + } diff --git a/jsprit-core/src/test/resources/finiteVrpWithShipmentsAndSolution.xml b/jsprit-core/src/test/resources/finiteVrpWithShipmentsAndSolution.xml index 357b5356..1171c3b8 100644 --- a/jsprit-core/src/test/resources/finiteVrpWithShipmentsAndSolution.xml +++ b/jsprit-core/src/test/resources/finiteVrpWithShipmentsAndSolution.xml @@ -81,6 +81,19 @@ + + + i(3,9) + + 1 + 0.0 + + + 0.0 + 4000.0 + + + @@ -143,6 +156,9 @@ 100.0 + + + diff --git a/jsprit-core/src/test/resources/infiniteWriterV2Test.xml b/jsprit-core/src/test/resources/infiniteWriterV2Test.xml index d5236fe7..a0d9b95f 100644 --- a/jsprit-core/src/test/resources/infiniteWriterV2Test.xml +++ b/jsprit-core/src/test/resources/infiniteWriterV2Test.xml @@ -6,15 +6,13 @@ - v - type + v1 + vehType - startLoc - + loc - endLoc - + loc 0.0 @@ -25,19 +23,9 @@ - type + vehType - 100 - 1000 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 10000 + 20 0.0 @@ -46,4 +34,53 @@ + + + loc2 + + 1 + + 4.0 + + + 0.0 + 1.7976931348623157E308 + + + + + loc + + 1 + + 2.0 + + + 0.0 + 1.7976931348623157E308 + + + + + + + 10.0 + + + noDriver + v1 + 0.0 + + 1 + 0.0 + 0.0 + + 0.0 + + + + + + + diff --git a/jsprit-examples/src/main/java/jsprit/examples/BicycleMessenger.java b/jsprit-examples/src/main/java/jsprit/examples/BicycleMessenger.java index 175967d8..431277fd 100644 --- a/jsprit-examples/src/main/java/jsprit/examples/BicycleMessenger.java +++ b/jsprit-examples/src/main/java/jsprit/examples/BicycleMessenger.java @@ -245,7 +245,7 @@ public class BicycleMessenger { VehicleRoutingTransportCosts routingCosts = new CrowFlyCosts(problemBuilder.getLocations()); //which is the default VehicleRoutingTransportCosts in builder above problemBuilder.setRoutingCost(routingCosts); //finally build the problem - problemBuilder.addPenaltyVehicles(20.0,50000); +// problemBuilder.addPenaltyVehicles(20.0,50000); VehicleRoutingProblem bicycleMessengerProblem = problemBuilder.build(); /* @@ -269,13 +269,14 @@ public class BicycleMessenger { //create your algorithm VehicleRoutingAlgorithmBuilder vraBuilder = new VehicleRoutingAlgorithmBuilder(bicycleMessengerProblem,"input/algorithmConfig_open.xml"); +// vraBuilder.setNuOfThreads(2); vraBuilder.addDefaultCostCalculators(); vraBuilder.setStateAndConstraintManager(stateManager, constraintManager); VehicleRoutingAlgorithm algorithm = vraBuilder.build(); - algorithm.setNuOfIterations(2000); + algorithm.setMaxIterations(5000); VariationCoefficientTermination prematureAlgorithmTermination = new VariationCoefficientTermination(200, 0.001); - algorithm.setPrematureAlgorithmTermination(prematureAlgorithmTermination); - algorithm.addListener(prematureAlgorithmTermination); +// algorithm.setPrematureAlgorithmTermination(prematureAlgorithmTermination); +// algorithm.addListener(prematureAlgorithmTermination); // algorithm.addListener(new AlgorithmSearchProgressChartListener("output/progress.png")); //search @@ -294,7 +295,8 @@ public class BicycleMessenger { //and the problem as well as the solution Plotter plotter1 = new Plotter(bicycleMessengerProblem, Solutions.bestOf(solutions)); - plotter1.plotShipments(false); + plotter1.setLabel(Plotter.Label.ID); + plotter1.plotShipments(false); // plotter1.setBoundingBox(5000, 45500, 25000, 66500); plotter1.plot("output/bicycleMessengerSolution.png", "bicycleMessenger"); diff --git a/jsprit-examples/src/main/java/jsprit/examples/HVRPBenchmarkExample.java b/jsprit-examples/src/main/java/jsprit/examples/HVRPBenchmarkExample.java index 773d2bc6..2d77d4fc 100644 --- a/jsprit-examples/src/main/java/jsprit/examples/HVRPBenchmarkExample.java +++ b/jsprit-examples/src/main/java/jsprit/examples/HVRPBenchmarkExample.java @@ -18,8 +18,6 @@ ******************************************************************************/ package jsprit.examples; -import java.util.Collection; - import jsprit.analysis.toolbox.AlgorithmSearchProgressChartListener; import jsprit.analysis.toolbox.GraphStreamViewer; import jsprit.analysis.toolbox.Plotter; @@ -34,6 +32,8 @@ import jsprit.instance.reader.VrphGoldenReader; import jsprit.instance.reader.VrphGoldenReader.VrphType; import jsprit.util.Examples; +import java.util.Collection; + /** * Shows how to benchmark the algorithm on different classical HVRP and FSM instances. * @@ -57,7 +57,7 @@ public class HVRPBenchmarkExample { //read modified Golden-instance, you can find all relevant instances in jsprit-instances/instances/vrph //you can build various problems, see VrphType doc for more details new VrphGoldenReader(vrpBuilder, VrphType.HVRPFD).read("input/cn_14mix.txt"); - vrpBuilder.addPenaltyVehicles(10.0); +// vrpBuilder.addPenaltyVehicles(10.0); VehicleRoutingProblem vrp = vrpBuilder.build(); //try also input//jsprit-examples/input/algorithmConfig_considerFixedCosts_routeLevel.xml diff --git a/jsprit-examples/src/main/java/jsprit/examples/HVRPExample.java b/jsprit-examples/src/main/java/jsprit/examples/HVRPExample.java index 87bda898..df4c8020 100644 --- a/jsprit-examples/src/main/java/jsprit/examples/HVRPExample.java +++ b/jsprit-examples/src/main/java/jsprit/examples/HVRPExample.java @@ -18,8 +18,6 @@ ******************************************************************************/ package jsprit.examples; -import java.util.Collection; - import jsprit.analysis.toolbox.GraphStreamViewer; import jsprit.analysis.toolbox.SolutionPrinter; import jsprit.analysis.toolbox.SolutionPrinter.Print; @@ -35,6 +33,8 @@ import jsprit.core.problem.vehicle.VehicleTypeImpl; import jsprit.core.util.Coordinate; import jsprit.core.util.Solutions; +import java.util.Collection; + /** * customers (id,x,y,demand) * 1 22 22 18 @@ -113,7 +113,7 @@ public class HVRPExample { vrpBuilder.addVehicle(vehicle3_1); //add penaltyVehicles to allow invalid solutions temporarily - vrpBuilder.addPenaltyVehicles(5, 1000); +// vrpBuilder.addPenaltyVehicles(5, 1000); //set fleetsize finite vrpBuilder.setFleetSize(FleetSize.FINITE); diff --git a/jsprit-examples/src/main/java/jsprit/examples/MultipleDepotExampleWithPenaltyVehicles.java b/jsprit-examples/src/main/java/jsprit/examples/MultipleDepotExampleWithPenaltyVehicles.java index 4ddc16e1..633825a0 100644 --- a/jsprit-examples/src/main/java/jsprit/examples/MultipleDepotExampleWithPenaltyVehicles.java +++ b/jsprit-examples/src/main/java/jsprit/examples/MultipleDepotExampleWithPenaltyVehicles.java @@ -16,8 +16,9 @@ ******************************************************************************/ package jsprit.examples; -import jsprit.analysis.toolbox.*; -import jsprit.analysis.toolbox.SolutionPrinter.Print; +import jsprit.analysis.toolbox.GraphStreamViewer; +import jsprit.analysis.toolbox.Plotter; +import jsprit.analysis.toolbox.StopWatch; import jsprit.core.algorithm.VehicleRoutingAlgorithm; import jsprit.core.algorithm.io.VehicleRoutingAlgorithms; import jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.Priority; @@ -28,6 +29,7 @@ import jsprit.core.problem.solution.VehicleRoutingProblemSolution; import jsprit.core.problem.vehicle.VehicleImpl; import jsprit.core.problem.vehicle.VehicleType; import jsprit.core.problem.vehicle.VehicleTypeImpl; +import jsprit.core.reporting.SolutionPrinter; import jsprit.core.util.Coordinate; import jsprit.core.util.Solutions; import jsprit.util.Examples; @@ -59,7 +61,7 @@ public class MultipleDepotExampleWithPenaltyVehicles { * * each with 14 vehicles each with a capacity of 500 and a maximum duration of 310 */ - int nuOfVehicles = 14; + int nuOfVehicles = 13; int capacity = 500; double maxDuration = 310; Coordinate firstDepotCoord = Coordinate.newInstance(-33, 33); @@ -68,7 +70,8 @@ public class MultipleDepotExampleWithPenaltyVehicles { int depotCounter = 1; for(Coordinate depotCoord : Arrays.asList(firstDepotCoord,second)){ for(int i=0;i solutions = vra.searchSolutions(); - SolutionPrinter.print(vrp,Solutions.bestOf(solutions),Print.VERBOSE); + SolutionPrinter.print(vrp, Solutions.bestOf(solutions), jsprit.core.reporting.SolutionPrinter.Print.VERBOSE); new Plotter(vrp, Solutions.bestOf(solutions)).plot("output/p08_solution.png", "p08");