Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UnassignedJobReasonTracker improvement #364

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.graphhopper.jsprit.core.problem.constraint.HardRouteConstraint;
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
import com.graphhopper.jsprit.core.util.FailedConstraintInfo;

import java.util.ArrayList;
import java.util.Collection;
Expand All @@ -38,24 +39,34 @@ InsertionData checkRouteContraints(JobInsertionContext insertionContext, Constra
for (HardRouteConstraint hardRouteConstraint : constraintManager.getHardRouteConstraints()) {
if (!hardRouteConstraint.fulfilled(insertionContext)) {
InsertionData emptyInsertionData = new InsertionData.NoInsertionFound();
emptyInsertionData.addFailedConstrainName(hardRouteConstraint.getClass().getSimpleName());
emptyInsertionData.addFailedConstrainInfo(FailedConstraintInfo.Builder.newInstance()
.setFailedConstraint(hardRouteConstraint.getClass().getSimpleName())
.loadInsertionContextData(insertionContext)
.build()
);
return emptyInsertionData;
}
}
return null;
}

ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime, Collection<String> failedActivityConstraints, ConstraintManager constraintManager) {
ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime, Collection<FailedConstraintInfo> failedActivityConstraints, ConstraintManager constraintManager) {
ConstraintsStatus notFulfilled = null;
List<String> failed = new ArrayList<>();
List<FailedConstraintInfo> failed = new ArrayList<>();
for (HardActivityConstraint c : constraintManager.getCriticalHardActivityConstraints()) {
ConstraintsStatus status = c.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime);
if (status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)) {
failedActivityConstraints.add(c.getClass().getSimpleName());
failedActivityConstraints.add(FailedConstraintInfo.Builder.newInstance()
.setFailedConstraint(c.getClass().getSimpleName())
.loadInsertionContextData(iFacts).build()
);
return status;
} else {
if (status.equals(ConstraintsStatus.NOT_FULFILLED)) {
failed.add(c.getClass().getSimpleName());
failed.add(FailedConstraintInfo.Builder.newInstance()
.setFailedConstraint(c.getClass().getSimpleName())
.loadInsertionContextData(iFacts).build()
);
notFulfilled = status;
}
}
Expand All @@ -68,11 +79,17 @@ ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, To
for (HardActivityConstraint c : constraintManager.getHighPrioHardActivityConstraints()) {
ConstraintsStatus status = c.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime);
if (status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK)) {
failedActivityConstraints.add(c.getClass().getSimpleName());
failedActivityConstraints.add(FailedConstraintInfo.Builder.newInstance()
.setFailedConstraint(c.getClass().getSimpleName())
.loadInsertionContextData(iFacts).build()
);
return status;
} else {
if (status.equals(ConstraintsStatus.NOT_FULFILLED)) {
failed.add(c.getClass().getSimpleName());
failed.add(FailedConstraintInfo.Builder.newInstance()
.setFailedConstraint(c.getClass().getSimpleName())
.loadInsertionContextData(iFacts).build()
);
notFulfilled = status;
}
}
Expand All @@ -85,7 +102,10 @@ ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, To
for (HardActivityConstraint constraint : constraintManager.getLowPrioHardActivityConstraints()) {
ConstraintsStatus status = constraint.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime);
if (status.equals(ConstraintsStatus.NOT_FULFILLED_BREAK) || status.equals(ConstraintsStatus.NOT_FULFILLED)) {
failedActivityConstraints.add(constraint.getClass().getSimpleName());
failedActivityConstraints.add(FailedConstraintInfo.Builder.newInstance()
.setFailedConstraint(constraint.getClass().getSimpleName())
.loadInsertionContextData(iFacts).build()
);
return status;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.graphhopper.jsprit.core.problem.job.Job;
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
import com.graphhopper.jsprit.core.util.FailedConstraintInfo;
import com.graphhopper.jsprit.core.util.RandomNumberGeneration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -93,8 +94,8 @@ public Collection<Job> insertJobs(Collection<VehicleRoute> vehicleRoutes, Collec
return badJobs;
}

public void markUnassigned(Job unassigned, List<String> reasons) {
insertionsListeners.informJobUnassignedListeners(unassigned, reasons);
public void markUnassigned(Job unassigned, List<FailedConstraintInfo> failedConstraints) {
insertionsListeners.informJobUnassignedListeners(unassigned, failedConstraints);
}

public abstract Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> vehicleRoutes, Collection<Job> unassignedJobs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> vehicleRout
for (VehicleRoute vehicleRoute : vehicleRoutes) {
InsertionData iData = bestInsertionCostCalculator.getInsertionData(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
if (iData instanceof InsertionData.NoInsertionFound) {
empty.getFailedConstraintNames().addAll(iData.getFailedConstraintNames());
empty.getFailedConstraints().addAll(iData.getFailedConstraints());
continue;
}
if (iData.getInsertionCost() < bestInsertionCost + noiseMaker.makeNoise()) {
Expand All @@ -90,11 +90,11 @@ public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> vehicleRout
vehicleRoutes.add(newRoute);
}
} else {
empty.getFailedConstraintNames().addAll(newIData.getFailedConstraintNames());
empty.getFailedConstraints().addAll(newIData.getFailedConstraints());
}
if (bestInsertion == null) {
badJobs.add(unassignedJob);
markUnassigned(unassignedJob, empty.getFailedConstraintNames());
markUnassigned(unassignedJob, empty.getFailedConstraints());
}
else insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import com.graphhopper.jsprit.core.problem.job.Job;
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
import com.graphhopper.jsprit.core.util.FailedConstraintInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -104,7 +105,7 @@ public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> vehicleRout
Collections.shuffle(unassignedJobList, random);
Collections.sort(unassignedJobList, new AccordingToPriorities());
List<Batch> batches = distributeRoutes(vehicleRoutes, nuOfBatches);
List<String> failedConstraintNames = new ArrayList<>();
List<FailedConstraintInfo> failedConstraints = new ArrayList<>();
for (final Job unassignedJob : unassignedJobList) {
Insertion bestInsertion = null;
double bestInsertionCost = Double.MAX_VALUE;
Expand All @@ -123,7 +124,7 @@ public Insertion call() throws Exception {
Future<Insertion> futureIData = completionService.take();
Insertion insertion = futureIData.get();
if (insertion.insertionData instanceof NoInsertionFound) {
failedConstraintNames.addAll(insertion.getInsertionData().getFailedConstraintNames());
failedConstraints.addAll(insertion.getInsertionData().getFailedConstraints());
continue;
}
if (insertion.getInsertionData().getInsertionCost() < bestInsertionCost) {
Expand All @@ -145,7 +146,7 @@ public Insertion call() throws Exception {
}
if (bestInsertion == null) {
badJobs.add(unassignedJob);
markUnassigned(unassignedJob, failedConstraintNames);
markUnassigned(unassignedJob, failedConstraints);
}
else insertJob(unassignedJob, bestInsertion.getInsertionData(), bestInsertion.getRoute());
}
Expand All @@ -160,7 +161,7 @@ private Insertion getBestInsertion(Batch batch, Job unassignedJob) {
for (VehicleRoute vehicleRoute : batch.routes) {
InsertionData iData = bestInsertionCostCalculator.getInsertionData(vehicleRoute, unassignedJob, NO_NEW_VEHICLE_YET, NO_NEW_DEPARTURE_TIME_YET, NO_NEW_DRIVER_YET, bestInsertionCost);
if (iData instanceof NoInsertionFound) {
empty.getFailedConstraintNames().addAll(iData.getFailedConstraintNames());
empty.getFailedConstraints().addAll(iData.getFailedConstraints());
continue;
}
if (iData.getInsertionCost() < bestInsertionCost) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import com.graphhopper.jsprit.core.problem.driver.Driver;
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
import com.graphhopper.jsprit.core.util.FailedConstraintInfo;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -76,7 +77,7 @@ List<Event> getEvents() {
return events;
}

private List<String> reasons = new ArrayList<>();
private List<FailedConstraintInfo> reasons = new ArrayList<>();

/**
* @return the additionalTime
Expand All @@ -85,11 +86,11 @@ public double getAdditionalTime() {
return additionalTime;
}

public void addFailedConstrainName(String name) {
reasons.add(name);
public void addFailedConstrainInfo(FailedConstraintInfo failedConstraintInfo) {
reasons.add(failedConstraintInfo);
}

public List<String> getFailedConstraintNames() {
public List<FailedConstraintInfo> getFailedConstraints() {
return reasons;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleFleetManager;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
import com.graphhopper.jsprit.core.util.FailedConstraintInfo;

import java.util.*;

Expand Down Expand Up @@ -79,7 +80,7 @@ static ScoredJob getBest(boolean switchAllowed, Set<String> initialVehicleIds, V
InsertionData secondBest = null;
TreeSet<VersionedInsertionData> priorityQueue = priorityQueues[j.getIndex()];
Iterator<VersionedInsertionData> iterator = priorityQueue.iterator();
List<String> failedConstraintNames = new ArrayList<>();
List<FailedConstraintInfo> failedConstraints = new ArrayList<>();
while(iterator.hasNext()){
VersionedInsertionData versionedIData = iterator.next();
if(bestRoute != null){
Expand All @@ -88,7 +89,7 @@ static ScoredJob getBest(boolean switchAllowed, Set<String> initialVehicleIds, V
}
}
if (versionedIData.getiData() instanceof InsertionData.NoInsertionFound) {
failedConstraintNames.addAll(versionedIData.getiData().getFailedConstraintNames());
failedConstraints.addAll(versionedIData.getiData().getFailedConstraints());
continue;
}
if(!(versionedIData.getRoute().getVehicle() instanceof VehicleImpl.NoVehicle)) {
Expand Down Expand Up @@ -140,9 +141,9 @@ static ScoredJob getBest(boolean switchAllowed, Set<String> initialVehicleIds, V
} else if (secondBest == null || (iData.getInsertionCost() < secondBest.getInsertionCost())) {
secondBest = iData;
}
} else failedConstraintNames.addAll(iData.getFailedConstraintNames());
} else failedConstraints.addAll(iData.getFailedConstraints());
if (best == null) {
badJobs.add(new ScoredJob.BadJob(j, failedConstraintNames));
badJobs.add(new ScoredJob.BadJob(j, failedConstraints));
continue;
}
double score = score(j, best, secondBest, scoringFunction);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.graphhopper.jsprit.core.problem.job.Break;
import com.graphhopper.jsprit.core.problem.job.Job;
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
import com.graphhopper.jsprit.core.util.FailedConstraintInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -121,7 +122,7 @@ public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> routes, Col
Job unassigned = bad.getJob();
jobs.remove(unassigned);
badJobs.add(unassigned);
markUnassigned(unassigned, bad.getInsertionData().getFailedConstraintNames());
markUnassigned(unassigned, bad.getInsertionData().getFailedConstraints());
}
}
return badJobs;
Expand Down Expand Up @@ -160,15 +161,15 @@ static ScoredJob getScoredJob(Collection<VehicleRoute> routes, Job unassignedJob
InsertionData best = null;
InsertionData secondBest = null;
VehicleRoute bestRoute = null;
List<String> failedConstraintNames = new ArrayList<>();
List<FailedConstraintInfo> failedConstraints = new ArrayList<>();
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) {
failedConstraintNames.addAll(iData.getFailedConstraintNames());
failedConstraints.addAll(iData.getFailedConstraints());
continue;
}
if (best == null) {
Expand Down Expand Up @@ -196,9 +197,9 @@ static ScoredJob getScoredJob(Collection<VehicleRoute> routes, Job unassignedJob
} else if (secondBest == null || (iData.getInsertionCost() < secondBest.getInsertionCost())) {
secondBest = iData;
}
} else failedConstraintNames.addAll(iData.getFailedConstraintNames());
} else failedConstraints.addAll(iData.getFailedConstraints());
if (best == null) {
ScoredJob.BadJob badJob = new ScoredJob.BadJob(unassignedJob, failedConstraintNames);
ScoredJob.BadJob badJob = new ScoredJob.BadJob(unassignedJob, failedConstraints);
return badJob;
}
double score = score(unassignedJob, best, secondBest, scoringFunction);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> routes, Col
Job unassigned = bad.getJob();
jobs.remove(unassigned);
badJobs.add(unassigned);
markUnassigned(unassigned, bad.getInsertionData().getFailedConstraintNames());
markUnassigned(unassigned, bad.getInsertionData().getFailedConstraints());
}
}
return badJobs;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> routes, Col
Job unassigned = bad.getJob();
jobs.remove(unassigned);
badJobs.add(unassigned);
markUnassigned(unassigned, bad.getInsertionData().getFailedConstraintNames());
markUnassigned(unassigned, bad.getInsertionData().getFailedConstraints());
}
}
return badJobs;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ public Collection<Job> insertUnassignedJobs(Collection<VehicleRoute> routes, Col
Job unassigned = bad.getJob();
jobs.remove(unassigned);
badJobs.add(unassigned);
markUnassigned(unassigned, bad.getInsertionData().getFailedConstraintNames());
markUnassigned(unassigned, bad.getInsertionData().getFailedConstraints());
}
}
return badJobs;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import com.graphhopper.jsprit.core.problem.job.Job;
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
import com.graphhopper.jsprit.core.util.FailedConstraintInfo;

import java.util.List;

Expand All @@ -30,13 +31,13 @@ class ScoredJob {

static class BadJob extends ScoredJob {

BadJob(Job job, List<String> failedConstraintNames) {
super(job, 0., getEmptyInsertion(failedConstraintNames), null, false);
BadJob(Job job, List<FailedConstraintInfo> failedConstraints) {
super(job, 0., getEmptyInsertion(failedConstraints), null, false);
}

private static InsertionData getEmptyInsertion(List<String> failedConstraintNames) {
private static InsertionData getEmptyInsertion(List<FailedConstraintInfo> failedConstraints) {
InsertionData empty = new InsertionData.NoInsertionFound();
empty.getFailedConstraintNames().addAll(failedConstraintNames);
empty.getFailedConstraints().addAll(failedConstraints);
return empty;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
import com.graphhopper.jsprit.core.util.FailedConstraintInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -111,7 +112,7 @@ public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job
InsertionData noInsertion = checkRouteContraints(insertionContext, constraintManager);
if (noInsertion != null) return noInsertion;

Collection<String> failedActivityConstraints = new ArrayList<>();
Collection<FailedConstraintInfo> failedActivityConstraints = new ArrayList<>();

/*
check soft constraints at route level
Expand Down Expand Up @@ -170,7 +171,7 @@ public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job
}
if(insertionIndex == InsertionData.NO_INDEX) {
InsertionData emptyInsertionData = new InsertionData.NoInsertionFound();
emptyInsertionData.getFailedConstraintNames().addAll(failedActivityConstraints);
emptyInsertionData.getFailedConstraints().addAll(failedActivityConstraints);
return emptyInsertionData;
}
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
Expand Down
Loading