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;
/**
/**
* Sets the scoring function.
*
* <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) {
ScoredJob bestScoredJob = null;
double bestScore = -1 * Double.MAX_VALUE;
for (Job unassignedJob : unassignedJobList) {
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){
ScoredJob scoredJob = getScoredJob(routes,unassignedJob,insertionCostsCalculator,scoringFunction);
if(scoredJob instanceof BadJob){
badJobs.add(unassignedJob);
continue;
}
double score = score(unassignedJob, best, secondBest);
if (score > bestScore) {
if(bestRoute == emptyRoute){
bestScoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, true);
if(bestScoredJob == null) bestScoredJob = scoredJob;
else{
if(scoredJob.getScore() > bestScoredJob.getScore()){
bestScoredJob = scoredJob;
}
else bestScoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, false);
bestScore = score;
}
}
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 score;
if(secondBest == null){
score = best.getInsertionCost() + scoringFunction.score(best,unassignedJob);
}
else{
score = (secondBest.getInsertionCost()-best.getInsertionCost()) + scoringFunction.score(best,unassignedJob);
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;
}
}
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;
/**
/**
* Sets the scoring function.
*
* <p>By default, the this.TimeWindowScorer is used.
@ -118,7 +117,7 @@ public class RegretInsertionConcurrent extends AbstractInsertionStrategy {
@Override
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;
}
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);
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>();
CkeckJobSequence position = new CkeckJobSequence(1, s1);
CkeckJobSequence position = new CkeckJobSequence(2, s1);
regretInsertion.addListener(position);
regretInsertion.insertJobs(routes,vrp.getJobs().values());
Assert.assertTrue(position.isCorrect());
@ -109,7 +109,7 @@ public class RegretInsertionTest {
RegretInsertion regretInsertion = new RegretInsertion(calculator,vrp);
Collection<VehicleRoute> routes = new ArrayList<VehicleRoute>();
CkeckJobSequence position = new CkeckJobSequence(1, s2);
CkeckJobSequence position = new CkeckJobSequence(2, s2);
regretInsertion.addListener(position);
regretInsertion.insertJobs(routes,vrp.getJobs().values());
Assert.assertTrue(position.isCorrect());