1
0
Fork 0
mirror of https://github.com/graphhopper/jsprit.git synced 2020-01-24 07:45:05 +01:00
This commit is contained in:
Ilya Builuk 2019-09-25 13:07:41 +00:00 committed by GitHub
commit 3b5a87c9a5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 84 additions and 8 deletions

View file

@ -67,6 +67,8 @@ final class BreakInsertionCalculator implements JobInsertionCostsCalculator {
private final AdditionalAccessEgressCalculator additionalAccessEgressCalculator; private final AdditionalAccessEgressCalculator additionalAccessEgressCalculator;
private final ServiceInsertionCalculator serviceInsertionCalculator;
public BreakInsertionCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts, ActivityInsertionCostsCalculator additionalTransportCostsCalculator, ConstraintManager constraintManager, JobActivityFactory activityFactory) { public BreakInsertionCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts, ActivityInsertionCostsCalculator additionalTransportCostsCalculator, ConstraintManager constraintManager, JobActivityFactory activityFactory) {
super(); super();
this.transportCosts = routingCosts; this.transportCosts = routingCosts;
@ -78,6 +80,7 @@ final class BreakInsertionCalculator implements JobInsertionCostsCalculator {
this.additionalTransportCostsCalculator = additionalTransportCostsCalculator; this.additionalTransportCostsCalculator = additionalTransportCostsCalculator;
additionalAccessEgressCalculator = new AdditionalAccessEgressCalculator(routingCosts); additionalAccessEgressCalculator = new AdditionalAccessEgressCalculator(routingCosts);
this.activityFactory = activityFactory; this.activityFactory = activityFactory;
this.serviceInsertionCalculator = new ServiceInsertionCalculator(routingCosts, activityCosts, additionalTransportCostsCalculator, constraintManager, activityFactory);
logger.debug("initialise " + this); logger.debug("initialise " + this);
} }
@ -105,6 +108,11 @@ final class BreakInsertionCalculator implements JobInsertionCostsCalculator {
BreakActivity breakAct2Insert = (BreakActivity) activityFactory.createActivities(breakToInsert).get(0); BreakActivity breakAct2Insert = (BreakActivity) activityFactory.createActivities(breakToInsert).get(0);
insertionContext.getAssociatedActivities().add(breakAct2Insert); insertionContext.getAssociatedActivities().add(breakAct2Insert);
if (!breakToInsert.hasVariableLocation()) {
breakAct2Insert.setLocation(breakToInsert.getLocation());
return serviceInsertionCalculator.getInsertionData(insertionContext, breakToInsert, breakAct2Insert, currentRoute, newVehicle, newVehicleDepartureTime, newDriver, bestKnownCosts);
}
/* /*
check hard constraints at route level check hard constraints at route level
*/ */

View file

@ -32,6 +32,7 @@ import com.graphhopper.jsprit.core.problem.misc.ActivityContext;
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext; import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute; import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
import com.graphhopper.jsprit.core.problem.solution.route.activity.End; import com.graphhopper.jsprit.core.problem.solution.route.activity.End;
import com.graphhopper.jsprit.core.problem.solution.route.activity.ServiceActivity;
import com.graphhopper.jsprit.core.problem.solution.route.activity.Start; import com.graphhopper.jsprit.core.problem.solution.route.activity.Start;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow; 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.solution.route.activity.TourActivity;
@ -94,11 +95,14 @@ final class ServiceInsertionCalculator extends AbstractInsertionCalculator {
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) { public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime); JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
Service service = (Service) jobToInsert; Service service = (Service) jobToInsert;
int insertionIndex = InsertionData.NO_INDEX; TourActivity deliveryAct2Insert = activityFactory.createActivities(service).get(0);
TourActivity deliveryAct2Insert = activityFactory.createActivities(service).get(0);
insertionContext.getAssociatedActivities().add(deliveryAct2Insert); insertionContext.getAssociatedActivities().add(deliveryAct2Insert);
return getInsertionData(insertionContext, service, deliveryAct2Insert, currentRoute, newVehicle, newVehicleDepartureTime, newDriver, bestKnownCosts);
}
InsertionData getInsertionData(final JobInsertionContext insertionContext, final Service service, final TourActivity deliveryAct2Insert,
final VehicleRoute currentRoute, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
/* /*
check hard constraints at route level check hard constraints at route level
*/ */
@ -114,7 +118,7 @@ final class ServiceInsertionCalculator extends AbstractInsertionCalculator {
double bestCost = bestKnownCosts; double bestCost = bestKnownCosts;
additionalICostsAtRouteLevel += additionalAccessEgressCalculator.getCosts(insertionContext); additionalICostsAtRouteLevel += additionalAccessEgressCalculator.getCosts(insertionContext);
TimeWindow bestTimeWindow = null; TimeWindow bestTimeWindow = null;
/* /*
generate new start and end for new vehicle generate new start and end for new vehicle
@ -126,6 +130,7 @@ final class ServiceInsertionCalculator extends AbstractInsertionCalculator {
TourActivity prevAct = start; TourActivity prevAct = start;
double prevActStartTime = newVehicleDepartureTime; double prevActStartTime = newVehicleDepartureTime;
int actIndex = 0; int actIndex = 0;
int insertionIndex = InsertionData.NO_INDEX;
Iterator<TourActivity> activityIterator = currentRoute.getActivities().iterator(); Iterator<TourActivity> activityIterator = currentRoute.getActivities().iterator();
boolean tourEnd = false; boolean tourEnd = false;
while(!tourEnd){ while(!tourEnd){
@ -136,7 +141,7 @@ final class ServiceInsertionCalculator extends AbstractInsertionCalculator {
tourEnd = true; tourEnd = true;
} }
boolean not_fulfilled_break = true; boolean not_fulfilled_break = true;
for(TimeWindow timeWindow : service.getTimeWindows()) { for(TimeWindow timeWindow : service.getTimeWindows()) {
deliveryAct2Insert.setTheoreticalEarliestOperationStartTime(timeWindow.getStart()); deliveryAct2Insert.setTheoreticalEarliestOperationStartTime(timeWindow.getStart());
deliveryAct2Insert.setTheoreticalLatestOperationStartTime(timeWindow.getEnd()); deliveryAct2Insert.setTheoreticalLatestOperationStartTime(timeWindow.getEnd());
ActivityContext activityContext = new ActivityContext(); ActivityContext activityContext = new ActivityContext();
@ -155,7 +160,7 @@ final class ServiceInsertionCalculator extends AbstractInsertionCalculator {
} else if (status.equals(ConstraintsStatus.NOT_FULFILLED)) { } else if (status.equals(ConstraintsStatus.NOT_FULFILLED)) {
not_fulfilled_break = false; not_fulfilled_break = false;
} }
} }
if(not_fulfilled_break) break; if(not_fulfilled_break) break;
double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActStartTime, newDriver, newVehicle); double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActStartTime, newDriver, newVehicle);
prevActStartTime = Math.max(nextActArrTime, nextAct.getTheoreticalEarliestOperationStartTime()) + activityCosts.getActivityDuration(nextAct,nextActArrTime,newDriver,newVehicle); prevActStartTime = Math.max(nextActArrTime, nextAct.getTheoreticalEarliestOperationStartTime()) + activityCosts.getActivityDuration(nextAct,nextActArrTime,newDriver,newVehicle);
@ -177,6 +182,4 @@ final class ServiceInsertionCalculator extends AbstractInsertionCalculator {
insertionData.setVehicleDepartureTime(newVehicleDepartureTime); insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
return insertionData; return insertionData;
} }
} }

View file

@ -0,0 +1,65 @@
package com.graphhopper.jsprit.core.problem;
import static org.junit.Assert.assertEquals;
import com.graphhopper.jsprit.core.algorithm.box.Jsprit;
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem.FleetSize;
import com.graphhopper.jsprit.core.problem.job.Break;
import com.graphhopper.jsprit.core.problem.job.Service;
import com.graphhopper.jsprit.core.problem.solution.route.VehicleRoute;
import com.graphhopper.jsprit.core.problem.solution.route.activity.BreakActivity;
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.VehicleImpl;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl.Builder;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleTypeImpl;
import com.graphhopper.jsprit.core.util.Solutions;
import org.junit.Test;
public class BreakAssignmentTest {
@Test
public void whenBreakHasFixedLocation_breakActivityHasLocationSpecified() {
VehicleImpl vehicle = Builder.newInstance("vehicle")
.setType(VehicleTypeImpl.Builder.newInstance("vehicleType")
.addCapacityDimension(0, 2)
.build())
.setStartLocation(Location.newInstance(0, 0))
.setBreak(Break.Builder.newInstance("break")
.setTimeWindow(TimeWindow.newInstance(5, 8))
.setLocation(Location.newInstance(6, 0))
.setServiceTime(1)
.build())
.build();
Service service1 = Service.Builder.newInstance("1")
.addSizeDimension(0, 1)
.setLocation(Location.newInstance(5, 0))
.setServiceTime(1)
.build();
Service service2 = Service.Builder.newInstance("2")
.addSizeDimension(0, 1)
.setLocation(Location.newInstance(10, 0))
.setServiceTime(10)
.build();
VehicleRoutingProblem problem = VehicleRoutingProblem.Builder.newInstance()
.addVehicle(vehicle)
.addJob(service1)
.addJob(service2)
.setFleetSize(FleetSize.FINITE)
.build();
Location location = findBreak(Solutions.bestOf(Jsprit.Builder
.newInstance(problem)
.buildAlgorithm().searchSolutions()).getRoutes().iterator().next())
.getLocation();
assertEquals(Location.newInstance(6, 0), location);
}
private BreakActivity findBreak(VehicleRoute route) {
for (TourActivity tourActivity : route.getTourActivities().getActivities()) {
if (tourActivity instanceof BreakActivity)
return (BreakActivity) tourActivity;
}
throw new IllegalStateException("Break activity is not found.");
}
}