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

event based sheduling and insertion

This commit is contained in:
oblonski 2015-05-19 22:52:59 +02:00
parent a4dd1d9ac5
commit 71fbc8ad38
14 changed files with 210 additions and 56 deletions

View file

@ -71,12 +71,15 @@ public abstract class AbstractInsertionStrategy implements InsertionStrategy{
private Inserter inserter; private Inserter inserter;
private EventListeners eventListeners;
protected VehicleRoutingProblem vrp; protected VehicleRoutingProblem vrp;
public AbstractInsertionStrategy(VehicleRoutingProblem vrp) { public AbstractInsertionStrategy(VehicleRoutingProblem vrp) {
this.insertionsListeners = new InsertionListeners(); this.insertionsListeners = new InsertionListeners();
this.vrp = vrp; this.vrp = vrp;
inserter = new Inserter(insertionsListeners, vrp); inserter = new Inserter(insertionsListeners, vrp);
eventListeners = new EventListeners();
} }
public void setRandom(Random random) { public void setRandom(Random random) {
@ -111,7 +114,14 @@ public abstract class AbstractInsertionStrategy implements InsertionStrategy{
protected void insertJob(Job unassignedJob, InsertionData iData, VehicleRoute inRoute){ protected void insertJob(Job unassignedJob, InsertionData iData, VehicleRoute inRoute){
logger.trace("insert: [jobId=" + unassignedJob.getId() + "]" + iData ); logger.trace("insert: [jobId=" + unassignedJob.getId() + "]" + iData );
inserter.insertJob(unassignedJob, iData, inRoute); insertionsListeners.informBeforeJobInsertion(unassignedJob, iData, inRoute);
if(!(inRoute.getVehicle().getId().equals(iData.getSelectedVehicle().getId()))){
insertionsListeners.informVehicleSwitched(inRoute, inRoute.getVehicle(), iData.getSelectedVehicle());
}
for(Event e : iData.getEvents()){
eventListeners.inform(e);
}
insertionsListeners.informJobInserted(unassignedJob, inRoute, iData.getInsertionCost(), iData.getAdditionalTime());
} }
} }

View file

@ -0,0 +1,7 @@
package jsprit.core.algorithm.recreate;
/**
* Created by schroeder on 19/05/15.
*/
public interface Event {
}

View file

@ -0,0 +1,10 @@
package jsprit.core.algorithm.recreate;
/**
* Created by schroeder on 19/05/15.
*/
interface EventListener {
void inform(Event event);
}

View file

@ -0,0 +1,23 @@
package jsprit.core.algorithm.recreate;
import java.util.ArrayList;
import java.util.List;
/**
* Created by schroeder on 19/05/15.
*/
class EventListeners {
private List<EventListener> listeners = new ArrayList<EventListener>();
public EventListeners() {
listeners.add(new InsertActivityListener());
listeners.add(new SwitchVehicleListener());
}
public void inform(Event event){
for(EventListener l : listeners){
l.inform(event);
}
}
}

View file

@ -0,0 +1,42 @@
package jsprit.core.algorithm.recreate;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.solution.route.activity.TourActivity;
import jsprit.core.problem.vehicle.Vehicle;
/**
* Created by schroeder on 19/05/15.
*/
class InsertActivity implements Event {
private VehicleRoute vehicleRoute;
private Vehicle newVehicle;
private TourActivity activity;
private int index;
public InsertActivity(VehicleRoute vehicleRoute, Vehicle newVehicle, TourActivity activity, int index) {
this.vehicleRoute = vehicleRoute;
this.newVehicle = newVehicle;
this.activity = activity;
this.index = index;
}
public Vehicle getNewVehicle() {
return newVehicle;
}
public VehicleRoute getVehicleRoute() {
return vehicleRoute;
}
public TourActivity getActivity() {
return activity;
}
public int getIndex() {
return index;
}
}

View file

@ -0,0 +1,21 @@
package jsprit.core.algorithm.recreate;
/**
* Created by schroeder on 19/05/15.
*/
class InsertActivityListener implements EventListener {
@Override
public void inform(Event event) {
if(event instanceof InsertActivity){
InsertActivity insertActivity = (InsertActivity) event;
if(!insertActivity.getNewVehicle().isReturnToDepot()){
if(insertActivity.getIndex()>=insertActivity.getVehicleRoute().getActivities().size()){
insertActivity.getVehicleRoute().getEnd().setLocation(insertActivity.getActivity().getLocation());
}
}
insertActivity.getVehicleRoute().getTourActivities().addActivity(insertActivity.getIndex(),((InsertActivity) event).getActivity());
}
}
}

View file

@ -19,6 +19,9 @@ package jsprit.core.algorithm.recreate;
import jsprit.core.problem.driver.Driver; import jsprit.core.problem.driver.Driver;
import jsprit.core.problem.vehicle.Vehicle; import jsprit.core.problem.vehicle.Vehicle;
import java.util.ArrayList;
import java.util.List;
/** /**
* Data object that collects insertion information. It collects insertionCosts, insertionIndeces, vehicle and driver to be employed * Data object that collects insertion information. It collects insertionCosts, insertionIndeces, vehicle and driver to be employed
* and departureTime of vehicle at vehicle's start location (e.g. depot). * and departureTime of vehicle at vehicle's start location (e.g. depot).
@ -65,7 +68,13 @@ public class InsertionData {
private double departureTime; private double departureTime;
private double additionalTime; private double additionalTime;
private List<Event> events = new ArrayList<Event>();
List<Event> getEvents(){
return events;
}
/** /**
* @return the additionalTime * @return the additionalTime
*/ */

View file

@ -62,6 +62,7 @@ final class JobInsertionConsideringFixCostsCalculator implements JobInsertionCos
double totalInsertionCost = iData.getInsertionCost() + fixcost_contribution; double totalInsertionCost = iData.getInsertionCost() + fixcost_contribution;
InsertionData insertionData = new InsertionData(totalInsertionCost, iData.getPickupInsertionIndex(), iData.getDeliveryInsertionIndex(), newVehicle, newDriver); InsertionData insertionData = new InsertionData(totalInsertionCost, iData.getPickupInsertionIndex(), iData.getDeliveryInsertionIndex(), newVehicle, newDriver);
insertionData.setVehicleDepartureTime(newVehicleDepartureTime); insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
insertionData.getEvents().addAll(iData.getEvents());
return insertionData; return insertionData;
} }

View file

@ -155,6 +155,8 @@ final class ServiceInsertionCalculator implements JobInsertionCostsCalculator{
return InsertionData.createEmptyInsertionData(); return InsertionData.createEmptyInsertionData();
} }
InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver); InsertionData insertionData = new InsertionData(bestCost, InsertionData.NO_INDEX, insertionIndex, newVehicle, newDriver);
insertionData.getEvents().add(new InsertActivity(currentRoute,newVehicle,deliveryAct2Insert,insertionIndex));
insertionData.getEvents().add(new SwitchVehicle(currentRoute,newVehicle,newVehicleDepartureTime));
insertionData.setVehicleDepartureTime(newVehicleDepartureTime); insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
return insertionData; return insertionData;
} }

View file

@ -225,6 +225,9 @@ final class ShipmentInsertionCalculator implements JobInsertionCostsCalculator{
} }
InsertionData insertionData = new InsertionData(bestCost, pickupInsertionIndex, deliveryInsertionIndex, newVehicle, newDriver); InsertionData insertionData = new InsertionData(bestCost, pickupInsertionIndex, deliveryInsertionIndex, newVehicle, newDriver);
insertionData.setVehicleDepartureTime(newVehicleDepartureTime); insertionData.setVehicleDepartureTime(newVehicleDepartureTime);
insertionData.getEvents().add(new InsertActivity(currentRoute,newVehicle,deliverShipment,deliveryInsertionIndex));
insertionData.getEvents().add(new InsertActivity(currentRoute,newVehicle,pickupShipment,pickupInsertionIndex));
insertionData.getEvents().add(new SwitchVehicle(currentRoute,newVehicle,newVehicleDepartureTime));
return insertionData; return insertionData;
} }

View file

@ -0,0 +1,34 @@
package jsprit.core.algorithm.recreate;
import jsprit.core.problem.solution.route.VehicleRoute;
import jsprit.core.problem.vehicle.Vehicle;
/**
* Created by schroeder on 19/05/15.
*/
class SwitchVehicle implements Event {
private VehicleRoute route;
private Vehicle vehicle;
private double departureTime;
public SwitchVehicle(VehicleRoute route, Vehicle vehicle, double departureTime) {
this.route = route;
this.vehicle = vehicle;
this.departureTime = departureTime;
}
public VehicleRoute getRoute() {
return route;
}
public Vehicle getVehicle() {
return vehicle;
}
public double getDepartureTime() {
return departureTime;
}
}

View file

@ -0,0 +1,15 @@
package jsprit.core.algorithm.recreate;
/**
* Created by schroeder on 19/05/15.
*/
class SwitchVehicleListener implements EventListener{
@Override
public void inform(Event event) {
if(event instanceof SwitchVehicle){
SwitchVehicle switchVehicle = (SwitchVehicle) event;
switchVehicle.getRoute().setVehicleAndDepartureTime(switchVehicle.getVehicle(),((SwitchVehicle) event).getDepartureTime());
}
}
}

View file

@ -168,6 +168,8 @@ public class RegretInsertionTest {
if(currentRoute.isEmpty()){ if(currentRoute.isEmpty()){
double mc = getCost(service.getLocation(), vehicle.getStartLocation()); double mc = getCost(service.getLocation(), vehicle.getStartLocation());
iData = new InsertionData(2*mc,-1,0,vehicle,newDriver); iData = new InsertionData(2*mc,-1,0,vehicle,newDriver);
iData.getEvents().add(new InsertActivity(currentRoute,vehicle,vrp.copyAndGetActivities(newJob).get(0),0));
iData.getEvents().add(new SwitchVehicle(currentRoute,vehicle,newVehicleDepartureTime));
} }
else { else {
double best = Double.MAX_VALUE; double best = Double.MAX_VALUE;
@ -189,6 +191,8 @@ public class RegretInsertionTest {
bestIndex = index; bestIndex = index;
} }
iData = new InsertionData(best,-1,bestIndex,vehicle,newDriver); iData = new InsertionData(best,-1,bestIndex,vehicle,newDriver);
iData.getEvents().add(new InsertActivity(currentRoute,vehicle,vrp.copyAndGetActivities(newJob).get(0),bestIndex));
iData.getEvents().add(new SwitchVehicle(currentRoute,vehicle,newVehicleDepartureTime));
} }
return iData; return iData;
} }

View file

@ -2,9 +2,24 @@
<problem xmlns="http://www.w3schools.com" <problem xmlns="http://www.w3schools.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3schools.com vrp_xml_schema.xsd"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3schools.com vrp_xml_schema.xsd">
<problemType> <problemType>
<fleetSize>INFINITE</fleetSize> <fleetSize>FINITE</fleetSize>
</problemType> </problemType>
<vehicles> <vehicles>
<vehicle>
<id>v2</id>
<typeId>vehType2</typeId>
<startLocation>
<id>loc</id>
</startLocation>
<endLocation>
<id>loc</id>
</endLocation>
<timeSchedule>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeSchedule>
<returnToDepot>true</returnToDepot>
</vehicle>
<vehicle> <vehicle>
<id>v1</id> <id>v1</id>
<typeId>vehType</typeId> <typeId>vehType</typeId>
@ -33,58 +48,16 @@
<time>0.0</time> <time>0.0</time>
</costs> </costs>
</type> </type>
<type>
<id>vehType2</id>
<capacity-dimensions>
<dimension index="0">200</dimension>
</capacity-dimensions>
<costs>
<fixed>0.0</fixed>
<distance>1.0</distance>
<time>0.0</time>
</costs>
</type>
</vehicleTypes> </vehicleTypes>
<services>
<service id="1" type="service">
<location>
<id>loc</id>
</location>
<capacity-dimensions>
<dimension index="0">1</dimension>
</capacity-dimensions>
<duration>2.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
<service id="2" type="service">
<location>
<id>loc2</id>
</location>
<capacity-dimensions>
<dimension index="0">1</dimension>
</capacity-dimensions>
<duration>4.0</duration>
<timeWindows>
<timeWindow>
<start>0.0</start>
<end>1.7976931348623157E308</end>
</timeWindow>
</timeWindows>
</service>
</services>
<solutions>
<solution>
<cost>10.0</cost>
<routes>
<route>
<driverId>noDriver</driverId>
<vehicleId>v1</vehicleId>
<start>0.0</start>
<act type="service">
<serviceId>1</serviceId>
<arrTime>0.0</arrTime>
<endTime>0.0</endTime>
</act>
<end>0.0</end>
</route>
</routes>
<unassignedJobs>
<job id="2"/>
</unassignedJobs>
</solution>
</solutions>
</problem> </problem>