mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
add new and unique random instance to ensure reproducibility of several run within the same jvm
This commit is contained in:
parent
7016f3baa3
commit
4efbd1cd1e
8 changed files with 216 additions and 82 deletions
|
|
@ -33,10 +33,7 @@ import jsprit.core.problem.vehicle.VehicleFleetManager;
|
||||||
import jsprit.core.problem.vehicle.VehicleTypeKey;
|
import jsprit.core.problem.vehicle.VehicleTypeKey;
|
||||||
import jsprit.core.util.ActivityTimeTracker;
|
import jsprit.core.util.ActivityTimeTracker;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by schroeder on 10.12.14.
|
* Created by schroeder on 10.12.14.
|
||||||
|
|
@ -71,6 +68,11 @@ public class PrettyAlgorithmBuilder {
|
||||||
this.searchStrategyManager = new SearchStrategyManager();
|
this.searchStrategyManager = new SearchStrategyManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PrettyAlgorithmBuilder setRandom(Random random){
|
||||||
|
searchStrategyManager.setRandom(random);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public PrettyAlgorithmBuilder withStrategy(SearchStrategy strategy, double weight){
|
public PrettyAlgorithmBuilder withStrategy(SearchStrategy strategy, double weight){
|
||||||
searchStrategyManager.addStrategy(strategy,weight);
|
searchStrategyManager.addStrategy(strategy,weight);
|
||||||
return this;
|
return this;
|
||||||
|
|
@ -164,4 +166,5 @@ public class PrettyAlgorithmBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import jsprit.core.util.RandomNumberGeneration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by schroeder on 16/01/15.
|
* Created by schroeder on 16/01/15.
|
||||||
|
|
@ -31,6 +32,8 @@ class InsertionNoiseMaker implements SoftActivityConstraint, IterationStartsList
|
||||||
|
|
||||||
private double noiseLevel = 0.1;
|
private double noiseLevel = 0.1;
|
||||||
|
|
||||||
|
private Random random = RandomNumberGeneration.getRandom();
|
||||||
|
|
||||||
public InsertionNoiseMaker(VehicleRoutingProblem vrp, double noiseLevel, double noiseProbability) {
|
public InsertionNoiseMaker(VehicleRoutingProblem vrp, double noiseLevel, double noiseProbability) {
|
||||||
this.vrp = vrp;
|
this.vrp = vrp;
|
||||||
this.noiseLevel = noiseLevel;
|
this.noiseLevel = noiseLevel;
|
||||||
|
|
@ -70,7 +73,7 @@ class InsertionNoiseMaker implements SoftActivityConstraint, IterationStartsList
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||||
if(RandomNumberGeneration.getRandom().nextDouble() < noiseProbability){
|
if(random.nextDouble() < noiseProbability){
|
||||||
makeNoise = true;
|
makeNoise = true;
|
||||||
}
|
}
|
||||||
else makeNoise = false;
|
else makeNoise = false;
|
||||||
|
|
@ -79,10 +82,13 @@ class InsertionNoiseMaker implements SoftActivityConstraint, IterationStartsList
|
||||||
@Override
|
@Override
|
||||||
public double getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
|
public double getCosts(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
|
||||||
if(makeNoise) {
|
if(makeNoise) {
|
||||||
return noiseLevel * maxCosts * RandomNumberGeneration.getRandom().nextDouble();
|
return noiseLevel * maxCosts * random.nextDouble();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setRandom(Random random) {
|
||||||
|
this.random = random;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import jsprit.core.util.Solutions;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.Random;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
|
@ -129,6 +130,8 @@ public class Jsprit {
|
||||||
|
|
||||||
private boolean addConstraints = true;
|
private boolean addConstraints = true;
|
||||||
|
|
||||||
|
private Random random = RandomNumberGeneration.newInstance();
|
||||||
|
|
||||||
public static Builder newInstance(VehicleRoutingProblem vrp){
|
public static Builder newInstance(VehicleRoutingProblem vrp){
|
||||||
return new Builder(vrp);
|
return new Builder(vrp);
|
||||||
}
|
}
|
||||||
|
|
@ -186,6 +189,11 @@ public class Jsprit {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder setRandom(Random random){
|
||||||
|
this.random = random;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public Builder setProperty(String key, String value){
|
public Builder setProperty(String key, String value){
|
||||||
properties.put(key,value);
|
properties.put(key,value);
|
||||||
return this;
|
return this;
|
||||||
|
|
@ -231,15 +239,28 @@ public class Jsprit {
|
||||||
|
|
||||||
private int minShare;
|
private int minShare;
|
||||||
|
|
||||||
|
private Random random = RandomNumberGeneration.getRandom();
|
||||||
|
|
||||||
|
public void setRandom(Random random) {
|
||||||
|
this.random = random;
|
||||||
|
}
|
||||||
|
|
||||||
public RuinShareFactoryImpl(int minShare, int maxShare) {
|
public RuinShareFactoryImpl(int minShare, int maxShare) {
|
||||||
if(maxShare < minShare) throw new IllegalArgumentException("maxShare must be equal or greater than minShare");
|
if(maxShare < minShare) throw new IllegalArgumentException("maxShare must be equal or greater than minShare");
|
||||||
this.minShare = minShare;
|
this.minShare = minShare;
|
||||||
this.maxShare = maxShare;
|
this.maxShare = maxShare;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RuinShareFactoryImpl(int minShare, int maxShare, Random random) {
|
||||||
|
if(maxShare < minShare) throw new IllegalArgumentException("maxShare must be equal or greater than minShare");
|
||||||
|
this.minShare = minShare;
|
||||||
|
this.maxShare = maxShare;
|
||||||
|
this.random = random;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int createNumberToBeRemoved() {
|
public int createNumberToBeRemoved() {
|
||||||
return (int) (minShare + (maxShare - minShare) * RandomNumberGeneration.getRandom().nextDouble());
|
return (int) (minShare + (maxShare - minShare) * random.nextDouble());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -260,6 +281,8 @@ public class Jsprit {
|
||||||
|
|
||||||
private Properties properties;
|
private Properties properties;
|
||||||
|
|
||||||
|
private Random random;
|
||||||
|
|
||||||
private Jsprit(Builder builder) {
|
private Jsprit(Builder builder) {
|
||||||
this.stateManager = builder.stateManager;
|
this.stateManager = builder.stateManager;
|
||||||
this.constraintManager = builder.constraintManager;
|
this.constraintManager = builder.constraintManager;
|
||||||
|
|
@ -268,6 +291,7 @@ public class Jsprit {
|
||||||
this.addCoreConstraints = builder.addConstraints;
|
this.addCoreConstraints = builder.addConstraints;
|
||||||
this.properties = builder.properties;
|
this.properties = builder.properties;
|
||||||
this.objectiveFunction = builder.objectiveFunction;
|
this.objectiveFunction = builder.objectiveFunction;
|
||||||
|
this.random = builder.random;
|
||||||
}
|
}
|
||||||
|
|
||||||
private VehicleRoutingAlgorithm create(final VehicleRoutingProblem vrp){
|
private VehicleRoutingAlgorithm create(final VehicleRoutingProblem vrp){
|
||||||
|
|
@ -287,33 +311,42 @@ public class Jsprit {
|
||||||
double noiseLevel = toDouble(getProperty(Parameter.INSERTION_NOISE_LEVEL.toString()));
|
double noiseLevel = toDouble(getProperty(Parameter.INSERTION_NOISE_LEVEL.toString()));
|
||||||
double noiseProbability = toDouble(getProperty(Parameter.INSERTION_NOISE_PROB.toString()));
|
double noiseProbability = toDouble(getProperty(Parameter.INSERTION_NOISE_PROB.toString()));
|
||||||
final InsertionNoiseMaker noiseMaker = new InsertionNoiseMaker(vrp, noiseLevel, noiseProbability);
|
final InsertionNoiseMaker noiseMaker = new InsertionNoiseMaker(vrp, noiseLevel, noiseProbability);
|
||||||
|
noiseMaker.setRandom(random);
|
||||||
constraintManager.addConstraint(noiseMaker);
|
constraintManager.addConstraint(noiseMaker);
|
||||||
|
|
||||||
JobNeighborhoods jobNeighborhoods = new JobNeighborhoodsFactory().createNeighborhoods(vrp, new AvgServiceAndShipmentDistance(vrp.getTransportCosts()), (int) (vrp.getJobs().values().size() * 0.5));
|
JobNeighborhoods jobNeighborhoods = new JobNeighborhoodsFactory().createNeighborhoods(vrp, new AvgServiceAndShipmentDistance(vrp.getTransportCosts()), (int) (vrp.getJobs().values().size() * 0.5));
|
||||||
jobNeighborhoods.initialise();
|
jobNeighborhoods.initialise();
|
||||||
|
|
||||||
RuinRadial radial = new RuinRadial(vrp,vrp.getJobs().size(),jobNeighborhoods);
|
RuinRadial radial = new RuinRadial(vrp,vrp.getJobs().size(),jobNeighborhoods);
|
||||||
|
radial.setRandom(random);
|
||||||
radial.setRuinShareFactory(new RuinShareFactoryImpl(
|
radial.setRuinShareFactory(new RuinShareFactoryImpl(
|
||||||
toInteger(properties.getProperty(Parameter.RADIAL_MIN_SHARE.toString())),
|
toInteger(properties.getProperty(Parameter.RADIAL_MIN_SHARE.toString())),
|
||||||
toInteger(properties.getProperty(Parameter.RADIAL_MAX_SHARE.toString())))
|
toInteger(properties.getProperty(Parameter.RADIAL_MAX_SHARE.toString())),
|
||||||
|
random)
|
||||||
);
|
);
|
||||||
|
|
||||||
final RuinRandom random_for_regret = new RuinRandom(vrp,0.5);
|
final RuinRandom random_for_regret = new RuinRandom(vrp,0.5);
|
||||||
|
random_for_regret.setRandom(random);
|
||||||
random_for_regret.setRuinShareFactory(new RuinShareFactoryImpl(
|
random_for_regret.setRuinShareFactory(new RuinShareFactoryImpl(
|
||||||
toInteger(properties.getProperty(Parameter.RANDOM_REGRET_MIN_SHARE.toString())),
|
toInteger(properties.getProperty(Parameter.RANDOM_REGRET_MIN_SHARE.toString())),
|
||||||
toInteger(properties.getProperty(Parameter.RANDOM_REGRET_MAX_SHARE.toString())))
|
toInteger(properties.getProperty(Parameter.RANDOM_REGRET_MAX_SHARE.toString())),
|
||||||
|
random)
|
||||||
);
|
);
|
||||||
|
|
||||||
final RuinRandom random_for_best = new RuinRandom(vrp,0.5);
|
final RuinRandom random_for_best = new RuinRandom(vrp,0.5);
|
||||||
|
random_for_best.setRandom(random);
|
||||||
random_for_best.setRuinShareFactory(new RuinShareFactoryImpl(
|
random_for_best.setRuinShareFactory(new RuinShareFactoryImpl(
|
||||||
toInteger(properties.getProperty(Parameter.RANDOM_BEST_MIN_SHARE.toString())),
|
toInteger(properties.getProperty(Parameter.RANDOM_BEST_MIN_SHARE.toString())),
|
||||||
toInteger(properties.getProperty(Parameter.RANDOM_BEST_MAX_SHARE.toString())))
|
toInteger(properties.getProperty(Parameter.RANDOM_BEST_MAX_SHARE.toString())),
|
||||||
|
random)
|
||||||
);
|
);
|
||||||
|
|
||||||
final RuinWorst worst = new RuinWorst(vrp, (int) (vrp.getJobs().values().size()*0.5));
|
final RuinWorst worst = new RuinWorst(vrp, (int) (vrp.getJobs().values().size()*0.5));
|
||||||
|
worst.setRandom(random);
|
||||||
worst.setRuinShareFactory(new RuinShareFactoryImpl(
|
worst.setRuinShareFactory(new RuinShareFactoryImpl(
|
||||||
toInteger(properties.getProperty(Parameter.WORST_MIN_SHARE.toString())),
|
toInteger(properties.getProperty(Parameter.WORST_MIN_SHARE.toString())),
|
||||||
toInteger(properties.getProperty(Parameter.WORST_MAX_SHARE.toString())))
|
toInteger(properties.getProperty(Parameter.WORST_MAX_SHARE.toString())),
|
||||||
|
random)
|
||||||
);
|
);
|
||||||
IterationStartsListener noise = new IterationStartsListener() {
|
IterationStartsListener noise = new IterationStartsListener() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -321,9 +354,9 @@ public class Jsprit {
|
||||||
worst.setNoiseMaker(new NoiseMaker() {
|
worst.setNoiseMaker(new NoiseMaker() {
|
||||||
|
|
||||||
public double makeNoise() {
|
public double makeNoise() {
|
||||||
if(RandomNumberGeneration.getRandom().nextDouble() < toDouble(getProperty(Parameter.RUIN_WORST_NOISE_PROB.toString()))) {
|
if(random.nextDouble() < toDouble(getProperty(Parameter.RUIN_WORST_NOISE_PROB.toString()))) {
|
||||||
return toDouble(getProperty(Parameter.RUIN_WORST_NOISE_LEVEL.toString()))
|
return toDouble(getProperty(Parameter.RUIN_WORST_NOISE_LEVEL.toString()))
|
||||||
* noiseMaker.maxCosts * RandomNumberGeneration.getRandom().nextDouble();
|
* noiseMaker.maxCosts * random.nextDouble();
|
||||||
}
|
}
|
||||||
else return 0.;
|
else return 0.;
|
||||||
}
|
}
|
||||||
|
|
@ -332,12 +365,14 @@ public class Jsprit {
|
||||||
};
|
};
|
||||||
|
|
||||||
final RuinClusters clusters = new RuinClusters(vrp,(int) (vrp.getJobs().values().size()*0.5),jobNeighborhoods);
|
final RuinClusters clusters = new RuinClusters(vrp,(int) (vrp.getJobs().values().size()*0.5),jobNeighborhoods);
|
||||||
|
clusters.setRandom(random);
|
||||||
clusters.setRuinShareFactory(new RuinShareFactoryImpl(
|
clusters.setRuinShareFactory(new RuinShareFactoryImpl(
|
||||||
toInteger(properties.getProperty(Parameter.WORST_MIN_SHARE.toString())),
|
toInteger(properties.getProperty(Parameter.WORST_MIN_SHARE.toString())),
|
||||||
toInteger(properties.getProperty(Parameter.WORST_MAX_SHARE.toString())))
|
toInteger(properties.getProperty(Parameter.WORST_MAX_SHARE.toString())),
|
||||||
|
random)
|
||||||
);
|
);
|
||||||
|
|
||||||
InsertionStrategy regret;
|
AbstractInsertionStrategy regret;
|
||||||
final RegretInsertion.DefaultScorer scorer;
|
final RegretInsertion.DefaultScorer scorer;
|
||||||
if(noThreads == null){
|
if(noThreads == null){
|
||||||
noThreads = toInteger(getProperty(Parameter.THREADS.toString()));
|
noThreads = toInteger(getProperty(Parameter.THREADS.toString()));
|
||||||
|
|
@ -369,8 +404,9 @@ public class Jsprit {
|
||||||
regretInsertion.setScoringFunction(scorer);
|
regretInsertion.setScoringFunction(scorer);
|
||||||
regret = regretInsertion;
|
regret = regretInsertion;
|
||||||
}
|
}
|
||||||
|
regret.setRandom(random);
|
||||||
|
|
||||||
InsertionStrategy best;
|
AbstractInsertionStrategy best;
|
||||||
if(vrp.getJobs().size() < 250 || es == null) {
|
if(vrp.getJobs().size() < 250 || es == null) {
|
||||||
BestInsertion bestInsertion = (BestInsertion) new InsertionBuilder(vrp, fm, stateManager, constraintManager)
|
BestInsertion bestInsertion = (BestInsertion) new InsertionBuilder(vrp, fm, stateManager, constraintManager)
|
||||||
.setInsertionStrategy(InsertionBuilder.Strategy.BEST)
|
.setInsertionStrategy(InsertionBuilder.Strategy.BEST)
|
||||||
|
|
@ -388,6 +424,7 @@ public class Jsprit {
|
||||||
.build();
|
.build();
|
||||||
best = bestInsertion;
|
best = bestInsertion;
|
||||||
}
|
}
|
||||||
|
best.setRandom(random);
|
||||||
|
|
||||||
final SchrimpfAcceptance schrimpfAcceptance = new SchrimpfAcceptance(1,toDouble(getProperty(Parameter.THRESHOLD_ALPHA.toString())));
|
final SchrimpfAcceptance schrimpfAcceptance = new SchrimpfAcceptance(1,toDouble(getProperty(Parameter.THRESHOLD_ALPHA.toString())));
|
||||||
IterationStartsListener schrimpfThreshold = new IterationStartsListener() {
|
IterationStartsListener schrimpfThreshold = new IterationStartsListener() {
|
||||||
|
|
@ -428,6 +465,7 @@ public class Jsprit {
|
||||||
|
|
||||||
|
|
||||||
PrettyAlgorithmBuilder prettyBuilder = PrettyAlgorithmBuilder.newInstance(vrp, fm, stateManager, constraintManager);
|
PrettyAlgorithmBuilder prettyBuilder = PrettyAlgorithmBuilder.newInstance(vrp, fm, stateManager, constraintManager);
|
||||||
|
prettyBuilder.setRandom(random);
|
||||||
if(addCoreConstraints){
|
if(addCoreConstraints){
|
||||||
prettyBuilder.addCoreStateAndConstraintStuff();
|
prettyBuilder.addCoreStateAndConstraintStuff();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,12 @@
|
||||||
package jsprit.core.algorithm.recreate;
|
package jsprit.core.algorithm.recreate;
|
||||||
|
|
||||||
import jsprit.core.algorithm.recreate.InsertionData.NoInsertionFound;
|
import jsprit.core.algorithm.recreate.InsertionData.NoInsertionFound;
|
||||||
import jsprit.core.algorithm.recreate.listener.InsertionListener;
|
|
||||||
import jsprit.core.algorithm.recreate.listener.InsertionListeners;
|
import jsprit.core.algorithm.recreate.listener.InsertionListeners;
|
||||||
import jsprit.core.problem.VehicleRoutingProblem;
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
import jsprit.core.problem.driver.Driver;
|
import jsprit.core.problem.driver.Driver;
|
||||||
import jsprit.core.problem.job.Job;
|
import jsprit.core.problem.job.Job;
|
||||||
import jsprit.core.problem.solution.route.VehicleRoute;
|
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||||
import jsprit.core.problem.vehicle.Vehicle;
|
import jsprit.core.problem.vehicle.Vehicle;
|
||||||
import jsprit.core.util.RandomNumberGeneration;
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
|
@ -40,7 +38,7 @@ import java.util.concurrent.*;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public final class BestInsertionConcurrent implements InsertionStrategy{
|
public final class BestInsertionConcurrent extends AbstractInsertionStrategy{
|
||||||
|
|
||||||
static class Batch {
|
static class Batch {
|
||||||
List<VehicleRoute> routes = new ArrayList<VehicleRoute>();
|
List<VehicleRoute> routes = new ArrayList<VehicleRoute>();
|
||||||
|
|
@ -71,8 +69,6 @@ public final class BestInsertionConcurrent implements InsertionStrategy{
|
||||||
|
|
||||||
private static Logger logger = LogManager.getLogger(BestInsertionConcurrent.class);
|
private static Logger logger = LogManager.getLogger(BestInsertionConcurrent.class);
|
||||||
|
|
||||||
private Random random = RandomNumberGeneration.getRandom();
|
|
||||||
|
|
||||||
private final static double NO_NEW_DEPARTURE_TIME_YET = -12345.12345;
|
private final static double NO_NEW_DEPARTURE_TIME_YET = -12345.12345;
|
||||||
|
|
||||||
private final static Vehicle NO_NEW_VEHICLE_YET = null;
|
private final static Vehicle NO_NEW_VEHICLE_YET = null;
|
||||||
|
|
@ -81,23 +77,21 @@ public final class BestInsertionConcurrent implements InsertionStrategy{
|
||||||
|
|
||||||
private InsertionListeners insertionsListeners;
|
private InsertionListeners insertionsListeners;
|
||||||
|
|
||||||
private Inserter inserter;
|
|
||||||
|
|
||||||
private JobInsertionCostsCalculator bestInsertionCostCalculator;
|
private JobInsertionCostsCalculator bestInsertionCostCalculator;
|
||||||
|
|
||||||
private int nuOfBatches;
|
private int nuOfBatches;
|
||||||
|
|
||||||
private ExecutorCompletionService<Insertion> completionService;
|
private ExecutorCompletionService<Insertion> completionService;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public void setRandom(Random random) {
|
public void setRandom(Random random) {
|
||||||
this.random = random;
|
super.random = random;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BestInsertionConcurrent(JobInsertionCostsCalculator jobInsertionCalculator, ExecutorService executorService, int nuOfBatches, VehicleRoutingProblem vehicleRoutingProblem) {
|
public BestInsertionConcurrent(JobInsertionCostsCalculator jobInsertionCalculator, ExecutorService executorService, int nuOfBatches, VehicleRoutingProblem vehicleRoutingProblem) {
|
||||||
super();
|
super(vehicleRoutingProblem);
|
||||||
this.insertionsListeners = new InsertionListeners();
|
this.insertionsListeners = new InsertionListeners();
|
||||||
this.nuOfBatches = nuOfBatches;
|
this.nuOfBatches = nuOfBatches;
|
||||||
inserter = new Inserter(insertionsListeners, vehicleRoutingProblem);
|
|
||||||
bestInsertionCostCalculator = jobInsertionCalculator;
|
bestInsertionCostCalculator = jobInsertionCalculator;
|
||||||
completionService = new ExecutorCompletionService<Insertion>(executorService);
|
completionService = new ExecutorCompletionService<Insertion>(executorService);
|
||||||
logger.info("initialise " + this);
|
logger.info("initialise " + this);
|
||||||
|
|
@ -109,16 +103,15 @@ public final class BestInsertionConcurrent implements InsertionStrategy{
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Job> insertJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs) {
|
||||||
insertionsListeners.informInsertionStarts(vehicleRoutes,unassignedJobs);
|
List<Job> badJobs = new ArrayList<Job>(unassignedJobs.size());
|
||||||
List<Job> badJobs = new ArrayList<Job>(unassignedJobs.size());
|
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
|
||||||
List<Job> unassignedJobList = new ArrayList<Job>(unassignedJobs);
|
|
||||||
Collections.shuffle(unassignedJobList, random);
|
Collections.shuffle(unassignedJobList, random);
|
||||||
List<Batch> batches = distributeRoutes(vehicleRoutes,nuOfBatches);
|
List<Batch> batches = distributeRoutes(vehicleRoutes,nuOfBatches);
|
||||||
for(final Job unassignedJob : unassignedJobList){
|
for(final Job unassignedJob : unassignedJobList){
|
||||||
Insertion bestInsertion = null;
|
Insertion bestInsertion = null;
|
||||||
double bestInsertionCost = Double.MAX_VALUE;
|
double bestInsertionCost = Double.MAX_VALUE;
|
||||||
for(final Batch batch : batches){
|
for(final Batch batch : batches){
|
||||||
completionService.submit(new Callable<Insertion>() {
|
completionService.submit(new Callable<Insertion>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -127,18 +120,18 @@ public final class BestInsertionConcurrent implements InsertionStrategy{
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
for (int i = 0; i < batches.size(); i++) {
|
for (int i = 0; i < batches.size(); i++) {
|
||||||
Future<Insertion> futureIData = completionService.take();
|
Future<Insertion> futureIData = completionService.take();
|
||||||
Insertion insertion = futureIData.get();
|
Insertion insertion = futureIData.get();
|
||||||
if (insertion == null) continue;
|
if (insertion == null) continue;
|
||||||
if (insertion.getInsertionData().getInsertionCost() < bestInsertionCost) {
|
if (insertion.getInsertionData().getInsertionCost() < bestInsertionCost) {
|
||||||
bestInsertion = insertion;
|
bestInsertion = insertion;
|
||||||
bestInsertionCost = insertion.getInsertionData().getInsertionCost();
|
bestInsertionCost = insertion.getInsertionData().getInsertionCost();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch(InterruptedException e){
|
} catch(InterruptedException e){
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
}
|
}
|
||||||
catch (ExecutionException e) {
|
catch (ExecutionException e) {
|
||||||
|
|
@ -146,34 +139,17 @@ public final class BestInsertionConcurrent implements InsertionStrategy{
|
||||||
logger.error(e.getCause().toString());
|
logger.error(e.getCause().toString());
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
VehicleRoute newRoute = VehicleRoute.emptyRoute();
|
||||||
InsertionData newIData = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
|
InsertionData newIData = bestInsertionCostCalculator.getInsertionData(newRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
|
||||||
if(newIData.getInsertionCost() < bestInsertionCost){
|
if(newIData.getInsertionCost() < bestInsertionCost){
|
||||||
bestInsertion = new Insertion(newRoute,newIData);
|
bestInsertion = new Insertion(newRoute,newIData);
|
||||||
vehicleRoutes.add(newRoute);
|
vehicleRoutes.add(newRoute);
|
||||||
batches.get(random.nextInt(batches.size())).routes.add(newRoute);
|
batches.get(random.nextInt(batches.size())).routes.add(newRoute);
|
||||||
}
|
}
|
||||||
if(bestInsertion == null) badJobs.add(unassignedJob);
|
if(bestInsertion == null) badJobs.add(unassignedJob);
|
||||||
else inserter.insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
else insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
|
||||||
}
|
}
|
||||||
insertionsListeners.informInsertionEndsListeners(vehicleRoutes);
|
return badJobs;
|
||||||
return badJobs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeListener(InsertionListener insertionListener) {
|
|
||||||
insertionsListeners.removeListener(insertionListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<InsertionListener> getListeners() {
|
|
||||||
return Collections.unmodifiableCollection(insertionsListeners.getListeners());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addListener(InsertionListener insertionListener) {
|
|
||||||
insertionsListeners.addListener(insertionListener);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
|
private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import org.apache.logging.log4j.Logger;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
|
||||||
class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCostsCalculator{
|
class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCostsCalculator{
|
||||||
|
|
@ -45,6 +46,12 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCostsC
|
||||||
|
|
||||||
private List<Double> departureTimeKnowledge = new ArrayList<Double>();
|
private List<Double> departureTimeKnowledge = new ArrayList<Double>();
|
||||||
|
|
||||||
|
public void setRandom(Random random) {
|
||||||
|
this.random = random;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Random random = RandomNumberGeneration.getRandom();
|
||||||
|
|
||||||
CalculatesServiceInsertionWithTimeScheduling(JobInsertionCostsCalculator jic, double t, double f) {
|
CalculatesServiceInsertionWithTimeScheduling(JobInsertionCostsCalculator jic, double t, double f) {
|
||||||
super();
|
super();
|
||||||
this.jic = jic;
|
this.jic = jic;
|
||||||
|
|
@ -61,7 +68,7 @@ class CalculatesServiceInsertionWithTimeScheduling implements JobInsertionCostsC
|
||||||
double departureTime = newVehicleDepartureTime;
|
double departureTime = newVehicleDepartureTime;
|
||||||
if(currentRoute.isEmpty()){
|
if(currentRoute.isEmpty()){
|
||||||
if(!departureTimeKnowledge.isEmpty()){
|
if(!departureTimeKnowledge.isEmpty()){
|
||||||
departureTime = departureTimeKnowledge.get(RandomNumberGeneration.getRandom().nextInt(departureTimeKnowledge.size()));
|
departureTime = departureTimeKnowledge.get(random.nextInt(departureTimeKnowledge.size()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(!currentRoute.getVehicle().getId().equals(newVehicle.getId())){
|
else if(!currentRoute.getVehicle().getId().equals(newVehicle.getId())){
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,12 @@ public class DBSCANClusterer {
|
||||||
|
|
||||||
private Double epsDistance;
|
private Double epsDistance;
|
||||||
|
|
||||||
|
private Random random = RandomNumberGeneration.getRandom();
|
||||||
|
|
||||||
|
public void setRandom(Random random) {
|
||||||
|
this.random = random;
|
||||||
|
}
|
||||||
|
|
||||||
public DBSCANClusterer(VehicleRoutingTransportCosts costs) {
|
public DBSCANClusterer(VehicleRoutingTransportCosts costs) {
|
||||||
this.costs = costs;
|
this.costs = costs;
|
||||||
}
|
}
|
||||||
|
|
@ -162,14 +168,13 @@ public class DBSCANClusterer {
|
||||||
}
|
}
|
||||||
List<Cluster<LocationWrapper>> clusterResults = getClusters(route,locations);
|
List<Cluster<LocationWrapper>> clusterResults = getClusters(route,locations);
|
||||||
if(clusterResults.isEmpty()) return Collections.emptyList();
|
if(clusterResults.isEmpty()) return Collections.emptyList();
|
||||||
Cluster<LocationWrapper> randomCluster = RandomUtils.nextItem(clusterResults, RandomNumberGeneration.getRandom());
|
Cluster<LocationWrapper> randomCluster = RandomUtils.nextItem(clusterResults, random);
|
||||||
return getJobList(randomCluster);
|
return getJobList(randomCluster);
|
||||||
}
|
}
|
||||||
|
|
||||||
private double sample(VehicleRoutingTransportCosts costs, VehicleRoute r) {
|
private double sample(VehicleRoutingTransportCosts costs, VehicleRoute r) {
|
||||||
double min = Double.MAX_VALUE;
|
double min = Double.MAX_VALUE;
|
||||||
double sum = 0;
|
double sum = 0;
|
||||||
Random random = RandomNumberGeneration.getRandom();
|
|
||||||
for(int i=0;i<noDistanceSamples;i++){
|
for(int i=0;i<noDistanceSamples;i++){
|
||||||
TourActivity act1 = RandomUtils.nextItem(r.getActivities(), random);
|
TourActivity act1 = RandomUtils.nextItem(r.getActivities(), random);
|
||||||
TourActivity act2 = RandomUtils.nextItem(r.getActivities(), random);
|
TourActivity act2 = RandomUtils.nextItem(r.getActivities(), random);
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ import jsprit.core.problem.job.Job;
|
||||||
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||||
import jsprit.core.problem.solution.route.VehicleRoute;
|
import jsprit.core.problem.solution.route.VehicleRoute;
|
||||||
import jsprit.core.problem.solution.route.activity.TourActivity;
|
import jsprit.core.problem.solution.route.activity.TourActivity;
|
||||||
import jsprit.core.util.RandomNumberGeneration;
|
|
||||||
import jsprit.core.util.RandomUtils;
|
import jsprit.core.util.RandomUtils;
|
||||||
import org.apache.commons.math3.ml.clustering.Clusterable;
|
import org.apache.commons.math3.ml.clustering.Clusterable;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
|
@ -43,8 +42,8 @@ public final class RuinClusters extends AbstractRuinStrategy implements Iteratio
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
public void informIterationStarts(int i, VehicleRoutingProblem problem, Collection<VehicleRoutingProblemSolution> solutions) {
|
||||||
minPts = 1 + RandomNumberGeneration.getRandom().nextInt(2);
|
minPts = 1 + random.nextInt(2);
|
||||||
epsFactor = 0.5 + RandomNumberGeneration.getRandom().nextDouble();
|
epsFactor = 0.5 + random.nextDouble();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class JobActivityWrapper implements Clusterable {
|
public static class JobActivityWrapper implements Clusterable {
|
||||||
|
|
@ -151,6 +150,7 @@ public final class RuinClusters extends AbstractRuinStrategy implements Iteratio
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DBSCANClusterer dbscan = new DBSCANClusterer(vrp.getTransportCosts());
|
DBSCANClusterer dbscan = new DBSCANClusterer(vrp.getTransportCosts());
|
||||||
|
dbscan.setRandom(random);
|
||||||
dbscan.setMinPts(minPts);
|
dbscan.setMinPts(minPts);
|
||||||
dbscan.setEpsFactor(epsFactor);
|
dbscan.setEpsFactor(epsFactor);
|
||||||
List<Job> cluster = dbscan.getRandomCluster(targetRoute);
|
List<Job> cluster = dbscan.getRandomCluster(targetRoute);
|
||||||
|
|
|
||||||
|
|
@ -511,6 +511,7 @@ public class JspritTest {
|
||||||
Assert.assertEquals(Solutions.bestOf(firstSolutions).getCost(),Solutions.bestOf(secondSolutions).getCost());
|
Assert.assertEquals(Solutions.bestOf(firstSolutions).getCost(),Solutions.bestOf(secondSolutions).getCost());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenTerminatingWithVariationCoefficient_terminationShouldBeReproducible(){
|
public void whenTerminatingWithVariationCoefficient_terminationShouldBeReproducible(){
|
||||||
|
|
||||||
|
|
@ -558,4 +559,102 @@ public class JspritTest {
|
||||||
Assert.assertEquals(Solutions.bestOf(firstSolutions).getCost(),Solutions.bestOf(secondSolutions).getCost());
|
Assert.assertEquals(Solutions.bestOf(firstSolutions).getCost(),Solutions.bestOf(secondSolutions).getCost());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenBiggerProblem_insertioPositionsShouldBeReproducibleWithoutResetingRNGExplicitly(){
|
||||||
|
|
||||||
|
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||||
|
new VrpXMLReader(vrpBuilder).read("src/test/resources/vrpnc1-jsprit-with-deliveries.xml");
|
||||||
|
VehicleRoutingProblem vrp = vrpBuilder.build();
|
||||||
|
|
||||||
|
RandomNumberGeneration.reset();
|
||||||
|
VehicleRoutingAlgorithm vra = Jsprit.createAlgorithm(vrp);
|
||||||
|
vra.setMaxIterations(200);
|
||||||
|
final List<Integer> firstRecord = new ArrayList<Integer>();
|
||||||
|
vra.addListener(new BeforeJobInsertionListener() {
|
||||||
|
@Override
|
||||||
|
public void informBeforeJobInsertion(Job job, InsertionData data, VehicleRoute route) {
|
||||||
|
firstRecord.add(data.getDeliveryInsertionIndex());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Collection<VehicleRoutingProblemSolution> firstSolutions = vra.searchSolutions();
|
||||||
|
|
||||||
|
// RandomNumberGeneration.reset();
|
||||||
|
VehicleRoutingAlgorithm second = Jsprit.createAlgorithm(vrp);
|
||||||
|
second.setMaxIterations(200);
|
||||||
|
final List<Integer> secondRecord = new ArrayList<Integer>();
|
||||||
|
second.addListener(new BeforeJobInsertionListener() {
|
||||||
|
@Override
|
||||||
|
public void informBeforeJobInsertion(Job job, InsertionData data, VehicleRoute route) {
|
||||||
|
secondRecord.add(data.getDeliveryInsertionIndex());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Collection<VehicleRoutingProblemSolution> secondSolutions = second.searchSolutions();
|
||||||
|
|
||||||
|
Assert.assertEquals(secondRecord.size(),firstRecord.size());
|
||||||
|
for(int i=0;i<firstRecord.size();i++){
|
||||||
|
if(!firstRecord.get(i).equals(secondRecord.get(i))){
|
||||||
|
Assert.assertFalse(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.assertTrue(true);
|
||||||
|
Assert.assertEquals(Solutions.bestOf(firstSolutions).getCost(),Solutions.bestOf(secondSolutions).getCost());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenBiggerProblem_ruinedJobsShouldBeReproducibleWithoutResetingRNGExplicitly(){
|
||||||
|
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||||
|
new VrpXMLReader(vrpBuilder).read("src/test/resources/vrpnc1-jsprit-with-deliveries.xml");
|
||||||
|
VehicleRoutingProblem vrp = vrpBuilder.build();
|
||||||
|
VehicleRoutingAlgorithm vra = Jsprit.createAlgorithm(vrp);
|
||||||
|
vra.setMaxIterations(200);
|
||||||
|
final List<String> firstRecord = new ArrayList<String>();
|
||||||
|
vra.addListener(new RuinListener() {
|
||||||
|
@Override
|
||||||
|
public void ruinStarts(Collection<VehicleRoute> routes) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removed(Job job, VehicleRoute fromRoute) {
|
||||||
|
firstRecord.add(job.getId());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
vra.searchSolutions();
|
||||||
|
|
||||||
|
// RandomNumberGeneration.reset();
|
||||||
|
VehicleRoutingAlgorithm second = Jsprit.createAlgorithm(vrp);
|
||||||
|
second.setMaxIterations(200);
|
||||||
|
final List<String> secondRecord = new ArrayList<String>();
|
||||||
|
second.addListener(new RuinListener() {
|
||||||
|
@Override
|
||||||
|
public void ruinStarts(Collection<VehicleRoute> routes) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ruinEnds(Collection<VehicleRoute> routes, Collection<Job> unassignedJobs) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removed(Job job, VehicleRoute fromRoute) {
|
||||||
|
secondRecord.add(job.getId());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
second.searchSolutions();
|
||||||
|
|
||||||
|
Assert.assertEquals(secondRecord.size(),firstRecord.size());
|
||||||
|
for(int i=0;i<firstRecord.size();i++){
|
||||||
|
if(!firstRecord.get(i).equals(secondRecord.get(i))){
|
||||||
|
Assert.assertFalse(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assert.assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue