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

create new services and serviceActivities, i.e. pickup and delivery as

well as their corresponding activities
This commit is contained in:
Stefan Schroeder 2013-08-28 18:23:26 +02:00
parent a66be4bd0a
commit e6f671cbcc
10 changed files with 291 additions and 135 deletions

View file

@ -1,7 +1,7 @@
package basics;
public class Delivery extends Service{
public final class Delivery extends Service{
public static class Builder extends Service.Builder {
@ -10,10 +10,14 @@ public class Delivery extends Service{
}
Builder(String id, int size) {
super(id, -1*size);
super(id, size);
}
public Delivery build(){
if(locationId == null) {
if(coord == null) throw new IllegalStateException("either locationId or a coordinate must be given. But is not.");
locationId = coord.toString();
}
this.setType("delivery");
return new Delivery(this);
}
@ -25,16 +29,4 @@ public class Delivery extends Service{
}
public static void main(String[] args) {
Delivery.Builder deliveryBuilder = Delivery.Builder.newInstance("myDelivery", 10);
Delivery delivery = (Delivery) deliveryBuilder.setLocationId("foo").build();
System.out.println("loc="+delivery.getLocationId());
System.out.println("capDemand="+delivery.getCapacityDemand());
}
}

View file

@ -1,6 +1,6 @@
package basics;
public class Pickup extends Service {
public final class Pickup extends Service {
public static class Builder extends Service.Builder {
@ -13,6 +13,10 @@ public class Pickup extends Service {
}
public Pickup build(){
if(locationId == null) {
if(coord == null) throw new IllegalStateException("either locationId or a coordinate must be given. But is not.");
locationId = coord.toString();
}
this.setType("pickup");
return new Pickup(this);
}
@ -23,15 +27,4 @@ public class Pickup extends Service {
super(builder);
}
public static void main(String[] args) {
Pickup.Builder pickupBuilder = Pickup.Builder.newInstance("myPick", 10);
Pickup pickup = (Pickup) pickupBuilder.setLocationId("foo").build();
System.out.println("loc="+pickup.getLocationId());
System.out.println("capDemand="+pickup.getCapacityDemand());
}
}

View file

@ -33,12 +33,12 @@ public class Service implements Job {
}
private String id;
private String locationId;
protected String locationId;
private String type = "service";
private Coordinate coord;
private double serviceTime;
private TimeWindow timeWindow = TimeWindow.newInstance(0.0, Double.MAX_VALUE);
private int demand;
protected Coordinate coord;
protected double serviceTime;
protected TimeWindow timeWindow = TimeWindow.newInstance(0.0, Double.MAX_VALUE);
protected int demand;
Builder(String id, int size) {
super();

View file

@ -38,26 +38,53 @@ import org.xml.sax.SAXException;
import util.Coordinate;
import util.Resource;
import basics.Delivery;
import basics.Pickup;
import basics.Service;
import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblem.FleetComposition;
import basics.VehicleRoutingProblem.FleetSize;
import basics.VehicleRoutingProblemSolution;
import basics.route.DefaultTourActivityFactory;
import basics.route.DeliveryActivity;
import basics.route.Driver;
import basics.route.DriverImpl;
import basics.route.End;
import basics.route.PickupActivity;
import basics.route.ServiceActivity;
import basics.route.Start;
import basics.route.TimeWindow;
import basics.route.TourActivity;
import basics.route.TourActivityFactory;
import basics.route.Vehicle;
import basics.route.VehicleImpl;
import basics.route.VehicleImpl.Builder;
import basics.route.VehicleRoute;
import basics.route.VehicleType;
import basics.route.VehicleTypeImpl;
public class VrpXMLReader{
public interface ServiceBuilderFactory {
Service.Builder createBuilder(String serviceType, String id, int size);
}
static class DefaultServiceBuilderFactory implements ServiceBuilderFactory{
@Override
public basics.Service.Builder createBuilder(String serviceType, String id, int size) {
if(serviceType.equals("pickup")){
return Pickup.Builder.newInstance(id, size);
}
else if(serviceType.equals("delivery")){
return Delivery.Builder.newInstance(id, size);
}
else{
return Service.Builder.newInstance(id, size);
}
}
}
private static Logger logger = Logger.getLogger(VrpXMLReader.class);
private VehicleRoutingProblem.Builder vrpBuilder;
@ -70,6 +97,18 @@ public class VrpXMLReader{
private Collection<VehicleRoutingProblemSolution> solutions;
private ServiceBuilderFactory serviceBuilderFactory = new DefaultServiceBuilderFactory();
private TourActivityFactory tourActivityFactory = new DefaultTourActivityFactory();
public void setTourActivityFactory(TourActivityFactory tourActivityFactory){
this.tourActivityFactory = tourActivityFactory;
}
public void setServiceBuilderFactory(ServiceBuilderFactory serviceBuilderFactory){
this.serviceBuilderFactory=serviceBuilderFactory;
}
/**
* @param schemaValidation the schemaValidation to set
*/
@ -170,10 +209,10 @@ public class VrpXMLReader{
if(arrTime == null) throw new IllegalStateException("act.arrTime is missing.");
String endTime = actConfig.getString("endTime");
if(endTime == null) throw new IllegalStateException("act.endTime is missing.");
ServiceActivity serviceActivity = ServiceActivity.newInstance(service);
serviceActivity.setArrTime(Double.parseDouble(arrTime));
serviceActivity.setEndTime(Double.parseDouble(endTime));
routeBuilder.addActivity(serviceActivity);
TourActivity tourActivity = tourActivityFactory.createActivity(service);
tourActivity.setArrTime(Double.parseDouble(arrTime));
tourActivity.setEndTime(Double.parseDouble(endTime));
routeBuilder.addActivity(tourActivity);
}
routes.add(routeBuilder.build());
}
@ -210,13 +249,12 @@ public class VrpXMLReader{
for(HierarchicalConfiguration serviceConfig : serviceConfigs){
String id = serviceConfig.getString("[@id]");
if(id == null) throw new IllegalStateException("service[@id] is missing.");
String name = serviceConfig.getString("[@type]");
if(name == null) name = "service";
String type = serviceConfig.getString("[@type]");
if(type == null) type = "service";
String capacityDemand = serviceConfig.getString("capacity-demand");
int cap = 0;
if(capacityDemand != null) cap = Integer.parseInt(capacityDemand);
Service.Builder builder = Service.Builder.newInstance(id, cap);
// builder.setType(name);
Service.Builder builder = serviceBuilderFactory.createBuilder(type, id, cap);
String serviceLocationId = serviceConfig.getString("locationId");
builder.setLocationId(serviceLocationId);
Coordinate serviceCoord = null;
@ -235,8 +273,6 @@ public class VrpXMLReader{
builder.setLocationId(serviceCoord.toString());
}
}
if(serviceConfig.containsKey("duration")){
builder.setServiceTime(serviceConfig.getDouble("duration"));
}
@ -264,15 +300,12 @@ public class VrpXMLReader{
Double fix = typeConfig.getDouble("costs.fixed");
Double timeC = typeConfig.getDouble("costs.time");
Double distC = typeConfig.getDouble("costs.distance");
// Double start = typeConfig.getDouble("timeSchedule.start");
// Double end = typeConfig.getDouble("timeSchedule.end");
if(typeId == null) throw new IllegalStateException("typeId is missing.");
if(capacity == null) throw new IllegalStateException("capacity is missing.");
VehicleTypeImpl.Builder typeBuilder = VehicleTypeImpl.Builder.newInstance(typeId, capacity);
if(fix != null) typeBuilder.setFixedCost(fix);
if(timeC != null) typeBuilder.setCostPerTime(timeC);
if(distC != null) typeBuilder.setCostPerDistance(distC);
// if(start != null && end != null) typeBuilder.setTimeSchedule(new TimeSchedule(start, end));
VehicleTypeImpl type = typeBuilder.build();
types.put(type.getTypeId(), type);
vrpBuilder.addVehicleType(type);
@ -310,7 +343,6 @@ public class VrpXMLReader{
if(start != null) builder.setEarliestStart(Double.parseDouble(start));
if(end != null) builder.setLatestArrival(Double.parseDouble(end));
VehicleImpl vehicle = builder.build();
// vehicleMap.put(vehicle.getId(), vehicle);
vrpBuilder.addVehicle(vehicle);
vehicleMap.put(vehicleId, vehicle);
}

View file

@ -39,6 +39,7 @@ import basics.VehicleRoutingProblem;
import basics.VehicleRoutingProblemSolution;
import basics.route.ServiceActivity;
import basics.route.TourActivity;
import basics.route.TourActivity.JobActivity;
import basics.route.Vehicle;
import basics.route.VehicleRoute;
import basics.route.VehicleType;
@ -84,7 +85,6 @@ public class VrpXMLWriter {
writeProblemType(xmlConfig);
writeVehiclesAndTheirTypes(xmlConfig);
writerServices(xmlConfig);
// writeShipments(xmlConfig);
writeSolutions(xmlConfig);
OutputFormat format = new OutputFormat();
@ -133,8 +133,8 @@ public class VrpXMLWriter {
int actCounter = 0;
for(TourActivity act : route.getTourActivities().getActivities()){
xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act("+actCounter+")[@type]", act.getName());
if(act instanceof ServiceActivity){
xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act("+actCounter+").serviceId", ((ServiceActivity) act).getJob().getId());
if(act instanceof JobActivity){
xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act("+actCounter+").serviceId", ((JobActivity) act).getJob().getId());
}
xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act("+actCounter+").arrTime", act.getArrTime());
xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act("+actCounter+").endTime", act.getEndTime());
@ -170,36 +170,6 @@ public class VrpXMLWriter {
}
// private void writeShipments(XMLConf xmlConfig) {
// String shipmentPathString = "shipments.shipment";
// int counter = 0;
// for(Job j : vrp.getJobs().values()){
// Shipment shipment = (Shipment) j;
// xmlConfig.setProperty(shipmentPathString + "("+counter+")[@id]", shipment.getId());
// if(shipment.getFromId() != null) xmlConfig.setProperty(shipmentPathString + "("+counter+").pickup.locationId", shipment.getFromId());
// if(shipment.getFromCoord() != null) {
// xmlConfig.setProperty(shipmentPathString + "("+counter+").pickup.coord[@x]", shipment.getFromCoord().getX());
// xmlConfig.setProperty(shipmentPathString + "("+counter+").pickup.coord[@y]", shipment.getFromCoord().getY());
// }
// if(shipment.getToId() != null) xmlConfig.setProperty(shipmentPathString + "("+counter+").delivery.locationId", shipment.getToId());
// if(shipment.getFromCoord() != null) {
// xmlConfig.setProperty(shipmentPathString + "("+counter+").delivery.coord[@x]", shipment.getToCoord().getX());
// xmlConfig.setProperty(shipmentPathString + "("+counter+").delivery.coord[@y]", shipment.getToCoord().getY());
// }
// xmlConfig.setProperty(shipmentPathString + "("+counter+").size", shipment.getSize());
// xmlConfig.setProperty(shipmentPathString + "("+counter+").pickup.serviceTime", shipment.getPickupServiceTime());
// xmlConfig.setProperty(shipmentPathString + "("+counter+").pickup.timeWindows.timeWindow(0).start", shipment.getPickupTW().getStart());
// xmlConfig.setProperty(shipmentPathString + "("+counter+").pickup.timeWindows.timeWindow(0).end", shipment.getPickupTW().getEnd());
//
// xmlConfig.setProperty(shipmentPathString + "("+counter+").delivery.serviceTime", shipment.getDeliveryServiceTime());
// xmlConfig.setProperty(shipmentPathString + "("+counter+").delivery.timeWindows.timeWindow(0).start", shipment.getDeliveryTW().getStart());
// xmlConfig.setProperty(shipmentPathString + "("+counter+").delivery.timeWindows.timeWindow(0).end", shipment.getDeliveryTW().getEnd());
//
// counter++;
// }
//
// }
private void writeProblemType(XMLConfiguration xmlConfig){
xmlConfig.setProperty("problemType.fleetSize", vrp.getFleetSize());
xmlConfig.setProperty("problemType.fleetComposition", vrp.getFleetComposition());
@ -207,19 +177,6 @@ public class VrpXMLWriter {
private void writeVehiclesAndTheirTypes(XMLConfiguration xmlConfig) {
// //depots
// Map<Depot,Integer> depot2id = new HashMap<Depot, Integer>();
// int depotCounter = 0;
// for(Depot depot : vrp.getDepots()){
// int depotId = depotCounter+1;
// depot2id.put(depot, depotId);
// xmlConfig.setProperty("depots.depot" + "("+depotCounter+")[@id]", (depotId));
// xmlConfig.setProperty("depots.depot" + "("+depotCounter+").locationId", depot.getId());
// xmlConfig.setProperty("depots.depot" + "("+depotCounter+").coord[@x]", depot.getCoord().getX());
// xmlConfig.setProperty("depots.depot" + "("+depotCounter+").coord[@y]", depot.getCoord().getY());
// depotCounter++;
// }
//vehicles
String vehiclePathString = new StringBuilder().append(Schema.VEHICLES).append(".").
append(Schema.VEHICLE).toString();
@ -234,13 +191,7 @@ public class VrpXMLWriter {
}
xmlConfig.setProperty(vehiclePathString + "("+counter+").timeSchedule.start", vehicle.getEarliestDeparture());
xmlConfig.setProperty(vehiclePathString + "("+counter+").timeSchedule.end", vehicle.getLatestArrival());
// if(vehicle.getLocationId() != null) xmlConfig.setProperty(vehiclePathString + "("+counter+").locationId", vehicle.getLocationId());
// if(vehicle.getCoord() != null) {
// xmlConfig.setProperty(vehiclePathString + "("+counter+").coord[@x]", vehicle.getCoord().getX());
// xmlConfig.setProperty(vehiclePathString + "("+counter+").coord[@y]", vehicle.getCoord().getY());
// }
// xmlConfig.setProperty(vehiclePathString + "("+counter+").earliestStart", vehicle.getEarliestDeparture());
// xmlConfig.setProperty(vehiclePathString + "("+counter+").latestEnd", vehicle.getLatestArrival());
counter++;
}
@ -250,8 +201,6 @@ public class VrpXMLWriter {
for(VehicleType type : vrp.getTypes()){
xmlConfig.setProperty(typePathString + "("+typeCounter+").id", type.getTypeId());
xmlConfig.setProperty(typePathString + "("+typeCounter+").capacity", type.getCapacity());
// xmlConfig.setProperty(typePathString + "("+typeCounter+").timeSchedule.start", type.getTimeSchedule().getEarliestStart());
// xmlConfig.setProperty(typePathString + "("+typeCounter+").timeSchedule.end", type.getTimeSchedule().getLatestEnd());
xmlConfig.setProperty(typePathString + "("+typeCounter+").costs.fixed", type.getVehicleCostParams().fix);
xmlConfig.setProperty(typePathString + "("+typeCounter+").costs.distance", type.getVehicleCostParams().perDistanceUnit);
xmlConfig.setProperty(typePathString + "("+typeCounter+").costs.time", type.getVehicleCostParams().perTimeUnit);
@ -259,35 +208,6 @@ public class VrpXMLWriter {
}
// //type2depot assignments
// int assignmentCounter = 0;
// boolean first = true;
// for(Depot depot : vrp.getDepotToVehicleTypeAssignments().keySet()){
// if(first){
// xmlConfig.setProperty("assignments[@type]", "vehicleType2depot");
// }
// for(VehicleType type : vrp.getDepotToVehicleTypeAssignments().get(depot)){
// xmlConfig.setProperty("assignments.assignment" + "("+assignmentCounter+").depotId", depot2id.get(depot));
// xmlConfig.setProperty("assignments.assignment" + "("+assignmentCounter+").vehicleTypeId", type.getTypeId());
// assignmentCounter++;
// }
// }
//
// //vehicle2depot assignments
// int vehicleAssignmentCounter = 0;
// boolean first_ = true;
// for(Depot depot : vrp.getDepotToVehicleAssignments().keySet()){
// if(first_){
// xmlConfig.setProperty("assignments[@type]", "vehicle2depot");
// }
// for(Vehicle vehicle : vrp.getDepotToVehicleAssignments().get(depot)){
// xmlConfig.setProperty("assignments.assignment" + "("+vehicleAssignmentCounter+").depotId", depot2id.get(depot));
// xmlConfig.setProperty("assignments.assignment" + "("+vehicleAssignmentCounter+").vehicleId", vehicle.getId());
// vehicleAssignmentCounter++;
// }
// }
//
}

View file

@ -0,0 +1,24 @@
package basics.route;
import basics.Delivery;
import basics.Pickup;
import basics.Service;
public class DefaultTourActivityFactory implements TourActivityFactory{
@Override
public TourActivity createActivity(Service service) {
TourActivity act;
if(service instanceof Pickup){
act = new PickupActivity((Pickup) service);
}
else if(service instanceof Delivery){
act = new DeliveryActivity((Delivery) service);
}
else{
act = ServiceActivity.newInstance(service);
}
return act;
}
}

View file

@ -0,0 +1,85 @@
package basics.route;
import basics.Delivery;
import basics.route.TourActivity.JobActivity;
public class DeliveryActivity implements JobActivity<Delivery>{
private Delivery delivery;
private double arrTime;
private double endTime;
public DeliveryActivity(Delivery delivery) {
super();
this.delivery = delivery;
}
private DeliveryActivity(DeliveryActivity deliveryActivity){
this.delivery=deliveryActivity.getJob();
this.arrTime=deliveryActivity.getArrTime();
this.endTime=deliveryActivity.getEndTime();
}
@Override
public int getCapacityDemand() {
return delivery.getCapacityDemand()*-1;
}
@Override
public String getName() {
return delivery.getType();
}
@Override
public String getLocationId() {
return delivery.getLocationId();
}
@Override
public double getTheoreticalEarliestOperationStartTime() {
return delivery.getTimeWindow().getStart();
}
@Override
public double getTheoreticalLatestOperationStartTime() {
return delivery.getTimeWindow().getEnd();
}
@Override
public double getOperationTime() {
return delivery.getServiceDuration();
}
@Override
public double getArrTime() {
return arrTime;
}
@Override
public double getEndTime() {
return endTime;
}
@Override
public void setArrTime(double arrTime) {
this.arrTime=arrTime;
}
@Override
public void setEndTime(double endTime) {
this.endTime=endTime;
}
@Override
public TourActivity duplicate() {
return new DeliveryActivity(this);
}
@Override
public Delivery getJob() {
return delivery;
}
}

View file

@ -0,0 +1,86 @@
package basics.route;
import basics.Pickup;
import basics.route.TourActivity.JobActivity;
public class PickupActivity implements JobActivity<Pickup>{
private Pickup pickup;
private double arrTime;
private double depTime;
public PickupActivity(Pickup pickup) {
super();
this.pickup = pickup;
}
private PickupActivity(PickupActivity pickupActivity){
this.pickup=pickupActivity.getJob();
this.arrTime=pickupActivity.getArrTime();
this.depTime=pickupActivity.getEndTime();
}
@Override
public String getName() {
return pickup.getType();
}
@Override
public String getLocationId() {
return pickup.getLocationId();
}
@Override
public double getTheoreticalEarliestOperationStartTime() {
return pickup.getTimeWindow().getStart();
}
@Override
public double getTheoreticalLatestOperationStartTime() {
return pickup.getTimeWindow().getEnd();
}
@Override
public double getOperationTime() {
return pickup.getServiceDuration();
}
@Override
public double getArrTime() {
return arrTime;
}
@Override
public double getEndTime() {
return depTime;
}
@Override
public void setArrTime(double arrTime) {
this.arrTime=arrTime;
}
@Override
public void setEndTime(double endTime) {
this.depTime=endTime;
}
@Override
public TourActivity duplicate() {
return new PickupActivity(this);
}
@Override
public Pickup getJob() {
return pickup;
}
@Override
public int getCapacityDemand() {
return pickup.getCapacityDemand();
}
}

View file

@ -31,6 +31,8 @@ public class ServiceActivity implements JobActivity<Service>{
public double endTime;
public int capacityDemand;
/**
* @return the arrTime
*/
@ -67,18 +69,31 @@ public class ServiceActivity implements JobActivity<Service>{
return new ServiceActivity(service);
}
/**
* creates a new instance of {@link ServiceActivity} with a flag that indicates whether smthing is unloaded or loaded.
*
* @param service
* @param capacityDemand
* @return
*/
// public static ServiceActivity newInstance(Service service, boolean isPickup){
// return new ServiceActivity(service, capacityDemand);
// }
private final Service service;
private ServiceActivity(Service service) {
protected ServiceActivity(Service service) {
counter++;
this.service = service;
this.capacityDemand = service.getCapacityDemand();
}
private ServiceActivity(ServiceActivity serviceActivity) {
protected ServiceActivity(ServiceActivity serviceActivity) {
counter++;
this.service = serviceActivity.getJob();
this.arrTime = serviceActivity.getArrTime();
this.endTime = serviceActivity.getEndTime();
this.capacityDemand = serviceActivity.getCapacityDemand();
}
@ -123,7 +138,7 @@ public class ServiceActivity implements JobActivity<Service>{
@Override
public int getCapacityDemand() {
return service.getCapacityDemand();
return this.capacityDemand;
}
@Override

View file

@ -0,0 +1,9 @@
package basics.route;
import basics.Service;
public interface TourActivityFactory {
public TourActivity createActivity(Service service);
}