mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
fix #156 and separate maxCosts calc from noiseMaker
This commit is contained in:
parent
1ece0e6819
commit
3696f361d3
5 changed files with 46 additions and 59 deletions
|
|
@ -1,80 +1,43 @@
|
||||||
package jsprit.core.algorithm.box;
|
package jsprit.core.algorithm.box;
|
||||||
|
|
||||||
import jsprit.core.algorithm.listener.IterationStartsListener;
|
import jsprit.core.algorithm.listener.IterationStartsListener;
|
||||||
import jsprit.core.problem.Location;
|
|
||||||
import jsprit.core.problem.VehicleRoutingProblem;
|
import jsprit.core.problem.VehicleRoutingProblem;
|
||||||
import jsprit.core.problem.constraint.SoftActivityConstraint;
|
import jsprit.core.problem.constraint.SoftActivityConstraint;
|
||||||
import jsprit.core.problem.job.Job;
|
|
||||||
import jsprit.core.problem.job.Service;
|
|
||||||
import jsprit.core.problem.job.Shipment;
|
|
||||||
import jsprit.core.problem.misc.JobInsertionContext;
|
import jsprit.core.problem.misc.JobInsertionContext;
|
||||||
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
|
||||||
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.RandomNumberGeneration;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by schroeder on 16/01/15.
|
* Created by schroeder on 16/01/15.
|
||||||
*/
|
*/
|
||||||
class InsertionNoiseMaker implements SoftActivityConstraint, IterationStartsListener {
|
class ConcurrentInsertionNoiseMaker implements SoftActivityConstraint, IterationStartsListener {
|
||||||
|
|
||||||
private final double noiseProbability;
|
private final double noiseProbability;
|
||||||
|
|
||||||
private boolean makeNoise = false;
|
private boolean makeNoise = false;
|
||||||
|
|
||||||
private VehicleRoutingProblem vrp;
|
|
||||||
|
|
||||||
double maxCosts = 0.;
|
|
||||||
|
|
||||||
private double noiseLevel = 0.1;
|
private double noiseLevel = 0.1;
|
||||||
|
|
||||||
private Random random = RandomNumberGeneration.newInstance();
|
private Random random = RandomNumberGeneration.newInstance();
|
||||||
|
|
||||||
private Random[] randomArray;
|
private Random[] randomArray;
|
||||||
|
|
||||||
public InsertionNoiseMaker(VehicleRoutingProblem vrp, double noiseLevel, double noiseProbability) {
|
private double maxCosts;
|
||||||
this.vrp = vrp;
|
|
||||||
|
ConcurrentInsertionNoiseMaker(VehicleRoutingProblem vrp, double maxCosts, double noiseLevel, double noiseProbability) {
|
||||||
this.noiseLevel = noiseLevel;
|
this.noiseLevel = noiseLevel;
|
||||||
this.noiseProbability = noiseProbability;
|
this.noiseProbability = noiseProbability;
|
||||||
|
this.maxCosts = maxCosts;
|
||||||
randomArray = new Random[vrp.getNuActivities()+2];
|
randomArray = new Random[vrp.getNuActivities()+2];
|
||||||
for(int i=0;i<randomArray.length;i++){
|
for(int i=0;i<randomArray.length;i++){
|
||||||
Random r = new Random();
|
Random r = new Random();
|
||||||
r.setSeed(random.nextLong());
|
r.setSeed(random.nextLong());
|
||||||
randomArray[i] = r;
|
randomArray[i] = r;
|
||||||
}
|
}
|
||||||
determineMaxCosts(vrp);
|
|
||||||
}
|
|
||||||
|
|
||||||
//@ToDo refactor determining max costs to allow skipping this
|
|
||||||
private void determineMaxCosts(VehicleRoutingProblem vrp) {
|
|
||||||
double max = 0.;
|
|
||||||
for (Job i : vrp.getJobs().values()) {
|
|
||||||
List<Location> fromLocations = getLocations(i);
|
|
||||||
for (Job j : vrp.getJobs().values()) {
|
|
||||||
List<Location> toLocations = getLocations(j);
|
|
||||||
for (Location iLoc : fromLocations) {
|
|
||||||
for (Location jLoc : toLocations) {
|
|
||||||
max = Math.max(max, vrp.getTransportCosts().getTransportCost(iLoc, jLoc, 0, null, vrp.getVehicles().iterator().next()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
maxCosts = max;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Location> getLocations(Job j) {
|
|
||||||
List<Location> locs = new ArrayList<Location>();
|
|
||||||
if (j instanceof Service) {
|
|
||||||
locs.add(((Service) j).getLocation());
|
|
||||||
} else if (j instanceof Shipment) {
|
|
||||||
locs.add(((Shipment) j).getPickupLocation());
|
|
||||||
locs.add(((Shipment) j).getDeliveryLocation());
|
|
||||||
}
|
|
||||||
return locs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -92,7 +55,6 @@ class InsertionNoiseMaker implements SoftActivityConstraint, IterationStartsList
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setRandom(Random random) {
|
public void setRandom(Random random) {
|
||||||
this.random = random;
|
this.random = random;
|
||||||
}
|
}
|
||||||
|
|
@ -308,14 +308,29 @@ public class Jsprit {
|
||||||
constraintManager = new ConstraintManager(vrp, stateManager);
|
constraintManager = new ConstraintManager(vrp, stateManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (noThreads == null) {
|
||||||
|
noThreads = toInteger(getProperty(Parameter.THREADS.toString()));
|
||||||
|
}
|
||||||
|
if (noThreads > 1) {
|
||||||
|
if (es == null) {
|
||||||
|
setupExecutorInternally = true;
|
||||||
|
es = Executors.newFixedThreadPool(noThreads);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
|
||||||
noiseMaker.setRandom(random);
|
|
||||||
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();
|
||||||
|
final double maxCosts = jobNeighborhoods.getMaxDistance();
|
||||||
|
|
||||||
|
IterationStartsListener noiseConfigurator;
|
||||||
|
|
||||||
|
ConcurrentInsertionNoiseMaker noiseMaker = new ConcurrentInsertionNoiseMaker(vrp, maxCosts, noiseLevel, noiseProbability);
|
||||||
|
noiseMaker.setRandom(random);
|
||||||
|
constraintManager.addConstraint(noiseMaker);
|
||||||
|
noiseConfigurator = noiseMaker;
|
||||||
|
|
||||||
RuinRadial radial = new RuinRadial(vrp, vrp.getJobs().size(), jobNeighborhoods);
|
RuinRadial radial = new RuinRadial(vrp, vrp.getJobs().size(), jobNeighborhoods);
|
||||||
radial.setRandom(random);
|
radial.setRandom(random);
|
||||||
|
|
@ -356,7 +371,7 @@ public class Jsprit {
|
||||||
public double makeNoise() {
|
public double makeNoise() {
|
||||||
if (random.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 * random.nextDouble();
|
* maxCosts * random.nextDouble();
|
||||||
} else return 0.;
|
} else return 0.;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -373,15 +388,7 @@ public class Jsprit {
|
||||||
|
|
||||||
AbstractInsertionStrategy regret;
|
AbstractInsertionStrategy regret;
|
||||||
final RegretInsertion.DefaultScorer scorer;
|
final RegretInsertion.DefaultScorer scorer;
|
||||||
if (noThreads == null) {
|
|
||||||
noThreads = toInteger(getProperty(Parameter.THREADS.toString()));
|
|
||||||
}
|
|
||||||
if (noThreads > 1) {
|
|
||||||
if (es == null) {
|
|
||||||
setupExecutorInternally = true;
|
|
||||||
es = Executors.newFixedThreadPool(noThreads);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (es != null) {
|
if (es != null) {
|
||||||
RegretInsertionConcurrent regretInsertion = (RegretInsertionConcurrent) new InsertionBuilder(vrp, fm, stateManager, constraintManager)
|
RegretInsertionConcurrent regretInsertion = (RegretInsertionConcurrent) new InsertionBuilder(vrp, fm, stateManager, constraintManager)
|
||||||
.setInsertionStrategy(InsertionBuilder.Strategy.REGRET)
|
.setInsertionStrategy(InsertionBuilder.Strategy.REGRET)
|
||||||
|
|
@ -434,7 +441,7 @@ public class Jsprit {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
SolutionCostCalculator objectiveFunction = getObjectiveFunction(vrp, noiseMaker.maxCosts);
|
SolutionCostCalculator objectiveFunction = getObjectiveFunction(vrp, maxCosts);
|
||||||
SearchStrategy radial_regret = new SearchStrategy(Strategy.RADIAL_REGRET.toString(), new SelectBest(), schrimpfAcceptance, objectiveFunction);
|
SearchStrategy radial_regret = new SearchStrategy(Strategy.RADIAL_REGRET.toString(), new SelectBest(), schrimpfAcceptance, objectiveFunction);
|
||||||
radial_regret.addModule(new RuinAndRecreateModule(Strategy.RADIAL_REGRET.toString(), regret, radial));
|
radial_regret.addModule(new RuinAndRecreateModule(Strategy.RADIAL_REGRET.toString(), regret, radial));
|
||||||
|
|
||||||
|
|
@ -482,7 +489,7 @@ public class Jsprit {
|
||||||
|
|
||||||
VehicleRoutingAlgorithm vra = prettyBuilder.build();
|
VehicleRoutingAlgorithm vra = prettyBuilder.build();
|
||||||
vra.addListener(schrimpfThreshold);
|
vra.addListener(schrimpfThreshold);
|
||||||
vra.addListener(noiseMaker);
|
vra.addListener(noiseConfigurator);
|
||||||
vra.addListener(noise);
|
vra.addListener(noise);
|
||||||
vra.addListener(clusters);
|
vra.addListener(clusters);
|
||||||
handleExecutorShutdown(vra);
|
handleExecutorShutdown(vra);
|
||||||
|
|
|
||||||
|
|
@ -13,4 +13,6 @@ public interface JobNeighborhoods {
|
||||||
|
|
||||||
public void initialise();
|
public void initialise();
|
||||||
|
|
||||||
|
public double getMaxDistance();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ class JobNeighborhoodsImpl implements JobNeighborhoods {
|
||||||
|
|
||||||
private JobDistance jobDistance;
|
private JobDistance jobDistance;
|
||||||
|
|
||||||
|
private double maxDistance = 0.;
|
||||||
|
|
||||||
public JobNeighborhoodsImpl(VehicleRoutingProblem vrp, JobDistance jobDistance) {
|
public JobNeighborhoodsImpl(VehicleRoutingProblem vrp, JobDistance jobDistance) {
|
||||||
super();
|
super();
|
||||||
this.vrp = vrp;
|
this.vrp = vrp;
|
||||||
|
|
@ -58,6 +60,11 @@ class JobNeighborhoodsImpl implements JobNeighborhoods {
|
||||||
calculateDistancesFromJob2Job();
|
calculateDistancesFromJob2Job();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getMaxDistance() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
private void calculateDistancesFromJob2Job() {
|
private void calculateDistancesFromJob2Job() {
|
||||||
logger.debug("preprocess distances between locations ...");
|
logger.debug("preprocess distances between locations ...");
|
||||||
StopWatch stopWatch = new StopWatch();
|
StopWatch stopWatch = new StopWatch();
|
||||||
|
|
@ -79,6 +86,7 @@ class JobNeighborhoodsImpl implements JobNeighborhoods {
|
||||||
for (Job j : vrp.getJobs().values()) {
|
for (Job j : vrp.getJobs().values()) {
|
||||||
if (i == j) continue;
|
if (i == j) continue;
|
||||||
double distance = jobDistance.getDistance(i, j);
|
double distance = jobDistance.getDistance(i, j);
|
||||||
|
if(distance > maxDistance) maxDistance = distance;
|
||||||
ReferencedJob refNode = new ReferencedJob(j, distance);
|
ReferencedJob refNode = new ReferencedJob(j, distance);
|
||||||
treeSet.add(refNode);
|
treeSet.add(refNode);
|
||||||
nuOfDistancesStored++;
|
nuOfDistancesStored++;
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,14 @@ class JobNeighborhoodsImplWithCapRestriction implements JobNeighborhoods {
|
||||||
|
|
||||||
private int capacity;
|
private int capacity;
|
||||||
|
|
||||||
|
private double maxDistance = 0.;
|
||||||
|
|
||||||
public JobNeighborhoodsImplWithCapRestriction(VehicleRoutingProblem vrp, JobDistance jobDistance, int capacity) {
|
public JobNeighborhoodsImplWithCapRestriction(VehicleRoutingProblem vrp, JobDistance jobDistance, int capacity) {
|
||||||
super();
|
super();
|
||||||
this.vrp = vrp;
|
this.vrp = vrp;
|
||||||
this.jobDistance = jobDistance;
|
this.jobDistance = jobDistance;
|
||||||
this.capacity = capacity;
|
this.capacity = capacity;
|
||||||
logger.debug("intialise {}", this);
|
logger.debug("initialize {}", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -64,6 +66,11 @@ class JobNeighborhoodsImplWithCapRestriction implements JobNeighborhoods {
|
||||||
calculateDistancesFromJob2Job();
|
calculateDistancesFromJob2Job();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getMaxDistance() {
|
||||||
|
return maxDistance;
|
||||||
|
}
|
||||||
|
|
||||||
private void calculateDistancesFromJob2Job() {
|
private void calculateDistancesFromJob2Job() {
|
||||||
logger.debug("preprocess distances between locations ...");
|
logger.debug("preprocess distances between locations ...");
|
||||||
StopWatch stopWatch = new StopWatch();
|
StopWatch stopWatch = new StopWatch();
|
||||||
|
|
@ -85,6 +92,7 @@ class JobNeighborhoodsImplWithCapRestriction implements JobNeighborhoods {
|
||||||
for (Job j : vrp.getJobs().values()) {
|
for (Job j : vrp.getJobs().values()) {
|
||||||
if (i == j) continue;
|
if (i == j) continue;
|
||||||
double distance = jobDistance.getDistance(i, j);
|
double distance = jobDistance.getDistance(i, j);
|
||||||
|
if(distance > maxDistance) maxDistance = distance;
|
||||||
ReferencedJob refNode = new ReferencedJob(j, distance);
|
ReferencedJob refNode = new ReferencedJob(j, distance);
|
||||||
if (treeSet.size() < capacity) {
|
if (treeSet.size() < capacity) {
|
||||||
treeSet.add(refNode);
|
treeSet.add(refNode);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue