The Vehicle Routing Problem with Time Windows¶
This example illustrates a model for the vehicle routing problem with time windows (VRPTW).
In the VRPTW the objective is to minimize the total cost of routing vehicles from a central depot to a set of customers. Each customer must be visited exactly once within a specified time window to deliver their required demand, each customer has a service time it takes to unload the vehicle, and each vehicle has a maximum capacity of goods to deliver. If a vehicle arrives early it is allowed to wait for the customer's time window to start.
Let be graph with vertices where are the customers such that the depot is split in a 'start' and and 'end' depot and is the edges connecting all customers with each other and the depot vertices. Edge is associated with a cost and a travel time . Vertex is associated with a time window and a demand . The vehicle capacity is denoted .
Usually the problem is formulated as a path based model
where paths are feasible paths in with accumulated edge cost and expresses if path visits customer .
The corresponding network model can be formulated as
where are paths in a graph subject to time and demand constraints modeled as disposable resources. Demand with vertex consumption and bounds for all and time with edge consumption and vertex bounds for all .
The problem is implemented as
with the graph and resource constraints described above. See the modeling section for details.
Fetching data
To fetch the benchmark data using fetch_vrptw
check out the examples.
# Vehicle Routing Problem with Time Windows
import flowty
import fetch_vrptw
name, n, E, C, D, q, T, A, B, X, Y = fetch_vrptw.fetch("Solomon", "R102", 25)
model = flowty.Model()
# one graph, it is identical for all vehicles
g = model.addGraph(obj=C, edges=E, source=0, sink=n - 1, L=1, U=n - 2, type="B")
# adds resources variables to the graph.
# travel time and customer time windows
model.addResourceDisposable(
graph=g, consumptionType="E", weight=T, boundsType="V", lb=A, ub=B
)
# demand and capacity
model.addResourceDisposable(
graph=g, consumptionType="V", weight=D, boundsType="V", lb=0, ub=q
)
# set partition constriants
for i in range(1, n - 1):
model += flowty.xsum(x for x in g.vars if i == x.source) == 1
# packing set
for i in range(1, n - 1):
model.addPackingSet([x for x in g.vars if i == x.source])
status = model.optimize()
# get the variable values
#
if (
status == flowty.OptimizationStatus.Optimal
or status == flowty.OptimizationStatus.Feasible
):
for path in model.solutions[0].paths:
print(f"Path {path.idx}")
for var in path.vars:
print(f" {var.name}")