1
0
Fork 0
mirror of https://github.com/graphhopper/jsprit.git synced 2020-01-24 07:45:05 +01:00

Merge remote-tracking branch 'origin/master'

This commit is contained in:
Michal Maciejewski 2018-09-26 15:19:19 +02:00
commit b68879303e
No known key found for this signature in database
GPG key ID: 015947E60A2AD77B
28 changed files with 1404 additions and 169 deletions

View file

@ -20,6 +20,7 @@ package com.graphhopper.jsprit.core.algorithm.box;
import com.graphhopper.jsprit.core.algorithm.PrettyAlgorithmBuilder;
import com.graphhopper.jsprit.core.algorithm.SearchStrategy;
import com.graphhopper.jsprit.core.algorithm.SearchStrategyModule;
import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm;
import com.graphhopper.jsprit.core.algorithm.acceptor.SchrimpfAcceptance;
import com.graphhopper.jsprit.core.algorithm.acceptor.SolutionAcceptor;
@ -124,7 +125,10 @@ public class Jsprit {
STRING_K_MIN("string_kmin"),
STRING_K_MAX("string_kmax"),
STRING_L_MIN("string_lmin"),
STRING_L_MAX("string_lmax");
STRING_L_MAX("string_lmax"),
MIN_UNASSIGNED("min_unassigned"),
PROPORTION_UNASSIGNED("proportion_unassigned");
String paraName;
@ -233,6 +237,9 @@ public class Jsprit {
defaults.put(Parameter.FAST_REGRET.toString(), String.valueOf(false));
defaults.put(Parameter.BREAK_SCHEDULING.toString(), String.valueOf(true));
defaults.put(Parameter.CONSTRUCTION.toString(), Construction.REGRET_INSERTION.toString());
defaults.put(Parameter.MIN_UNASSIGNED.toString(), String.valueOf(Integer.MAX_VALUE));
defaults.put(Parameter.PROPORTION_UNASSIGNED.toString(), String.valueOf(1.0));
return defaults;
}
@ -526,8 +533,8 @@ public class Jsprit {
boolean fastRegret = Boolean.parseBoolean(getProperty(Parameter.FAST_REGRET.toString()));
if (es != null) {
if(fastRegret){
RegretInsertionConcurrentFast regretInsertion = (RegretInsertionConcurrentFast) new InsertionBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
.setInsertionStrategy(InsertionBuilder.Strategy.REGRET)
RegretInsertionConcurrentFast regretInsertion = (RegretInsertionConcurrentFast) new InsertionStrategyBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
.setInsertionStrategy(InsertionStrategyBuilder.Strategy.REGRET)
.setConcurrentMode(es, noThreads)
.setFastRegret(true)
.considerFixedCosts(toDouble(getProperty(Parameter.FIXED_COST_PARAM.toString())))
@ -540,8 +547,8 @@ public class Jsprit {
regret = regretInsertion;
}
else {
RegretInsertionConcurrent regretInsertion = (RegretInsertionConcurrent) new InsertionBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
.setInsertionStrategy(InsertionBuilder.Strategy.REGRET)
RegretInsertionConcurrent regretInsertion = (RegretInsertionConcurrent) new InsertionStrategyBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
.setInsertionStrategy(InsertionStrategyBuilder.Strategy.REGRET)
.setConcurrentMode(es, noThreads)
.considerFixedCosts(toDouble(getProperty(Parameter.FIXED_COST_PARAM.toString())))
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
@ -553,8 +560,8 @@ public class Jsprit {
}
} else {
if(fastRegret) {
RegretInsertionFast regretInsertion = (RegretInsertionFast) new InsertionBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
.setInsertionStrategy(InsertionBuilder.Strategy.REGRET)
RegretInsertionFast regretInsertion = (RegretInsertionFast) new InsertionStrategyBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
.setInsertionStrategy(InsertionStrategyBuilder.Strategy.REGRET)
.setFastRegret(true)
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
.considerFixedCosts(toDouble(getProperty(Parameter.FIXED_COST_PARAM.toString())))
@ -566,8 +573,8 @@ public class Jsprit {
regret = regretInsertion;
}
else{
RegretInsertion regretInsertion = (RegretInsertion) new InsertionBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
.setInsertionStrategy(InsertionBuilder.Strategy.REGRET)
RegretInsertion regretInsertion = (RegretInsertion) new InsertionStrategyBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
.setInsertionStrategy(InsertionStrategyBuilder.Strategy.REGRET)
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
.considerFixedCosts(toDouble(getProperty(Parameter.FIXED_COST_PARAM.toString())))
.setActivityInsertionCostCalculator(activityInsertion)
@ -581,16 +588,16 @@ public class Jsprit {
AbstractInsertionStrategy best;
if (vrp.getJobs().size() < 250 || es == null) {
BestInsertion bestInsertion = (BestInsertion) new InsertionBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
.setInsertionStrategy(InsertionBuilder.Strategy.BEST)
BestInsertion bestInsertion = (BestInsertion) new InsertionStrategyBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
.setInsertionStrategy(InsertionStrategyBuilder.Strategy.BEST)
.considerFixedCosts(Double.valueOf(properties.getProperty(Parameter.FIXED_COST_PARAM.toString())))
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
.setActivityInsertionCostCalculator(activityInsertion)
.build();
best = bestInsertion;
} else {
BestInsertionConcurrent bestInsertion = (BestInsertionConcurrent) new InsertionBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
.setInsertionStrategy(InsertionBuilder.Strategy.BEST)
BestInsertionConcurrent bestInsertion = (BestInsertionConcurrent) new InsertionStrategyBuilder(vrp, vehicleFleetManager, stateManager, constraintManager)
.setInsertionStrategy(InsertionStrategyBuilder.Strategy.BEST)
.considerFixedCosts(Double.valueOf(properties.getProperty(Parameter.FIXED_COST_PARAM.toString())))
.setAllowVehicleSwitch(toBoolean(getProperty(Parameter.VEHICLE_SWITCH.toString())))
.setConcurrentMode(es, noThreads)
@ -621,34 +628,34 @@ public class Jsprit {
SolutionCostCalculator objectiveFunction = getObjectiveFunction(vrp, maxCosts);
SearchStrategy radial_regret = new SearchStrategy(Strategy.RADIAL_REGRET.toString(), new SelectBest(), acceptor, objectiveFunction);
radial_regret.addModule(new RuinAndRecreateModule(Strategy.RADIAL_REGRET.toString(), regret, radial));
radial_regret.addModule(configureModule(new RuinAndRecreateModule(Strategy.RADIAL_REGRET.toString(), regret, radial)));
SearchStrategy radial_best = new SearchStrategy(Strategy.RADIAL_BEST.toString(), new SelectBest(), acceptor, objectiveFunction);
radial_best.addModule(new RuinAndRecreateModule(Strategy.RADIAL_BEST.toString(), best, radial));
radial_best.addModule(configureModule(new RuinAndRecreateModule(Strategy.RADIAL_BEST.toString(), best, radial)));
SearchStrategy random_best = new SearchStrategy(Strategy.RANDOM_BEST.toString(), new SelectBest(), acceptor, objectiveFunction);
random_best.addModule(new RuinAndRecreateModule(Strategy.RANDOM_BEST.toString(), best, random_for_best));
random_best.addModule(configureModule(new RuinAndRecreateModule(Strategy.RANDOM_BEST.toString(), best, random_for_best)));
SearchStrategy random_regret = new SearchStrategy(Strategy.RANDOM_REGRET.toString(), new SelectBest(), acceptor, objectiveFunction);
random_regret.addModule(new RuinAndRecreateModule(Strategy.RANDOM_REGRET.toString(), regret, random_for_regret));
random_regret.addModule(configureModule(new RuinAndRecreateModule(Strategy.RANDOM_REGRET.toString(), regret, random_for_regret)));
SearchStrategy worst_regret = new SearchStrategy(Strategy.WORST_REGRET.toString(), new SelectBest(), acceptor, objectiveFunction);
worst_regret.addModule(new RuinAndRecreateModule(Strategy.WORST_REGRET.toString(), regret, worst));
worst_regret.addModule(configureModule(new RuinAndRecreateModule(Strategy.WORST_REGRET.toString(), regret, worst)));
SearchStrategy worst_best = new SearchStrategy(Strategy.WORST_BEST.toString(), new SelectBest(), acceptor, objectiveFunction);
worst_best.addModule(new RuinAndRecreateModule(Strategy.WORST_BEST.toString(), best, worst));
worst_best.addModule(configureModule(new RuinAndRecreateModule(Strategy.WORST_BEST.toString(), best, worst)));
final SearchStrategy clusters_regret = new SearchStrategy(Strategy.CLUSTER_REGRET.toString(), new SelectBest(), acceptor, objectiveFunction);
clusters_regret.addModule(new RuinAndRecreateModule(Strategy.CLUSTER_REGRET.toString(), regret, clusters));
clusters_regret.addModule(configureModule(new RuinAndRecreateModule(Strategy.CLUSTER_REGRET.toString(), regret, clusters)));
final SearchStrategy clusters_best = new SearchStrategy(Strategy.CLUSTER_BEST.toString(), new SelectBest(), acceptor, objectiveFunction);
clusters_best.addModule(new RuinAndRecreateModule(Strategy.CLUSTER_BEST.toString(), best, clusters));
clusters_best.addModule(configureModule(new RuinAndRecreateModule(Strategy.CLUSTER_BEST.toString(), best, clusters)));
SearchStrategy stringRegret = new SearchStrategy(Strategy.STRING_REGRET.toString(), new SelectBest(), acceptor, objectiveFunction);
stringRegret.addModule(new RuinAndRecreateModule(Strategy.STRING_REGRET.toString(), regret, stringRuin));
stringRegret.addModule(configureModule(new RuinAndRecreateModule(Strategy.STRING_REGRET.toString(), regret, stringRuin)));
SearchStrategy stringBest = new SearchStrategy(Strategy.STRING_BEST.toString(), new SelectBest(), acceptor, objectiveFunction);
stringBest.addModule(new RuinAndRecreateModule(Strategy.STRING_BEST.toString(), best, stringRuin));
stringBest.addModule(configureModule(new RuinAndRecreateModule(Strategy.STRING_BEST.toString(), best, stringRuin)));
PrettyAlgorithmBuilder prettyBuilder = PrettyAlgorithmBuilder.newInstance(vrp, vehicleFleetManager, stateManager, constraintManager);
prettyBuilder.setRandom(random);
@ -697,6 +704,13 @@ public class Jsprit {
}
private SearchStrategyModule configureModule(RuinAndRecreateModule ruinAndRecreateModule) {
ruinAndRecreateModule.setRandom(random);
ruinAndRecreateModule.setMinUnassignedJobsToBeReinserted(Integer.valueOf(properties.getProperty(Parameter.MIN_UNASSIGNED.toString())));
ruinAndRecreateModule.setProportionOfUnassignedJobsToBeReinserted(Double.valueOf(properties.getProperty(Parameter.PROPORTION_UNASSIGNED.toString())));
return ruinAndRecreateModule;
}
private DefaultScorer getRegretScorer(VehicleRoutingProblem vrp) {
DefaultScorer scorer = new DefaultScorer(vrp);
scorer.setTimeWindowParam(Double.valueOf(properties.getProperty(Parameter.REGRET_TIME_WINDOW_SCORER.toString())));

View file

@ -26,9 +26,7 @@ import com.graphhopper.jsprit.core.algorithm.ruin.listener.RuinListener;
import com.graphhopper.jsprit.core.problem.job.Job;
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.*;
public class RuinAndRecreateModule implements SearchStrategyModule {
@ -39,6 +37,12 @@ public class RuinAndRecreateModule implements SearchStrategyModule {
private String moduleName;
private Random random = new Random(4711);
private int minUnassignedJobsToBeReinserted = Integer.MAX_VALUE;
private double proportionOfUnassignedJobsToBeReinserted = 1d;
public RuinAndRecreateModule(String moduleName, InsertionStrategy insertion, RuinStrategy ruin) {
super();
this.insertion = insertion;
@ -46,16 +50,58 @@ public class RuinAndRecreateModule implements SearchStrategyModule {
this.moduleName = moduleName;
}
/**
* To make overall results reproducible, make sure this class is provided with the "global" random number generator.
*
* @param random
*/
public void setRandom(Random random) {
this.random = random;
}
/**
* Minimum number of unassigned jobs that is reinserted in each iteration.
*
* @param minUnassignedJobsToBeReinserted
*/
public void setMinUnassignedJobsToBeReinserted(int minUnassignedJobsToBeReinserted) {
this.minUnassignedJobsToBeReinserted = minUnassignedJobsToBeReinserted;
}
/**
* Proportion of unassigned jobs that is reinserted in each iteration.
*
* @param proportionOfUnassignedJobsToBeReinserted
*/
public void setProportionOfUnassignedJobsToBeReinserted(double proportionOfUnassignedJobsToBeReinserted) {
this.proportionOfUnassignedJobsToBeReinserted = proportionOfUnassignedJobsToBeReinserted;
}
@Override
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution vrpSolution) {
Collection<Job> ruinedJobs = ruin.ruin(vrpSolution.getRoutes());
Set<Job> ruinedJobSet = new HashSet<Job>();
public VehicleRoutingProblemSolution runAndGetSolution(VehicleRoutingProblemSolution previousVrpSolution) {
Collection<Job> ruinedJobs = ruin.ruin(previousVrpSolution.getRoutes());
Set<Job> ruinedJobSet = new HashSet<>();
ruinedJobSet.addAll(ruinedJobs);
ruinedJobSet.addAll(vrpSolution.getUnassignedJobs());
Collection<Job> unassignedJobs = insertion.insertJobs(vrpSolution.getRoutes(), ruinedJobSet);
vrpSolution.getUnassignedJobs().clear();
vrpSolution.getUnassignedJobs().addAll(unassignedJobs);
return vrpSolution;
List<Job> stillUnassignedInThisIteration = new ArrayList<>();
if (previousVrpSolution.getUnassignedJobs().size() < minUnassignedJobsToBeReinserted) {
ruinedJobSet.addAll(previousVrpSolution.getUnassignedJobs());
} else {
int noUnassignedToBeInserted = Math.max(minUnassignedJobsToBeReinserted, (int) (previousVrpSolution.getUnassignedJobs().size() * proportionOfUnassignedJobsToBeReinserted));
List<Job> jobList = new ArrayList<>(previousVrpSolution.getUnassignedJobs());
Collections.shuffle(jobList, random);
for (int i = 0; i < noUnassignedToBeInserted; i++) {
ruinedJobSet.add(jobList.get(i));
}
for (int i = noUnassignedToBeInserted; i < jobList.size(); i++) {
stillUnassignedInThisIteration.add(jobList.get(i));
}
}
Collection<Job> unassignedJobs = insertion.insertJobs(previousVrpSolution.getRoutes(), ruinedJobSet);
previousVrpSolution.getUnassignedJobs().clear();
previousVrpSolution.getUnassignedJobs().addAll(unassignedJobs);
previousVrpSolution.getUnassignedJobs().addAll(stillUnassignedInThisIteration);
VehicleRoutingProblemSolution newSolution = previousVrpSolution;
return newSolution;
}

View file

@ -49,25 +49,25 @@ final class BreakInsertionCalculator implements JobInsertionCostsCalculator {
private static final Logger logger = LoggerFactory.getLogger(BreakInsertionCalculator.class);
private HardRouteConstraint hardRouteLevelConstraint;
private final HardRouteConstraint hardRouteLevelConstraint;
private HardActivityConstraint hardActivityLevelConstraint;
private final HardActivityConstraint hardActivityLevelConstraint;
private SoftRouteConstraint softRouteConstraint;
private final SoftRouteConstraint softRouteConstraint;
private SoftActivityConstraint softActivityConstraint;
private final SoftActivityConstraint softActivityConstraint;
private VehicleRoutingTransportCosts transportCosts;
private final VehicleRoutingTransportCosts transportCosts;
private final VehicleRoutingActivityCosts activityCosts;
private ActivityInsertionCostsCalculator additionalTransportCostsCalculator;
private final ActivityInsertionCostsCalculator additionalTransportCostsCalculator;
private JobActivityFactory activityFactory;
private final JobActivityFactory activityFactory;
private AdditionalAccessEgressCalculator additionalAccessEgressCalculator;
private final AdditionalAccessEgressCalculator additionalAccessEgressCalculator;
public BreakInsertionCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts, ActivityInsertionCostsCalculator additionalTransportCostsCalculator, ConstraintManager constraintManager) {
public BreakInsertionCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts, ActivityInsertionCostsCalculator additionalTransportCostsCalculator, ConstraintManager constraintManager, JobActivityFactory activityFactory) {
super();
this.transportCosts = routingCosts;
this.activityCosts = activityCosts;
@ -77,12 +77,10 @@ final class BreakInsertionCalculator implements JobInsertionCostsCalculator {
softRouteConstraint = constraintManager;
this.additionalTransportCostsCalculator = additionalTransportCostsCalculator;
additionalAccessEgressCalculator = new AdditionalAccessEgressCalculator(routingCosts);
this.activityFactory = activityFactory;
logger.debug("initialise " + this);
}
public void setJobActivityFactory(JobActivityFactory jobActivityFactory) {
this.activityFactory = jobActivityFactory;
}
@Override
public String toString() {

View file

@ -0,0 +1,30 @@
/*
* Licensed to GraphHopper GmbH under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* GraphHopper GmbH licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.graphhopper.jsprit.core.algorithm.recreate;
import com.graphhopper.jsprit.core.problem.JobActivityFactory;
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
public class BreakInsertionCalculatorFactory implements JobInsertionCostsCalculatorFactory {
@Override
public JobInsertionCostsCalculator create(VehicleRoutingProblem vrp, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, JobActivityFactory jobActivityFactory, ConstraintManager constraintManager) {
return new BreakInsertionCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), activityInsertionCostsCalculator, constraintManager, jobActivityFactory);
}
}

View file

@ -49,8 +49,7 @@ public class BreakScheduling implements InsertionStartsListener,JobInsertedListe
public BreakScheduling(VehicleRoutingProblem vrp, StateManager stateManager, ConstraintManager constraintManager) {
this.stateManager = stateManager;
this.breakInsertionCalculator = new BreakInsertionCalculator(vrp.getTransportCosts(),vrp.getActivityCosts(),new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(),vrp.getActivityCosts(),stateManager),constraintManager);
this.breakInsertionCalculator.setJobActivityFactory(vrp.getJobActivityFactory());
this.breakInsertionCalculator = new BreakInsertionCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), new LocalActivityInsertionCostsCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), stateManager), constraintManager, vrp.getJobActivityFactory());
eventListeners = new EventListeners();
}

View file

@ -28,7 +28,10 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
/**
* use InsertionStrategyBuilder instead
*/
@Deprecated
public class InsertionBuilder {
private boolean fastRegret;

View file

@ -0,0 +1,239 @@
/*
* Licensed to GraphHopper GmbH under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* GraphHopper GmbH licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.graphhopper.jsprit.core.algorithm.recreate;
import com.graphhopper.jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners;
import com.graphhopper.jsprit.core.algorithm.recreate.listener.InsertionListener;
import com.graphhopper.jsprit.core.algorithm.state.StateManager;
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleFleetManager;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
public class InsertionStrategyBuilder {
private boolean fastRegret;
public enum Strategy {
REGRET, BEST
}
private VehicleRoutingProblem vrp;
private StateManager stateManager;
private boolean local = true;
private ConstraintManager constraintManager;
private VehicleFleetManager fleetManager;
private double weightOfFixedCosts;
private boolean considerFixedCosts = false;
private ActivityInsertionCostsCalculator actInsertionCostsCalculator = null;
private int forwaredLooking;
private int memory;
private ExecutorService executor;
private int nuOfThreads;
private double timeSlice;
private int nNeighbors;
private boolean timeScheduling = false;
private boolean allowVehicleSwitch = true;
private boolean addDefaultCostCalc = true;
private Strategy strategy = Strategy.BEST;
private boolean isFastRegret = false;
private JobInsertionCostsCalculatorFactory shipmentInsertionCalculatorFactory;
private JobInsertionCostsCalculatorFactory serviceInsertionCalculatorFactory;
private JobInsertionCostsCalculatorFactory breakInsertionCalculatorFactory;
public InsertionStrategyBuilder(VehicleRoutingProblem vrp, VehicleFleetManager vehicleFleetManager, StateManager stateManager, ConstraintManager constraintManager) {
super();
this.vrp = vrp;
this.stateManager = stateManager;
this.constraintManager = constraintManager;
this.fleetManager = vehicleFleetManager;
}
public InsertionStrategyBuilder setShipmentInsertionCalculatorFactory(JobInsertionCostsCalculatorFactory shipmentInsertionCalculatorFactory) {
this.shipmentInsertionCalculatorFactory = shipmentInsertionCalculatorFactory;
return this;
}
public InsertionStrategyBuilder setServiceInsertionCalculator(JobInsertionCostsCalculatorFactory serviceInsertionCalculator) {
this.serviceInsertionCalculatorFactory = serviceInsertionCalculator;
return this;
}
public InsertionStrategyBuilder setBreakInsertionCalculator(JobInsertionCostsCalculatorFactory breakInsertionCalculator) {
this.breakInsertionCalculatorFactory = breakInsertionCalculator;
return this;
}
public InsertionStrategyBuilder setInsertionStrategy(Strategy strategy) {
this.strategy = strategy;
return this;
}
public InsertionStrategyBuilder setRouteLevel(int forwardLooking, int memory) {
local = false;
this.forwaredLooking = forwardLooking;
this.memory = memory;
return this;
}
public InsertionStrategyBuilder setRouteLevel(int forwardLooking, int memory, boolean addDefaultMarginalCostCalculation) {
local = false;
this.forwaredLooking = forwardLooking;
this.memory = memory;
this.addDefaultCostCalc = addDefaultMarginalCostCalculation;
return this;
}
public InsertionStrategyBuilder setFastRegret(boolean fastRegret) {
this.isFastRegret = fastRegret;
return this;
}
public InsertionStrategyBuilder setLocalLevel() {
local = true;
return this;
}
/**
* If addDefaulMarginalCostCalculation is false, no calculator is set which implicitly assumes that marginal cost calculation
* is controlled by your custom soft constraints.
*
* @param addDefaultMarginalCostCalculation
* @return
*/
public InsertionStrategyBuilder setLocalLevel(boolean addDefaultMarginalCostCalculation) {
local = true;
addDefaultCostCalc = addDefaultMarginalCostCalculation;
return this;
}
public InsertionStrategyBuilder considerFixedCosts(double weightOfFixedCosts) {
this.weightOfFixedCosts = weightOfFixedCosts;
this.considerFixedCosts = true;
return this;
}
public InsertionStrategyBuilder setActivityInsertionCostCalculator(ActivityInsertionCostsCalculator activityInsertionCostsCalculator) {
this.actInsertionCostsCalculator = activityInsertionCostsCalculator;
return this;
}
public InsertionStrategyBuilder setConcurrentMode(ExecutorService executor, int nuOfThreads) {
this.executor = executor;
this.nuOfThreads = nuOfThreads;
return this;
}
public InsertionStrategy build() {
List<InsertionListener> iListeners = new ArrayList<InsertionListener>();
List<VehicleRoutingAlgorithmListeners.PrioritizedVRAListener> algorithmListeners = new ArrayList<VehicleRoutingAlgorithmListeners.PrioritizedVRAListener>();
JobInsertionCostsCalculatorBuilder calcBuilder = new JobInsertionCostsCalculatorBuilder(iListeners, algorithmListeners);
if (local) {
calcBuilder.setLocalLevel(addDefaultCostCalc);
} else {
calcBuilder.setRouteLevel(forwaredLooking, memory, addDefaultCostCalc);
}
if (shipmentInsertionCalculatorFactory != null)
calcBuilder.setShipmentCalculatorFactory(shipmentInsertionCalculatorFactory);
if (serviceInsertionCalculatorFactory != null)
calcBuilder.setServiceCalculatorFactory(serviceInsertionCalculatorFactory);
if (breakInsertionCalculatorFactory != null)
calcBuilder.setBreakCalculatorFactory(breakInsertionCalculatorFactory);
calcBuilder.setConstraintManager(constraintManager);
calcBuilder.setStateManager(stateManager);
calcBuilder.setVehicleRoutingProblem(vrp);
calcBuilder.setVehicleFleetManager(fleetManager);
calcBuilder.setActivityInsertionCostsCalculator(actInsertionCostsCalculator);
if (considerFixedCosts) {
calcBuilder.considerFixedCosts(weightOfFixedCosts);
}
if (timeScheduling) {
calcBuilder.experimentalTimeScheduler(timeSlice, nNeighbors);
}
calcBuilder.setAllowVehicleSwitch(allowVehicleSwitch);
JobInsertionCostsCalculator costCalculator = calcBuilder.build();
InsertionStrategy insertion;
if (strategy.equals(Strategy.BEST)) {
if (executor == null) {
insertion = new BestInsertion(costCalculator, vrp);
} else {
insertion = new BestInsertionConcurrent(costCalculator, executor, nuOfThreads, vrp);
}
} else if (strategy.equals(Strategy.REGRET)) {
if (executor == null) {
if (isFastRegret) {
RegretInsertionFast regret = new RegretInsertionFast(costCalculator, vrp, fleetManager);
regret.setSwitchAllowed(allowVehicleSwitch);
insertion = regret;
} else {
RegretInsertion regret = new RegretInsertion(costCalculator, vrp);
insertion = regret;
}
} else {
if (isFastRegret) {
RegretInsertionConcurrentFast regret = new RegretInsertionConcurrentFast(costCalculator, vrp, executor, fleetManager);
regret.setSwitchAllowed(allowVehicleSwitch);
insertion = regret;
} else {
RegretInsertionConcurrent regret = new RegretInsertionConcurrent(costCalculator, vrp, executor);
insertion = regret;
}
}
} else throw new IllegalStateException("you should never get here");
for (InsertionListener l : iListeners) insertion.addListener(l);
return insertion;
}
public InsertionStrategyBuilder setAllowVehicleSwitch(boolean allowVehicleSwitch) {
this.allowVehicleSwitch = allowVehicleSwitch;
return this;
}
}

View file

@ -25,6 +25,6 @@ import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
public interface JobInsertionCostsCalculator {
public InsertionData getInsertionData(VehicleRoute currentRoute, Job newJob, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownCosts);
InsertionData getInsertionData(VehicleRoute currentRoute, Job newJob, Vehicle newVehicle, double newVehicleDepartureTime, Driver newDriver, double bestKnownCosts);
}

View file

@ -94,6 +94,12 @@ public class JobInsertionCostsCalculatorBuilder {
private boolean addDefaultCostCalc = true;
private JobInsertionCostsCalculatorFactory shipmentCalculatorFactory = new ShipmentInsertionCalculatorFactory();
private JobInsertionCostsCalculatorFactory serviceCalculatorFactory = new ServiceInsertionCalculatorFactory();
private JobInsertionCostsCalculatorFactory breakCalculatorFactory = new BreakInsertionCalculatorFactory();
/**
* Constructs the builder.
* <p>
@ -109,6 +115,24 @@ public class JobInsertionCostsCalculatorBuilder {
this.algorithmListeners = algorithmListeners;
}
public JobInsertionCostsCalculatorBuilder setShipmentCalculatorFactory(JobInsertionCostsCalculatorFactory shipmentCalculatorFactory) {
if (shipmentCalculatorFactory == null) return this;
this.shipmentCalculatorFactory = shipmentCalculatorFactory;
return this;
}
public JobInsertionCostsCalculatorBuilder setServiceCalculatorFactory(JobInsertionCostsCalculatorFactory serviceCalculatorFactory) {
if (serviceCalculatorFactory == null) return this;
this.serviceCalculatorFactory = serviceCalculatorFactory;
return this;
}
public JobInsertionCostsCalculatorBuilder setBreakCalculatorFactory(JobInsertionCostsCalculatorFactory breakCalculatorFactory) {
if (breakCalculatorFactory == null) return this;
this.breakCalculatorFactory = breakCalculatorFactory;
return this;
}
/**
* Sets activityStates. MUST be set.
*
@ -287,20 +311,17 @@ public class JobInsertionCostsCalculatorBuilder {
}
};
ShipmentInsertionCalculator shipmentInsertion = new ShipmentInsertionCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(),actInsertionCalc, constraintManager);
shipmentInsertion.setJobActivityFactory(activityFactory);
ServiceInsertionCalculator serviceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), actInsertionCalc, constraintManager);
serviceInsertion.setJobActivityFactory(activityFactory);
BreakInsertionCalculator breakInsertionCalculator = new BreakInsertionCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), actInsertionCalc, constraintManager);
breakInsertionCalculator.setJobActivityFactory(activityFactory);
JobInsertionCostsCalculator shipmentInsertion = shipmentCalculatorFactory.create(vrp, actInsertionCalc, activityFactory, constraintManager);
JobInsertionCostsCalculator serviceInsertion = serviceCalculatorFactory.create(vrp, actInsertionCalc, activityFactory, constraintManager);
JobInsertionCostsCalculator breakInsertion = breakCalculatorFactory.create(vrp, actInsertionCalc, activityFactory, constraintManager);
JobCalculatorSwitcher switcher = new JobCalculatorSwitcher();
switcher.put(Shipment.class, shipmentInsertion);
switcher.put(Service.class, serviceInsertion);
switcher.put(Pickup.class, serviceInsertion);
switcher.put(Delivery.class, serviceInsertion);
switcher.put(Break.class, breakInsertionCalculator);
switcher.put(Break.class, breakInsertion);
CalculatorPlusListeners calculatorPlusListeners = new CalculatorPlusListeners(switcher);
if (configLocal != null) {

View file

@ -0,0 +1,29 @@
/*
* Licensed to GraphHopper GmbH under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* GraphHopper GmbH licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.graphhopper.jsprit.core.algorithm.recreate;
import com.graphhopper.jsprit.core.problem.JobActivityFactory;
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
public interface JobInsertionCostsCalculatorFactory {
JobInsertionCostsCalculator create(VehicleRoutingProblem vrp, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, JobActivityFactory jobActivityFactory, ConstraintManager constraintManager);
}

View file

@ -37,7 +37,7 @@ import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
*
* @author stefan
*/
class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCalculator {
public class LocalActivityInsertionCostsCalculator implements ActivityInsertionCostsCalculator {
private VehicleRoutingTransportCosts routingCosts;

View file

@ -55,38 +55,35 @@ final class ServiceInsertionCalculator extends AbstractInsertionCalculator {
// private HardActivityConstraint hardActivityLevelConstraint;
private SoftRouteConstraint softRouteConstraint;
private final SoftRouteConstraint softRouteConstraint;
private SoftActivityConstraint softActivityConstraint;
private final SoftActivityConstraint softActivityConstraint;
private VehicleRoutingTransportCosts transportCosts;
private final VehicleRoutingTransportCosts transportCosts;
private final VehicleRoutingActivityCosts activityCosts;
private ActivityInsertionCostsCalculator additionalTransportCostsCalculator;
private final ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
private JobActivityFactory activityFactory;
private final JobActivityFactory activityFactory;
private AdditionalAccessEgressCalculator additionalAccessEgressCalculator;
private final AdditionalAccessEgressCalculator additionalAccessEgressCalculator;
private ConstraintManager constraintManager;
private final ConstraintManager constraintManager;
public ServiceInsertionCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts, ActivityInsertionCostsCalculator additionalTransportCostsCalculator, ConstraintManager constraintManager) {
public ServiceInsertionCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, ConstraintManager constraintManager, JobActivityFactory activityFactory) {
super();
this.transportCosts = routingCosts;
this.activityCosts = activityCosts;
this.constraintManager = constraintManager;
softActivityConstraint = constraintManager;
softRouteConstraint = constraintManager;
this.additionalTransportCostsCalculator = additionalTransportCostsCalculator;
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
additionalAccessEgressCalculator = new AdditionalAccessEgressCalculator(routingCosts);
this.activityFactory = activityFactory;
logger.debug("initialise {}", this);
}
public void setJobActivityFactory(JobActivityFactory jobActivityFactory) {
this.activityFactory = jobActivityFactory;
}
@Override
public String toString() {
return "[name=calculatesServiceInsertion]";
@ -151,7 +148,7 @@ final class ServiceInsertionCalculator extends AbstractInsertionCalculator {
ConstraintsStatus status = fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime, failedActivityConstraints, constraintManager);
if (status.equals(ConstraintsStatus.FULFILLED)) {
double additionalICostsAtActLevel = softActivityConstraint.getCosts(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
double additionalTransportationCosts = additionalTransportCostsCalculator.getCosts(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
double additionalTransportationCosts = activityInsertionCostsCalculator.getCosts(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
if (additionalICostsAtRouteLevel + additionalICostsAtActLevel + additionalTransportationCosts < bestCost) {
bestCost = additionalICostsAtRouteLevel + additionalICostsAtActLevel + additionalTransportationCosts;
insertionIndex = actIndex;

View file

@ -0,0 +1,30 @@
/*
* Licensed to GraphHopper GmbH under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* GraphHopper GmbH licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.graphhopper.jsprit.core.algorithm.recreate;
import com.graphhopper.jsprit.core.problem.JobActivityFactory;
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
public class ServiceInsertionCalculatorFactory implements JobInsertionCostsCalculatorFactory {
@Override
public JobInsertionCostsCalculator create(VehicleRoutingProblem vrp, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, JobActivityFactory jobActivityFactory, ConstraintManager constraintManager) {
return new ServiceInsertionCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), activityInsertionCostsCalculator, constraintManager, jobActivityFactory);
}
}

View file

@ -48,25 +48,21 @@ final class ShipmentInsertionCalculator extends AbstractInsertionCalculator {
private final ConstraintManager constraintManager;
// private HardRouteConstraint hardRouteLevelConstraint;
//
// private HardActivityConstraint hardActivityLevelConstraint;
private final SoftRouteConstraint softRouteConstraint;
private SoftRouteConstraint softRouteConstraint;
private final SoftActivityConstraint softActivityConstraint;
private SoftActivityConstraint softActivityConstraint;
private final ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
private final VehicleRoutingTransportCosts transportCosts;
private VehicleRoutingTransportCosts transportCosts;
private final VehicleRoutingActivityCosts activityCosts;
private VehicleRoutingActivityCosts activityCosts;
private final JobActivityFactory activityFactory;
private JobActivityFactory activityFactory;
private final AdditionalAccessEgressCalculator additionalAccessEgressCalculator;
private AdditionalAccessEgressCalculator additionalAccessEgressCalculator;
public ShipmentInsertionCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, ConstraintManager constraintManager) {
public ShipmentInsertionCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, ConstraintManager constraintManager, JobActivityFactory jobActivityFactory) {
super();
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
this.constraintManager = constraintManager;
@ -75,16 +71,13 @@ final class ShipmentInsertionCalculator extends AbstractInsertionCalculator {
this.transportCosts = routingCosts;
this.activityCosts = activityCosts;
additionalAccessEgressCalculator = new AdditionalAccessEgressCalculator(routingCosts);
this.activityFactory = jobActivityFactory;
logger.debug("initialise {}", this);
}
public void setJobActivityFactory(JobActivityFactory activityFactory) {
this.activityFactory = activityFactory;
}
@Override
public String toString() {
return "[name=calculatesServiceInsertion]";
return "[name=calculatesShipmentInsertion]";
}
/**

View file

@ -0,0 +1,30 @@
/*
* Licensed to GraphHopper GmbH under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* GraphHopper GmbH licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.graphhopper.jsprit.core.algorithm.recreate;
import com.graphhopper.jsprit.core.problem.JobActivityFactory;
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
public class ShipmentInsertionCalculatorFactory implements JobInsertionCostsCalculatorFactory {
@Override
public JobInsertionCostsCalculator create(VehicleRoutingProblem vrp, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, JobActivityFactory jobActivityFactory, ConstraintManager constraintManager) {
return new ShipmentInsertionCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), activityInsertionCostsCalculator, constraintManager, jobActivityFactory);
}
}

View file

@ -0,0 +1,274 @@
/*
* Licensed to GraphHopper GmbH under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* GraphHopper GmbH licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.graphhopper.jsprit.core.algorithm.recreate;
import com.graphhopper.jsprit.core.problem.JobActivityFactory;
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
import com.graphhopper.jsprit.core.problem.constraint.HardActivityConstraint.ConstraintsStatus;
import com.graphhopper.jsprit.core.problem.constraint.SoftActivityConstraint;
import com.graphhopper.jsprit.core.problem.constraint.SoftRouteConstraint;
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import com.graphhopper.jsprit.core.problem.driver.Driver;
import com.graphhopper.jsprit.core.problem.job.Job;
import com.graphhopper.jsprit.core.problem.job.Shipment;
import com.graphhopper.jsprit.core.problem.misc.ActivityContext;
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
import com.graphhopper.jsprit.core.problem.solution.route.activity.End;
import com.graphhopper.jsprit.core.problem.solution.route.activity.Start;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public final class ShipmentInsertionCalculatorFlex extends AbstractInsertionCalculator {
private static final Logger logger = LoggerFactory.getLogger(ShipmentInsertionCalculatorFlex.class);
private final ConstraintManager constraintManager;
// private HardRouteConstraint hardRouteLevelConstraint;
//
// private HardActivityConstraint hardActivityLevelConstraint;
private SoftRouteConstraint softRouteConstraint;
private SoftActivityConstraint softActivityConstraint;
private ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
private VehicleRoutingTransportCosts transportCosts;
private VehicleRoutingActivityCosts activityCosts;
private JobActivityFactory activityFactory;
private AdditionalAccessEgressCalculator additionalAccessEgressCalculator;
private int evalIndexPickup = Integer.MAX_VALUE;
private int evalIndexDelivery = Integer.MAX_VALUE;
public void setEvalIndexPickup(int evalIndexPickup) {
this.evalIndexPickup = evalIndexPickup;
}
public void setEvalIndexDelivery(int evalIndexDelivery) {
this.evalIndexDelivery = evalIndexDelivery;
}
public ShipmentInsertionCalculatorFlex(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts, ActivityInsertionCostsCalculator activityInsertionCostsCalculator, ConstraintManager constraintManager) {
super();
this.activityInsertionCostsCalculator = activityInsertionCostsCalculator;
this.constraintManager = constraintManager;
this.softActivityConstraint = constraintManager;
this.softRouteConstraint = constraintManager;
this.transportCosts = routingCosts;
this.activityCosts = activityCosts;
additionalAccessEgressCalculator = new AdditionalAccessEgressCalculator(routingCosts);
logger.debug("initialise {}", this);
}
public void setJobActivityFactory(JobActivityFactory activityFactory) {
this.activityFactory = activityFactory;
}
@Override
public String toString() {
return "[name=calculatesServiceInsertion]";
}
/**
* Calculates the marginal cost of inserting job i locally. This is based on the
* assumption that cost changes can entirely covered by only looking at the predecessor i-1 and its successor i+1.
*/
@Override
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
Shipment shipment = (Shipment) jobToInsert;
TourActivity pickupShipment = activityFactory.createActivities(shipment).get(0);
TourActivity deliverShipment = activityFactory.createActivities(shipment).get(1);
insertionContext.getAssociatedActivities().add(pickupShipment);
insertionContext.getAssociatedActivities().add(deliverShipment);
/*
check hard route constraints
*/
InsertionData noInsertion = checkRouteContraints(insertionContext, constraintManager);
if (noInsertion != null) return noInsertion;
/*
check soft route constraints
*/
double additionalICostsAtRouteLevel = softRouteConstraint.getCosts(insertionContext);
double bestCost = bestKnownCosts;
additionalICostsAtRouteLevel += additionalAccessEgressCalculator.getCosts(insertionContext);
int pickupInsertionIndex = InsertionData.NO_INDEX;
int deliveryInsertionIndex = InsertionData.NO_INDEX;
TimeWindow bestPickupTimeWindow = null;
TimeWindow bestDeliveryTimeWindow = null;
Start start = new Start(newVehicle.getStartLocation(), newVehicle.getEarliestDeparture(), newVehicle.getLatestArrival());
start.setEndTime(newVehicleDepartureTime);
End end = new End(newVehicle.getEndLocation(), 0.0, newVehicle.getLatestArrival());
ActivityContext pickupContext = new ActivityContext();
TourActivity prevAct = start;
double prevActEndTime = newVehicleDepartureTime;
//loops
int i = 0;
boolean tourEnd = false;
//pickupShipmentLoop
List<TourActivity> activities = currentRoute.getTourActivities().getActivities();
List<String> failedActivityConstraints = new ArrayList<>();
while (!tourEnd) {
TourActivity nextAct;
if (i < activities.size()) {
nextAct = activities.get(i);
} else {
nextAct = end;
tourEnd = true;
}
if (i > evalIndexPickup) break;
if (i == evalIndexPickup || evalIndexPickup == Integer.MAX_VALUE) {
boolean pickupInsertionNotFulfilledBreak = true;
for (TimeWindow pickupTimeWindow : shipment.getPickupTimeWindows()) {
pickupShipment.setTheoreticalEarliestOperationStartTime(pickupTimeWindow.getStart());
pickupShipment.setTheoreticalLatestOperationStartTime(pickupTimeWindow.getEnd());
ActivityContext activityContext = new ActivityContext();
activityContext.setInsertionIndex(i);
insertionContext.setActivityContext(activityContext);
ConstraintsStatus pickupShipmentConstraintStatus = fulfilled(insertionContext, prevAct, pickupShipment, nextAct, prevActEndTime, failedActivityConstraints, constraintManager);
if (pickupShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED)) {
pickupInsertionNotFulfilledBreak = false;
continue;
} else if (pickupShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)) {
continue;
} else if (pickupShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)) {
pickupInsertionNotFulfilledBreak = false;
}
double additionalPickupICosts = softActivityConstraint.getCosts(insertionContext, prevAct, pickupShipment, nextAct, prevActEndTime);
double pickupAIC = calculate(insertionContext, prevAct, pickupShipment, nextAct, prevActEndTime);
double shipmentPickupArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocation(), pickupShipment.getLocation(), prevActEndTime, newDriver, newVehicle);
double shipmentPickupEndTime = Math.max(shipmentPickupArrTime, pickupShipment.getTheoreticalEarliestOperationStartTime()) + activityCosts.getActivityDuration(pickupShipment, shipmentPickupArrTime, newDriver, newVehicle);
pickupContext.setArrivalTime(shipmentPickupArrTime);
pickupContext.setEndTime(shipmentPickupEndTime);
pickupContext.setInsertionIndex(i);
insertionContext.setRelatedActivityContext(pickupContext);
TourActivity prevActForDeliveryLoop = pickupShipment;
double prevActEndTimeForDeliveryLoop = shipmentPickupEndTime;
/*
--------------------------------
*/
//deliverShipmentLoop
int j = i;
boolean tourEndInDeliveryLoop = false;
while (!tourEndInDeliveryLoop) {
TourActivity nextActForDeliveryLoop;
if (j < activities.size()) {
nextActForDeliveryLoop = activities.get(j);
} else {
nextActForDeliveryLoop = end;
tourEndInDeliveryLoop = true;
}
if (j > evalIndexDelivery) break;
if (j == evalIndexDelivery || evalIndexDelivery == Integer.MAX_VALUE) {
boolean deliveryInsertionNotFulfilledBreak = true;
for (TimeWindow deliveryTimeWindow : shipment.getDeliveryTimeWindows()) {
deliverShipment.setTheoreticalEarliestOperationStartTime(deliveryTimeWindow.getStart());
deliverShipment.setTheoreticalLatestOperationStartTime(deliveryTimeWindow.getEnd());
ActivityContext activityContext_ = new ActivityContext();
activityContext_.setInsertionIndex(j);
insertionContext.setActivityContext(activityContext_);
ConstraintsStatus deliverShipmentConstraintStatus = fulfilled(insertionContext, prevActForDeliveryLoop, deliverShipment, nextActForDeliveryLoop, prevActEndTimeForDeliveryLoop, failedActivityConstraints, constraintManager);
if (deliverShipmentConstraintStatus.equals(ConstraintsStatus.FULFILLED)) {
double additionalDeliveryICosts = softActivityConstraint.getCosts(insertionContext, prevActForDeliveryLoop, deliverShipment, nextActForDeliveryLoop, prevActEndTimeForDeliveryLoop);
double deliveryAIC = calculate(insertionContext, prevActForDeliveryLoop, deliverShipment, nextActForDeliveryLoop, prevActEndTimeForDeliveryLoop);
double totalActivityInsertionCosts = pickupAIC + deliveryAIC
+ additionalICostsAtRouteLevel + additionalPickupICosts + additionalDeliveryICosts;
if (totalActivityInsertionCosts < bestCost) {
bestCost = totalActivityInsertionCosts;
pickupInsertionIndex = i;
deliveryInsertionIndex = j;
bestPickupTimeWindow = pickupTimeWindow;
bestDeliveryTimeWindow = deliveryTimeWindow;
}
deliveryInsertionNotFulfilledBreak = false;
} else if (deliverShipmentConstraintStatus.equals(ConstraintsStatus.NOT_FULFILLED)) {
deliveryInsertionNotFulfilledBreak = false;
}
}
if (deliveryInsertionNotFulfilledBreak) break;
}
//update prevAct and endTime
double nextActArrTime = prevActEndTimeForDeliveryLoop + transportCosts.getTransportTime(prevActForDeliveryLoop.getLocation(), nextActForDeliveryLoop.getLocation(), prevActEndTimeForDeliveryLoop, newDriver, newVehicle);
prevActEndTimeForDeliveryLoop = Math.max(nextActArrTime, nextActForDeliveryLoop.getTheoreticalEarliestOperationStartTime()) + activityCosts.getActivityDuration(nextActForDeliveryLoop, nextActArrTime, newDriver, newVehicle);
prevActForDeliveryLoop = nextActForDeliveryLoop;
j++;
}
}
if (pickupInsertionNotFulfilledBreak) {
break;
}
}
//update prevAct and endTime
double nextActArrTime = prevActEndTime + transportCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActEndTime, newDriver, newVehicle);
prevActEndTime = Math.max(nextActArrTime, nextAct.getTheoreticalEarliestOperationStartTime()) + activityCosts.getActivityDuration(nextAct, nextActArrTime, newDriver, newVehicle);
prevAct = nextAct;
i++;
}
if (pickupInsertionIndex == InsertionData.NO_INDEX) {
InsertionData emptyInsertionData = new InsertionData.NoInsertionFound();
emptyInsertionData.getFailedConstraintNames().addAll(failedActivityConstraints);
return emptyInsertionData;
}
InsertionData insertionData = new InsertionData(bestCost, pickupInsertionIndex, deliveryInsertionIndex, newVehicle, newDriver);
pickupShipment.setTheoreticalEarliestOperationStartTime(bestPickupTimeWindow.getStart());
pickupShipment.setTheoreticalLatestOperationStartTime(bestPickupTimeWindow.getEnd());
deliverShipment.setTheoreticalEarliestOperationStartTime(bestDeliveryTimeWindow.getStart());
deliverShipment.setTheoreticalLatestOperationStartTime(bestDeliveryTimeWindow.getEnd());
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
insertionData.getEvents().add(new InsertActivity(currentRoute, newVehicle, deliverShipment, deliveryInsertionIndex));
insertionData.getEvents().add(new InsertActivity(currentRoute, newVehicle, pickupShipment, pickupInsertionIndex));
insertionData.getEvents().add(new SwitchVehicle(currentRoute, newVehicle, newVehicleDepartureTime));
return insertionData;
}
private double calculate(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double departureTimeAtPrevAct) {
return activityInsertionCostsCalculator.getCosts(iFacts, prevAct, nextAct, newAct, departureTimeAtPrevAct);
}
}

View file

@ -87,7 +87,7 @@ public class VehicleRoutingProblem {
private FleetSize fleetSize = FleetSize.INFINITE;
private Collection<VehicleType> vehicleTypes = new ArrayList<VehicleType>();
private Map<String, VehicleType> vehicleTypes = new HashMap<>();
private Collection<VehicleRoute> initialRoutes = new ArrayList<VehicleRoute>();
@ -387,8 +387,13 @@ public class VehicleRoutingProblem {
incVehicleTypeIdIndexCounter();
}
uniqueVehicles.add(vehicle);
if (!vehicleTypes.contains(vehicle.getType())) {
vehicleTypes.add(vehicle.getType());
if (!vehicleTypes.containsKey(vehicle.getType().getTypeId())) {
vehicleTypes.put(vehicle.getType().getTypeId(), vehicle.getType());
} else {
VehicleType existingType = vehicleTypes.get(vehicle.getType().getTypeId());
if (!vehicle.getType().equals(existingType)) {
throw new IllegalArgumentException("A type with type id " + vehicle.getType().getTypeId() + " already exists. However, types are different. Please use unique vehicle types only.");
}
}
String startLocationId = vehicle.getStartLocation().getId();
addLocationToTentativeLocations(vehicle.getStartLocation());
@ -496,7 +501,7 @@ public class VehicleRoutingProblem {
* @return collection of vehicle-types
*/
public Collection<VehicleType> getAddedVehicleTypes() {
return Collections.unmodifiableCollection(vehicleTypes);
return Collections.unmodifiableCollection(vehicleTypes.values());
}
/**
@ -588,7 +593,7 @@ public class VehicleRoutingProblem {
this.jobs = builder.jobs;
this.fleetSize = builder.fleetSize;
this.vehicles = builder.uniqueVehicles;
this.vehicleTypes = builder.vehicleTypes;
this.vehicleTypes = builder.vehicleTypes.values();
this.initialVehicleRoutes = builder.initialRoutes;
this.transportCosts = builder.transportCosts;
this.activityCosts = builder.activityCosts;

View file

@ -22,7 +22,7 @@ import com.graphhopper.jsprit.core.problem.Capacity;
import com.graphhopper.jsprit.core.problem.Skills;
/**
* Pickup extends Service and is intended to model a Service where smth is LOADED (i.e. picked up) to a transport unit.
* Break extends Service and is intended to model a time-window based driver break.
*
* @author schroeder
*/
@ -31,7 +31,7 @@ public class Break extends Service {
public static class Builder extends Service.Builder<Break> {
/**
* Returns a new instance of builder that builds a pickup.
* Returns a new instance of builder that builds a break.
*
* @param id the id of the pickup
* @return the builder
@ -47,9 +47,9 @@ public class Break extends Service {
}
/**
* Builds Pickup.
* Builds Break.
* <p>
* <p>Pickup type is "pickup"
* <p>Pickup type is "break"
*
* @return pickup
* @throws IllegalStateException if neither locationId nor coordinate has been set

View file

@ -81,6 +81,37 @@ public class VehicleTypeImpl implements VehicleType {
public String toString() {
return "[fixed=" + fix + "][perTime=" + perTransportTimeUnit + "][perDistance=" + perDistanceUnit + "][perWaitingTimeUnit=" + perWaitingTimeUnit + "]";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof VehicleCostParams)) return false;
VehicleCostParams that = (VehicleCostParams) o;
if (Double.compare(that.fix, fix) != 0) return false;
if (Double.compare(that.perTransportTimeUnit, perTransportTimeUnit) != 0) return false;
if (Double.compare(that.perDistanceUnit, perDistanceUnit) != 0) return false;
if (Double.compare(that.perWaitingTimeUnit, perWaitingTimeUnit) != 0) return false;
return Double.compare(that.perServiceTimeUnit, perServiceTimeUnit) == 0;
}
@Override
public int hashCode() {
int result;
long temp;
temp = Double.doubleToLongBits(fix);
result = (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(perTransportTimeUnit);
result = 31 * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(perDistanceUnit);
result = 31 * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(perWaitingTimeUnit);
result = 31 * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(perServiceTimeUnit);
result = 31 * result + (int) (temp ^ (temp >>> 32));
return result;
}
}
/**
@ -299,32 +330,30 @@ public class VehicleTypeImpl implements VehicleType {
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((typeId == null) ? 0 : typeId.hashCode());
return result;
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof VehicleTypeImpl)) return false;
VehicleTypeImpl that = (VehicleTypeImpl) o;
if (Double.compare(that.maxVelocity, maxVelocity) != 0) return false;
if (!typeId.equals(that.typeId)) return false;
if (profile != null ? !profile.equals(that.profile) : that.profile != null) return false;
if (!vehicleCostParams.equals(that.vehicleCostParams)) return false;
return capacityDimensions.equals(that.capacityDimensions);
}
/**
* Two vehicle-types are equal if they have the same vehicleId.
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
VehicleTypeImpl other = (VehicleTypeImpl) obj;
if (typeId == null) {
if (other.typeId != null)
return false;
} else if (!typeId.equals(other.typeId))
return false;
return true;
public int hashCode() {
int result;
long temp;
result = typeId.hashCode();
result = 31 * result + (profile != null ? profile.hashCode() : 0);
result = 31 * result + vehicleCostParams.hashCode();
result = 31 * result + capacityDimensions.hashCode();
temp = Double.doubleToLongBits(maxVelocity);
result = 31 * result + (int) (temp ^ (temp >>> 32));
return result;
}
private final String typeId;

View file

@ -0,0 +1,85 @@
/*
* Licensed to GraphHopper GmbH under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* GraphHopper GmbH licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.graphhopper.jsprit.core.algorithm.module;
import com.graphhopper.jsprit.core.algorithm.recreate.InsertionStrategy;
import com.graphhopper.jsprit.core.algorithm.ruin.RuinStrategy;
import com.graphhopper.jsprit.core.problem.job.Job;
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static org.mockito.Mockito.mock;
public class RuinAndRecreateModuleTest {
@Test
public void initialNumOfUnassignedShouldWorkCorrectly() {
InsertionStrategy insertionStrategy = mock(InsertionStrategy.class);
RuinStrategy ruinStrategy = mock(RuinStrategy.class);
RuinAndRecreateModule module = new RuinAndRecreateModule("name", insertionStrategy, ruinStrategy);
Collection<VehicleRoute> routes = new ArrayList<>();
List<Job> unassigned = new ArrayList<>();
for (int i = 0; i < 20; i++) {
unassigned.add(mock(Job.class));
}
VehicleRoutingProblemSolution previousSolution = new VehicleRoutingProblemSolution(routes, unassigned, 0);
VehicleRoutingProblemSolution newSolution = module.runAndGetSolution(previousSolution);
Assert.assertEquals(0, newSolution.getUnassignedJobs().size());
}
@Test
public void proportionOfUnassignedShouldWorkCorrectly() {
InsertionStrategy insertionStrategy = mock(InsertionStrategy.class);
RuinStrategy ruinStrategy = mock(RuinStrategy.class);
RuinAndRecreateModule module = new RuinAndRecreateModule("name", insertionStrategy, ruinStrategy);
module.setMinUnassignedJobsToBeReinserted(5);
module.setProportionOfUnassignedJobsToBeReinserted(0.01);
Collection<VehicleRoute> routes = new ArrayList<>();
List<Job> unassigned = new ArrayList<>();
for (int i = 0; i < 20; i++) {
unassigned.add(mock(Job.class));
}
VehicleRoutingProblemSolution previousSolution = new VehicleRoutingProblemSolution(routes, unassigned, 0);
VehicleRoutingProblemSolution newSolution = module.runAndGetSolution(previousSolution);
Assert.assertEquals(15, newSolution.getUnassignedJobs().size());
}
@Test
public void proportionOfUnassignedShouldWorkCorrectly2() {
InsertionStrategy insertionStrategy = mock(InsertionStrategy.class);
RuinStrategy ruinStrategy = mock(RuinStrategy.class);
RuinAndRecreateModule module = new RuinAndRecreateModule("name", insertionStrategy, ruinStrategy);
module.setMinUnassignedJobsToBeReinserted(5);
module.setProportionOfUnassignedJobsToBeReinserted(0.5);
Collection<VehicleRoute> routes = new ArrayList<>();
List<Job> unassigned = new ArrayList<>();
for (int i = 0; i < 20; i++) {
unassigned.add(mock(Job.class));
}
VehicleRoutingProblemSolution previousSolution = new VehicleRoutingProblemSolution(routes, unassigned, 0);
VehicleRoutingProblemSolution newSolution = module.runAndGetSolution(previousSolution);
Assert.assertEquals(10, newSolution.getUnassignedJobs().size());
}
}

View file

@ -90,7 +90,7 @@ public class ServiceInsertionAndLoadConstraintsTest {
ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
ShipmentInsertionCalculator insertionCalculator;
// ShipmentInsertionCalculator insertionCalculator;
VehicleRoutingProblem vehicleRoutingProblem;
@ -109,7 +109,7 @@ public class ServiceInsertionAndLoadConstraintsTest {
private void createInsertionCalculator(HardRouteConstraint hardRouteLevelConstraint) {
ConstraintManager constraintManager = new ConstraintManager(mock(VehicleRoutingProblem.class), mock(RouteAndActivityStateGetter.class));
constraintManager.addConstraint(hardRouteLevelConstraint);
insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager);
// insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager, );
}
@Test
@ -143,10 +143,9 @@ public class ServiceInsertionAndLoadConstraintsTest {
stateManager.informInsertionStarts(Arrays.asList(route), null);
JobCalculatorSwitcher switcher = new JobCalculatorSwitcher();
ServiceInsertionCalculator serviceInsertionCalc = new ServiceInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager);
serviceInsertionCalc.setJobActivityFactory(activityFactory);
ShipmentInsertionCalculator insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager);
insertionCalculator.setJobActivityFactory(activityFactory);
ServiceInsertionCalculator serviceInsertionCalc = new ServiceInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager, activityFactory);
ShipmentInsertionCalculator insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager, activityFactory);
switcher.put(Pickup.class, serviceInsertionCalc);
switcher.put(Delivery.class, serviceInsertionCalc);

View file

@ -0,0 +1,367 @@
/*
* Licensed to GraphHopper GmbH under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* GraphHopper GmbH licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.graphhopper.jsprit.core.algorithm.recreate;
import com.graphhopper.jsprit.core.algorithm.recreate.listener.InsertionListeners;
import com.graphhopper.jsprit.core.algorithm.state.StateManager;
import com.graphhopper.jsprit.core.problem.AbstractActivity;
import com.graphhopper.jsprit.core.problem.JobActivityFactory;
import com.graphhopper.jsprit.core.problem.Location;
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
import com.graphhopper.jsprit.core.problem.constraint.HardRouteConstraint;
import com.graphhopper.jsprit.core.problem.constraint.PickupAndDeliverShipmentLoadActivityLevelConstraint;
import com.graphhopper.jsprit.core.problem.constraint.ShipmentPickupsFirstConstraint;
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import com.graphhopper.jsprit.core.problem.driver.Driver;
import com.graphhopper.jsprit.core.problem.driver.DriverImpl;
import com.graphhopper.jsprit.core.problem.job.Pickup;
import com.graphhopper.jsprit.core.problem.job.Service;
import com.graphhopper.jsprit.core.problem.job.Shipment;
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
import com.graphhopper.jsprit.core.problem.solution.route.activity.DeliverShipment;
import com.graphhopper.jsprit.core.problem.solution.route.activity.PickupService;
import com.graphhopper.jsprit.core.problem.solution.route.activity.PickupShipment;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
import com.graphhopper.jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleType;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleTypeImpl;
import com.graphhopper.jsprit.core.util.CostFactory;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ShipmentInsertionCalculatorFlexTest {
VehicleRoutingTransportCosts routingCosts;
VehicleRoutingProblem vehicleRoutingProblem;
VehicleRoutingActivityCosts activityCosts = new VehicleRoutingActivityCosts() {
@Override
public double getActivityCost(TourActivity tourAct, double arrivalTime, Driver driver, Vehicle vehicle) {
return 0;
}
@Override
public double getActivityDuration(TourActivity tourAct, double arrivalTime, Driver driver, Vehicle vehicle) {
return tourAct.getOperationTime();
}
};
HardRouteConstraint hardRouteLevelConstraint = new HardRouteConstraint() {
@Override
public boolean fulfilled(JobInsertionContext insertionContext) {
return true;
}
};
ActivityInsertionCostsCalculator activityInsertionCostsCalculator;
ShipmentInsertionCalculatorFlex insertionCalculator;
Vehicle vehicle;
ConstraintManager constraintManager;
@Before
public void doBefore() {
routingCosts = CostFactory.createManhattanCosts();
VehicleType type = VehicleTypeImpl.Builder.newInstance("t").addCapacityDimension(0, 2).setCostPerDistance(1).build();
vehicle = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("0,0")).setType(type).build();
activityInsertionCostsCalculator = new LocalActivityInsertionCostsCalculator(routingCosts, activityCosts, mock(StateManager.class));
constraintManager = new ConstraintManager(mock(VehicleRoutingProblem.class), mock(RouteAndActivityStateGetter.class));
constraintManager.addConstraint(hardRouteLevelConstraint);
vehicleRoutingProblem = mock(VehicleRoutingProblem.class);
}
// private void createInsertionCalculator(HardRouteConstraint hardRouteLevelConstraint) {
// ConstraintManager constraintManager = new ConstraintManager(mock(VehicleRoutingProblem.class), mock(RouteAndActivityStateGetter.class));
// constraintManager.addConstraint(hardRouteLevelConstraint);
// insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager, );
// }
@Test
public void whenCalculatingInsertionCostsOfShipment_itShouldReturnCorrectCostValue() {
Shipment shipment = Shipment.Builder.newInstance("s").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("0,10").build()).setDeliveryLocation(Location.newInstance("10,0")).build();
VehicleRoute route = VehicleRoute.emptyRoute();
JobActivityFactory activityFactory = mock(JobActivityFactory.class);
List<AbstractActivity> activities = new ArrayList<AbstractActivity>();
activities.add(new PickupShipment(shipment));
activities.add(new DeliverShipment(shipment));
when(activityFactory.createActivities(shipment)).thenReturn(activities);
insertionCalculator = new ShipmentInsertionCalculatorFlex(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager);
insertionCalculator.setJobActivityFactory(activityFactory);
InsertionData iData = insertionCalculator.getInsertionData(route, shipment, vehicle, 0.0, null, Double.MAX_VALUE);
assertEquals(40.0, iData.getInsertionCost(), 0.05);
}
@Test
public void whenCalculatingInsertionIntoExistingRoute_itShouldReturnCorrectCosts() {
Shipment shipment = Shipment.Builder.newInstance("s").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("0,10").build()).setDeliveryLocation(Location.newInstance("10,0")).build();
Shipment shipment2 = Shipment.Builder.newInstance("s2").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("10,10").build()).setDeliveryLocation(Location.newInstance("0,0")).build();
VehicleRoute route = VehicleRoute.emptyRoute();
when(vehicleRoutingProblem.copyAndGetActivities(shipment)).thenReturn(getTourActivities(shipment));
new Inserter(new InsertionListeners(), vehicleRoutingProblem).insertJob(shipment, new InsertionData(0, 0, 0, vehicle, null), route);
JobActivityFactory activityFactory = mock(JobActivityFactory.class);
List<AbstractActivity> activities = new ArrayList<AbstractActivity>();
activities.add(new PickupShipment(shipment2));
activities.add(new DeliverShipment(shipment2));
when(activityFactory.createActivities(shipment2)).thenReturn(activities);
insertionCalculator = new ShipmentInsertionCalculatorFlex(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager);
insertionCalculator.setJobActivityFactory(activityFactory);
InsertionData iData = insertionCalculator.getInsertionData(route, shipment2, vehicle, 0.0, null, Double.MAX_VALUE);
assertEquals(0.0, iData.getInsertionCost(), 0.05);
assertEquals(1, iData.getPickupInsertionIndex());
assertEquals(2, iData.getDeliveryInsertionIndex());
}
private List<AbstractActivity> getTourActivities(Shipment shipment) {
List<AbstractActivity> acts = new ArrayList<AbstractActivity>();
PickupShipment pick = new PickupShipment(shipment);
DeliverShipment del = new DeliverShipment(shipment);
acts.add(pick);
acts.add(del);
return acts;
}
@Test
public void whenInsertingShipmentInRouteWithNotEnoughCapacity_itShouldReturnNoInsertion() {
Shipment shipment = Shipment.Builder.newInstance("s").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("0,10").build()).setDeliveryLocation(Location.newInstance("10,0")).build();
Shipment shipment2 = Shipment.Builder.newInstance("s2").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("10,10").build()).setDeliveryLocation(Location.newInstance("0,0")).build();
VehicleRoute route = VehicleRoute.emptyRoute();
when(vehicleRoutingProblem.copyAndGetActivities(shipment)).thenReturn(getTourActivities(shipment));
new Inserter(new InsertionListeners(), vehicleRoutingProblem).insertJob(shipment, new InsertionData(0, 0, 0, vehicle, null), route);
constraintManager = new ConstraintManager(mock(VehicleRoutingProblem.class), mock(RouteAndActivityStateGetter.class));
constraintManager.addConstraint(new HardRouteConstraint() {
@Override
public boolean fulfilled(JobInsertionContext insertionContext) {
return false;
}
});
JobActivityFactory activityFactory = mock(JobActivityFactory.class);
List<AbstractActivity> activities = new ArrayList<AbstractActivity>();
activities.add(new PickupShipment(shipment2));
activities.add(new DeliverShipment(shipment2));
when(activityFactory.createActivities(shipment2)).thenReturn(activities);
insertionCalculator = new ShipmentInsertionCalculatorFlex(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager);
insertionCalculator.setJobActivityFactory(activityFactory);
InsertionData iData = insertionCalculator.getInsertionData(route, shipment2, vehicle, 0.0, null, Double.MAX_VALUE);
assertTrue(iData instanceof InsertionData.NoInsertionFound);
}
@Test
public void whenInsertingThirdShipment_itShouldCalcCorrectVal() {
Shipment shipment = Shipment.Builder.newInstance("s").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("0,10").build()).setDeliveryLocation(Location.newInstance("10,0")).build();
Shipment shipment2 = Shipment.Builder.newInstance("s2").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("10,10").build()).setDeliveryLocation(Location.newInstance("0,0")).build();
Shipment shipment3 = Shipment.Builder.newInstance("s3").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("0,0").build()).setDeliveryLocation(Location.newInstance("9,10")).build();
VehicleRoute route = VehicleRoute.emptyRoute();
when(vehicleRoutingProblem.copyAndGetActivities(shipment)).thenReturn(getTourActivities(shipment));
when(vehicleRoutingProblem.copyAndGetActivities(shipment2)).thenReturn(getTourActivities(shipment2));
Inserter inserter = new Inserter(new InsertionListeners(), vehicleRoutingProblem);
inserter.insertJob(shipment, new InsertionData(0, 0, 0, vehicle, null), route);
inserter.insertJob(shipment2, new InsertionData(0, 1, 2, vehicle, null), route);
JobActivityFactory activityFactory = mock(JobActivityFactory.class);
List<AbstractActivity> activities = new ArrayList<AbstractActivity>();
activities.add(new PickupShipment(shipment3));
activities.add(new DeliverShipment(shipment3));
when(activityFactory.createActivities(shipment3)).thenReturn(activities);
insertionCalculator = new ShipmentInsertionCalculatorFlex(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager);
insertionCalculator.setJobActivityFactory(activityFactory);
InsertionData iData = insertionCalculator.getInsertionData(route, shipment3, vehicle, 0.0, null, Double.MAX_VALUE);
assertEquals(0.0, iData.getInsertionCost(), 0.05);
assertEquals(0, iData.getPickupInsertionIndex());
assertEquals(1, iData.getDeliveryInsertionIndex());
}
@Test
public void whenInsertingThirdShipment_itShouldCalcCorrectVal2() {
Shipment shipment = Shipment.Builder.newInstance("s").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("0,10").build()).setDeliveryLocation(Location.newInstance("10,0")).build();
Shipment shipment2 = Shipment.Builder.newInstance("s2").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("10,10").build()).setDeliveryLocation(Location.newInstance("0,0")).build();
Shipment shipment3 = Shipment.Builder.newInstance("s3").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("0,0").build()).setDeliveryLocation(Location.newInstance("9,9")).build();
when(vehicleRoutingProblem.copyAndGetActivities(shipment)).thenReturn(getTourActivities(shipment));
when(vehicleRoutingProblem.copyAndGetActivities(shipment2)).thenReturn(getTourActivities(shipment2));
VehicleRoute route = VehicleRoute.emptyRoute();
Inserter inserter = new Inserter(new InsertionListeners(), vehicleRoutingProblem);
inserter.insertJob(shipment, new InsertionData(0, 0, 0, vehicle, null), route);
inserter.insertJob(shipment2, new InsertionData(0, 1, 2, vehicle, null), route);
JobActivityFactory activityFactory = mock(JobActivityFactory.class);
List<AbstractActivity> activities = new ArrayList<AbstractActivity>();
activities.add(new PickupShipment(shipment3));
activities.add(new DeliverShipment(shipment3));
when(activityFactory.createActivities(shipment3)).thenReturn(activities);
insertionCalculator = new ShipmentInsertionCalculatorFlex(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager);
insertionCalculator.setJobActivityFactory(activityFactory);
InsertionData iData = insertionCalculator.getInsertionData(route, shipment3, vehicle, 0.0, null, Double.MAX_VALUE);
assertEquals(2.0, iData.getInsertionCost(), 0.05);
assertEquals(0, iData.getPickupInsertionIndex());
assertEquals(1, iData.getDeliveryInsertionIndex());
}
@Test
public void whenInstertingShipmentWithLoadConstraintWhereCapIsNotSufficient_capConstraintsAreFulfilled() {
Shipment shipment = Shipment.Builder.newInstance("s").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("0,10").build()).setDeliveryLocation(Location.newInstance("10,0")).build();
Shipment shipment2 = Shipment.Builder.newInstance("s2").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("10,10").build()).setDeliveryLocation(Location.newInstance("0,0")).build();
Shipment shipment3 = Shipment.Builder.newInstance("s3").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("0,0").build()).setDeliveryLocation(Location.newInstance("9,9")).build();
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
VehicleRoutingProblem vrp = vrpBuilder.addJob(shipment).addJob(shipment2).addJob(shipment3).build();
VehicleRoute route = VehicleRoute.emptyRoute();
route.setVehicleAndDepartureTime(vehicle, 0.0);
Inserter inserter = new Inserter(new InsertionListeners(), vrp);
inserter.insertJob(shipment, new InsertionData(0, 0, 0, vehicle, null), route);
inserter.insertJob(shipment2, new InsertionData(0, 1, 2, vehicle, null), route);
StateManager stateManager = new StateManager(vrp);
stateManager.updateLoadStates();
stateManager.informInsertionStarts(Arrays.asList(route), null);
ConstraintManager constraintManager = new ConstraintManager(vrp, stateManager);
constraintManager.addConstraint(new PickupAndDeliverShipmentLoadActivityLevelConstraint(stateManager), ConstraintManager.Priority.CRITICAL);
constraintManager.addConstraint(new ShipmentPickupsFirstConstraint(), ConstraintManager.Priority.CRITICAL);
ShipmentInsertionCalculatorFlex insertionCalculator = new ShipmentInsertionCalculatorFlex(routingCosts, activityCosts,
activityInsertionCostsCalculator, constraintManager);
insertionCalculator.setJobActivityFactory(vrp.getJobActivityFactory());
InsertionData iData = insertionCalculator.getInsertionData(route, shipment3, vehicle, 0.0, DriverImpl.noDriver(), Double.MAX_VALUE);
assertTrue(iData instanceof InsertionData.NoInsertionFound);
}
@Ignore
@Test
public void whenInsertingShipmentWithLoadConstraintWhereCapIsNotSufficient_capConstraintsAreFulfilledV2() {
Shipment shipment = Shipment.Builder.newInstance("s").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("0,10").build()).setDeliveryLocation(Location.newInstance("10,0")).build();
Shipment shipment2 = Shipment.Builder.newInstance("s2").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("10,10").build()).setDeliveryLocation(Location.newInstance("0,0")).build();
Shipment shipment3 = Shipment.Builder.newInstance("s3").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("0,0").build()).setDeliveryLocation(Location.newInstance("9,9")).build();
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
VehicleRoutingProblem vrp = vrpBuilder.addJob(shipment).addJob(shipment2).addJob(shipment3).build();
VehicleRoute route = VehicleRoute.emptyRoute();
route.setVehicleAndDepartureTime(vehicle, 0.0);
Inserter inserter = new Inserter(new InsertionListeners(), vrp);
inserter.insertJob(shipment, new InsertionData(0, 0, 0, vehicle, null), route);
inserter.insertJob(shipment2, new InsertionData(0, 1, 2, vehicle, null), route);
StateManager stateManager = new StateManager(vrp);
stateManager.updateLoadStates();
stateManager.informInsertionStarts(Arrays.asList(route), null);
ConstraintManager constraintManager = new ConstraintManager(vrp, stateManager);
constraintManager.addConstraint(new PickupAndDeliverShipmentLoadActivityLevelConstraint(stateManager), ConstraintManager.Priority.CRITICAL);
// constraintManager.addConstraint(new ShipmentPickupsFirstConstraint(), ConstraintManager.Priority.CRITICAL);
ShipmentInsertionCalculatorFlex insertionCalculator = new ShipmentInsertionCalculatorFlex(routingCosts, activityCosts,
activityInsertionCostsCalculator, constraintManager);
insertionCalculator.setEvalIndexPickup(0);
insertionCalculator.setEvalIndexDelivery(3);
insertionCalculator.setJobActivityFactory(vrp.getJobActivityFactory());
InsertionData iData = insertionCalculator.getInsertionData(route, shipment3, vehicle, 0.0, DriverImpl.noDriver(), Double.MAX_VALUE);
assertTrue(iData instanceof InsertionData.NoInsertionFound);
}
@Test
public void whenInsertingServiceWhileNoCapIsAvailable_itMustReturnNoInsertionData() {
Shipment shipment = Shipment.Builder.newInstance("s").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("0,10").build()).setDeliveryLocation(Location.newInstance("0,0")).build();
Shipment shipment2 = Shipment.Builder.newInstance("s2").addSizeDimension(0, 1).setPickupLocation(Location.Builder.newInstance().setId("10,10").build()).setDeliveryLocation(Location.newInstance("0,0")).build();
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
VehicleRoutingProblem vrp = vrpBuilder.addJob(shipment).addJob(shipment2).build();
VehicleRoute route = VehicleRoute.emptyRoute();
route.setVehicleAndDepartureTime(vehicle, 0.0);
Inserter inserter = new Inserter(new InsertionListeners(), vrp);
inserter.insertJob(shipment, new InsertionData(0, 0, 0, vehicle, null), route);
inserter.insertJob(shipment2, new InsertionData(0, 1, 2, vehicle, null), route);
StateManager stateManager = new StateManager(vrp);
stateManager.updateLoadStates();
stateManager.informInsertionStarts(Arrays.asList(route), null);
ConstraintManager constraintManager = new ConstraintManager(vrp, stateManager);
constraintManager.addLoadConstraint();
stateManager.informInsertionStarts(Arrays.asList(route), null);
Pickup service = (Pickup) Pickup.Builder.newInstance("pick").addSizeDimension(0, 1).setLocation(Location.newInstance("5,5")).build();
JobActivityFactory activityFactory = mock(JobActivityFactory.class);
List<AbstractActivity> activities = new ArrayList<AbstractActivity>();
activities.add(new PickupService(service));
when(activityFactory.createActivities(service)).thenReturn(activities);
JobCalculatorSwitcher switcher = new JobCalculatorSwitcher();
ServiceInsertionCalculator serviceInsertionCalc = new ServiceInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager, activityFactory);
ShipmentInsertionCalculatorFlex insertionCalculator = new ShipmentInsertionCalculatorFlex(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager);
insertionCalculator.setJobActivityFactory(activityFactory);
switcher.put(Pickup.class, serviceInsertionCalc);
switcher.put(Service.class, serviceInsertionCalc);
switcher.put(Shipment.class, insertionCalculator);
InsertionData iData = switcher.getInsertionData(route, service, vehicle, 0, DriverImpl.noDriver(), Double.MAX_VALUE);
// routeActVisitor.visit(route);
assertEquals(3, iData.getDeliveryInsertionIndex());
}
}

View file

@ -94,21 +94,24 @@ public class ShipmentInsertionCalculatorTest {
Vehicle vehicle;
ConstraintManager constraintManager;
@Before
public void doBefore() {
routingCosts = CostFactory.createManhattanCosts();
VehicleType type = VehicleTypeImpl.Builder.newInstance("t").addCapacityDimension(0, 2).setCostPerDistance(1).build();
vehicle = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance("0,0")).setType(type).build();
activityInsertionCostsCalculator = new LocalActivityInsertionCostsCalculator(routingCosts, activityCosts, mock(StateManager.class));
createInsertionCalculator(hardRouteLevelConstraint);
constraintManager = new ConstraintManager(mock(VehicleRoutingProblem.class), mock(RouteAndActivityStateGetter.class));
constraintManager.addConstraint(hardRouteLevelConstraint);
vehicleRoutingProblem = mock(VehicleRoutingProblem.class);
}
private void createInsertionCalculator(HardRouteConstraint hardRouteLevelConstraint) {
ConstraintManager constraintManager = new ConstraintManager(mock(VehicleRoutingProblem.class), mock(RouteAndActivityStateGetter.class));
constraintManager.addConstraint(hardRouteLevelConstraint);
insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager);
}
// private void createInsertionCalculator(HardRouteConstraint hardRouteLevelConstraint) {
// ConstraintManager constraintManager = new ConstraintManager(mock(VehicleRoutingProblem.class), mock(RouteAndActivityStateGetter.class));
// constraintManager.addConstraint(hardRouteLevelConstraint);
// insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager, );
// }
@Test
public void whenCalculatingInsertionCostsOfShipment_itShouldReturnCorrectCostValue() {
@ -119,7 +122,7 @@ public class ShipmentInsertionCalculatorTest {
activities.add(new PickupShipment(shipment));
activities.add(new DeliverShipment(shipment));
when(activityFactory.createActivities(shipment)).thenReturn(activities);
insertionCalculator.setJobActivityFactory(activityFactory);
insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager, activityFactory);
InsertionData iData = insertionCalculator.getInsertionData(route, shipment, vehicle, 0.0, null, Double.MAX_VALUE);
assertEquals(40.0, iData.getInsertionCost(), 0.05);
}
@ -137,7 +140,7 @@ public class ShipmentInsertionCalculatorTest {
activities.add(new PickupShipment(shipment2));
activities.add(new DeliverShipment(shipment2));
when(activityFactory.createActivities(shipment2)).thenReturn(activities);
insertionCalculator.setJobActivityFactory(activityFactory);
insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager, activityFactory);
InsertionData iData = insertionCalculator.getInsertionData(route, shipment2, vehicle, 0.0, null, Double.MAX_VALUE);
assertEquals(0.0, iData.getInsertionCost(), 0.05);
@ -161,7 +164,9 @@ public class ShipmentInsertionCalculatorTest {
VehicleRoute route = VehicleRoute.emptyRoute();
when(vehicleRoutingProblem.copyAndGetActivities(shipment)).thenReturn(getTourActivities(shipment));
new Inserter(new InsertionListeners(), vehicleRoutingProblem).insertJob(shipment, new InsertionData(0, 0, 0, vehicle, null), route);
createInsertionCalculator(new HardRouteConstraint() {
constraintManager = new ConstraintManager(mock(VehicleRoutingProblem.class), mock(RouteAndActivityStateGetter.class));
constraintManager.addConstraint(new HardRouteConstraint() {
@Override
public boolean fulfilled(JobInsertionContext insertionContext) {
@ -175,7 +180,7 @@ public class ShipmentInsertionCalculatorTest {
activities.add(new PickupShipment(shipment2));
activities.add(new DeliverShipment(shipment2));
when(activityFactory.createActivities(shipment2)).thenReturn(activities);
insertionCalculator.setJobActivityFactory(activityFactory);
insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager, activityFactory);
InsertionData iData = insertionCalculator.getInsertionData(route, shipment2, vehicle, 0.0, null, Double.MAX_VALUE);
assertTrue(iData instanceof InsertionData.NoInsertionFound);
@ -201,7 +206,7 @@ public class ShipmentInsertionCalculatorTest {
activities.add(new PickupShipment(shipment3));
activities.add(new DeliverShipment(shipment3));
when(activityFactory.createActivities(shipment3)).thenReturn(activities);
insertionCalculator.setJobActivityFactory(activityFactory);
insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager, activityFactory);
InsertionData iData = insertionCalculator.getInsertionData(route, shipment3, vehicle, 0.0, null, Double.MAX_VALUE);
assertEquals(0.0, iData.getInsertionCost(), 0.05);
@ -226,7 +231,7 @@ public class ShipmentInsertionCalculatorTest {
activities.add(new PickupShipment(shipment3));
activities.add(new DeliverShipment(shipment3));
when(activityFactory.createActivities(shipment3)).thenReturn(activities);
insertionCalculator.setJobActivityFactory(activityFactory);
insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager, activityFactory);
InsertionData iData = insertionCalculator.getInsertionData(route, shipment3, vehicle, 0.0, null, Double.MAX_VALUE);
@ -260,8 +265,7 @@ public class ShipmentInsertionCalculatorTest {
constraintManager.addConstraint(new ShipmentPickupsFirstConstraint(), ConstraintManager.Priority.CRITICAL);
ShipmentInsertionCalculator insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityCosts,
activityInsertionCostsCalculator, constraintManager);
insertionCalculator.setJobActivityFactory(vrp.getJobActivityFactory());
activityInsertionCostsCalculator, constraintManager, vrp.getJobActivityFactory());
InsertionData iData = insertionCalculator.getInsertionData(route, shipment3, vehicle, 0.0, DriverImpl.noDriver(), Double.MAX_VALUE);
assertTrue(iData instanceof InsertionData.NoInsertionFound);
@ -293,22 +297,20 @@ public class ShipmentInsertionCalculatorTest {
stateManager.informInsertionStarts(Arrays.asList(route), null);
JobCalculatorSwitcher switcher = new JobCalculatorSwitcher();
ServiceInsertionCalculator serviceInsertionCalc = new ServiceInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager);
ShipmentInsertionCalculator insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager);
switcher.put(Pickup.class, serviceInsertionCalc);
switcher.put(Service.class, serviceInsertionCalc);
switcher.put(Shipment.class, insertionCalculator);
// Service service = Service.Builder.newInstance("pick", 1).setLocationId("5,5").build();
Pickup service = (Pickup) Pickup.Builder.newInstance("pick").addSizeDimension(0, 1).setLocation(Location.newInstance("5,5")).build();
JobActivityFactory activityFactory = mock(JobActivityFactory.class);
List<AbstractActivity> activities = new ArrayList<AbstractActivity>();
activities.add(new PickupService(service));
when(activityFactory.createActivities(service)).thenReturn(activities);
insertionCalculator.setJobActivityFactory(activityFactory);
serviceInsertionCalc.setJobActivityFactory(activityFactory);
JobCalculatorSwitcher switcher = new JobCalculatorSwitcher();
ServiceInsertionCalculator serviceInsertionCalc = new ServiceInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager, activityFactory);
ShipmentInsertionCalculator insertionCalculator = new ShipmentInsertionCalculator(routingCosts, activityCosts, activityInsertionCostsCalculator, constraintManager, activityFactory);
switcher.put(Pickup.class, serviceInsertionCalc);
switcher.put(Service.class, serviceInsertionCalc);
switcher.put(Shipment.class, insertionCalculator);
InsertionData iData = switcher.getInsertionData(route, service, vehicle, 0, DriverImpl.noDriver(), Double.MAX_VALUE);
// routeActVisitor.visit(route);

View file

@ -136,13 +136,13 @@ public class TestCalculatesServiceInsertion {
VehicleRoutingActivityCosts actCosts = mock(VehicleRoutingActivityCosts.class);
serviceInsertion = new ServiceInsertionCalculator(costs, vrp.getActivityCosts(), new LocalActivityInsertionCostsCalculator(costs, actCosts, states), cManager);
serviceInsertion.setJobActivityFactory(new JobActivityFactory() {
serviceInsertion = new ServiceInsertionCalculator(costs, vrp.getActivityCosts(), new LocalActivityInsertionCostsCalculator(costs, actCosts, states), cManager, new JobActivityFactory() {
@Override
public List<AbstractActivity> createActivities(Job job) {
return vrp.copyAndGetActivities(job);
}
});
}
@Test

View file

@ -316,6 +316,17 @@ public class VehicleRoutingProblemTest {
builder.addVehicle(vehicle2);
}
@Test(expected = IllegalArgumentException.class)
public void whenAddingVehicleTypesWithSameIdButDifferentCosts_itShouldThrowException() {
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
VehicleType type1 = VehicleTypeImpl.Builder.newInstance("type").build();
VehicleType type2 = VehicleTypeImpl.Builder.newInstance("type").setCostPerServiceTime(2d).build();
VehicleImpl vehicle1 = VehicleImpl.Builder.newInstance("v1").setStartLocation(Location.newInstance("loc")).setType(type1).build();
VehicleImpl vehicle2 = VehicleImpl.Builder.newInstance("v2").setStartLocation(Location.newInstance("loc")).setType(type2).build();
builder.addVehicle(vehicle1);
builder.addVehicle(vehicle2);
}
@Test(expected = IllegalArgumentException.class)
public void whenBuildingProblemWithSameBreakId_itShouldThrowException(){
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();

View file

@ -124,6 +124,7 @@ public class VehicleTypeImplTest {
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("type").setCostPerDistance(-10).build();
}
@Test
public void whenSettingPerDistanceCosts_itShouldBeSetCorrectly() {
VehicleTypeImpl type = VehicleTypeImpl.Builder.newInstance("type").setCostPerDistance(10).build();
assertEquals(10.0, type.getVehicleCostParams().perDistanceUnit, 0.0);
@ -166,4 +167,32 @@ public class VehicleTypeImplTest {
assertEquals(42, two.getUserData());
assertNull(three.getUserData());
}
@Test
public void typesShouldBeEqual() {
VehicleType one = VehicleTypeImpl.Builder.newInstance("type").setFixedCost(100).build();
VehicleType two = VehicleTypeImpl.Builder.newInstance("type").setFixedCost(100).build();
assertTrue(one.equals(two));
}
@Test
public void typesShouldBeNotEqual() {
VehicleType one = VehicleTypeImpl.Builder.newInstance("type").build();
VehicleType two = VehicleTypeImpl.Builder.newInstance("type").setFixedCost(100).build();
assertFalse(one.equals(two));
}
@Test
public void typesShouldBeNotEqual2() {
VehicleType one = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 10).build();
VehicleType two = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 20).build();
assertFalse(one.equals(two));
}
@Test
public void typesShouldBeEqual2() {
VehicleType one = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 10).build();
VehicleType two = VehicleTypeImpl.Builder.newInstance("type").addCapacityDimension(0, 10).build();
assertTrue(one.equals(two));
}
}