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

fix bug 329 part 1 for services #332

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ public Collection<Vehicle> get(VehicleRoute vehicleRoute) {
stateManager.addStateUpdater(new UpdateActivityTimes(vrp.getTransportCosts(), ActivityTimeTracker.ActivityPolicy.AS_SOON_AS_TIME_WINDOW_OPENS, vrp.getActivityCosts()));
stateManager.addStateUpdater(new UpdateVariableCosts(vrp.getActivityCosts(), vrp.getTransportCosts(), stateManager));
stateManager.addStateUpdater(new UpdateFutureWaitingTimes(stateManager, vrp.getTransportCosts()));

stateManager.addStateUpdater(new UpdateVehicleDependentTimes(vrp.getTransportCosts(), vrp.getActivityCosts(), stateManager, vrp.getVehicles()));
stateManager.addStateUpdater(new UpdateVehicleDependentFutureWaitingTimes(stateManager, vrp.getVehicles()));
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import com.graphhopper.jsprit.core.algorithm.listener.VehicleRoutingAlgorithmListeners.PrioritizedVRAListener;
import com.graphhopper.jsprit.core.algorithm.recreate.listener.InsertionListener;
import com.graphhopper.jsprit.core.algorithm.state.StateManager;
import com.graphhopper.jsprit.core.problem.AbstractActivity;
import com.graphhopper.jsprit.core.problem.JobActivityFactory;
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
Expand Down Expand Up @@ -289,12 +290,18 @@ public List<AbstractActivity> createActivities(Job job) {
};
ShipmentInsertionCalculator shipmentInsertion = new ShipmentInsertionCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(),actInsertionCalc, constraintManager);
shipmentInsertion.setJobActivityFactory(activityFactory);
shipmentInsertion.setStateManager((StateManager) statesManager);

ServiceInsertionCalculator serviceInsertion = new ServiceInsertionCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), actInsertionCalc, constraintManager);
serviceInsertion.setJobActivityFactory(activityFactory);
serviceInsertion.setStateManager((StateManager) statesManager);

BreakInsertionCalculator breakInsertionCalculator = new BreakInsertionCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), actInsertionCalc, constraintManager);
breakInsertionCalculator.setJobActivityFactory(activityFactory);

shipmentInsertion.setBreakInsertionCalculator(breakInsertionCalculator);
serviceInsertion.setBreakInsertionCalculator(breakInsertionCalculator);

JobCalculatorSwitcher switcher = new JobCalculatorSwitcher();
switcher.put(Shipment.class, shipmentInsertion);
switcher.put(Service.class, serviceInsertion);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
*/
package com.graphhopper.jsprit.core.algorithm.recreate;

import com.graphhopper.jsprit.core.algorithm.state.InternalStates;
import com.graphhopper.jsprit.core.algorithm.state.StateManager;
import com.graphhopper.jsprit.core.problem.JobActivityFactory;
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
import com.graphhopper.jsprit.core.problem.constraint.HardActivityConstraint.ConstraintsStatus;
Expand All @@ -25,15 +27,11 @@
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import com.graphhopper.jsprit.core.problem.driver.Driver;
import com.graphhopper.jsprit.core.problem.job.Job;
import com.graphhopper.jsprit.core.problem.job.Service;
import com.graphhopper.jsprit.core.problem.job.*;
import com.graphhopper.jsprit.core.problem.misc.ActivityContext;
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.activity.End;
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.TourActivity;
import com.graphhopper.jsprit.core.problem.solution.route.activity.*;
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -71,6 +69,10 @@ final class ServiceInsertionCalculator extends AbstractInsertionCalculator {

private ConstraintManager constraintManager;

private StateManager stateManager;

private BreakInsertionCalculator breakInsertionCalculator;

public ServiceInsertionCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts, ActivityInsertionCostsCalculator additionalTransportCostsCalculator, ConstraintManager constraintManager) {
super();
this.transportCosts = routingCosts;
Expand All @@ -87,6 +89,14 @@ public void setJobActivityFactory(JobActivityFactory jobActivityFactory) {
this.activityFactory = jobActivityFactory;
}

public void setStateManager(StateManager stateManager) {
this.stateManager = stateManager;
}

public void setBreakInsertionCalculator(BreakInsertionCalculator breakInsertionCalculator) {
this.breakInsertionCalculator = breakInsertionCalculator;
}

@Override
public String toString() {
return "[name=calculatesServiceInsertion]";
Expand Down Expand Up @@ -149,6 +159,58 @@ public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job
activityContext.setInsertionIndex(actIndex);
insertionContext.setActivityContext(activityContext);
ConstraintsStatus status = fulfilled(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime, failedActivityConstraints, constraintManager);

// check if new vehicle has break
Break aBreak = newVehicle.getBreak();
if (aBreak != null) {
// check if break has been inserted
if (!currentRoute.getTourActivities().servesJob(aBreak)) {
// get new route end time before insertion of newAct
Double routeEndTime = stateManager.getRouteState(currentRoute, newVehicle, InternalStates.END_TIME, Double.class);
if (routeEndTime == null) routeEndTime = newVehicle.getEarliestDeparture();
// get future waiting of nextAct in the new route
Double futureWaiting = stateManager.getActivityState(nextAct, newVehicle, InternalStates.FUTURE_WAITING, Double.class);
if (futureWaiting == null) futureWaiting = 0.;
// get nextAct end time delay after insertion of newAct in the new route
double newActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocation(), deliveryAct2Insert.getLocation(), prevActStartTime, newDriver, newVehicle);
double newActEndTime = Math.max(deliveryAct2Insert.getTheoreticalEarliestOperationStartTime(), newActArrTime) + activityCosts.getActivityDuration(deliveryAct2Insert, newActArrTime, newDriver, newVehicle);
double nextActArrTime = newActEndTime + transportCosts.getTransportTime(deliveryAct2Insert.getLocation(), nextAct.getLocation(), newActEndTime, newDriver, newVehicle);
double nextActEndTime = Math.max(nextAct.getTheoreticalEarliestOperationStartTime(), nextActArrTime) + activityCosts.getActivityDuration(nextAct, nextActArrTime, newDriver, newVehicle);
Double nextActEndTimeOld = stateManager.getActivityState(nextAct, newVehicle, InternalStates.END_TIME, Double.class);
if (nextActEndTimeOld == null) nextActEndTimeOld = routeEndTime;
double nextActEndTimeDelay = Math.max(0., nextActEndTime - nextActEndTimeOld);
// get new route end time after insertion of newAct
double routeEndTimeNew = routeEndTime + Math.max(0., nextActEndTimeDelay - futureWaiting);
// check if new route end time later than break time window
if (routeEndTimeNew > aBreak.getTimeWindow().getEnd()) {
VehicleRoute.Builder routeBuilder = VehicleRoute.Builder.newInstance(newVehicle, newDriver);
routeBuilder.setJobActivityFactory(activityFactory);
for (int tourActIndex = 0; tourActIndex < currentRoute.getActivities().size(); tourActIndex++) {
if (tourActIndex == actIndex) {
addJobActToRouteBuilder(routeBuilder, jobToInsert, deliveryAct2Insert);
}
TourActivity tourActivity = currentRoute.getActivities().get(tourActIndex);
if (tourActivity instanceof TourActivity.JobActivity) {
addJobActToRouteBuilder(routeBuilder, ((TourActivity.JobActivity) tourActivity).getJob(), tourActivity);
}
}
if (actIndex == currentRoute.getActivities().size()) {
addJobActToRouteBuilder(routeBuilder, jobToInsert, deliveryAct2Insert);
}
routeBuilder.setDepartureTime(newVehicleDepartureTime);
VehicleRoute route = routeBuilder.build();
stateManager.reCalculateStates(route);
// check if break can be inserted
InsertionData iData = breakInsertionCalculator.getInsertionData(route, aBreak, newVehicle, newVehicleDepartureTime, newDriver, Double.MAX_VALUE);
if (iData instanceof InsertionData.NoInsertionFound) {
status = ConstraintsStatus.NOT_FULFILLED;
}
if (!currentRoute.isEmpty())
stateManager.reCalculateStates(currentRoute);
}
}
}

if (status.equals(ConstraintsStatus.FULFILLED)) {
double additionalICostsAtActLevel = softActivityConstraint.getCosts(insertionContext, prevAct, deliveryAct2Insert, nextAct, prevActStartTime);
double additionalTransportationCosts = additionalTransportCostsCalculator.getCosts(insertionContext, prevAct, nextAct, deliveryAct2Insert, prevActStartTime);
Expand Down Expand Up @@ -182,5 +244,24 @@ public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job
return insertionData;
}


private void addJobActToRouteBuilder(VehicleRoute.Builder routeBuilder, Job job, TourActivity tourActivity) {
if (job instanceof Pickup)
routeBuilder.addPickup((Pickup) job);
else if (job instanceof Delivery)
routeBuilder.addDelivery((Delivery) job);
else if (job instanceof Service)
routeBuilder.addService((Service) job);
else if (job instanceof Break)
routeBuilder.addBreak((Break) job);
else if (job instanceof Shipment) {
if (tourActivity instanceof PickupShipment)
routeBuilder.addPickup((Shipment) job);
else if (tourActivity instanceof DeliverShipment)
routeBuilder.addDelivery((Shipment) job);
else
throw new IllegalStateException("tourActivity " + tourActivity.getName());
}
else
throw new IllegalStateException("job " + job.getName());
}
}
Loading