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

mod regret insertion

This commit is contained in:
oblonski 2014-11-28 10:29:09 +01:00
parent cebbe3a60d
commit 600e29f353
3 changed files with 76 additions and 125 deletions

View file

@ -184,8 +184,7 @@ public class RegretInsertion extends AbstractInsertionStrategy {
private JobInsertionCostsCalculator insertionCostsCalculator; private JobInsertionCostsCalculator insertionCostsCalculator;
/**
/**
* Sets the scoring function. * Sets the scoring function.
* *
* <p>By default, the this.TimeWindowScorer is used. * <p>By default, the this.TimeWindowScorer is used.
@ -242,73 +241,87 @@ public class RegretInsertion extends AbstractInsertionStrategy {
private ScoredJob nextJob(Collection<VehicleRoute> routes, List<Job> unassignedJobList, List<Job> badJobs) { private ScoredJob nextJob(Collection<VehicleRoute> routes, List<Job> unassignedJobList, List<Job> badJobs) {
ScoredJob bestScoredJob = null; ScoredJob bestScoredJob = null;
double bestScore = -1 * Double.MAX_VALUE;
for (Job unassignedJob : unassignedJobList) { for (Job unassignedJob : unassignedJobList) {
InsertionData best = null; ScoredJob scoredJob = getScoredJob(routes,unassignedJob,insertionCostsCalculator,scoringFunction);
InsertionData secondBest = null; if(scoredJob instanceof BadJob){
VehicleRoute bestRoute = null;
double benchmark = Double.MAX_VALUE;
for (VehicleRoute route : routes) {
if (secondBest != null) {
benchmark = secondBest.getInsertionCost();
}
InsertionData iData = insertionCostsCalculator.getInsertionData(route, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, benchmark);
if (iData instanceof InsertionData.NoInsertionFound) continue;
if (best == null) {
best = iData;
bestRoute = route;
} else if (iData.getInsertionCost() < best.getInsertionCost()) {
secondBest = best;
best = iData;
bestRoute = route;
} else if (secondBest == null || (iData.getInsertionCost() < secondBest.getInsertionCost())) {
secondBest = iData;
}
}
VehicleRoute emptyRoute = VehicleRoute.emptyRoute();
InsertionData iData = insertionCostsCalculator.getInsertionData(emptyRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, benchmark);
if (!(iData instanceof InsertionData.NoInsertionFound)) {
// iData = new InsertionData(iData.getInsertionCost()*1000.,iData.getPickupInsertionIndex(),iData.getDeliveryInsertionIndex(),iData.getSelectedVehicle(),iData.getSelectedDriver());
if (best == null) {
best = iData;
bestRoute = emptyRoute;
} else if (iData.getInsertionCost() < best.getInsertionCost()) {
secondBest = best;
best = iData;
bestRoute = emptyRoute;
} else if (secondBest == null || (iData.getInsertionCost() < secondBest.getInsertionCost())) {
secondBest = iData;
}
}
if(best == null){
badJobs.add(unassignedJob); badJobs.add(unassignedJob);
continue; continue;
} }
double score = score(unassignedJob, best, secondBest); if(bestScoredJob == null) bestScoredJob = scoredJob;
if (score > bestScore) { else{
if(bestRoute == emptyRoute){ if(scoredJob.getScore() > bestScoredJob.getScore()){
bestScoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, true); bestScoredJob = scoredJob;
} }
else bestScoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, false);
bestScore = score;
} }
} }
return bestScoredJob; return bestScoredJob;
} }
static ScoredJob getScoredJob(Collection<VehicleRoute> routes, Job unassignedJob, JobInsertionCostsCalculator insertionCostsCalculator, ScoringFunction scoringFunction) {
InsertionData best = null;
InsertionData secondBest = null;
VehicleRoute bestRoute = null;
private double score(Job unassignedJob, InsertionData best, InsertionData secondBest) { double benchmark = Double.MAX_VALUE;
double score; for (VehicleRoute route : routes) {
if(secondBest == null){ if (secondBest != null) {
score = best.getInsertionCost() + scoringFunction.score(best,unassignedJob); benchmark = secondBest.getInsertionCost();
} }
else{ InsertionData iData = insertionCostsCalculator.getInsertionData(route, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, benchmark);
score = (secondBest.getInsertionCost()-best.getInsertionCost()) + scoringFunction.score(best,unassignedJob); if (iData instanceof InsertionData.NoInsertionFound) continue;
if (best == null) {
best = iData;
bestRoute = route;
} else if (iData.getInsertionCost() < best.getInsertionCost()) {
secondBest = best;
best = iData;
bestRoute = route;
} else if (secondBest == null || (iData.getInsertionCost() < secondBest.getInsertionCost())) {
secondBest = iData;
}
} }
return score;
VehicleRoute emptyRoute = VehicleRoute.emptyRoute();
InsertionData iData = insertionCostsCalculator.getInsertionData(emptyRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, benchmark);
if (!(iData instanceof InsertionData.NoInsertionFound)) {
if (best == null) {
best = iData;
bestRoute = emptyRoute;
} else if (iData.getInsertionCost() < best.getInsertionCost()) {
secondBest = best;
best = iData;
bestRoute = emptyRoute;
} else if (secondBest == null || (iData.getInsertionCost() < secondBest.getInsertionCost())) {
secondBest = iData;
}
}
if(best == null){
return new RegretInsertion.BadJob(unassignedJob);
}
double score = score(unassignedJob, best, secondBest, scoringFunction);
ScoredJob scoredJob;
if(bestRoute == emptyRoute){
scoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, true);
}
else scoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, false);
return scoredJob;
}
static double score(Job unassignedJob, InsertionData best, InsertionData secondBest, ScoringFunction scoringFunction) {
if(best == null){
throw new IllegalStateException("cannot insert job " + unassignedJob.getId());
}
double score;
if(secondBest == null){ //either there is only one vehicle or there are more vehicles, but they cannot load unassignedJob
//if only one vehicle, I want the job to be inserted with min iCosts
//if there are more vehicles, I want this job to be prioritized since there are no alternatives
score = Integer.MAX_VALUE - best.getInsertionCost() + scoringFunction.score(best, unassignedJob);
}
else{
score = (secondBest.getInsertionCost()-best.getInsertionCost()) + scoringFunction.score(best, unassignedJob);
}
return score;
} }

View file

@ -53,8 +53,7 @@ public class RegretInsertionConcurrent extends AbstractInsertionStrategy {
private final ExecutorCompletionService<ScoredJob> completionService; private final ExecutorCompletionService<ScoredJob> completionService;
/**
/**
* Sets the scoring function. * Sets the scoring function.
* *
* <p>By default, the this.TimeWindowScorer is used. * <p>By default, the this.TimeWindowScorer is used.
@ -118,7 +117,7 @@ public class RegretInsertionConcurrent extends AbstractInsertionStrategy {
@Override @Override
public ScoredJob call() throws Exception { public ScoredJob call() throws Exception {
return getScoredJob(routes, unassignedJob); return RegretInsertion.getScoredJob(routes, unassignedJob, insertionCostsCalculator, scoringFunction);
} }
}); });
@ -152,71 +151,10 @@ public class RegretInsertionConcurrent extends AbstractInsertionStrategy {
return bestScoredJob; return bestScoredJob;
} }
private ScoredJob getScoredJob(Collection<VehicleRoute> routes, Job unassignedJob) {
InsertionData best = null;
InsertionData secondBest = null;
VehicleRoute bestRoute = null;
double benchmark = Double.MAX_VALUE;
for (VehicleRoute route : routes) {
if (secondBest != null) {
benchmark = secondBest.getInsertionCost();
}
InsertionData iData = insertionCostsCalculator.getInsertionData(route, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, benchmark);
if (iData instanceof InsertionData.NoInsertionFound) continue;
if (best == null) {
best = iData;
bestRoute = route;
} else if (iData.getInsertionCost() < best.getInsertionCost()) {
secondBest = best;
best = iData;
bestRoute = route;
} else if (secondBest == null || (iData.getInsertionCost() < secondBest.getInsertionCost())) {
secondBest = iData;
}
}
VehicleRoute emptyRoute = VehicleRoute.emptyRoute();
InsertionData iData = insertionCostsCalculator.getInsertionData(emptyRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, benchmark);
if (!(iData instanceof InsertionData.NoInsertionFound)) {
// iData = new InsertionData(iData.getInsertionCost()*1000.,iData.getPickupInsertionIndex(),iData.getDeliveryInsertionIndex(),iData.getSelectedVehicle(),iData.getSelectedDriver());
if (best == null) {
best = iData;
bestRoute = emptyRoute;
} else if (iData.getInsertionCost() < best.getInsertionCost()) {
secondBest = best;
best = iData;
bestRoute = emptyRoute;
} else if (secondBest == null || (iData.getInsertionCost() < secondBest.getInsertionCost())) {
secondBest = iData;
}
}
if(best == null){
return new RegretInsertion.BadJob(unassignedJob);
}
double score = score(unassignedJob, best, secondBest);
ScoredJob scoredJob;
if(bestRoute == emptyRoute){
scoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, true);
}
else scoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, false);
return scoredJob;
}
private double score(Job unassignedJob, InsertionData best, InsertionData secondBest) {
if(best == null){
throw new IllegalStateException("cannot insert job " + unassignedJob.getId());
}
double score;
if(secondBest == null){
score = best.getInsertionCost() + scoringFunction.score(best,unassignedJob);
}
else{
score = (secondBest.getInsertionCost()-best.getInsertionCost()) + scoringFunction.score(best,unassignedJob);
}
return score;
}
} }

View file

@ -80,7 +80,7 @@ public class RegretInsertionTest {
RegretInsertion regretInsertion = new RegretInsertion(calculator,vrp); RegretInsertion regretInsertion = new RegretInsertion(calculator,vrp);
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>(); Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>();
CkeckJobSequence position = new CkeckJobSequence(1, s1); CkeckJobSequence position = new CkeckJobSequence(2, s1);
regretInsertion.addListener(position); regretInsertion.addListener(position);
regretInsertion.insertJobs(routes,vrp.getJobs().values()); regretInsertion.insertJobs(routes,vrp.getJobs().values());
Assert.assertTrue(position.isCorrect()); Assert.assertTrue(position.isCorrect());
@ -109,7 +109,7 @@ public class RegretInsertionTest {
RegretInsertion regretInsertion = new RegretInsertion(calculator,vrp); RegretInsertion regretInsertion = new RegretInsertion(calculator,vrp);
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>(); Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>();
CkeckJobSequence position = new CkeckJobSequence(1, s2); CkeckJobSequence position = new CkeckJobSequence(2, s2);
regretInsertion.addListener(position); regretInsertion.addListener(position);
regretInsertion.insertJobs(routes,vrp.getJobs().values()); regretInsertion.insertJobs(routes,vrp.getJobs().values());
Assert.assertTrue(position.isCorrect()); Assert.assertTrue(position.isCorrect());