Skip to content

Commit

Permalink
Added a refinement phase to the two-step routing library.
Browse files Browse the repository at this point in the history
In this refinement phase, the solver collects all sequences of visits to
a parking location, and resolves them using a modified local model to
reoptimize for exactly the shipments delivered in these visits. It
replaces the base local routes with the refined ones and then re-solves
the global model by using the original solution as a warm-start.

This refinement has the following effects:
- it can merge visits from multiple delivery rounds in the original
  (unrefined) solution, thus removing unnecessary returns to the parking
  location to pick up more shipments.
- by removing these returns to parking, it can save some time and open
  up opportunities to deliver even more shipments in the saved time, or
  better organize shipments now that the delivery rounds are known.

We observed that it is very effective at reducing the inefficient
returns, but it can also help with reducing other types of parking
issues and even reduce skipped shipments.

After the two refinement phases, there might still be unnecessary visits
to the parking location - typically they would be created by the refined
global phase that can now perform some shipments that were skipped in
the original model.
  • Loading branch information
ondrasej committed Nov 13, 2023
1 parent 2ae8d23 commit f24ec40
Show file tree
Hide file tree
Showing 9 changed files with 2,307 additions and 40 deletions.
2 changes: 1 addition & 1 deletion python/cfr/two_step_routing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This directory contains a Python library that uses the Cloud Fleet Routing (CFR)
API to optimize routes with two-step deliveries: under this model, shipments can
be handled in two ways:
- delivered directly: the vehicle handling the shipment arrives directly to the
final delivery addres.
final delivery address.
- delivered through a parking location: when handling the shipment, the vehicle
parks at a specified parking location, while the driver delivers the shipment
by foot.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
{
"allowLargeDeadlineDespiteInterruptionRisk": true,
"considerRoadTraffic": true,
"injectedFirstSolutionRoutes": [
{
"vehicleIndex": 0,
"visits": [
{ "isPickup": false, "shipmentIndex": 0, "shipmentLabel": "s:8 S009" },
{
"isPickup": false,
"shipmentIndex": 1,
"shipmentLabel": "p:0 S001,S004,S003,S002"
},
{ "isPickup": false, "shipmentIndex": 2, "shipmentLabel": "p:1 S007" }
]
},
{
"vehicleIndex": 1,
"visits": [
{
"isPickup": false,
"shipmentIndex": 3,
"shipmentLabel": "p:2 S006,S008,S005"
}
]
}
],
"label": "my_little_model/global",
"model": {
"globalEndTime": "2023-08-12T00:00:00.000Z",
"globalStartTime": "2023-08-11T00:00:00.000Z",
"shipments": [
{
"allowedVehicleIndices": [0, 1],
"deliveries": [
{
"arrivalWaypoint": {
"location": {
"latLng": { "latitude": 48.86597, "longitude": 2.3489 }
}
},
"duration": "150s"
}
],
"label": "s:8 S009"
},
{
"allowedVehicleIndices": [0],
"costsPerVehicle": [100, 200],
"costsPerVehicleIndices": [0, 1],
"deliveries": [
{
"arrivalWaypoint": {
"location": {
"latLng": { "latitude": 48.86482, "longitude": 2.34932 }
}
},
"duration": "1176s",
"tags": ["P001"],
"timeWindows": [
{
"endTime": "2023-08-11T15:49:26Z",
"startTime": "2023-08-11T13:49:26Z"
}
]
}
],
"label": "p:0 S001,S004,S003,S002"
},
{
"allowedVehicleIndices": [0],
"deliveries": [
{
"arrivalWaypoint": {
"location": {
"latLng": { "latitude": 48.86482, "longitude": 2.34932 }
}
},
"duration": "449s",
"tags": ["P002", "parking: P002"]
}
],
"label": "p:1 S007",
"loadDemands": { "ore": { "amount": "1" }, "wood": { "amount": "5" } }
},
{
"allowedVehicleIndices": [1],
"deliveries": [
{
"arrivalWaypoint": {
"location": {
"latLng": { "latitude": 48.86482, "longitude": 2.34932 }
}
},
"duration": "750s",
"tags": ["P002", "parking: P002"]
}
],
"label": "p:2 S006,S008,S005",
"loadDemands": { "ore": { "amount": "2" }, "wheat": { "amount": "3" } }
}
],
"transitionAttributes": [
{ "cost": 1, "dstTag": "S002", "srcTag": "S001" },
{
"cost": 1000,
"delay": "180s",
"dstTag": "parking: P002",
"excludedSrcTag": "parking: P002"
},
{
"delay": "180s",
"excludedDstTag": "parking: P002",
"srcTag": "parking: P002"
},
{ "delay": "60s", "dstTag": "parking: P002", "srcTag": "parking: P002" }
],
"vehicles": [
{
"costPerHour": 60,
"costPerKilometer": 1,
"endTimeWindows": [
{
"endTime": "2023-08-11T21:00:00.000Z",
"startTime": "2023-08-11T16:00:00.000Z"
}
],
"endWaypoint": {
"location": {
"latLng": { "latitude": 48.86321, "longitude": 2.34767 }
}
},
"label": "V001",
"startTimeWindows": [
{
"endTime": "2023-08-11T08:00:00.000Z",
"startTime": "2023-08-11T08:00:00.000Z"
}
],
"startWaypoint": {
"location": {
"latLng": { "latitude": 48.86321, "longitude": 2.34767 }
}
},
"travelDurationMultiple": 1,
"travelMode": 1
},
{
"costPerHour": 60,
"costPerKilometer": 1,
"endTimeWindows": [
{
"endTime": "2023-08-11T21:00:00.000Z",
"startTime": "2023-08-11T20:00:00.000Z"
}
],
"endWaypoint": {
"location": {
"latLng": { "latitude": 48.86321, "longitude": 2.34767 }
}
},
"label": "V002",
"startTimeWindows": [
{
"endTime": "2023-08-11T08:00:00.000Z",
"startTime": "2023-08-11T08:00:00.000Z"
}
],
"startWaypoint": {
"location": {
"latLng": { "latitude": 48.86321, "longitude": 2.34767 }
}
},
"travelDurationMultiple": 1,
"travelMode": 1
}
]
},
"parent": "my_awesome_project",
"searchMode": 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
{
"allowLargeDeadlineDespiteInterruptionRisk": true,
"label": "my_little_model/refined_local",
"model": {
"globalEndTime": "2023-08-12T00:00:00.000Z",
"globalStartTime": "2023-08-11T00:00:00.000Z",
"shipments": [
{
"allowedVehicleIndices": [0],
"deliveries": [
{
"arrivalWaypoint": {
"location": {
"latLng": { "latitude": 48.86471, "longitude": 2.34901 }
}
},
"duration": "120s",
"tags": ["S001"]
}
],
"label": "0: S001"
},
{
"allowedVehicleIndices": [0],
"deliveries": [
{
"arrivalWaypoint": {
"location": {
"latLng": { "latitude": 48.86593, "longitude": 2.34886 }
}
},
"duration": "150s",
"tags": ["S002"]
}
],
"label": "1: S002"
},
{
"allowedVehicleIndices": [1],
"deliveries": [
{
"arrivalWaypoint": {
"location": {
"latLng": { "latitude": 48.86594, "longitude": 2.34887 }
}
},
"duration": "60s",
"timeWindows": [{ "startTime": "2023-08-11T12:00:00.000Z" }]
}
],
"label": "2: S003"
},
{
"allowedVehicleIndices": [2],
"deliveries": [
{
"arrivalWaypoint": {
"location": {
"latLng": { "latitude": 48.86595, "longitude": 2.34888 }
}
},
"duration": "60s",
"timeWindows": [
{
"endTime": "2023-08-11T16:00:00.000Z",
"startTime": "2023-08-11T14:00:00.000Z"
}
]
}
],
"label": "3: S004"
},
{
"allowedVehicleIndices": [3],
"deliveries": [
{
"arrivalWaypoint": {
"location": {
"latLng": { "latitude": 48.86596, "longitude": 2.34889 }
}
},
"duration": "150s"
}
],
"label": "4: S005"
},
{
"allowedVehicleIndices": [3],
"deliveries": [
{
"arrivalWaypoint": {
"location": {
"latLng": { "latitude": 48.86597, "longitude": 2.3489 }
}
},
"duration": "150s"
}
],
"label": "5: S006",
"loadDemands": { "ore": { "amount": "2" }, "wheat": { "amount": "3" } }
},
{
"allowedVehicleIndices": [4],
"deliveries": [
{
"arrivalWaypoint": {
"location": {
"latLng": { "latitude": 48.86597, "longitude": 2.3489 }
}
},
"duration": "150s"
}
],
"label": "6: S007",
"loadDemands": { "ore": { "amount": "1" }, "wood": { "amount": "5" } }
},
{
"allowedVehicleIndices": [5],
"deliveries": [
{
"arrivalWaypoint": {
"location": {
"latLng": { "latitude": 48.86597, "longitude": 2.3489 }
}
},
"duration": "150s"
}
],
"label": "7: S008"
}
],
"transitionAttributes": [{ "cost": 1, "dstTag": "S002", "srcTag": "S001" }],
"vehicles": [
{
"costPerHour": 300,
"costPerKilometer": 60,
"endTags": ["P001"],
"endWaypoint": {
"location": {
"latLng": { "latitude": 48.86482, "longitude": 2.34932 }
}
},
"fixedCost": 10000,
"label": "P001 [refinement]/0",
"loadLimits": { "ore": { "maxLoad": "2" } },
"routeDurationLimit": { "maxDuration": "1800s" },
"startTags": ["P001"],
"startWaypoint": {
"location": {
"latLng": { "latitude": 48.86482, "longitude": 2.34932 }
}
},
"travelDurationMultiple": 1.1,
"travelMode": 1
},
{
"costPerHour": 300,
"costPerKilometer": 60,
"endTags": ["P002"],
"endWaypoint": {
"location": {
"latLng": { "latitude": 48.86482, "longitude": 2.34932 }
}
},
"fixedCost": 10000,
"label": "P002 [vehicles=(0,)]/0",
"loadLimits": { "ore": { "maxLoad": "2" } },
"startTags": ["P002"],
"startWaypoint": {
"location": {
"latLng": { "latitude": 48.86482, "longitude": 2.34932 }
}
},
"travelDurationMultiple": 1.0,
"travelMode": 2
},
{
"costPerHour": 300,
"costPerKilometer": 60,
"endTags": ["P002"],
"endWaypoint": {
"location": {
"latLng": { "latitude": 48.86482, "longitude": 2.34932 }
}
},
"fixedCost": 10000,
"label": "P002 [refinement]/0",
"loadLimits": { "ore": { "maxLoad": "2" } },
"startTags": ["P002"],
"startWaypoint": {
"location": {
"latLng": { "latitude": 48.86482, "longitude": 2.34932 }
}
},
"travelDurationMultiple": 1.0,
"travelMode": 2
}
]
},
"parent": "my_awesome_project",
"searchMode": 1
}
Loading

0 comments on commit f24ec40

Please sign in to comment.