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:
commit
b68879303e
28 changed files with 1404 additions and 169 deletions
|
|
@ -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())));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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]";
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue