diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/io/VrpXMLReader.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/io/VrpXMLReader.java index 6c81bd16..57c3d52a 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/io/VrpXMLReader.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/io/VrpXMLReader.java @@ -390,11 +390,11 @@ public class VrpXMLReader { if (pickupServiceTime != null) builder.setPickupServiceTime(Double.parseDouble(pickupServiceTime)); //pickup-tw - String pickupTWStart = shipmentConfig.getString("pickup.timeWindows.timeWindow(0).start"); - String pickupTWEnd = shipmentConfig.getString("pickup.timeWindows.timeWindow(0).end"); - if (pickupTWStart != null && pickupTWEnd != null) { - TimeWindow pickupTW = TimeWindow.newInstance(Double.parseDouble(pickupTWStart), Double.parseDouble(pickupTWEnd)); - builder.setPickupTimeWindow(pickupTW); + List pickupTWConfigs = shipmentConfig.configurationsAt("pickup.timeWindows.timeWindow"); + if (!pickupTWConfigs.isEmpty()) { + for (HierarchicalConfiguration pu_twConfig : pickupTWConfigs) { + builder.addPickupTimeWindow(TimeWindow.newInstance(pu_twConfig.getDouble("start"), pu_twConfig.getDouble("end"))); + } } //delivery location @@ -424,11 +424,11 @@ public class VrpXMLReader { if (deliveryServiceTime != null) builder.setDeliveryServiceTime(Double.parseDouble(deliveryServiceTime)); //delivery-tw - String delTWStart = shipmentConfig.getString("delivery.timeWindows.timeWindow(0).start"); - String delTWEnd = shipmentConfig.getString("delivery.timeWindows.timeWindow(0).end"); - if (delTWStart != null && delTWEnd != null) { - TimeWindow delTW = TimeWindow.newInstance(Double.parseDouble(delTWStart), Double.parseDouble(delTWEnd)); - builder.setDeliveryTimeWindow(delTW); + List deliveryTWConfigs = shipmentConfig.configurationsAt("delivery.timeWindows.timeWindow"); + if (!deliveryTWConfigs.isEmpty()) { + for (HierarchicalConfiguration dl_twConfig : deliveryTWConfigs) { + builder.addDeliveryTimeWindow(TimeWindow.newInstance(dl_twConfig.getDouble("start"), dl_twConfig.getDouble("end"))); + } } //read skills @@ -514,7 +514,7 @@ public class VrpXMLReader { List deliveryTWConfigs = serviceConfig.configurationsAt("timeWindows.timeWindow"); if (!deliveryTWConfigs.isEmpty()) { for (HierarchicalConfiguration twConfig : deliveryTWConfigs) { - builder.setTimeWindow(TimeWindow.newInstance(twConfig.getDouble("start"), twConfig.getDouble("end"))); + builder.addTimeWindow(TimeWindow.newInstance(twConfig.getDouble("start"), twConfig.getDouble("end"))); } } @@ -564,6 +564,7 @@ public class VrpXMLReader { typeBuilder.addCapacityDimension(index, value); } } + Double fix = typeConfig.getDouble("costs.fixed"); Double timeC = typeConfig.getDouble("costs.time"); Double distC = typeConfig.getDouble("costs.distance"); @@ -671,6 +672,19 @@ public class VrpXMLReader { for (String skill : skillTokens) builder.addSkill(skill.toLowerCase()); } + // read break + List breakTWConfigs = vehicleConfig.configurationsAt("break.timeWindows.timeWindow"); + if (!breakTWConfigs.isEmpty()) { + String breakDurationString = vehicleConfig.getString("breaks.duration"); + Break.Builder current_break = Break.Builder.newInstance(vehicleId); + current_break.setServiceTime(Double.parseDouble(breakDurationString)); + for (HierarchicalConfiguration twConfig : breakTWConfigs) { + current_break.addTimeWindow(TimeWindow.newInstance(twConfig.getDouble("start"), twConfig.getDouble("end"))); + } + builder.setBreak(current_break.build()); + } + + //build vehicle VehicleImpl vehicle = builder.build(); vrpBuilder.addVehicle(vehicle); diff --git a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/io/VrpXMLWriter.java b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/io/VrpXMLWriter.java index f533c701..506122d0 100644 --- a/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/io/VrpXMLWriter.java +++ b/jsprit-core/src/main/java/com/graphhopper/jsprit/core/problem/io/VrpXMLWriter.java @@ -19,11 +19,13 @@ package com.graphhopper.jsprit.core.problem.io; import com.graphhopper.jsprit.core.problem.Location; import com.graphhopper.jsprit.core.problem.Skills; import com.graphhopper.jsprit.core.problem.VehicleRoutingProblem; +import com.graphhopper.jsprit.core.problem.job.Break; import com.graphhopper.jsprit.core.problem.job.Job; import com.graphhopper.jsprit.core.problem.job.Service; import com.graphhopper.jsprit.core.problem.job.Shipment; import com.graphhopper.jsprit.core.problem.solution.VehicleRoutingProblemSolution; 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.TourActivity; import com.graphhopper.jsprit.core.problem.vehicle.Vehicle; import com.graphhopper.jsprit.core.problem.vehicle.VehicleType; @@ -148,6 +150,8 @@ public class VrpXMLWriter { xmlConfig.setProperty(path + "(" + routeCounter + ").act(" + actCounter + ").serviceId", job.getId()); } else if (job instanceof Shipment) { xmlConfig.setProperty(path + "(" + routeCounter + ").act(" + actCounter + ").shipmentId", job.getId()); + } else if (job instanceof Break) { + xmlConfig.setProperty(path + "(" + routeCounter + ").act(" + actCounter + ").breakId", job.getId()); } else { throw new IllegalStateException("cannot write solution correctly since job-type is not know. make sure you use either service or shipment, or another writer"); } @@ -183,6 +187,8 @@ public class VrpXMLWriter { xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act(" + actCounter + ").serviceId", job.getId()); } else if (job instanceof Shipment) { xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act(" + actCounter + ").shipmentId", job.getId()); + } else if (job instanceof Break) { + xmlConfig.setProperty(solutionPath + "(" + counter + ").routes.route(" + routeCounter + ").act(" + actCounter + ").breakId", job.getId()); } else { throw new IllegalStateException("cannot write solution correctly since job-type is not know. make sure you use either service or shipment, or another writer"); } @@ -224,9 +230,15 @@ public class VrpXMLWriter { xmlConfig.setProperty(shipmentPathString + "(" + counter + ").capacity-dimensions.dimension(" + i + ")[@index]", i); xmlConfig.setProperty(shipmentPathString + "(" + counter + ").capacity-dimensions.dimension(" + i + ")", service.getSize().get(i)); } + + Collection tws = service.getTimeWindows(); + int index = 0; xmlConfig.setProperty(shipmentPathString + "(" + counter + ").duration", service.getServiceDuration()); - xmlConfig.setProperty(shipmentPathString + "(" + counter + ").timeWindows.timeWindow(0).start", service.getTimeWindow().getStart()); - xmlConfig.setProperty(shipmentPathString + "(" + counter + ").timeWindows.timeWindow(0).end", service.getTimeWindow().getEnd()); + for(TimeWindow tw : tws) { + xmlConfig.setProperty(shipmentPathString + "(" + counter + ").timeWindows.timeWindow(" + index + ").start", tw.getStart()); + xmlConfig.setProperty(shipmentPathString + "(" + counter + ").timeWindows.timeWindow(" + index + ").end", tw.getEnd()); + ++index; + } //skills String skillString = getSkillString(service); @@ -260,10 +272,14 @@ public class VrpXMLWriter { xmlConfig.setProperty(shipmentPathString + "(" + counter + ").pickup.location.index", shipment.getPickupLocation().getIndex()); } + Collection pu_tws = shipment.getPickupTimeWindows(); + int index = 0; xmlConfig.setProperty(shipmentPathString + "(" + counter + ").pickup.duration", shipment.getPickupServiceTime()); - xmlConfig.setProperty(shipmentPathString + "(" + counter + ").pickup.timeWindows.timeWindow(0).start", shipment.getPickupTimeWindow().getStart()); - xmlConfig.setProperty(shipmentPathString + "(" + counter + ").pickup.timeWindows.timeWindow(0).end", shipment.getPickupTimeWindow().getEnd()); - + for(TimeWindow tw : pu_tws) { + xmlConfig.setProperty(shipmentPathString + "(" + counter + ").pickup.timeWindows.timeWindow(" + index + ").start", tw.getStart()); + xmlConfig.setProperty(shipmentPathString + "(" + counter + ").pickup.timeWindows.timeWindow(" + index + ").end", tw.getEnd()); + ++index; + } if (shipment.getDeliveryLocation().getId() != null) xmlConfig.setProperty(shipmentPathString + "(" + counter + ").delivery.location.id", shipment.getDeliveryLocation().getId()); @@ -275,9 +291,14 @@ public class VrpXMLWriter { xmlConfig.setProperty(shipmentPathString + "(" + counter + ").delivery.location.index", shipment.getDeliveryLocation().getIndex()); } - xmlConfig.setProperty(shipmentPathString + "(" + counter + ").delivery.duration", shipment.getDeliveryServiceTime()); - xmlConfig.setProperty(shipmentPathString + "(" + counter + ").delivery.timeWindows.timeWindow(0).start", shipment.getDeliveryTimeWindow().getStart()); - xmlConfig.setProperty(shipmentPathString + "(" + counter + ").delivery.timeWindows.timeWindow(0).end", shipment.getDeliveryTimeWindow().getEnd()); + Collection del_tws = shipment.getDeliveryTimeWindows(); + xmlConfig.setProperty(shipmentPathString + "(" + counter + ").delivery.duration", shipment.getDeliveryServiceTime()); + index = 0; + for(TimeWindow tw : del_tws) { + xmlConfig.setProperty(shipmentPathString + "(" + counter + ").delivery.timeWindows.timeWindow(" + index + ").start", tw.getStart()); + xmlConfig.setProperty(shipmentPathString + "(" + counter + ").delivery.timeWindows.timeWindow(" + index + ").end", tw.getEnd()); + ++index; + } for (int i = 0; i < shipment.getSize().getNuOfDimensions(); i++) { xmlConfig.setProperty(shipmentPathString + "(" + counter + ").capacity-dimensions.dimension(" + i + ")[@index]", i); @@ -330,6 +351,16 @@ public class VrpXMLWriter { xmlConfig.setProperty(vehiclePathString + "(" + counter + ").timeSchedule.start", vehicle.getEarliestDeparture()); xmlConfig.setProperty(vehiclePathString + "(" + counter + ").timeSchedule.end", vehicle.getLatestArrival()); + if (vehicle.getBreak() != null) { + Collection tws = vehicle.getBreak().getTimeWindows(); + int index = 0; + xmlConfig.setProperty(vehiclePathString + "(" + counter + ").break.duration", vehicle.getBreak().getServiceDuration()); + for(TimeWindow tw : tws) { + xmlConfig.setProperty(vehiclePathString + "(" + counter + ").break.timeWindows.timeWindow(" + index + ").start", tw.getStart()); + xmlConfig.setProperty(vehiclePathString + "(" + counter + ").break.timeWindows.timeWindow(" + index + ").end", tw.getEnd()); + ++index; + } + } xmlConfig.setProperty(vehiclePathString + "(" + counter + ").returnToDepot", vehicle.isReturnToDepot()); //write skills diff --git a/jsprit-core/src/main/resources/vrp_xml_schema.xsd b/jsprit-core/src/main/resources/vrp_xml_schema.xsd index 8ed94b85..a621bcc9 100644 --- a/jsprit-core/src/main/resources/vrp_xml_schema.xsd +++ b/jsprit-core/src/main/resources/vrp_xml_schema.xsd @@ -62,6 +62,7 @@ + @@ -368,6 +369,20 @@ + + + + + + + + + + + + +