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:
parent
cebbe3a60d
commit
600e29f353
3 changed files with 76 additions and 125 deletions
|
|
@ -184,7 +184,6 @@ public class RegretInsertion extends AbstractInsertionStrategy {
|
||||||
|
|
||||||
private JobInsertionCostsCalculator insertionCostsCalculator;
|
private JobInsertionCostsCalculator insertionCostsCalculator;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the scoring function.
|
* Sets the scoring function.
|
||||||
*
|
*
|
||||||
|
|
@ -242,9 +241,23 @@ 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) {
|
||||||
|
ScoredJob scoredJob = getScoredJob(routes,unassignedJob,insertionCostsCalculator,scoringFunction);
|
||||||
|
if(scoredJob instanceof BadJob){
|
||||||
|
badJobs.add(unassignedJob);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(bestScoredJob == null) bestScoredJob = scoredJob;
|
||||||
|
else{
|
||||||
|
if(scoredJob.getScore() > bestScoredJob.getScore()){
|
||||||
|
bestScoredJob = scoredJob;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bestScoredJob;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ScoredJob getScoredJob(Collection<VehicleRoute> routes, Job unassignedJob, JobInsertionCostsCalculator insertionCostsCalculator, ScoringFunction scoringFunction) {
|
||||||
InsertionData best = null;
|
InsertionData best = null;
|
||||||
InsertionData secondBest = null;
|
InsertionData secondBest = null;
|
||||||
VehicleRoute bestRoute = null;
|
VehicleRoute bestRoute = null;
|
||||||
|
|
@ -271,7 +284,6 @@ public class RegretInsertion extends AbstractInsertionStrategy {
|
||||||
VehicleRoute emptyRoute = VehicleRoute.emptyRoute();
|
VehicleRoute emptyRoute = VehicleRoute.emptyRoute();
|
||||||
InsertionData iData = insertionCostsCalculator.getInsertionData(emptyRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, benchmark);
|
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 (!(iData instanceof InsertionData.NoInsertionFound)) {
|
||||||
// iData = new InsertionData(iData.getInsertionCost()*1000.,iData.getPickupInsertionIndex(),iData.getDeliveryInsertionIndex(),iData.getSelectedVehicle(),iData.getSelectedDriver());
|
|
||||||
if (best == null) {
|
if (best == null) {
|
||||||
best = iData;
|
best = iData;
|
||||||
bestRoute = emptyRoute;
|
bestRoute = emptyRoute;
|
||||||
|
|
@ -284,26 +296,27 @@ public class RegretInsertion extends AbstractInsertionStrategy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(best == null){
|
if(best == null){
|
||||||
badJobs.add(unassignedJob);
|
return new RegretInsertion.BadJob(unassignedJob);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
double score = score(unassignedJob, best, secondBest);
|
double score = score(unassignedJob, best, secondBest, scoringFunction);
|
||||||
if (score > bestScore) {
|
ScoredJob scoredJob;
|
||||||
if(bestRoute == emptyRoute){
|
if(bestRoute == emptyRoute){
|
||||||
bestScoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, true);
|
scoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, true);
|
||||||
}
|
}
|
||||||
else bestScoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, false);
|
else scoredJob = new ScoredJob(unassignedJob, score, best, bestRoute, false);
|
||||||
bestScore = score;
|
return scoredJob;
|
||||||
}
|
|
||||||
}
|
|
||||||
return bestScoredJob;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private double score(Job unassignedJob, InsertionData best, InsertionData secondBest) {
|
static double score(Job unassignedJob, InsertionData best, InsertionData secondBest, ScoringFunction scoringFunction) {
|
||||||
|
if(best == null){
|
||||||
|
throw new IllegalStateException("cannot insert job " + unassignedJob.getId());
|
||||||
|
}
|
||||||
double score;
|
double score;
|
||||||
if(secondBest == null){
|
if(secondBest == null){ //either there is only one vehicle or there are more vehicles, but they cannot load unassignedJob
|
||||||
score = best.getInsertionCost() + scoringFunction.score(best,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{
|
else{
|
||||||
score = (secondBest.getInsertionCost()-best.getInsertionCost()) + scoringFunction.score(best, unassignedJob);
|
score = (secondBest.getInsertionCost()-best.getInsertionCost()) + scoringFunction.score(best, unassignedJob);
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,6 @@ public class RegretInsertionConcurrent extends AbstractInsertionStrategy {
|
||||||
|
|
||||||
private final ExecutorCompletionService<ScoredJob> completionService;
|
private final ExecutorCompletionService<ScoredJob> completionService;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the scoring function.
|
* Sets the scoring function.
|
||||||
*
|
*
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue