mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
BreakForMultipleTimeWindows (#68)
* BreakForMultipleTimeWindows * location fix * builder * extend from service * oops * extends break * extends service * BreakForMultipleTimeWindowsActivity * so * oops * cr * location with same id different coordinate * leave skills as is :O * test * fixes with tests
This commit is contained in:
parent
07944d6dd6
commit
c75cd5df9e
8 changed files with 473 additions and 11 deletions
|
|
@ -0,0 +1,141 @@
|
|||
package com.graphhopper.jsprit.core.algorithm.recreate;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.JobActivityFactory;
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.*;
|
||||
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.BreakForMultipleTimeWindows;
|
||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||
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.BreakForMultipleTimeWindowsActivity;
|
||||
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.TourActivity;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
final class BreakForMultipleTimeWindowsInsertionCalculator implements JobInsertionCostsCalculator {
|
||||
private static final Logger logger = LoggerFactory.getLogger(BreakInsertionCalculator.class);
|
||||
|
||||
private ConstraintManager constraintManager;
|
||||
|
||||
private VehicleRoutingTransportCosts transportCosts;
|
||||
|
||||
private final VehicleRoutingActivityCosts activityCosts;
|
||||
|
||||
private ActivityInsertionCostsCalculator additionalTransportCostsCalculator;
|
||||
|
||||
private JobActivityFactory activityFactory;
|
||||
|
||||
private AdditionalAccessEgressCalculator additionalAccessEgressCalculator;
|
||||
|
||||
public BreakForMultipleTimeWindowsInsertionCalculator(VehicleRoutingTransportCosts routingCosts, VehicleRoutingActivityCosts activityCosts, ActivityInsertionCostsCalculator additionalTransportCostsCalculator, ConstraintManager constraintManager) {
|
||||
this.transportCosts = routingCosts;
|
||||
this.activityCosts = activityCosts;
|
||||
this.constraintManager = constraintManager;
|
||||
this.additionalTransportCostsCalculator = additionalTransportCostsCalculator;
|
||||
additionalAccessEgressCalculator = new AdditionalAccessEgressCalculator(routingCosts);
|
||||
logger.debug("initialise " + this);
|
||||
}
|
||||
|
||||
public void setJobActivityFactory(JobActivityFactory jobActivityFactory) {
|
||||
this.activityFactory = jobActivityFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[name=calculatesServiceInsertion]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the marginal cost of inserting job i locally. This is based on the
|
||||
* assumption that cost changes can entirely covered by only looking at the predecessor i-1 and its successor i+1.
|
||||
*/
|
||||
@Override
|
||||
public InsertionData getInsertionData(final VehicleRoute currentRoute, final Job jobToInsert, final Vehicle newVehicle, double newVehicleDepartureTime, final Driver newDriver, final double bestKnownCosts) {
|
||||
BreakForMultipleTimeWindows breakToInsert = (BreakForMultipleTimeWindows) jobToInsert;
|
||||
JobInsertionContext insertionContext = new JobInsertionContext(currentRoute, jobToInsert, newVehicle, newDriver, newVehicleDepartureTime);
|
||||
int insertionIndex = InsertionData.NO_INDEX;
|
||||
|
||||
BreakForMultipleTimeWindowsActivity breakAct2Insert = (BreakForMultipleTimeWindowsActivity) activityFactory.createActivities(breakToInsert).get(0);
|
||||
insertionContext.getAssociatedActivities().add(breakAct2Insert);
|
||||
|
||||
/*
|
||||
check hard constraints at route level
|
||||
*/
|
||||
if (!constraintManager.fulfilled(insertionContext)) {
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
|
||||
/*
|
||||
check soft constraints at route level
|
||||
*/
|
||||
double additionalICostsAtRouteLevel = constraintManager.getCosts(insertionContext);
|
||||
|
||||
double bestCost = bestKnownCosts;
|
||||
additionalICostsAtRouteLevel += additionalAccessEgressCalculator.getCosts(insertionContext);
|
||||
|
||||
/*
|
||||
generate new start and end for new vehicle
|
||||
*/
|
||||
Start start = new Start(newVehicle.getStartLocation(), newVehicle.getEarliestDeparture(), Double.MAX_VALUE);
|
||||
start.setEndTime(newVehicleDepartureTime);
|
||||
End end = new End(newVehicle.getEndLocation(), 0.0, newVehicle.getLatestArrival());
|
||||
|
||||
Location bestLocation = null;
|
||||
|
||||
TourActivity prevAct = start;
|
||||
double prevActStartTime = newVehicleDepartureTime;
|
||||
int actIndex = 0;
|
||||
Iterator<TourActivity> activityIterator = currentRoute.getActivities().iterator();
|
||||
boolean tourEnd = false;
|
||||
while (!tourEnd) {
|
||||
TourActivity nextAct;
|
||||
if (activityIterator.hasNext()) nextAct = activityIterator.next();
|
||||
else {
|
||||
nextAct = end;
|
||||
tourEnd = true;
|
||||
}
|
||||
boolean breakThis = true;
|
||||
final Location location = Location.Builder.newInstance().setId(breakAct2Insert.getJob().getLocation().getId()).setCoordinate(prevAct.getLocation().getCoordinate()).build();
|
||||
breakAct2Insert.setLocation(location);
|
||||
breakAct2Insert.setTheoreticalEarliestOperationStartTime(breakToInsert.getTimeWindow().getStart());
|
||||
breakAct2Insert.setTheoreticalLatestOperationStartTime(breakToInsert.getTimeWindow().getEnd());
|
||||
HardActivityConstraint.ConstraintsStatus status = constraintManager.fulfilled(insertionContext, prevAct, breakAct2Insert, nextAct, prevActStartTime);
|
||||
if (status.equals(HardActivityConstraint.ConstraintsStatus.FULFILLED)) {
|
||||
//from job2insert induced costs at activity level
|
||||
double additionalICostsAtActLevel = constraintManager.getCosts(insertionContext, prevAct, breakAct2Insert, nextAct, prevActStartTime);
|
||||
double additionalTransportationCosts = additionalTransportCostsCalculator.getCosts(insertionContext, prevAct, nextAct, breakAct2Insert, prevActStartTime);
|
||||
if (additionalICostsAtRouteLevel + additionalICostsAtActLevel + additionalTransportationCosts < bestCost) {
|
||||
bestCost = additionalICostsAtRouteLevel + additionalICostsAtActLevel + additionalTransportationCosts;
|
||||
insertionIndex = actIndex;
|
||||
bestLocation = location;
|
||||
}
|
||||
breakThis = false;
|
||||
} else if (status.equals(HardActivityConstraint.ConstraintsStatus.NOT_FULFILLED)) {
|
||||
breakThis = false;
|
||||
}
|
||||
|
||||
double nextActArrTime = prevActStartTime + transportCosts.getTransportTime(prevAct.getLocation(), nextAct.getLocation(), prevActStartTime, newDriver, newVehicle);
|
||||
prevActStartTime = Math.max(nextActArrTime, nextAct.getTheoreticalEarliestOperationStartTime()) + activityCosts.getActivityDuration(prevAct, nextAct,nextActArrTime,newDriver,newVehicle);
|
||||
prevAct = nextAct;
|
||||
actIndex++;
|
||||
if (breakThis) break;
|
||||
}
|
||||
if (insertionIndex == InsertionData.NO_INDEX) {
|
||||
return InsertionData.createEmptyInsertionData();
|
||||
}
|
||||
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
|
||||
breakAct2Insert.setLocation(bestLocation);
|
||||
insertionData.getEvents().add(new InsertBreak(currentRoute, newVehicle, breakAct2Insert, insertionIndex));
|
||||
insertionData.getEvents().add(new SwitchVehicle(currentRoute, newVehicle, newVehicleDepartureTime));
|
||||
insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
|
||||
return insertionData;
|
||||
}
|
||||
}
|
||||
|
|
@ -280,7 +280,6 @@ public class JobInsertionCostsCalculatorBuilder {
|
|||
}
|
||||
|
||||
JobActivityFactory activityFactory = new JobActivityFactory() {
|
||||
|
||||
@Override
|
||||
public List<AbstractActivity> createActivities(Job job) {
|
||||
return vrp.copyAndGetActivities(job);
|
||||
|
|
@ -295,12 +294,16 @@ public class JobInsertionCostsCalculatorBuilder {
|
|||
BreakInsertionCalculator breakInsertionCalculator = new BreakInsertionCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), actInsertionCalc, constraintManager);
|
||||
breakInsertionCalculator.setJobActivityFactory(activityFactory);
|
||||
|
||||
BreakForMultipleTimeWindowsInsertionCalculator breakForMultipleTimeWindowsInsertionCalculator = new BreakForMultipleTimeWindowsInsertionCalculator(vrp.getTransportCosts(), vrp.getActivityCosts(), actInsertionCalc, constraintManager);
|
||||
breakForMultipleTimeWindowsInsertionCalculator.setJobActivityFactory(activityFactory);
|
||||
|
||||
JobCalculatorSwitcher switcher = new JobCalculatorSwitcher();
|
||||
switcher.put(Shipment.class, shipmentInsertion);
|
||||
switcher.put(Service.class, serviceInsertion);
|
||||
switcher.put(Pickup.class, serviceInsertion);
|
||||
switcher.put(Delivery.class, serviceInsertion);
|
||||
switcher.put(Break.class, breakInsertionCalculator);
|
||||
switcher.put(BreakForMultipleTimeWindows.class, breakForMultipleTimeWindowsInsertionCalculator);
|
||||
switcher.put(ShipmentWithMutablePickupDeliverOptions.class, shipmentInsertion);
|
||||
|
||||
CalculatorPlusListeners calculatorPlusListeners = new CalculatorPlusListeners(switcher);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
package com.graphhopper.jsprit.core.algorithm.recreate;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.JobActivityFactory;
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.HardActivityConstraint.ConstraintsStatus;
|
||||
import com.graphhopper.jsprit.core.problem.constraint.SoftActivityConstraint;
|
||||
|
|
@ -30,10 +31,7 @@ import com.graphhopper.jsprit.core.problem.job.Shipment;
|
|||
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;
|
||||
|
|
@ -175,7 +173,6 @@ final class ShipmentInsertionCalculator extends AbstractInsertionCalculator {
|
|||
insertionContext.setRelatedActivityContext(pickupContext);
|
||||
|
||||
double prevActEndTime_deliveryLoop = shipmentPickupEndTime;
|
||||
|
||||
/*
|
||||
--------------------------------
|
||||
*/
|
||||
|
|
@ -220,6 +217,14 @@ final class ShipmentInsertionCalculator extends AbstractInsertionCalculator {
|
|||
//update prevAct and endTime
|
||||
double nextActArrTime = prevActEndTime_deliveryLoop + transportCosts.getTransportTime(prevAct_deliveryLoop.getLocation(), nextAct_deliveryLoop.getLocation(), prevActEndTime_deliveryLoop, newDriver, newVehicle);
|
||||
prevActEndTime_deliveryLoop = Math.max(nextActArrTime, nextAct_deliveryLoop.getTheoreticalEarliestOperationStartTime()) + activityCosts.getActivityDuration(prevAct_deliveryLoop, nextAct_deliveryLoop,nextActArrTime,newDriver,newVehicle);
|
||||
if (i == j && nextAct_deliveryLoop instanceof BreakForMultipleTimeWindowsActivity) {
|
||||
final BreakForMultipleTimeWindowsActivity breakForMultipleTimeWindowsActivity = (BreakForMultipleTimeWindowsActivity) nextAct_deliveryLoop.duplicate();
|
||||
final Location location = Location.Builder.newInstance()
|
||||
.setId(breakForMultipleTimeWindowsActivity.getJob().getLocation().getId())
|
||||
.setCoordinate(prevAct_deliveryLoop.getLocation().getCoordinate()).build();
|
||||
breakForMultipleTimeWindowsActivity.setLocation(location);
|
||||
nextAct_deliveryLoop = breakForMultipleTimeWindowsActivity;
|
||||
}
|
||||
prevAct_deliveryLoop = nextAct_deliveryLoop;
|
||||
j++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
package com.graphhopper.jsprit.core.problem.job;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.Capacity;
|
||||
|
||||
public class BreakForMultipleTimeWindows extends Service {
|
||||
|
||||
public static class Builder extends Service.Builder<BreakForMultipleTimeWindows> {
|
||||
|
||||
/**
|
||||
* Returns a new instance of builder that builds a pickup.
|
||||
*
|
||||
* @param id the id of the pickup
|
||||
* @return the builder
|
||||
*/
|
||||
public static BreakForMultipleTimeWindows.Builder newInstance(String id) {
|
||||
return new BreakForMultipleTimeWindows.Builder(id);
|
||||
}
|
||||
|
||||
private boolean variableLocation = true;
|
||||
|
||||
Builder(String id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds Pickup.
|
||||
* <p>
|
||||
* <p>Pickup type is "pickup"
|
||||
*
|
||||
* @return pickup
|
||||
* @throws IllegalStateException if neither locationId nor coordinate has been set
|
||||
*/
|
||||
public BreakForMultipleTimeWindows build() {
|
||||
if (location != null) {
|
||||
variableLocation = false;
|
||||
}
|
||||
this.setType("break");
|
||||
super.capacity = Capacity.Builder.newInstance().build();
|
||||
super.skills = skillBuilder.build();
|
||||
return new BreakForMultipleTimeWindows(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean variableLocation = true;
|
||||
|
||||
BreakForMultipleTimeWindows(BreakForMultipleTimeWindows.Builder builder) {
|
||||
super(builder);
|
||||
this.variableLocation = builder.variableLocation;
|
||||
}
|
||||
|
||||
public boolean hasVariableLocation() {
|
||||
return variableLocation;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
package com.graphhopper.jsprit.core.problem.solution.route.activity;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.AbstractActivity;
|
||||
import com.graphhopper.jsprit.core.problem.Capacity;
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.job.BreakForMultipleTimeWindows;
|
||||
import com.graphhopper.jsprit.core.problem.job.Service;
|
||||
|
||||
public class BreakForMultipleTimeWindowsActivity extends AbstractActivity implements TourActivity.JobActivity{
|
||||
public static int counter = 0;
|
||||
|
||||
public double arrTime;
|
||||
|
||||
public double endTime;
|
||||
|
||||
private Location location;
|
||||
|
||||
private double duration;
|
||||
|
||||
/**
|
||||
* @return the arrTime
|
||||
*/
|
||||
public double getArrTime() {
|
||||
return arrTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param arrTime the arrTime to set
|
||||
*/
|
||||
public void setArrTime(double arrTime) {
|
||||
this.arrTime = arrTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the endTime
|
||||
*/
|
||||
public double getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param endTime the endTime to set
|
||||
*/
|
||||
public void setEndTime(double endTime) {
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
public static BreakForMultipleTimeWindowsActivity copyOf(BreakForMultipleTimeWindowsActivity breakActivity) {
|
||||
return new BreakForMultipleTimeWindowsActivity(breakActivity);
|
||||
}
|
||||
|
||||
public static BreakForMultipleTimeWindowsActivity newInstance(BreakForMultipleTimeWindows aBreak) {
|
||||
return new BreakForMultipleTimeWindowsActivity(aBreak);
|
||||
}
|
||||
|
||||
private final BreakForMultipleTimeWindows aBreak;
|
||||
|
||||
private double earliest = 0;
|
||||
|
||||
private double latest = Double.MAX_VALUE;
|
||||
|
||||
protected BreakForMultipleTimeWindowsActivity(BreakForMultipleTimeWindows aBreak) {
|
||||
counter++;
|
||||
this.aBreak = aBreak;
|
||||
this.duration = aBreak.getServiceDuration();
|
||||
this.location = aBreak.getLocation();
|
||||
}
|
||||
|
||||
protected BreakForMultipleTimeWindowsActivity(BreakForMultipleTimeWindowsActivity breakActivity) {
|
||||
counter++;
|
||||
this.aBreak = (BreakForMultipleTimeWindows) breakActivity.getJob();
|
||||
this.arrTime = breakActivity.getArrTime();
|
||||
this.endTime = breakActivity.getEndTime();
|
||||
this.location = breakActivity.getLocation();
|
||||
setIndex(breakActivity.getIndex());
|
||||
this.earliest = breakActivity.getTheoreticalEarliestOperationStartTime();
|
||||
this.latest = breakActivity.getTheoreticalLatestOperationStartTime();
|
||||
this.duration = breakActivity.getOperationTime();
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((aBreak == null) ? 0 : aBreak.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
BreakForMultipleTimeWindowsActivity other = (BreakForMultipleTimeWindowsActivity) obj;
|
||||
if (aBreak == null) {
|
||||
if (other.aBreak != null)
|
||||
return false;
|
||||
} else if (!aBreak.equals(other.aBreak))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public double getTheoreticalEarliestOperationStartTime() {
|
||||
return earliest;
|
||||
}
|
||||
|
||||
public double getTheoreticalLatestOperationStartTime() {
|
||||
return latest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getOperationTime() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public void setOperationTime(double duration){
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(Location breakLocation) {
|
||||
this.location = breakLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Service getJob() {
|
||||
return aBreak;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[type=" + getName() + "][location=" + getLocation()
|
||||
+ "][size=" + getSize().toString()
|
||||
+ "][twStart=" + Activities.round(getTheoreticalEarliestOperationStartTime())
|
||||
+ "][twEnd=" + Activities.round(getTheoreticalLatestOperationStartTime()) + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTheoreticalEarliestOperationStartTime(double earliest) {
|
||||
this.earliest = earliest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTheoreticalLatestOperationStartTime(double latest) {
|
||||
this.latest = latest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return aBreak.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TourActivity duplicate() {
|
||||
return new BreakForMultipleTimeWindowsActivity(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Capacity getSize() {
|
||||
return aBreak.getSize();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
package com.graphhopper.jsprit.core.problem.solution.route.activity;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.AbstractActivity;
|
||||
import com.graphhopper.jsprit.core.problem.job.BreakForMultipleTimeWindows;
|
||||
import com.graphhopper.jsprit.core.problem.job.Delivery;
|
||||
import com.graphhopper.jsprit.core.problem.job.Pickup;
|
||||
import com.graphhopper.jsprit.core.problem.job.Service;
|
||||
|
|
@ -27,7 +28,9 @@ public class DefaultTourActivityFactory implements TourActivityFactory {
|
|||
@Override
|
||||
public AbstractActivity createActivity(Service service) {
|
||||
AbstractActivity act;
|
||||
if (service instanceof Pickup) {
|
||||
if (service instanceof BreakForMultipleTimeWindows) {
|
||||
act = new BreakForMultipleTimeWindowsActivity((BreakForMultipleTimeWindows) service);
|
||||
} else if (service instanceof Pickup) {
|
||||
act = new PickupService((Pickup) service);
|
||||
} else if (service instanceof Delivery) {
|
||||
act = new DeliverService((Delivery) service);
|
||||
|
|
|
|||
|
|
@ -31,27 +31,27 @@ 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.driver.DriverImpl;
|
||||
import com.graphhopper.jsprit.core.problem.job.BreakForMultipleTimeWindows;
|
||||
import com.graphhopper.jsprit.core.problem.job.Pickup;
|
||||
import com.graphhopper.jsprit.core.problem.job.Service;
|
||||
import com.graphhopper.jsprit.core.problem.job.Shipment;
|
||||
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.DeliverShipment;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.PickupService;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.PickupShipment;
|
||||
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.solution.route.state.RouteAndActivityStateGetter;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleType;
|
||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleTypeImpl;
|
||||
import com.graphhopper.jsprit.core.util.CostFactory;
|
||||
import com.graphhopper.jsprit.core.util.ManhattanCosts;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
|
@ -316,5 +316,48 @@ public class ShipmentInsertionCalculatorTest {
|
|||
assertEquals(3, iData.getDeliveryInsertionIndex());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenPickupInsertedBeforeBreak() {
|
||||
final BreakForMultipleTimeWindows breakForMultipleTimeWindows =
|
||||
BreakForMultipleTimeWindows.Builder.newInstance("break")
|
||||
.setLocation(Location.newInstance(5, 10))
|
||||
.addTimeWindow(20, 20)
|
||||
.setServiceTime(5)
|
||||
.build();
|
||||
final VehicleImpl vehicle = VehicleImpl.Builder.newInstance(UUID.randomUUID().toString())
|
||||
.setStartLocation(Location.newInstance(0, 0))
|
||||
.build();
|
||||
final VehicleRoute route = VehicleRoute.Builder.newInstance(vehicle)
|
||||
.addService(breakForMultipleTimeWindows)
|
||||
.build();
|
||||
|
||||
route.getActivities().get(0).setArrTime(5);
|
||||
route.getActivities().get(0).setEndTime(10);
|
||||
|
||||
Shipment shipment = Shipment.Builder.newInstance("shipment")
|
||||
.setPickupLocation(Location.newInstance(0,10))
|
||||
.setPickupTimeWindow(new TimeWindow(0, 20))
|
||||
.setPickupServiceTime(10)
|
||||
.setDeliveryLocation(Location.newInstance(10,10))
|
||||
.setDeliveryTimeWindow(new TimeWindow(60, 160))
|
||||
.setDeliveryServiceTime(10)
|
||||
.build();
|
||||
|
||||
VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance().addJob(shipment).addJob(breakForMultipleTimeWindows).build();
|
||||
|
||||
StateManager stateManager = new StateManager(vrp);
|
||||
final ConstraintManager constraintManager = new ConstraintManager(vrp, stateManager);
|
||||
ShipmentInsertionCalculator insertionCalculator = new ShipmentInsertionCalculator(new ManhattanCosts() {
|
||||
@Override
|
||||
public double getTransportTime(Location from, Location to, double departureTime, Driver driver, Vehicle vehicle) {
|
||||
return (to.getId() != null && to.getId().equals("break")) ? .0 : super.getTransportTime(from, to, departureTime, driver, vehicle);
|
||||
}
|
||||
}, activityCosts,
|
||||
activityInsertionCostsCalculator, constraintManager);
|
||||
insertionCalculator.setJobActivityFactory(vrp.getJobActivityFactory());
|
||||
|
||||
InsertionData iData = insertionCalculator.getInsertionData(route, shipment, vehicle, 0.0, null, Double.MAX_VALUE);
|
||||
assertEquals(0, iData.getPickupInsertionIndex());
|
||||
assertEquals(0, iData.getDeliveryInsertionIndex());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
package com.graphhopper.jsprit.core.problem.job;
|
||||
|
||||
import com.graphhopper.jsprit.core.problem.Location;
|
||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class BreakForMultipleTimeWindowsTest {
|
||||
|
||||
@Test
|
||||
public void breakCreatedWithDriverIdAndSkills() {
|
||||
final String serviceId = UUID.randomUUID().toString();
|
||||
final String skill = UUID.randomUUID().toString();
|
||||
final BreakForMultipleTimeWindows breakForMultipleTimeWindows =
|
||||
BreakForMultipleTimeWindows.Builder.newInstance(serviceId)
|
||||
.setLocation(Location.newInstance(-0.25, 0.25))
|
||||
.addTimeWindow(0, 60)
|
||||
.setServiceTime(20)
|
||||
.addRequiredSkill(skill)
|
||||
.setPriority(1)
|
||||
.build();
|
||||
|
||||
assertTrue(breakForMultipleTimeWindows.getRequiredSkills().containsSkill(skill));
|
||||
assertEquals(Location.newInstance(-0.25, 0.25), breakForMultipleTimeWindows.getLocation());
|
||||
assertEquals(new TimeWindow(0, 60), breakForMultipleTimeWindows.getTimeWindow());
|
||||
assertEquals(20, breakForMultipleTimeWindows.getServiceDuration(), .0001);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue