mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
tests added
This commit is contained in:
parent
e64e4d2041
commit
efbf3c0362
2 changed files with 184 additions and 30 deletions
|
|
@ -25,14 +25,15 @@ import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
|
||||||
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingActivityCosts;
|
||||||
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
import com.graphhopper.jsprit.core.problem.cost.VehicleRoutingTransportCosts;
|
||||||
import com.graphhopper.jsprit.core.problem.cost.WaitingTimeCosts;
|
import com.graphhopper.jsprit.core.problem.cost.WaitingTimeCosts;
|
||||||
|
import com.graphhopper.jsprit.core.problem.driver.Driver;
|
||||||
|
import com.graphhopper.jsprit.core.problem.job.Delivery;
|
||||||
import com.graphhopper.jsprit.core.problem.job.Job;
|
import com.graphhopper.jsprit.core.problem.job.Job;
|
||||||
|
import com.graphhopper.jsprit.core.problem.job.Pickup;
|
||||||
import com.graphhopper.jsprit.core.problem.job.Service;
|
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.VehicleRoute;
|
||||||
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.vehicle.FiniteFleetManagerFactory;
|
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
|
||||||
import com.graphhopper.jsprit.core.problem.vehicle.Vehicle;
|
import com.graphhopper.jsprit.core.problem.vehicle.*;
|
||||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleFleetManager;
|
|
||||||
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
|
|
||||||
import com.graphhopper.jsprit.core.util.Coordinate;
|
import com.graphhopper.jsprit.core.util.Coordinate;
|
||||||
import com.graphhopper.jsprit.core.util.CostFactory;
|
import com.graphhopper.jsprit.core.util.CostFactory;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
|
@ -42,6 +43,7 @@ import org.junit.Test;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* unit tests to test vehicle dependent time window updater
|
* unit tests to test vehicle dependent time window updater
|
||||||
|
|
@ -268,5 +270,86 @@ public class UpdateVehicleDependentTimeWindowTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSquash () {
|
||||||
|
Location pickupLocation = Location.newInstance(random.nextDouble(), random.nextDouble());
|
||||||
|
final double fixedDurationInSameLocation = random.nextDouble(), activityDuration = 10 + random.nextDouble(), travelTime = random.nextDouble();
|
||||||
|
|
||||||
|
Pickup pickup = Pickup.Builder.newInstance("pick1").setLocation(pickupLocation).setTimeWindow(TimeWindow.newInstance(0, 40)).setServiceTime(activityDuration).build();
|
||||||
|
Pickup pickup2 = Pickup.Builder.newInstance("pick2").setLocation(pickupLocation).setTimeWindow(TimeWindow.newInstance(0, 40)).setServiceTime(activityDuration).build();
|
||||||
|
|
||||||
|
Delivery delivery = Delivery.Builder.newInstance("del1").setLocation(Location.newInstance(random.nextDouble(), random.nextDouble())).setTimeWindow(TimeWindow.newInstance(0, 40)).setServiceTime(activityDuration).build();
|
||||||
|
Delivery delivery2 = Delivery.Builder.newInstance("del2").setLocation(Location.newInstance(random.nextDouble(), random.nextDouble())).setTimeWindow(TimeWindow.newInstance(0, 40)).setServiceTime(activityDuration).build();
|
||||||
|
|
||||||
|
Vehicle vehicle = VehicleImpl.Builder.newInstance("v").setStartLocation(Location.newInstance(random.nextDouble(), random.nextDouble())).setType(VehicleTypeImpl.Builder.newInstance("type").build()).build();
|
||||||
|
|
||||||
|
VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance();
|
||||||
|
final VehicleRoutingProblem vrp = vrpBuilder.addJob(pickup).addJob(pickup2).addJob(delivery).addJob(delivery2).addVehicle(vehicle).setFleetSize(VehicleRoutingProblem.FleetSize.FINITE).build();
|
||||||
|
|
||||||
|
route = VehicleRoute.Builder.newInstance(vehicle, mock(Driver.class)).setJobActivityFactory(new JobActivityFactory() {
|
||||||
|
@Override
|
||||||
|
public List<AbstractActivity> createActivities(Job job) {
|
||||||
|
return vrp.copyAndGetActivities(job);
|
||||||
|
}
|
||||||
|
}).addService(pickup).addService(pickup2).addService(delivery).addService(delivery2).build();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
VehicleRoutingTransportCosts transportCosts = getTransportCosts(travelTime);
|
||||||
|
|
||||||
|
activityCosts = new WaitingTimeCosts() {
|
||||||
|
@Override
|
||||||
|
public double getActivityDuration(TourActivity prevAct, TourActivity tourAct, double arrivalTime, Driver driver, Vehicle vehicle) {
|
||||||
|
return prevAct != null && prevAct.getLocation().getCoordinate().equals(tourAct.getLocation().getCoordinate()) ? fixedDurationInSameLocation : tourAct.getOperationTime();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
stateManager = new StateManager(vrp);
|
||||||
|
|
||||||
|
final UpdateVehicleDependentPracticalTimeWindows timeWindowsUpdater = new UpdateVehicleDependentPracticalTimeWindows(stateManager, transportCosts, activityCosts);
|
||||||
|
timeWindowsUpdater.visit(route);
|
||||||
|
|
||||||
|
double latestArrivalAt4Act = 40,
|
||||||
|
latestArrivalAt3Act = latestArrivalAt4Act - activityDuration - travelTime,
|
||||||
|
latestArrivalAt2Act = latestArrivalAt3Act - fixedDurationInSameLocation - travelTime,
|
||||||
|
latestArrivalAt1Act = latestArrivalAt2Act - activityDuration;
|
||||||
|
|
||||||
|
assertEquals(stateManager.getActivityState(route.getActivities().get(3), vehicle, InternalStates.LATEST_OPERATION_START_TIME, Double.class), latestArrivalAt4Act, 0.001);
|
||||||
|
assertEquals(stateManager.getActivityState(route.getActivities().get(2), vehicle, InternalStates.LATEST_OPERATION_START_TIME, Double.class), latestArrivalAt3Act, 0.001);
|
||||||
|
assertEquals(stateManager.getActivityState(route.getActivities().get(1), vehicle, InternalStates.LATEST_OPERATION_START_TIME, Double.class), latestArrivalAt2Act, 0.001);
|
||||||
|
assertEquals(stateManager.getActivityState(route.getActivities().get(0), vehicle, InternalStates.LATEST_OPERATION_START_TIME, Double.class), latestArrivalAt1Act, 0.001);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VehicleRoutingTransportCosts getTransportCosts(final double travelTime) {
|
||||||
|
return new VehicleRoutingTransportCosts() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getDistance(Location from, Location to, double departureTime, Vehicle vehicle) {
|
||||||
|
return from.getCoordinate().equals(to.getCoordinate()) ? 0 : travelTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getTransportTime(Location from, Location to, double departureTime, Driver driver, Vehicle vehicle) {
|
||||||
|
return from.getCoordinate().equals(to.getCoordinate()) ? 0 : travelTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getTransportCost(Location from, Location to, double departureTime, Driver driver, Vehicle vehicle) {
|
||||||
|
return from.getCoordinate().equals(to.getCoordinate()) ? 0 : travelTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getBackwardTransportTime(Location from, Location to, double arrivalTime, Driver driver, Vehicle vehicle) {
|
||||||
|
return from.getCoordinate().equals(to.getCoordinate()) ? 0 : travelTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getBackwardTransportCost(Location from, Location to, double arrivalTime, Driver driver, Vehicle vehicle) {
|
||||||
|
return from.getCoordinate().equals(to.getCoordinate()) ? 0 : travelTime;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,10 +31,7 @@ import com.graphhopper.jsprit.core.problem.job.Job;
|
||||||
import com.graphhopper.jsprit.core.problem.job.Service;
|
import com.graphhopper.jsprit.core.problem.job.Service;
|
||||||
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.BreakActivity;
|
import com.graphhopper.jsprit.core.problem.solution.route.activity.*;
|
||||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.DeliveryActivity;
|
|
||||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.PickupService;
|
|
||||||
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
|
|
||||||
import com.graphhopper.jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
|
import com.graphhopper.jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter;
|
||||||
import com.graphhopper.jsprit.core.problem.vehicle.*;
|
import com.graphhopper.jsprit.core.problem.vehicle.*;
|
||||||
import com.graphhopper.jsprit.core.util.CostFactory;
|
import com.graphhopper.jsprit.core.util.CostFactory;
|
||||||
|
|
@ -353,13 +350,13 @@ public class VehicleDependentTimeWindowWithStartTimeAndMaxOperationTimeTest {
|
||||||
* |--- nextAct ---|
|
* |--- nextAct ---|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
Random random = new Random();
|
||||||
@Test
|
@Test
|
||||||
public void testSquash () {
|
public void testSquashNotEnd () {
|
||||||
Random random = new Random();
|
|
||||||
final double fixedCostAtSameLocation = random.nextDouble(),
|
final double fixedCostAtSameLocation = random.nextDouble(),
|
||||||
travelTime = random.nextDouble(),
|
travelTime = random.nextDouble(),
|
||||||
firstActDuration = 5, nextActivitiesDuration = 4.0,
|
firstActDuration = 5, nextActivitiesDuration = 4.0,
|
||||||
vehicleLatestArrival = firstActDuration + nextActivitiesDuration + fixedCostAtSameLocation + travelTime * 3;
|
vehicleLatestArrival = firstActDuration + nextActivitiesDuration + fixedCostAtSameLocation + travelTime * 3;
|
||||||
|
|
||||||
Location locationFirst = Location.newInstance(random.nextDouble(), random.nextDouble());
|
Location locationFirst = Location.newInstance(random.nextDouble(), random.nextDouble());
|
||||||
Location locationSecond = Location.newInstance(random.nextDouble(), random.nextDouble());
|
Location locationSecond = Location.newInstance(random.nextDouble(), random.nextDouble());
|
||||||
|
|
@ -372,24 +369,9 @@ public class VehicleDependentTimeWindowWithStartTimeAndMaxOperationTimeTest {
|
||||||
|
|
||||||
RouteAndActivityStateGetter routeAndActivityStateGetter = mock(RouteAndActivityStateGetter.class);
|
RouteAndActivityStateGetter routeAndActivityStateGetter = mock(RouteAndActivityStateGetter.class);
|
||||||
|
|
||||||
TourActivity prevAct = mock(DeliveryActivity.class),
|
TourActivity prevAct = getTourActivity(.0, firstActDuration, firstActDuration, locationFirst);
|
||||||
newAct = mock(DeliveryActivity.class),
|
TourActivity newAct = getTourActivity(firstActDuration, firstActDuration + nextActivitiesDuration + fixedCostAtSameLocation + travelTime * 2, nextActivitiesDuration, locationSecond);
|
||||||
nextAct = mock(DeliveryActivity.class);
|
TourActivity nextAct = getTourActivity(firstActDuration, firstActDuration + nextActivitiesDuration + fixedCostAtSameLocation + travelTime * 2, nextActivitiesDuration, locationSecond);
|
||||||
|
|
||||||
when(prevAct.getTheoreticalEarliestOperationStartTime()).thenReturn(.0);
|
|
||||||
when(prevAct.getTheoreticalLatestOperationStartTime()).thenReturn(firstActDuration);
|
|
||||||
when(prevAct.getOperationTime()).thenReturn(firstActDuration);
|
|
||||||
when(prevAct.getLocation()).thenReturn(locationFirst);
|
|
||||||
|
|
||||||
when(newAct.getTheoreticalEarliestOperationStartTime()).thenReturn(firstActDuration);
|
|
||||||
when(newAct.getTheoreticalLatestOperationStartTime()).thenReturn(firstActDuration + nextActivitiesDuration + fixedCostAtSameLocation + travelTime * 2);
|
|
||||||
when(newAct.getOperationTime()).thenReturn(nextActivitiesDuration);
|
|
||||||
when(newAct.getLocation()).thenReturn(locationSecond);
|
|
||||||
|
|
||||||
when(nextAct.getTheoreticalEarliestOperationStartTime()).thenReturn(firstActDuration);
|
|
||||||
when(nextAct.getTheoreticalLatestOperationStartTime()).thenReturn(firstActDuration + nextActivitiesDuration + fixedCostAtSameLocation + travelTime * 2);
|
|
||||||
when(nextAct.getOperationTime()).thenReturn(nextActivitiesDuration);
|
|
||||||
when(nextAct.getLocation()).thenReturn(locationSecond);
|
|
||||||
|
|
||||||
when(routeAndActivityStateGetter.getActivityState(nextAct, vehicle, InternalStates.LATEST_OPERATION_START_TIME, Double.class)).thenReturn(vehicleLatestArrival - travelTime - nextActivitiesDuration);
|
when(routeAndActivityStateGetter.getActivityState(nextAct, vehicle, InternalStates.LATEST_OPERATION_START_TIME, Double.class)).thenReturn(vehicleLatestArrival - travelTime - nextActivitiesDuration);
|
||||||
|
|
||||||
|
|
@ -398,6 +380,95 @@ public class VehicleDependentTimeWindowWithStartTimeAndMaxOperationTimeTest {
|
||||||
assertEquals(timeWindowConstraints.fulfilled(iFacts, prevAct, newAct, nextAct, 5.0), HardActivityConstraint.ConstraintsStatus.FULFILLED);
|
assertEquals(timeWindowConstraints.fulfilled(iFacts, prevAct, newAct, nextAct, 5.0), HardActivityConstraint.ConstraintsStatus.FULFILLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNoSquashEnd () {
|
||||||
|
final double fixedCostAtSameLocation = random.nextDouble(),
|
||||||
|
travelTime = random.nextDouble(),
|
||||||
|
firstActDuration = 5, nextActivitiesDuration = 4.0,
|
||||||
|
vehicleLatestArrival = firstActDuration + nextActivitiesDuration + fixedCostAtSameLocation + travelTime * 3;
|
||||||
|
|
||||||
|
Location locationFirst = Location.newInstance(random.nextDouble(), random.nextDouble());
|
||||||
|
Location locationSecond = Location.newInstance(random.nextDouble(), random.nextDouble());
|
||||||
|
|
||||||
|
Vehicle vehicle = mock(Vehicle.class);
|
||||||
|
when(vehicle.getLatestArrival()).thenReturn(vehicleLatestArrival);
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(false);
|
||||||
|
|
||||||
|
JobInsertionContext iFacts = mock(JobInsertionContext.class);
|
||||||
|
when(iFacts.getNewVehicle()).thenReturn(vehicle);
|
||||||
|
|
||||||
|
TourActivity prevAct = getTourActivity(.0, firstActDuration, firstActDuration, locationFirst);
|
||||||
|
TourActivity newAct = getTourActivity(firstActDuration, firstActDuration + nextActivitiesDuration + fixedCostAtSameLocation + travelTime * 2, nextActivitiesDuration, locationSecond);
|
||||||
|
End end = new End(locationSecond, firstActDuration, firstActDuration + nextActivitiesDuration + fixedCostAtSameLocation + travelTime * 2);
|
||||||
|
|
||||||
|
final VehicleDependentTimeWindowConstraints timeWindowConstraints = new VehicleDependentTimeWindowConstraints(mock(RouteAndActivityStateGetter.class), getTransportCosts(travelTime), getActivityCost(fixedCostAtSameLocation));
|
||||||
|
|
||||||
|
assertEquals(timeWindowConstraints.fulfilled(iFacts, prevAct, newAct, end, 5.0), HardActivityConstraint.ConstraintsStatus.FULFILLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSquashEndReturnToDepot () {
|
||||||
|
final double fixedCostAtSameLocation = random.nextDouble(),
|
||||||
|
travelTime = random.nextDouble(),
|
||||||
|
firstActDuration = 5.0, newActivityDuration = 4.0,
|
||||||
|
vehicleLatestArrival = firstActDuration + fixedCostAtSameLocation + travelTime;
|
||||||
|
|
||||||
|
Location location = Location.newInstance(random.nextDouble(), random.nextDouble());
|
||||||
|
Location depot = Location.newInstance(random.nextDouble(), random.nextDouble());
|
||||||
|
|
||||||
|
Vehicle vehicle = mock(Vehicle.class);
|
||||||
|
when(vehicle.getLatestArrival()).thenReturn(vehicleLatestArrival);
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(true);
|
||||||
|
when(vehicle.getEndLocation()).thenReturn(depot);
|
||||||
|
|
||||||
|
JobInsertionContext iFacts = mock(JobInsertionContext.class);
|
||||||
|
when(iFacts.getNewVehicle()).thenReturn(vehicle);
|
||||||
|
|
||||||
|
TourActivity prevAct = getTourActivity(.0, firstActDuration, firstActDuration, location);
|
||||||
|
TourActivity newAct = getTourActivity(firstActDuration, firstActDuration + fixedCostAtSameLocation, newActivityDuration, location);
|
||||||
|
End end = new End(depot, firstActDuration, firstActDuration + fixedCostAtSameLocation + travelTime);
|
||||||
|
|
||||||
|
final VehicleDependentTimeWindowConstraints timeWindowConstraints = new VehicleDependentTimeWindowConstraints(mock(RouteAndActivityStateGetter.class), getTransportCosts(travelTime), getActivityCost(fixedCostAtSameLocation));
|
||||||
|
|
||||||
|
assertEquals(timeWindowConstraints.fulfilled(iFacts, prevAct, newAct, end, 5.0), HardActivityConstraint.ConstraintsStatus.FULFILLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSquashEndNoReturnToDepot () {
|
||||||
|
final double fixedCostAtSameLocation = random.nextDouble(),
|
||||||
|
travelTime = random.nextDouble(),
|
||||||
|
firstActDuration = 5.0, newActivityDuration = 4.0,
|
||||||
|
vehicleLatestArrival = firstActDuration + fixedCostAtSameLocation;
|
||||||
|
|
||||||
|
Location location = Location.newInstance(random.nextDouble(), random.nextDouble());
|
||||||
|
Location depot = Location.newInstance(random.nextDouble(), random.nextDouble());
|
||||||
|
|
||||||
|
Vehicle vehicle = mock(Vehicle.class);
|
||||||
|
when(vehicle.getLatestArrival()).thenReturn(vehicleLatestArrival);
|
||||||
|
when(vehicle.isReturnToDepot()).thenReturn(false);
|
||||||
|
when(vehicle.getEndLocation()).thenReturn(depot);
|
||||||
|
|
||||||
|
JobInsertionContext iFacts = mock(JobInsertionContext.class);
|
||||||
|
when(iFacts.getNewVehicle()).thenReturn(vehicle);
|
||||||
|
|
||||||
|
TourActivity prevAct = getTourActivity(.0, firstActDuration, firstActDuration, location);
|
||||||
|
TourActivity newAct = getTourActivity(firstActDuration, firstActDuration + fixedCostAtSameLocation, newActivityDuration, location);
|
||||||
|
End end = new End(depot, firstActDuration, firstActDuration + fixedCostAtSameLocation);
|
||||||
|
|
||||||
|
final VehicleDependentTimeWindowConstraints timeWindowConstraints = new VehicleDependentTimeWindowConstraints(mock(RouteAndActivityStateGetter.class), getTransportCosts(travelTime), getActivityCost(fixedCostAtSameLocation));
|
||||||
|
|
||||||
|
assertEquals(timeWindowConstraints.fulfilled(iFacts, prevAct, newAct, end, 5.0), HardActivityConstraint.ConstraintsStatus.FULFILLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TourActivity getTourActivity(double start, double end, double activityDuration, Location location) {
|
||||||
|
TourActivity act = mock(DeliveryActivity.class);
|
||||||
|
when(act.getTheoreticalEarliestOperationStartTime()).thenReturn(start);
|
||||||
|
when(act.getTheoreticalLatestOperationStartTime()).thenReturn(end);
|
||||||
|
when(act.getOperationTime()).thenReturn(activityDuration);
|
||||||
|
when(act.getLocation()).thenReturn(location);
|
||||||
|
return act;
|
||||||
|
}
|
||||||
|
|
||||||
private VehicleRoutingActivityCosts getActivityCost(final double fixedCostAtSameLocation) {
|
private VehicleRoutingActivityCosts getActivityCost(final double fixedCostAtSameLocation) {
|
||||||
return new VehicleRoutingActivityCosts() {
|
return new VehicleRoutingActivityCosts() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue