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 2e94d01e..1840024a 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/InsertionInitialSolutionFactory.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/InsertionInitialSolutionFactory.java @@ -25,6 +25,7 @@ import jsprit.core.problem.solution.InitialSolutionFactory; import jsprit.core.problem.solution.SolutionCostCalculator; import jsprit.core.problem.solution.VehicleRoutingProblemSolution; import jsprit.core.problem.solution.route.VehicleRoute; +import jsprit.core.problem.vehicle.Vehicle; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -60,7 +61,11 @@ public final class InsertionInitialSolutionFactory implements InitialSolutionFac } private List getUnassignedJobs(VehicleRoutingProblem vrp) { - return new ArrayList(vrp.getJobs().values()); + ArrayList jobs = new ArrayList(vrp.getJobs().values()); + for(Vehicle v : vrp.getVehicles()){ + if(v.getBreak() != null) jobs.add(v.getBreak()); + } + return jobs; } } diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/BreakInsertionCalculator.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/BreakInsertionCalculator.java index e511fa72..976537aa 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/BreakInsertionCalculator.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/BreakInsertionCalculator.java @@ -95,6 +95,7 @@ final class BreakInsertionCalculator implements JobInsertionCostsCalculator{ public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) { Break breakToInsert = (Break) jobToInsert; if(newVehicle.getBreak() == null || newVehicle.getBreak() != breakToInsert) return InsertionData.createEmptyInsertionData(); + if(currentRoute.isEmpty()) return InsertionData.createEmptyInsertionData(); JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime); int insertionIndex = InsertionData.NO_INDEX; @@ -160,11 +161,11 @@ final class BreakInsertionCalculator implements JobInsertionCostsCalculator{ } else if (status.equals(ConstraintsStatus.NOT_FULFILLED)) { breakThis = false; } - double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActStartTime, newDriver, newVehicle); - prevActStartTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct); - prevAct = nextAct; - actIndex++; } + double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActStartTime, newDriver, newVehicle); + prevActStartTime = CalculationUtils.getActivityEndTime(nextActArrTime, nextAct); + prevAct = nextAct; + actIndex++; if(breakThis) break; } if(insertionIndex == InsertionData.NO_INDEX) { diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/InsertBreakListener.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/InsertBreakListener.java index bf8bbd4d..df265750 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/InsertBreakListener.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/InsertBreakListener.java @@ -1,12 +1,16 @@ package jsprit.core.algorithm.recreate; import jsprit.core.problem.solution.route.VehicleRoute; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; /** * Created by schroeder on 19/05/15. */ class InsertBreakListener implements EventListener { + private static final Logger logger = LogManager.getLogger(); + @Override public void inform(Event event) { if(event instanceof InsertBreak){ @@ -20,7 +24,9 @@ class InsertBreakListener implements EventListener { if(!vehicleRoute.isEmpty()){ if(vehicleRoute.getVehicle() != ((InsertBreak) event).getNewVehicle()){ if(vehicleRoute.getVehicle().getBreak() != null){ - vehicleRoute.getTourActivities().removeJob(vehicleRoute.getVehicle().getBreak()); + boolean removed = vehicleRoute.getTourActivities().removeJob(vehicleRoute.getVehicle().getBreak()); + if(removed) + logger.trace("remove old break " + vehicleRoute.getVehicle().getBreak()); } } } diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/LocalActivityInsertionCostsCalculator.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/LocalActivityInsertionCostsCalculator.java index 02209716..e83d04ce 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/LocalActivityInsertionCostsCalculator.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/LocalActivityInsertionCostsCalculator.java @@ -66,6 +66,7 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal double newAct_endTime = CalculationUtils.getActivityEndTime(newAct_arrTime, newAct); double act_costs_newAct = activityCosts.getActivityCost(newAct, newAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle()); +// if(newAct instanceof BreakActivity) act_costs_newAct = 0.; if(isEnd(nextAct) && !toDepot(iFacts.getNewVehicle())) return tp_costs_prevAct_newAct; @@ -74,6 +75,7 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal double nextAct_arrTime = newAct_endTime + tp_time_newAct_nextAct; double endTime_nextAct_new = CalculationUtils.getActivityEndTime(nextAct_arrTime, nextAct); double act_costs_nextAct = activityCosts.getActivityCost(nextAct, nextAct_arrTime, iFacts.getNewDriver(), iFacts.getNewVehicle()); +// if(nextAct instanceof BreakActivity) act_costs_nextAct = 0; double totalCosts = tp_costs_prevAct_newAct + tp_costs_newAct_nextAct + solutionCompletenessRatio * activityCostsWeight * (act_costs_newAct + act_costs_nextAct); @@ -87,6 +89,7 @@ class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCal double arrTime_nextAct = depTimeAtPrevAct + routingCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevAct.getEndTime(), iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle()); double endTime_nextAct_old = CalculationUtils.getActivityEndTime(arrTime_nextAct,nextAct); double actCost_nextAct = activityCosts.getActivityCost(nextAct, arrTime_nextAct, iFacts.getRoute().getDriver(), iFacts.getRoute().getVehicle()); +// if(nextAct instanceof BreakActivity) actCost_nextAct = 0; double endTimeDelay_nextAct = Math.max(0, endTime_nextAct_new - endTime_nextAct_old); Double futureWaiting = stateManager.getActivityState(nextAct, iFacts.getRoute().getVehicle(), InternalStates.FUTURE_WAITING, Double.class); diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/SwitchVehicleListener.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/SwitchVehicleListener.java index cdb8d9a4..3708ec09 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/SwitchVehicleListener.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/SwitchVehicleListener.java @@ -1,15 +1,33 @@ package jsprit.core.algorithm.recreate; +import jsprit.core.problem.job.Break; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + /** * Created by schroeder on 19/05/15. */ class SwitchVehicleListener implements EventListener{ + private static final Logger logger = LogManager.getLogger(); + @Override public void inform(Event event) { if(event instanceof SwitchVehicle){ SwitchVehicle switchVehicle = (SwitchVehicle) event; + if(vehiclesDifferent((SwitchVehicle) event)) { + logger.trace("switch vehicle (" + ((SwitchVehicle) event).getRoute().getVehicle().getId() + " to " + ((SwitchVehicle) event).getVehicle().getId() + ")"); + Break aBreak = ((SwitchVehicle) event).getRoute().getVehicle().getBreak(); + if (aBreak != null) { + boolean removed = ((SwitchVehicle) event).getRoute().getTourActivities().removeJob(aBreak); + if (removed) logger.trace("remove " + aBreak.getId()); + } + } switchVehicle.getRoute().setVehicleAndDepartureTime(switchVehicle.getVehicle(),((SwitchVehicle) event).getDepartureTime()); } } + + private boolean vehiclesDifferent(SwitchVehicle event) { + return !event.getRoute().getVehicle().getId().equals(event.getVehicle().getId()); + } } diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/RuinBreaks.java b/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/RuinBreaks.java index f1f84fc2..f3f56f75 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/RuinBreaks.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/ruin/RuinBreaks.java @@ -4,6 +4,8 @@ import jsprit.core.algorithm.ruin.listener.RuinListener; import jsprit.core.problem.job.Break; import jsprit.core.problem.job.Job; import jsprit.core.problem.solution.route.VehicleRoute; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.util.Collection; @@ -12,6 +14,8 @@ import java.util.Collection; */ public class RuinBreaks implements RuinListener { + private final static Logger logger = LogManager.getLogger(); + @Override public void ruinStarts(Collection routes) {} @@ -21,6 +25,7 @@ public class RuinBreaks implements RuinListener { Break aBreak = r.getVehicle().getBreak(); if(aBreak != null){ r.getTourActivities().removeJob(aBreak); + logger.trace("ruin: " + aBreak.getId()); unassignedJobs.add(aBreak); } } diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateFutureWaitingTimes.java b/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateFutureWaitingTimes.java index 61b99284..d5cb3090 100644 --- a/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateFutureWaitingTimes.java +++ b/jsprit-core/src/main/java/jsprit/core/algorithm/state/UpdateFutureWaitingTimes.java @@ -52,7 +52,9 @@ public class UpdateFutureWaitingTimes implements ReverseActivityVisitor, StateUp @Override public void visit(TourActivity activity) { states.putInternalTypedActivityState(activity,route.getVehicle(),InternalStates.FUTURE_WAITING,futureWaiting); - futureWaiting += Math.max(activity.getTheoreticalEarliestOperationStartTime() - activity.getArrTime(),0); +// if(!(activity instanceof BreakActivity)) { + futureWaiting += Math.max(activity.getTheoreticalEarliestOperationStartTime() - activity.getArrTime(), 0); +// } } @Override diff --git a/jsprit-examples/src/main/java/jsprit/examples/BreakExample.java b/jsprit-examples/src/main/java/jsprit/examples/BreakExample.java index ab5bc9d7..212033b8 100644 --- a/jsprit-examples/src/main/java/jsprit/examples/BreakExample.java +++ b/jsprit-examples/src/main/java/jsprit/examples/BreakExample.java @@ -47,19 +47,22 @@ public class BreakExample { * get a vehicle type-builder and build a type with the typeId "vehicleType" and one capacity dimension, i.e. weight, and capacity dimension value of 2 */ final int WEIGHT_INDEX = 0; - VehicleTypeImpl.Builder vehicleTypeBuilder = VehicleTypeImpl.Builder.newInstance("vehicleType").addCapacityDimension(WEIGHT_INDEX, 4); + VehicleTypeImpl.Builder vehicleTypeBuilder = VehicleTypeImpl.Builder.newInstance("vehicleType") + .addCapacityDimension(WEIGHT_INDEX, 2).setCostPerWaitingTime(1.); VehicleType vehicleType = vehicleTypeBuilder.build(); /* * get a vehicle-builder and build a vehicle located at (10,10) with type "vehicleType" */ - Builder vehicleBuilder = Builder.newInstance("vehicle"); + Builder vehicleBuilder = Builder.newInstance("v1"); vehicleBuilder.setStartLocation(Location.newInstance(10, 10)); - Break myFirstBreak = (Break) Break.Builder.newInstance("myFirstBreak").setTimeWindow(TimeWindow.newInstance(30, 50)).setServiceTime(10).build(); + Break myFirstBreak = (Break) Break.Builder.newInstance("myFirstBreak").setTimeWindow(TimeWindow.newInstance(10, 15)).setServiceTime(100).build(); vehicleBuilder.setBreak(myFirstBreak); vehicleBuilder.setType(vehicleType); VehicleImpl vehicle = vehicleBuilder.build(); - + + VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance(0, 10)).setType(vehicleType) + .setBreak((Break) Break.Builder.newInstance("mySecondBreak").setTimeWindow(TimeWindow.newInstance(5,10)).setServiceTime(10).build()).build(); /* * build services at the required locations, each with a capacity-demand of 1. */ @@ -72,7 +75,7 @@ public class BreakExample { VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance(); vrpBuilder.addVehicle(vehicle); - vrpBuilder.addJob(service1).addJob(service2).addJob(service3).addJob(service4); + vrpBuilder.addJob(service1).addJob(service2).addJob(service3).addJob(service4).addVehicle(v2); vrpBuilder.setFleetSize(VehicleRoutingProblem.FleetSize.FINITE); VehicleRoutingProblem problem = vrpBuilder.build(); diff --git a/jsprit-examples/src/main/java/jsprit/examples/VariableStartAndWaitingTimeExample.java b/jsprit-examples/src/main/java/jsprit/examples/VariableStartAndWaitingTimeExample.java index 7e9c80ae..4320b816 100644 --- a/jsprit-examples/src/main/java/jsprit/examples/VariableStartAndWaitingTimeExample.java +++ b/jsprit-examples/src/main/java/jsprit/examples/VariableStartAndWaitingTimeExample.java @@ -4,6 +4,7 @@ import jsprit.analysis.toolbox.AlgorithmSearchProgressChartListener; import jsprit.analysis.toolbox.Plotter; import jsprit.core.algorithm.VehicleRoutingAlgorithm; import jsprit.core.algorithm.box.Jsprit; +import jsprit.core.algorithm.ruin.RuinBreaks; import jsprit.core.algorithm.state.StateManager; import jsprit.core.algorithm.state.UpdateFutureWaitingTimes; import jsprit.core.analysis.SolutionAnalyser; @@ -11,6 +12,7 @@ import jsprit.core.problem.Location; import jsprit.core.problem.VehicleRoutingProblem; import jsprit.core.problem.constraint.ConstraintManager; import jsprit.core.problem.cost.TransportDistance; +import jsprit.core.problem.job.Break; import jsprit.core.problem.job.Service; import jsprit.core.problem.solution.SolutionCostCalculator; import jsprit.core.problem.solution.VehicleRoutingProblemSolution; @@ -36,17 +38,37 @@ public class VariableStartAndWaitingTimeExample { public static void main(String[] args) { - VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("type").setCostPerDistance(4.).setCostPerWaitingTime(2.0).build(); - VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("type1").setCostPerDistance(4.).setCostPerWaitingTime(2.0).build(); + VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("type") + .addCapacityDimension(0,22) + .setCostPerDistance(4.).setCostPerWaitingTime(2.0).build(); + VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("type2") + .addCapacityDimension(0,22) + .setCostPerDistance(4.).setCostPerWaitingTime(2.0).build(); + VehicleTypeImpl type3 = VehicleTypeImpl.Builder.newInstance("type3") + .addCapacityDimension(0,22) + .setCostPerDistance(4.).setCostPerWaitingTime(2.0).build(); +// VehicleTypeImpl type1 = VehicleTypeImpl.Builder.newInstance("type1").setCostPerDistance(4.).setCostPerWaitingTime(2.0).build(); // VehicleTypeImpl type2 = VehicleTypeImpl.Builder.newInstance("type2").setCostPerDistance(4.).setCostPerWaitingTime(2.0).build(); - VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setType(type).setReturnToDepot(false) + VehicleImpl v2 = VehicleImpl.Builder.newInstance("v2").setType(type).setReturnToDepot(true) .setStartLocation(Location.newInstance(0, 0)) - .setEarliestStart(0).setLatestArrival(220) + .setEarliestStart(0).setLatestArrival(420) + .setBreak((Break) Break.Builder.newInstance("v2-break").setTimeWindow(TimeWindow.newInstance(50,70)).setServiceTime(100).build()) .build(); - VehicleImpl v3 = VehicleImpl.Builder.newInstance("v3").setType(type1).setReturnToDepot(false) - .setStartLocation(Location.newInstance(0, 10)) - .setEarliestStart(200).setLatestArrival(450) + VehicleImpl v3 = VehicleImpl.Builder.newInstance("v3").setType(type2).setReturnToDepot(true) + .setStartLocation(Location.newInstance(0.5, 10.5)) + .setBreak((Break) Break.Builder.newInstance("v3-break").setTimeWindow(TimeWindow.newInstance(50,70)).setServiceTime(100).build()) + .setEarliestStart(0).setLatestArrival(420) + .build(); + VehicleImpl v4 = VehicleImpl.Builder.newInstance("v4").setType(type3).setReturnToDepot(true) + .setStartLocation(Location.newInstance(7, 10.5)) + .setBreak((Break) Break.Builder.newInstance("v4-break").setTimeWindow(TimeWindow.newInstance(50,70)).setServiceTime(50).build()) + .setEarliestStart(0).setLatestArrival(420) + .build(); + VehicleImpl v5 = VehicleImpl.Builder.newInstance("v5").setType(type3).setReturnToDepot(true) + .setStartLocation(Location.newInstance(7, 10.5)) + .setBreak((Break) Break.Builder.newInstance("v5-break").setTimeWindow(TimeWindow.newInstance(300,350)).setServiceTime(20).build()) + .setEarliestStart(250).setLatestArrival(420) .build(); // VehicleImpl v4 = VehicleImpl.Builder.newInstance("v4").setType(type2).setReturnToDepot(true) // .setStartLocation(Location.newInstance(0, 0)).build(); @@ -55,14 +77,18 @@ public class VariableStartAndWaitingTimeExample { for(int i=0;i<40;i++){ Service s = Service.Builder.newInstance("s_"+i).setServiceTime(5) // .setTimeWindow(TimeWindow.newInstance(0,100*(1+r.nextInt(3)))) - .setLocation(Location.newInstance(1 - r.nextInt(5), 10 + r.nextInt(10))).build(); + .setLocation(Location.newInstance(1 - r.nextInt(5), 10 + r.nextInt(10))) + .addSizeDimension(0,1) + .build(); vrpBuilder.addJob(s); } - Service s1 = Service.Builder.newInstance("s12").setLocation(Location.newInstance(-3, 15)).setTimeWindow(TimeWindow.newInstance(290, 600)).build(); - Service s4 = Service.Builder.newInstance("s13").setLocation(Location.newInstance(0,20)).setTimeWindow(TimeWindow.newInstance(290, 340)).build(); - Service s2 = Service.Builder.newInstance("s10").setLocation(Location.newInstance(-1, 15)).setTimeWindow(TimeWindow.newInstance(300, 350)).build(); - Service s3 = Service.Builder.newInstance("s11").setLocation(Location.newInstance(10, 10)).setTimeWindow(TimeWindow.newInstance(300, 600)).build(); - vrpBuilder.addJob(s1).addJob(s2).addJob(s3).addJob(s4).addVehicle(v2).addVehicle(v3); + Service s1 = Service.Builder.newInstance("s12").addSizeDimension(0,1).setLocation(Location.newInstance(-3, 15)).setTimeWindow(TimeWindow.newInstance(290, 600)).build(); + Service s4 = Service.Builder.newInstance("s13").addSizeDimension(0,1).setLocation(Location.newInstance(0, 20)).setTimeWindow(TimeWindow.newInstance(290, 340)).build(); + Service s2 = Service.Builder.newInstance("s10").addSizeDimension(0,1).setLocation(Location.newInstance(-1, 15)).setTimeWindow(TimeWindow.newInstance(300, 350)).build(); + Service s3 = Service.Builder.newInstance("s11").addSizeDimension(0,1).setLocation(Location.newInstance(10, 10)).setTimeWindow(TimeWindow.newInstance(300, 600)).build(); + vrpBuilder + .addJob(s1).addJob(s2).addJob(s3).addJob(s4) + .addVehicle(v2).addVehicle(v3).addVehicle(v4).addVehicle(v5); vrpBuilder.setFleetSize(VehicleRoutingProblem.FleetSize.FINITE); final VehicleRoutingProblem vrp = vrpBuilder.build(); @@ -77,6 +103,11 @@ public class VariableStartAndWaitingTimeExample { .addCoreStateAndConstraintStuff(true) .setStateAndConstraintManager(stateManager, constraintManager) .setProperty(Jsprit.Parameter.THRESHOLD_INI, "0.1") + .setProperty(Jsprit.Strategy.CLUSTER_REGRET, "0.") + .setProperty(Jsprit.Strategy.CLUSTER_BEST, "0.") +// .setProperty(Jsprit.Strategy.WORST_REGRET, "0.") +// .setProperty(Jsprit.Strategy.RANDOM_REGRET, "0.") +// .setProperty(Jsprit.Strategy.RADIAL_REGRET, "0.") // .setProperty(Jsprit.Parameter.THRESHOLD_ALPHA, "0.3") // .setProperty(Parameter.) // .setProperty(Jsprit.Parameter.CONSTRUCTION, Jsprit.Construction.BEST_INSERTION.toString()) @@ -102,6 +133,7 @@ public class VariableStartAndWaitingTimeExample { } }; VehicleRoutingAlgorithm vra = algorithmFactory.createAlgorithm(vrp); + vra.addListener(new RuinBreaks()); vra.setMaxIterations(2000); vra.addListener(new AlgorithmSearchProgressChartListener("output/search")); VehicleRoutingProblemSolution solution = Solutions.bestOf(vra.searchSolutions());