我想尽量减少乘客在车上的时间。
如果有一个接送点LEFT
和一个接送点,CENTER
并且两者都去,BOTTOM
那么车辆应该LEFT
先接,因为CENTER
有点在去的路上BOTTOM
。
我如何告诉 JSprit 优先考虑这个?
我已经尝试使用这个简单的例子来实现一个 RouteConstraint 来惩罚车辆的总时间,从pickupShipment
to deliverShipment
:
import com.graphhopper.jsprit.core.algorithm.VehicleRoutingAlgorithm;
import com.graphhopper.jsprit.core.algorithm.box.Jsprit;
import com.graphhopper.jsprit.core.algorithm.selector.SelectBest;
import com.graphhopper.jsprit.core.algorithm.state.StateManager;
import com.graphhopper.jsprit.core.problem.Location;
import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem;
import com.graphhopper.jsprit.core.problem.constraint.ConstraintManager;
import com.graphhopper.jsprit.core.problem.constraint.SoftRouteConstraint;
import com.graphhopper.jsprit.core.problem.job.Shipment;
import com.graphhopper.jsprit.core.problem.misc.JobInsertionContext;
import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TimeWindow;
import com.graphhopper.jsprit.core.problem.solution.route.activity.TourActivity;
import com.graphhopper.jsprit.core.problem.vehicle.VehicleImpl;
import com.graphhopper.jsprit.core.reporting.SolutionPrinter;
import junit.framework.TestCase;
import java.util.LinkedList;
public class PenalizeExtraTimeInVehicleTest extends TestCase {
final Location LEFT = Location.newInstance(10.0, 50.0);
final Location CENTER = Location.newInstance(50.0, 50.0);
final Location BOTTOM = Location.newInstance(50.0, 90.0);
public void testPickUpWithoutWastingTime() {
VehicleRoutingProblem vrp = VehicleRoutingProblem.Builder.newInstance()
.setFleetSize(VehicleRoutingProblem.FleetSize.FINITE)
.addVehicle(VehicleImpl.Builder.newInstance("V-1")
.setStartLocation(BOTTOM)
.build())
.addJob(Shipment.Builder.newInstance("Center_to_Bot")
.setPickupTimeWindow(TimeWindow.newInstance(100.0, 200.0))
.setDeliveryTimeWindow(TimeWindow.newInstance(200.0, 300.0))
.setPickupLocation(CENTER)
.setDeliveryLocation(BOTTOM)
.build())
.addJob(Shipment.Builder.newInstance("Left_to_Bot1") // if this doesn't end with "1" it will be picked up first
.setPickupTimeWindow(TimeWindow.newInstance(100.0, 200.0))
.setDeliveryTimeWindow(TimeWindow.newInstance(200.0, 300.0))
.setPickupLocation(LEFT)
.setDeliveryLocation(BOTTOM)
.build())
.build();
final StateManager stateManager = new StateManager(vrp);
final ConstraintManager constraintManager = new ConstraintManager(vrp, stateManager);
constraintManager.addConstraint(new SoftRouteConstraint() {
/**
* Penalize for total time in vehicle for all passengers in a route.
*/
@Override
public double getCosts( JobInsertionContext insertionContext ) {
LinkedList<Double> stack = new LinkedList<>();
double timeInVehicle = 0.0;
for ( TourActivity eachAct : insertionContext.getRoute().getActivities() ) {
if ( "pickupShipment".equals(eachAct.getName())) {
stack.push(eachAct.getEndTime());
} else if ("deliverShipment".equals(eachAct.getName())) {
final Double popped = stack.pop();
timeInVehicle += eachAct.getArrTime() - popped;
}
}
return timeInVehicle;
}
});
final VehicleRoutingAlgorithm algorithm = Jsprit.Builder.newInstance(vrp)
.setStateAndConstraintManager(stateManager, constraintManager)
.buildAlgorithm();
VehicleRoutingProblemSolution solution = new SelectBest().selectSolution(algorithm.searchSolutions());
SolutionPrinter.print(vrp, solution, SolutionPrinter.Print.VERBOSE);
final TourActivity firstActivity = solution.getRoutes().iterator().next().getActivities().get(0);
assertEquals("Left_to_Bot", ((TourActivity.JobActivity) firstActivity).getJob().getId());
}
}
center
这给出了下面的结果,在离开之前顽固地拿起left
.
另外值得注意的是,Job.id
影响结果。如果我重命名Left_to_Bot1
为Left_to_Bot
它将首先被拾取。
+--------------------------------------------------------------------------------------------------------------------------------+
| detailed solution |
+---------+----------------------+-----------------------+-----------------+-----------------+-----------------+-----------------+
| route | vehicle | activity | job | arrTime | endTime | costs |
+---------+----------------------+-----------------------+-----------------+-----------------+-----------------+-----------------+
| 1 | V-1 | start | - | undef | 0 | 0 |
| 1 | V-1 | pickupShipment | Left_to_Bot1 | 57 | 100 | 57 |
| 1 | V-1 | pickupShipment | Center_to_Bot | 140 | 140 | 97 |
| 1 | V-1 | deliverShipment | Left_to_Bot1 | 180 | 200 | 137 |
| 1 | V-1 | deliverShipment | Center_to_Bot | 200 | 200 | 137 |
| 1 | V-1 | end | - | 200 | undef | 137 |
+--------------------------------------------------------------------------------------------------------------------------------+