diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/RegretInsertion.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/RegretInsertion.java
index c7736e86..9bafffd1 100644
--- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/RegretInsertion.java
+++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/RegretInsertion.java
@@ -27,10 +27,7 @@ import jsprit.core.problem.solution.route.VehicleRoute;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
/**
* Insertion based on regret approach.
@@ -185,6 +182,33 @@ public class RegretInsertion extends AbstractInsertionStrategy {
}
+ static class VersionedInsertionData {
+
+ private InsertionData iData;
+
+ private VehicleRoute route;
+
+ private int version;
+
+ public VersionedInsertionData(InsertionData iData, int version, VehicleRoute route) {
+ this.iData = iData;
+ this.version = version;
+ this.route = route;
+ }
+
+ public InsertionData getiData() {
+ return iData;
+ }
+
+ public int getVersion() {
+ return version;
+ }
+
+ public VehicleRoute getRoute() {
+ return route;
+ }
+ }
+
private static Logger logger = LogManager.getLogger(RegretInsertion.class);
private ScoringFunction scoringFunction;
@@ -192,6 +216,7 @@ public class RegretInsertion extends AbstractInsertionStrategy {
private JobInsertionCostsCalculator insertionCostsCalculator;
+
/**
* Sets the scoring function.
*
@@ -247,17 +272,35 @@ public class RegretInsertion extends AbstractInsertionStrategy {
}
List jobs = new ArrayList(unassignedJobs);
+ PriorityQueue[] priorityQueues = new PriorityQueue[vrp.getJobs().values().size() + 2];
+ VehicleRoute lastModified = null;
+ boolean firstRun = true;
+ int updateRound = 0;
+ Map updates = new HashMap();
while (!jobs.isEmpty()) {
List unassignedJobList = new ArrayList(jobs);
List badJobList = new ArrayList();
- ScoredJob bestScoredJob = nextJob(routes, unassignedJobList, badJobList);
+ if(firstRun){
+ firstRun = false;
+ updateInsertionData(priorityQueues, routes, unassignedJobList, badJobList, updateRound, updates);
+ }
+ else{
+ updateInsertionData(priorityQueues, Arrays.asList(lastModified), unassignedJobList, badJobList, updateRound, updates);
+ }
+ updateRound++;
+ ScoredJob bestScoredJob = getBest(priorityQueues,updates,unassignedJobList,badJobList);
+// InsertionData d = insertionCostsCalculator.getInsertionData(bestScoredJob.getRoute(), bestScoredJob.getJob(), NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE);
+//
+// ScoredJob bestScoredJob = nextJob(routes, unassignedJobList, badJobList);
if (bestScoredJob != null) {
if (bestScoredJob.isNewRoute()) {
routes.add(bestScoredJob.getRoute());
}
insertJob(bestScoredJob.getJob(), bestScoredJob.getInsertionData(), bestScoredJob.getRoute());
jobs.remove(bestScoredJob.getJob());
+ lastModified = bestScoredJob.getRoute();
}
+ else throw new IllegalStateException("fooo");
for (Job bad : badJobList) {
jobs.remove(bad);
badJobs.add(bad);
@@ -266,6 +309,106 @@ public class RegretInsertion extends AbstractInsertionStrategy {
return badJobs;
}
+ private ScoredJob getBest(PriorityQueue[] priorityQueues, Map updates, List unassignedJobList, List badJobs) {
+ ScoredJob bestScoredJob = null;
+ for(Job j : unassignedJobList){
+ VehicleRoute bestRoute = null;
+ InsertionData best = null;
+ InsertionData secondBest = null;
+ PriorityQueue priorityQueue = priorityQueues[j.getIndex()];
+ Iterator iterator = priorityQueue.iterator();
+ while(iterator.hasNext()){
+ VersionedInsertionData versionedIData = iterator.next();
+ if(versionedIData.getiData() instanceof InsertionData.NoInsertionFound) continue;
+ int currentDataVersion = updates.get(versionedIData.getRoute());
+ if(versionedIData.getVersion() == currentDataVersion){
+ if(best == null) {
+ best = versionedIData.getiData();
+ bestRoute = versionedIData.getRoute();
+ }
+ else {
+ secondBest = versionedIData.getiData();
+ break;
+ }
+ }
+ }
+ VehicleRoute emptyRoute = VehicleRoute.emptyRoute();
+ InsertionData iData = insertionCostsCalculator.getInsertionData(emptyRoute, j, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE);
+ 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) {
+ badJobs.add(j);
+ continue;
+ }
+ double score = score(j, best, secondBest, scoringFunction);
+ ScoredJob scoredJob;
+ if (bestRoute == emptyRoute) {
+ scoredJob = new ScoredJob(j, score, best, bestRoute, true);
+ } else scoredJob = new ScoredJob(j, score, best, bestRoute, false);
+
+ if(bestScoredJob == null){
+ bestScoredJob = scoredJob;
+ }
+ else if(scoredJob.getScore() > bestScoredJob.getScore()){
+ bestScoredJob = scoredJob;
+ }
+ }
+ return bestScoredJob;
+ }
+
+ private Comparator getComparator(){
+ return new Comparator() {
+ @Override
+ public int compare(VersionedInsertionData o1, VersionedInsertionData o2) {
+ if(o1.getiData().getInsertionCost() < o2.getiData().getInsertionCost()) return -1;
+ return 1;
+ }
+ };
+ }
+
+ private void updateInsertionData(PriorityQueue[] priorityQueues, Collection routes, List unassignedJobList, List badJobList, int updateRound, Map updates) {
+ for (Job unassignedJob : unassignedJobList) {
+ if(priorityQueues[unassignedJob.getIndex()] == null){
+ priorityQueues[unassignedJob.getIndex()] = new PriorityQueue(unassignedJobList.size(), getComparator());
+ }
+ for(VehicleRoute route : routes) {
+
+ InsertionData iData = insertionCostsCalculator.getInsertionData(route, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, Double.MAX_VALUE);
+ priorityQueues[unassignedJob.getIndex()].add(new VersionedInsertionData(iData,updateRound,route));
+ updates.put(route,updateRound);
+ }
+
+//
+//
+//
+// 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;
+// } else if (scoredJob.getScore() == bestScoredJob.getScore()) {
+// if (scoredJob.getJob().getId().compareTo(bestScoredJob.getJob().getId()) <= 0) {
+// bestScoredJob = scoredJob;
+// }
+// }
+// }
+ }
+ }
+
private VehicleRoute findRoute(Collection routes, Job job) {
for(VehicleRoute r : routes){
if(r.getVehicle().getBreak() == job) return r;
diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/VehicleTypeDependentJobInsertionCalculator.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/VehicleTypeDependentJobInsertionCalculator.java
index dcf57359..6dc17a48 100644
--- a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/VehicleTypeDependentJobInsertionCalculator.java
+++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/VehicleTypeDependentJobInsertionCalculator.java
@@ -93,6 +93,9 @@ final class VehicleTypeDependentJobInsertionCalculator implements JobInsertionCo
}
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle vehicle, double newVehicleDepartureTime, final Driver driver, final double bestKnownCost) {
+ if(vehicle != null){
+ return insertionCalculator.getInsertionData(currentRoute, jobToInsert, vehicle, newVehicleDepartureTime, driver, bestKnownCost);
+ }
Vehicle selectedVehicle = currentRoute.getVehicle();
Driver selectedDriver = currentRoute.getDriver();
InsertionData bestIData = InsertionData.createEmptyInsertionData();
@@ -122,6 +125,10 @@ final class VehicleTypeDependentJobInsertionCalculator implements JobInsertionCo
return bestIData;
}
+ VehicleFleetManager getFleetManager(){
+ return fleetManager;
+ }
+
private boolean isVehicleWithInitialRoute(Vehicle selectedVehicle) {
return initialVehicleIds.contains(selectedVehicle.getId());
}