1
0
Fork 0
mirror of https://github.com/graphhopper/jsprit.git synced 2020-01-24 07:45:05 +01:00

Merge branch 'master' into bicycle-messenger

Conflicts:
	jsprit-examples/src/main/java/jsprit/examples/BicycleMessenger.java
This commit is contained in:
Stefan Schroeder 2013-12-03 17:16:20 +01:00
commit 70ff6a83d7
24 changed files with 1904 additions and 212 deletions

View file

@ -22,6 +22,7 @@ import java.util.List;
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.solution.route.activity.End;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.vehicle.Vehicle;
@ -33,10 +34,10 @@ final class AuxilliaryCostCalculator {
private final VehicleRoutingActivityCosts activityCosts;
public AuxilliaryCostCalculator(final VehicleRoutingTransportCosts routingCosts, final VehicleRoutingActivityCosts costFunction) {
public AuxilliaryCostCalculator(final VehicleRoutingTransportCosts routingCosts, final VehicleRoutingActivityCosts actCosts) {
super();
this.routingCosts = routingCosts;
this.activityCosts = costFunction;
this.activityCosts = actCosts;
}
/**
@ -59,6 +60,11 @@ final class AuxilliaryCostCalculator {
double departureTimePrevAct = depTime;
while(actIter.hasNext()){
TourActivity act = actIter.next();
if(act instanceof End){
if(!vehicle.isReturnToDepot()){
return cost;
}
}
double transportCost = routingCosts.getTransportCost(prevAct.getLocationId(), act.getLocationId(), departureTimePrevAct, driver, vehicle);
double transportTime = routingCosts.getTransportTime(prevAct.getLocationId(), act.getLocationId(), departureTimePrevAct, driver, vehicle);
cost += transportCost;
@ -72,37 +78,5 @@ final class AuxilliaryCostCalculator {
return cost;
}
public double costOfPath(String startLocationId, final double startTime, final List<TourActivity> path, String endLocationId, final Driver driver, final Vehicle vehicle){
if(path.isEmpty()){
return 0.0;
}
double cost = 0.0;
// Iterator<TourActivity> actIter = path.iterator();
String prevActLocation = startLocationId;
// TourActivity prevAct = actIter.next();
double startCost = 0.0;
cost += startCost;
double departureTimePrevAct = startTime;
for(TourActivity act : path){
// TourActivity act = actIter.next();
double transportCost = routingCosts.getTransportCost(prevActLocation, act.getLocationId(), departureTimePrevAct, driver, vehicle);
double transportTime = routingCosts.getTransportTime(prevActLocation, act.getLocationId(), departureTimePrevAct, driver, vehicle);
cost += transportCost;
double actStartTime = departureTimePrevAct + transportTime;
double earliestOperationStartTime = Math.max(actStartTime, act.getTheoreticalEarliestOperationStartTime());
double actEndTime = earliestOperationStartTime + act.getOperationTime();
departureTimePrevAct = actEndTime;
cost += activityCosts.getActivityCost(act, actStartTime, driver, vehicle);
prevActLocation = act.getLocationId();
}
/*
*!!! ENDLOCATION
=> Start u. End können primitiv sein.
*/
return cost;
}
}

View file

@ -72,7 +72,6 @@ class Inserter {
}
private void setEndLocation(VehicleRoute route, Service service) {
route.getEnd().setCoordinate(service.getCoord());
route.getEnd().setLocationId(service.getLocationId());
}
@ -106,7 +105,6 @@ class Inserter {
}
private void setEndLocation(VehicleRoute route, Shipment shipment) {
route.getEnd().setCoordinate(shipment.getDeliveryCoord());
route.getEnd().setLocationId(shipment.getDeliveryLocation());
}

View file

@ -25,9 +25,7 @@ import java.util.Map;
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Delivery;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Pickup;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.job.Shipment;
import jsprit.core.problem.solution.route.activity.TourActivity;
@ -64,9 +62,11 @@ public class VehicleRoutingProblem {
*
* <p>DELIVERIES_FIRST corresponds to the vehicle routing problem with back hauls, i.e. before a vehicle is not entirely unloaded, no pickup can be made.
*
* @deprecated define constraint directly - since constraints are too diverse to put them in an enum
* @author stefan
*
*/
@Deprecated
public enum Constraint {
DELIVERIES_FIRST
}
@ -186,12 +186,6 @@ public class VehicleRoutingProblem {
};
}
public void addProblemConstraint(Constraint constraint){
if(!problemConstraints.contains(constraint)) problemConstraints.add(constraint);
}
/**
* Sets routing costs.
*
@ -218,39 +212,6 @@ public class VehicleRoutingProblem {
return this;
}
/**
* Sets the fleetComposition.
*
* <p>FleetComposition is either FleetComposition.HETEROGENEOUS or FleetComposition.HOMOGENEOUS
*
* @deprecated has no effect
* @param fleetComposition
* @return
*/
@Deprecated
public Builder setFleetComposition(FleetComposition fleetComposition){
this.fleetComposition = fleetComposition;
return this;
}
/**
* Adds a service to jobList.
*
* <p>If jobList already contains service, a warning message is printed, and the existing job will be overwritten.
*
* @deprecated use addJob(...) instead
* @param service
* @return
*/
@Deprecated
public Builder addService(Service service){
coordinates.put(service.getLocationId(), service.getCoord());
if(jobs.containsKey(service.getId())){ logger.warn("service " + service + " already in job list. overrides existing job."); }
jobs.put(service.getId(),service);
services.add(service);
return this;
}
/**
* Adds a job which is either a service or a shipment.
*
@ -297,30 +258,6 @@ public class VehicleRoutingProblem {
return this;
}
/**
* Adds a vehicleType.
*
* @deprecated use add vehicle instead
* @param type
* @return builder
*/
@Deprecated
public Builder addVehicleType(VehicleType type){
vehicleTypes.add(type);
return this;
}
/**
* Sets the neighborhood.
*
* @param neighborhood
* @return
*/
public Builder setNeighborhood(Neighborhood neighborhood){
this.neighborhood = neighborhood;
return this;
}
/**
* Sets the activityCostFunction that considers also activities on a vehicle-route.
*
@ -391,8 +328,15 @@ public class VehicleRoutingProblem {
return Collections.unmodifiableCollection(vehicles);
}
public void addConstraint(jsprit.core.problem.constraint.Constraint constraint){
/**
* Adds constraint to problem.
*
* @param constraint
* @return
*/
public Builder addConstraint(jsprit.core.problem.constraint.Constraint constraint){
constraints.add(constraint);
return this;
}
/**
@ -407,6 +351,75 @@ public class VehicleRoutingProblem {
public Collection<Job> getAddedJobs(){
return Collections.unmodifiableCollection(jobs.values());
}
/**
* Sets the fleetComposition.
*
* <p>FleetComposition is either FleetComposition.HETEROGENEOUS or FleetComposition.HOMOGENEOUS
*
* @deprecated has no effect
* @param fleetComposition
* @return
*/
@Deprecated
public Builder setFleetComposition(FleetComposition fleetComposition){
this.fleetComposition = fleetComposition;
return this;
}
/**
* Adds a service to jobList.
*
* <p>If jobList already contains service, a warning message is printed, and the existing job will be overwritten.
*
* @deprecated use addJob(...) instead
* @param service
* @return
*/
@Deprecated
public Builder addService(Service service){
coordinates.put(service.getLocationId(), service.getCoord());
if(jobs.containsKey(service.getId())){ logger.warn("service " + service + " already in job list. overrides existing job."); }
jobs.put(service.getId(),service);
services.add(service);
return this;
}
/**
* Adds a vehicleType.
*
* @deprecated use add vehicle instead
* @param type
* @return builder
*/
@Deprecated
public Builder addVehicleType(VehicleType type){
vehicleTypes.add(type);
return this;
}
/**
* Sets the neighborhood.
*
* @deprecated use HardRoute- or ActivityLevelConstraint instead
* @param neighborhood
* @return
*/
@Deprecated
public Builder setNeighborhood(Neighborhood neighborhood){
this.neighborhood = neighborhood;
return this;
}
/**
*
* @deprecated use .addConstraint(new ServiceDeliveriesFirstConstraint())
* @param constraint
*/
@Deprecated
public void addProblemConstraint(Constraint constraint){
if(!problemConstraints.contains(constraint)) problemConstraints.add(constraint);
}
}
/**
@ -485,13 +498,6 @@ public class VehicleRoutingProblem {
"transportCost="+transportCosts+"][activityCosts="+activityCosts+"]";
}
/**
* @return the neighborhood
*/
public Neighborhood getNeighborhood() {
return neighborhood;
}
/**
* Returns fleet-composition.
*
@ -521,15 +527,6 @@ public class VehicleRoutingProblem {
return Collections.unmodifiableMap(jobs);
}
/**
* Returns unmodifiable collection of problem-constraints.
*
* @return
*/
public Collection<Constraint> getProblemConstraints(){
return Collections.unmodifiableCollection(problemConstraints);
}
/**
* Returns the entire, unmodifiable collection of types.
*
@ -568,9 +565,34 @@ public class VehicleRoutingProblem {
return activityCosts;
}
/**
* Returns an unmodifiable collection of constraints.
*
* @return
*/
public Collection<jsprit.core.problem.constraint.Constraint> getConstraints(){
return Collections.unmodifiableCollection(constraints);
}
/**
* @deprecated see builder.setNeighborhood(...). addConstraint(...) instead.
* @return the neighborhood
*/
@Deprecated
public Neighborhood getNeighborhood() {
return neighborhood;
}
/**
* Returns unmodifiable collection of problem-constraints.
*
* @deprecated use .getConstraints() and builder.add
* @return
*/
@Deprecated
public Collection<Constraint> getProblemConstraints(){
return Collections.unmodifiableCollection(problemConstraints);
}
}

View file

@ -1,8 +1,9 @@
package jsprit.core.problem.constraint;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.log4j.Logger;
import java.util.Collections;
import java.util.List;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.VehicleRoutingProblem.Constraint;
@ -10,6 +11,8 @@ import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
import org.apache.log4j.Logger;
public class ConstraintManager implements HardActivityStateLevelConstraint, HardRouteStateLevelConstraint{
public static enum Priority {
@ -96,4 +99,11 @@ public class ConstraintManager implements HardActivityStateLevelConstraint, Hard
return actLevelConstraintManager.fulfilled(iFacts, prevAct, newAct, nextAct, prevActDepTime);
}
public Collection<jsprit.core.problem.constraint.Constraint> getConstraints(){
List<jsprit.core.problem.constraint.Constraint> constraints = new ArrayList<jsprit.core.problem.constraint.Constraint>();
constraints.addAll(actLevelConstraintManager.getAllConstraints());
constraints.addAll(routeLevelConstraintManager.getConstraints());
return Collections.unmodifiableCollection(constraints);
}
}

View file

@ -2,6 +2,8 @@ package jsprit.core.problem.constraint;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import jsprit.core.problem.constraint.ConstraintManager.Priority;
import jsprit.core.problem.misc.JobInsertionContext;
@ -28,6 +30,20 @@ class HardActivityLevelConstraintManager implements HardActivityStateLevelConstr
}
}
Collection<HardActivityStateLevelConstraint> getCriticalConstraints(){ return Collections.unmodifiableCollection(criticalConstraints); }
Collection<HardActivityStateLevelConstraint> getHighPrioConstraints(){ return Collections.unmodifiableCollection(highPrioConstraints); }
Collection<HardActivityStateLevelConstraint> getLowPrioConstraints(){ return Collections.unmodifiableCollection(lowPrioConstraints); }
Collection<HardActivityStateLevelConstraint> getAllConstraints(){
List<HardActivityStateLevelConstraint> c = new ArrayList<HardActivityStateLevelConstraint>();
c.addAll(criticalConstraints);
c.addAll(highPrioConstraints);
c.addAll(lowPrioConstraints);
return Collections.unmodifiableCollection(c);
}
@Override
public ConstraintsStatus fulfilled(JobInsertionContext iFacts, TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
ConstraintsStatus notFulfilled = null;

View file

@ -2,6 +2,7 @@ package jsprit.core.problem.constraint;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import jsprit.core.problem.misc.JobInsertionContext;
@ -14,6 +15,8 @@ class HardRouteLevelConstraintManager implements HardRouteStateLevelConstraint {
hardConstraints.add(constraint);
}
Collection<HardRouteStateLevelConstraint> getConstraints(){ return Collections.unmodifiableCollection(hardConstraints); }
@Override
public boolean fulfilled(JobInsertionContext insertionContext) {
for(HardRouteStateLevelConstraint constraint : hardConstraints){

View file

@ -35,11 +35,11 @@ public final class End implements TourActivity {
private Coordinate coordinate;
public Coordinate getCoordinate() {
Coordinate getCoordinate() {
return coordinate;
}
public void setCoordinate(Coordinate coordinate) {
void setCoordinate(Coordinate coordinate) {
this.coordinate = coordinate;
}

View file

@ -65,11 +65,11 @@ public final class Start implements TourActivity {
public Coordinate getCoordinate() {
Coordinate getCoordinate() {
return coordinate;
}
public void setCoordinate(Coordinate coordinate) {
void setCoordinate(Coordinate coordinate) {
this.coordinate = coordinate;
}

View file

@ -45,6 +45,14 @@ public class VehicleImpl implements Vehicle {
}
/**
* builds the vehicle.
*
* <p>by default, it returns to the depot.
*
* @author stefan
*
*/
public static class Builder {
static Logger log = Logger.getLogger(Builder.class);
private String id;

View file

@ -0,0 +1,103 @@
package jsprit.core.algorithm.recreate;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.Arrays;
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.solution.route.activity.End;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.vehicle.Vehicle;
import org.junit.Before;
import org.junit.Test;
public class TestAuxilliaryCostCalculator {
private VehicleRoutingTransportCosts routingCosts;
private VehicleRoutingActivityCosts actCosts;
private Vehicle vehicle;
@Before
public void doBefore(){
vehicle = mock(Vehicle.class);
routingCosts = mock(VehicleRoutingTransportCosts.class);
actCosts = mock(VehicleRoutingActivityCosts.class);
when(routingCosts.getTransportCost("i", "j", 0.0, null, vehicle)).thenReturn(2.0);
when(routingCosts.getTransportTime("i", "j", 0.0, null, vehicle)).thenReturn(0.0);
when(routingCosts.getTransportCost("i", "k", 0.0, null, vehicle)).thenReturn(3.0);
when(routingCosts.getTransportTime("i", "k", 0.0, null, vehicle)).thenReturn(0.0);
when(routingCosts.getTransportCost("k", "j", 0.0, null, vehicle)).thenReturn(3.0);
when(routingCosts.getTransportTime("k", "j", 0.0, null, vehicle)).thenReturn(0.0);
}
@Test
public void whenRouteIsClosed_itCalculatesCostUpToEnd_v1(){
TourActivity prevAct = mock(TourActivity.class);
when(prevAct.getLocationId()).thenReturn("i");
TourActivity nextAct = mock(TourActivity.class);
when(nextAct.getLocationId()).thenReturn("j");
TourActivity newAct = mock(TourActivity.class);
when(newAct.getLocationId()).thenReturn("k");
when(vehicle.isReturnToDepot()).thenReturn(true);
AuxilliaryCostCalculator aCalc = new AuxilliaryCostCalculator(routingCosts, actCosts);
double costs = aCalc.costOfPath(Arrays.asList(prevAct,newAct,nextAct), 0.0, null, vehicle);
assertEquals(6.0,costs,0.01);
}
@Test
public void whenRouteIsClosed_itCalculatesCostUpToEnd_v2(){
TourActivity prevAct = mock(TourActivity.class);
when(prevAct.getLocationId()).thenReturn("i");
End nextAct = End.newInstance("j", 0.0, 0.0);
TourActivity newAct = mock(TourActivity.class);
when(newAct.getLocationId()).thenReturn("k");
when(vehicle.isReturnToDepot()).thenReturn(true);
AuxilliaryCostCalculator aCalc = new AuxilliaryCostCalculator(routingCosts, actCosts);
double costs = aCalc.costOfPath(Arrays.asList(prevAct,newAct,nextAct), 0.0, null, vehicle);
assertEquals(6.0,costs,0.01);
}
@Test
public void whenRouteIsOpen_itCalculatesCostUpToEnd_v1(){
TourActivity prevAct = mock(TourActivity.class);
when(prevAct.getLocationId()).thenReturn("i");
TourActivity nextAct = mock(TourActivity.class);
when(nextAct.getLocationId()).thenReturn("j");
TourActivity newAct = mock(TourActivity.class);
when(newAct.getLocationId()).thenReturn("k");
when(vehicle.isReturnToDepot()).thenReturn(false);
AuxilliaryCostCalculator aCalc = new AuxilliaryCostCalculator(routingCosts, actCosts);
double costs = aCalc.costOfPath(Arrays.asList(prevAct,newAct,nextAct), 0.0, null, vehicle);
assertEquals(6.0,costs,0.01);
}
@Test
public void whenRouteIsOpen_itCalculatesCostUpToEnd_v2(){
TourActivity prevAct = mock(TourActivity.class);
when(prevAct.getLocationId()).thenReturn("i");
End nextAct = End.newInstance("j", 0.0, 0.0);
TourActivity newAct = mock(TourActivity.class);
when(newAct.getLocationId()).thenReturn("k");
when(vehicle.isReturnToDepot()).thenReturn(false);
AuxilliaryCostCalculator aCalc = new AuxilliaryCostCalculator(routingCosts, actCosts);
double costs = aCalc.costOfPath(Arrays.asList(prevAct,newAct,nextAct), 0.0, null, vehicle);
assertEquals(3.0,costs,0.01);
}
}

View file

@ -267,9 +267,6 @@ public class TestCalculatesServiceInsertion {
assertEquals(2, iData.getDeliveryInsertionIndex());
}
@Test
public void whenInsertingAndRouteIsOpen(){
assertTrue(false);
}
}

View file

@ -83,12 +83,14 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
when(vehicle.getLocationId()).thenReturn("0,0");
when(vehicle.getEarliestDeparture()).thenReturn(0.0);
when(vehicle.getLatestArrival()).thenReturn(100.0);
when(vehicle.isReturnToDepot()).thenReturn(true);
newVehicle = mock(Vehicle.class);
when(newVehicle.getCapacity()).thenReturn(1000);
when(newVehicle.getLocationId()).thenReturn("0,0");
when(newVehicle.getEarliestDeparture()).thenReturn(0.0);
when(newVehicle.getLatestArrival()).thenReturn(100.0);
when(newVehicle.isReturnToDepot()).thenReturn(true);
driver = DriverImpl.noDriver();
@ -240,10 +242,5 @@ public class TestCalculatesServiceInsertionOnRouteLevel {
assertEquals(2, iData.getDeliveryInsertionIndex());
}
@Test
public void whenInsertingAndRouteIsOpen(){
assertTrue(false);
}
}

View file

@ -1,7 +1,122 @@
package jsprit.core.algorithm.recreate;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import jsprit.core.algorithm.recreate.listener.InsertionListeners;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Service;
import jsprit.core.problem.job.Shipment;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
import org.junit.Test;
public class TestInserter {
@Test
public void whenInsertingServiceAndRouteIsClosed_itInsertsCorrectly(){
Service service = mock(Service.class);
Vehicle vehicle = mock(Vehicle.class);
when(vehicle.getLocationId()).thenReturn("vehLoc");
when(vehicle.isReturnToDepot()).thenReturn(true);
when(vehicle.getId()).thenReturn("vehId");
VehicleRoute route = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)).addService(service).build();
//start - pick(shipment) - del(shipment) - end
Service serviceToInsert = mock(Service.class);
when(serviceToInsert.getLocationId()).thenReturn("delLoc");
InsertionData iData = mock(InsertionData.class);
when(iData.getDeliveryInsertionIndex()).thenReturn(1);
when(iData.getSelectedVehicle()).thenReturn(vehicle);
Inserter inserter = new Inserter(mock(InsertionListeners.class));
inserter.insertJob(serviceToInsert, iData, route);
assertEquals(2,route.getTourActivities().getActivities().size());
assertEquals(route.getTourActivities().getActivities().get(1).getLocationId(),serviceToInsert.getLocationId());
assertEquals(route.getEnd().getLocationId(),vehicle.getLocationId());
}
@Test
public void whenInsertingServiceAndRouteIsOpen_itInsertsCorrectlyAndSwitchesEndLocation(){
Service service = mock(Service.class);
Vehicle vehicle = mock(Vehicle.class);
when(vehicle.getLocationId()).thenReturn("vehLoc");
when(vehicle.isReturnToDepot()).thenReturn(false);
when(vehicle.getId()).thenReturn("vehId");
VehicleRoute route = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)).addService(service).build();
Service serviceToInsert = mock(Service.class);
when(serviceToInsert.getLocationId()).thenReturn("delLoc");
InsertionData iData = mock(InsertionData.class);
when(iData.getDeliveryInsertionIndex()).thenReturn(1);
when(iData.getSelectedVehicle()).thenReturn(vehicle);
Inserter inserter = new Inserter(mock(InsertionListeners.class));
inserter.insertJob(serviceToInsert, iData, route);
assertEquals(2,route.getTourActivities().getActivities().size());
assertEquals(route.getTourActivities().getActivities().get(1).getLocationId(),serviceToInsert.getLocationId());
assertEquals(route.getEnd().getLocationId(),serviceToInsert.getLocationId());
}
@Test
public void whenInsertingShipmentAndRouteIsClosed_itInsertsCorrectly(){
Shipment shipment = mock(Shipment.class);
Vehicle vehicle = mock(Vehicle.class);
when(vehicle.getLocationId()).thenReturn("vehLoc");
when(vehicle.isReturnToDepot()).thenReturn(true);
when(vehicle.getId()).thenReturn("vehId");
VehicleRoute route = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)).addPickup(shipment).addDelivery(shipment).build();
//start - pick(shipment) - del(shipment) - end
Shipment shipmentToInsert = mock(Shipment.class);
when(shipmentToInsert.getDeliveryLocation()).thenReturn("delLoc");
when(shipmentToInsert.getPickupLocation()).thenReturn("pickLoc");
InsertionData iData = mock(InsertionData.class);
when(iData.getPickupInsertionIndex()).thenReturn(2);
when(iData.getDeliveryInsertionIndex()).thenReturn(2);
when(iData.getSelectedVehicle()).thenReturn(vehicle);
Inserter inserter = new Inserter(mock(InsertionListeners.class));
inserter.insertJob(shipmentToInsert, iData, route);
assertEquals(4,route.getTourActivities().getActivities().size());
assertEquals(route.getTourActivities().getActivities().get(2).getLocationId(),shipmentToInsert.getPickupLocation());
assertEquals(route.getTourActivities().getActivities().get(3).getLocationId(),shipmentToInsert.getDeliveryLocation());
assertEquals(route.getEnd().getLocationId(),vehicle.getLocationId());
}
@Test
public void whenInsertingShipmentAndRouteIsOpen_itInsertsCorrectlyAndSwitchesEndLocation(){
Shipment shipment = mock(Shipment.class);
Vehicle vehicle = mock(Vehicle.class);
when(vehicle.getLocationId()).thenReturn("vehLoc");
when(vehicle.isReturnToDepot()).thenReturn(false);
when(vehicle.getId()).thenReturn("vehId");
VehicleRoute route = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)).addPickup(shipment).addDelivery(shipment).build();
//start - pick(shipment) - del(shipment) - end
Shipment shipmentToInsert = mock(Shipment.class);
when(shipmentToInsert.getDeliveryLocation()).thenReturn("delLoc");
when(shipmentToInsert.getPickupLocation()).thenReturn("pickLoc");
InsertionData iData = mock(InsertionData.class);
when(iData.getPickupInsertionIndex()).thenReturn(2);
when(iData.getDeliveryInsertionIndex()).thenReturn(2);
when(iData.getSelectedVehicle()).thenReturn(vehicle);
Inserter inserter = new Inserter(mock(InsertionListeners.class));
inserter.insertJob(shipmentToInsert, iData, route);
assertEquals(4,route.getTourActivities().getActivities().size());
assertEquals(route.getTourActivities().getActivities().get(2).getLocationId(),shipmentToInsert.getPickupLocation());
assertEquals(route.getTourActivities().getActivities().get(3).getLocationId(),shipmentToInsert.getDeliveryLocation());
assertEquals(route.getEnd().getLocationId(),shipmentToInsert.getDeliveryLocation());
}
}

View file

@ -0,0 +1,113 @@
package jsprit.core.algorithm.recreate;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import jsprit.core.algorithm.recreate.ActivityInsertionCostsCalculator.ActivityInsertionCosts;
import jsprit.core.problem.cost.VehicleRoutingActivityCosts;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.misc.JobInsertionContext;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.End;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.vehicle.Vehicle;
import org.junit.Before;
import org.junit.Test;
public class TestLocalActivityInsertionCostsCalculator {
VehicleRoutingTransportCosts tpCosts;
VehicleRoutingActivityCosts actCosts;
LocalActivityInsertionCostsCalculator calc;
Vehicle vehicle;
VehicleRoute route;
JobInsertionContext jic;
@Before
public void doBefore(){
vehicle = mock(Vehicle.class);
route = mock(VehicleRoute.class);
when(route.isEmpty()).thenReturn(false);
when(route.getVehicle()).thenReturn(vehicle);
jic = mock(JobInsertionContext.class);
when(jic.getRoute()).thenReturn(route);
when(jic.getNewVehicle()).thenReturn(vehicle);
tpCosts = mock(VehicleRoutingTransportCosts.class);
when(tpCosts.getTransportCost("i", "j", 0.0, null, vehicle)).thenReturn(2.0);
when(tpCosts.getTransportTime("i", "j", 0.0, null, vehicle)).thenReturn(0.0);
when(tpCosts.getTransportCost("i", "k", 0.0, null, vehicle)).thenReturn(3.0);
when(tpCosts.getTransportTime("i", "k", 0.0, null, vehicle)).thenReturn(0.0);
when(tpCosts.getTransportCost("k", "j", 0.0, null, vehicle)).thenReturn(3.0);
when(tpCosts.getTransportTime("k", "j", 0.0, null, vehicle)).thenReturn(0.0);
actCosts = mock(VehicleRoutingActivityCosts.class);
calc = new LocalActivityInsertionCostsCalculator(tpCosts, actCosts);
}
@Test
public void whenInsertingActBetweenTwoRouteActs_itCalcsMarginalTpCosts(){
TourActivity prevAct = mock(TourActivity.class);
when(prevAct.getLocationId()).thenReturn("i");
TourActivity nextAct = mock(TourActivity.class);
when(nextAct.getLocationId()).thenReturn("j");
TourActivity newAct = mock(TourActivity.class);
when(newAct.getLocationId()).thenReturn("k");
when(vehicle.isReturnToDepot()).thenReturn(true);
ActivityInsertionCosts costs = calc.getCosts(jic, prevAct, nextAct, newAct, 0.0);
assertEquals(4.0,costs.getAdditionalCosts(),0.01);
}
@Test
public void whenInsertingActBetweenLastActAndEnd_itCalcsMarginalTpCosts(){
TourActivity prevAct = mock(TourActivity.class);
when(prevAct.getLocationId()).thenReturn("i");
End nextAct = End.newInstance("j", 0.0, 0.0);
TourActivity newAct = mock(TourActivity.class);
when(newAct.getLocationId()).thenReturn("k");
when(vehicle.isReturnToDepot()).thenReturn(true);
ActivityInsertionCosts costs = calc.getCosts(jic, prevAct, nextAct, newAct, 0.0);
assertEquals(4.0,costs.getAdditionalCosts(),0.01);
}
@Test
public void whenInsertingActBetweenTwoRouteActsAndRouteIsOpen_itCalcsMarginalTpCosts(){
TourActivity prevAct = mock(TourActivity.class);
when(prevAct.getLocationId()).thenReturn("i");
TourActivity nextAct = mock(TourActivity.class);
when(nextAct.getLocationId()).thenReturn("j");
TourActivity newAct = mock(TourActivity.class);
when(newAct.getLocationId()).thenReturn("k");
when(vehicle.isReturnToDepot()).thenReturn(false);
ActivityInsertionCosts costs = calc.getCosts(jic, prevAct, nextAct, newAct, 0.0);
assertEquals(4.0,costs.getAdditionalCosts(),0.01);
}
@Test
public void whenInsertingActBetweenLastActAndEndAndRouteIsOpen_itCalculatesTpCostsFromPrevToNewAct(){
TourActivity prevAct = mock(TourActivity.class);
when(prevAct.getLocationId()).thenReturn("i");
End nextAct = End.newInstance("j", 0.0, 0.0);
TourActivity newAct = mock(TourActivity.class);
when(newAct.getLocationId()).thenReturn("k");
when(vehicle.isReturnToDepot()).thenReturn(false);
ActivityInsertionCosts costs = calc.getCosts(jic, prevAct, nextAct, newAct, 0.0);
assertEquals(3.0,costs.getAdditionalCosts(),0.01);
}
}

View file

@ -17,8 +17,9 @@
package jsprit.core.problem;
import static org.junit.Assert.assertEquals;
import jsprit.core.problem.VehicleRoutingProblem;
import static org.mockito.Mockito.mock;
import jsprit.core.problem.VehicleRoutingProblem.FleetSize;
import jsprit.core.problem.constraint.Constraint;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Shipment;
import jsprit.core.problem.vehicle.Vehicle;
@ -82,5 +83,15 @@ public class VehicleRoutingProblemBuilderTest {
assertEquals(s2,vrp.getJobs().get("s2"));
}
@Test
public void whenConstraintsAdded_theyShouldAppearInConstraintCollection(){
Constraint c1 = mock(Constraint.class);
Constraint c2 = mock(Constraint.class);
VehicleRoutingProblem.Builder builder = VehicleRoutingProblem.Builder.newInstance();
builder.addConstraint(c1).addConstraint(c2);
VehicleRoutingProblem problem = builder.build();
assertEquals(2,problem.getConstraints().size());
}
}

View file

@ -0,0 +1,34 @@
package jsprit.core.problem.constraint;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import java.util.ArrayList;
import java.util.List;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
import org.junit.Test;
public class TestConstraintManager {
@Test
public void whenGettingConstraintsViaConstructor_theyShouldBeResolvedCorrectly(){
List<Constraint> constraints = new ArrayList<Constraint>();
constraints.add(new ServiceDeliveriesFirstConstraint());
constraints.add(mock(HardRouteStateLevelConstraint.class));
ConstraintManager cManager = new ConstraintManager(mock(VehicleRoutingProblem.class),mock(RouteAndActivityStateGetter.class),constraints);
assertEquals(2,cManager.getConstraints().size());
}
@Test
public void whenGettingConstraintsViaConstructorAndAtLeastOneConstraintCannotBeResolved_itShouldOnlyAddTheKnownConstraints(){
List<Constraint> constraints = new ArrayList<Constraint>();
constraints.add(new ServiceDeliveriesFirstConstraint());
constraints.add(mock(Constraint.class));
ConstraintManager cManager = new ConstraintManager(mock(VehicleRoutingProblem.class),mock(RouteAndActivityStateGetter.class),constraints);
assertEquals(1,cManager.getConstraints().size());
}
}

View file

@ -1,8 +1,8 @@
package jsprit.core.problem.solution.route;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.job.Shipment;
import jsprit.core.problem.vehicle.Vehicle;
@ -60,18 +60,73 @@ public class VehicleRouteBuilderTest {
}
@Test
public void whenBuildingOpenRoute(){
assertTrue(false);
public void whenBuildingClosedRoute_routeEndShouldHaveLocationOfVehicle(){
Shipment s = mock(Shipment.class);
Shipment s2 = mock(Shipment.class);
Vehicle vehicle = mock(Vehicle.class);
when(vehicle.isReturnToDepot()).thenReturn(true);
when(vehicle.getLocationId()).thenReturn("vehLoc");
VehicleRoute.Builder builder = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class));
builder.addPickup(s);
builder.addPickup(s2);
builder.addDelivery(s);
builder.addDelivery(s2);
VehicleRoute route = builder.build();
assertEquals(route.getEnd().getLocationId(), vehicle.getLocationId());
}
@Test
public void whenBuildingOpenRoute_routeEndShouldHaveLocationOfLastActivity(){
Shipment s = mock(Shipment.class);
Shipment s2 = mock(Shipment.class);
when(s2.getDeliveryLocation()).thenReturn("delLoc");
Vehicle vehicle = mock(Vehicle.class);
when(vehicle.isReturnToDepot()).thenReturn(false);
when(vehicle.getLocationId()).thenReturn("vehLoc");
VehicleRoute.Builder builder = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class));
builder.addPickup(s);
builder.addPickup(s2);
builder.addDelivery(s);
builder.addDelivery(s2);
VehicleRoute route = builder.build();
assertEquals(route.getEnd().getLocationId(), s2.getDeliveryLocation());
}
@Test
public void whenSettingDepartureTime(){
assertTrue(false);
Shipment s = mock(Shipment.class);
Shipment s2 = mock(Shipment.class);
when(s2.getDeliveryLocation()).thenReturn("delLoc");
Vehicle vehicle = mock(Vehicle.class);
when(vehicle.isReturnToDepot()).thenReturn(false);
when(vehicle.getLocationId()).thenReturn("vehLoc");
VehicleRoute.Builder builder = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class));
builder.addPickup(s);
builder.addPickup(s2);
builder.addDelivery(s);
builder.addDelivery(s2);
builder.setDepartureTime(100);
VehicleRoute route = builder.build();
assertEquals(100.0,route.getDepartureTime(),0.01);
assertEquals(100.0,route.getStart().getEndTime(),0.01);
}
@Test
public void whenSettingEndTime(){
assertTrue(false);
Shipment s = mock(Shipment.class);
Shipment s2 = mock(Shipment.class);
when(s2.getDeliveryLocation()).thenReturn("delLoc");
Vehicle vehicle = mock(Vehicle.class);
when(vehicle.isReturnToDepot()).thenReturn(false);
when(vehicle.getLocationId()).thenReturn("vehLoc");
VehicleRoute.Builder builder = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class));
builder.addPickup(s);
builder.addPickup(s2);
builder.addDelivery(s);
builder.addDelivery(s2);
builder.setRouteEndArrivalTime(100.0);
VehicleRoute route = builder.build();
assertEquals(100.0,route.getEnd().getArrTime(),0.01);
}
}

View file

@ -1,31 +0,0 @@
item id pickup_x pickup_y deliver_x deliver_y
envelope 1 13745 55419 13883 55756
envelope 2 8406 53246 13937 55854
envelope 3 15738 57396 35996 79499
envelope 4 12045 60418 19349 57118
envelope 5 13750 56416 35733 78403
envelope 6 13190 57068 11860 59749
envelope 7 15021 55768 14098 57379
envelope 8 11513 58543 11501 59683
envelope 9 12013 64155 14120 59301
envelope 10 15006 57578 35511 78426
envelope 11 11450 58819 11916 58338
envelope 12 13728 56304 35524 79013
envelope 13 15104 60923 17937 57066
envelope 14 11373 58388 13983 53804
envelope 15 18575 55186 18718 54381
envelope 16 11639 50071 17363 58375
envelope 17 11273 53410 10860 60441
envelope 18 13766 59041 13963 57769
envelope 19 16138 55801 16183 56024
envelope 20 13728 56146 14301 61694
envelope 21 12848 57059 13586 59734
envelope 22 13645 56488 13955 55859
envelope 23 12896 56838 13937 55908
envelope 24 13341 58150 35709 78924
envelope 25 13483 57303 13614 57820
envelope 26 12741 63478 15230 59838
envelope 27 14676 51691 16501 48361
envelope 28 13748 54933 14120 56110
envelope 29 17875 59565 20453 61903
envelope 30 9772 56424 6404 55601

View file

@ -1,6 +0,0 @@
type id x y
messenger A 13750 57578
messenger B 15104 53410
messenger C 13728 55801
messenger D 12741 63478
messenger E 14676 18575

File diff suppressed because it is too large Load diff

View file

@ -4,9 +4,7 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -19,8 +17,10 @@ import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.VehicleRoutingProblem.Builder;
import jsprit.core.problem.VehicleRoutingProblem.FleetSize;
import jsprit.core.problem.constraint.HardActivityStateLevelConstraint;
import jsprit.core.problem.constraint.HardRouteStateLevelConstraint;
import jsprit.core.problem.cost.VehicleRoutingTransportCosts;
import jsprit.core.problem.driver.DriverImpl;
import jsprit.core.problem.io.VrpXMLWriter;
import jsprit.core.problem.job.Job;
import jsprit.core.problem.job.Shipment;
import jsprit.core.problem.misc.JobInsertionContext;
@ -39,42 +39,22 @@ public class BicycleMessenger {
static class ThreeTimesLessThanDirectRouteConstraint implements HardActivityStateLevelConstraint {
private VehicleRoutingTransportCosts vrpCosts;
private VehicleRoutingTransportCosts routingCosts;
//jobId map direct-distance by nearestMessenger
private Map<String,Double> bestMessengers = new HashMap<String, Double>();
public ThreeTimesLessThanDirectRouteConstraint(VehicleRoutingTransportCosts vrpCosts, Collection<Job> envelopes, Collection<Vehicle> messengers) {
super();
this.vrpCosts = vrpCosts;
determineNearestMessenger(envelopes,messengers);
}
private void determineNearestMessenger(Collection<Job> envelopes,Collection<Vehicle> messengers) {
for(Job envelope : envelopes){
double minDirect = Double.MAX_VALUE;
for(Vehicle m : messengers){
double direct = getDirectRouteDistance(envelope,m);
if(direct < minDirect){
minDirect = direct;
}
}
bestMessengers.put(envelope.getId(), minDirect);
}
}
private double getDirectRouteDistance(Job job, Vehicle v) {
Shipment envelope = (Shipment) job;
double direct = vrpCosts.getTransportTime(v.getLocationId(), envelope.getPickupLocation(), 0.0, DriverImpl.noDriver(), v) +
vrpCosts.getTransportTime(envelope.getPickupLocation(), envelope.getDeliveryLocation(), 0.0, DriverImpl.noDriver(), v);
return direct;
public ThreeTimesLessThanDirectRouteConstraint(Map<String, Double> nearestMessengers, VehicleRoutingTransportCosts routingCosts) {
this.bestMessengers = nearestMessengers;
this.routingCosts = routingCosts;
}
@Override
public ConstraintsStatus fulfilled(JobInsertionContext iFacts,TourActivity prevAct, TourActivity newAct, TourActivity nextAct, double prevActDepTime) {
if(newAct instanceof DeliverShipment){
double deliveryTime = prevActDepTime + vrpCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
if(deliveryTime > 3 * bestMessengers.get(((DeliverShipment) newAct).getJob().getId())){
double deliveryTime = prevActDepTime + routingCosts.getTransportTime(prevAct.getLocationId(), newAct.getLocationId(), prevActDepTime, iFacts.getNewDriver(), iFacts.getNewVehicle());
double directTimeOfNearestMessenger = bestMessengers.get(((DeliverShipment) newAct).getJob().getId());
if(deliveryTime > 3 * directTimeOfNearestMessenger){
return ConstraintsStatus.NOT_FULFILLED_BREAK;
}
}
@ -83,21 +63,52 @@ public class BicycleMessenger {
}
static class IgnoreMessengerThatCanNeverMeetTimeRequirements implements HardRouteStateLevelConstraint {
private Map<String,Double> bestMessengers = new HashMap<String, Double>();
private VehicleRoutingTransportCosts routingCosts;
public IgnoreMessengerThatCanNeverMeetTimeRequirements(Map<String, Double> bestMessengers,VehicleRoutingTransportCosts routingCosts) {
super();
this.bestMessengers = bestMessengers;
this.routingCosts = routingCosts;
}
@Override
public boolean fulfilled(JobInsertionContext insertionContext) {
double timeOfDirectRoute = getTimeOfDirectRoute(insertionContext.getJob(), insertionContext.getNewVehicle(), routingCosts);
double timeOfNearestMessenger = bestMessengers.get(insertionContext.getJob().getId());
if(timeOfDirectRoute > 3 * timeOfNearestMessenger){
return false;
}
return true;
}
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
VehicleRoutingProblem.Builder problemBuilder = VehicleRoutingProblem.Builder.newInstance();
readEnvelopes(problemBuilder);
readMessengers(problemBuilder);
VehicleRoutingTransportCosts routingCosts = new CrowFlyCosts(problemBuilder.getLocations());
Map<String,Double> nearestMessengers = getNearestMessengers(routingCosts, problemBuilder.getAddedJobs(), problemBuilder.getAddedVehicles());
problemBuilder.setFleetSize(FleetSize.FINITE);
// problemBuilder.addConstraint(new ThreeTimesLessThanDirectRouteConstraint(new CrowFlyCosts(problemBuilder.getLocations()),problemBuilder.getAddedJobs(),problemBuilder.getAddedVehicles()));
problemBuilder.addConstraint(new ThreeTimesLessThanDirectRouteConstraint(nearestMessengers, routingCosts));
problemBuilder.addConstraint(new IgnoreMessengerThatCanNeverMeetTimeRequirements(nearestMessengers, routingCosts));
VehicleRoutingProblem bicycleMessengerProblem = problemBuilder.build();
VehicleRoutingAlgorithm algorithm = VehicleRoutingAlgorithms.readAndCreateAlgorithm(bicycleMessengerProblem, 5,"input/algorithmConfig_open.xml");
// algorithm.setPrematureAlgorithmTermination(new IterationWithoutImprovementTermination(200));
VehicleRoutingAlgorithm algorithm = VehicleRoutingAlgorithms.readAndCreateAlgorithm(bicycleMessengerProblem,"input/algorithmConfig_open.xml");
algorithm.setPrematureAlgorithmTermination(new IterationWithoutImprovementTermination(200));
Collection<VehicleRoutingProblemSolution> solutions = algorithm.searchSolutions();
SolutionPrinter.print(Solutions.bestOf(solutions));
@ -113,7 +124,31 @@ public class BicycleMessenger {
// plotter1.setBoundingBox(10000, 47500, 20000, 67500);
plotter1.plot("output/bicycleMessengerSolution.png", "bicycleMessenger");
new VrpXMLWriter(bicycleMessengerProblem, solutions).write("output/bicycleMessenger.xml");
}
static Map<String,Double> getNearestMessengers(VehicleRoutingTransportCosts routingCosts, Collection<Job> envelopes, Collection<Vehicle> messengers) {
Map<String,Double> nearestMessengers = new HashMap<String, Double>();
for(Job envelope : envelopes){
double minDirect = Double.MAX_VALUE;
for(Vehicle m : messengers){
double direct = getTimeOfDirectRoute(envelope, m, routingCosts);
if(direct < minDirect){
minDirect = direct;
}
}
nearestMessengers.put(envelope.getId(), minDirect);
}
return nearestMessengers;
}
static double getTimeOfDirectRoute(Job job, Vehicle v, VehicleRoutingTransportCosts routingCosts) {
Shipment envelope = (Shipment) job;
double direct = routingCosts.getTransportTime(v.getLocationId(), envelope.getPickupLocation(), 0.0, DriverImpl.noDriver(), v) +
routingCosts.getTransportTime(envelope.getPickupLocation(), envelope.getDeliveryLocation(), 0.0, DriverImpl.noDriver(), v);
return direct;
}
private static void readEnvelopes(Builder problemBuilder) throws IOException {
@ -134,7 +169,7 @@ public class BicycleMessenger {
BufferedReader reader = new BufferedReader(new FileReader(new File("input/bicycle_messenger_supply.txt")));
String line = null;
boolean firstLine = true;
VehicleType messengerType = VehicleTypeImpl.Builder.newInstance("messengerType", Integer.MAX_VALUE).setCostPerDistance(1).build();
VehicleType messengerType = VehicleTypeImpl.Builder.newInstance("messengerType", 15).setCostPerDistance(1).build();
while((line = reader.readLine()) != null){
if(firstLine) { firstLine = false; continue; }
String[] tokens = line.split("\\s+");

View file

@ -27,7 +27,6 @@ import jsprit.core.algorithm.selector.SelectBest;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.io.VrpXMLReader;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import jsprit.instance.reader.SolomonReader;
public class SolomonOpenExample {

View file

@ -28,6 +28,7 @@ import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
import jsprit.core.algorithm.selector.SelectBest;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.VehicleRoutingProblem.Constraint;
import jsprit.core.problem.constraint.ServiceDeliveriesFirstConstraint;
import jsprit.core.problem.io.VrpXMLReader;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
@ -62,7 +63,8 @@ public class VRPWithBackhaulsExample {
/*
* Finally, the problem can be built. By default, transportCosts are crowFlyDistances (as usually used for vrp-instances).
*/
vrpBuilder.addProblemConstraint(Constraint.DELIVERIES_FIRST);
// vrpBuilder.addProblemConstraint(Constraint.DELIVERIES_FIRST);
vrpBuilder.addConstraint(new ServiceDeliveriesFirstConstraint());
VehicleRoutingProblem vrp = vrpBuilder.build();

View file

@ -28,6 +28,7 @@ import jsprit.core.algorithm.io.VehicleRoutingAlgorithms;
import jsprit.core.algorithm.selector.SelectBest;
import jsprit.core.problem.VehicleRoutingProblem;
import jsprit.core.problem.VehicleRoutingProblem.Constraint;
import jsprit.core.problem.constraint.ServiceDeliveriesFirstConstraint;
import jsprit.core.problem.io.VrpXMLReader;
import jsprit.core.problem.solution.VehicleRoutingProblemSolution;
@ -62,7 +63,7 @@ public class VRPWithBackhaulsExample2 {
/*
* add the backhaul constraint to the problem
*/
vrpBuilder.addProblemConstraint(Constraint.DELIVERIES_FIRST);
vrpBuilder.addConstraint(new ServiceDeliveriesFirstConstraint());
/*
* Finally, the problem can be built. By default, transportCosts are crowFlyDistances (as usually used for vrp-instances).