Download
"""
PyCSP3 Model (see pycsp.org)
Data can come:
- either directly from a JSON file
- or from an intermediate parser
Example:
python CVRP.py -data=example.json
"""
from pycsp3 import *
nNodes, capacity, demands, distances = data
nVehicles = nNodes // 4 # This is a kind of hard coding, which can be at least used for Set A (Augerat, 1995)
def max_tour():
t = sorted(demands)
i, s = 1, 0
while i < nNodes and s < capacity:
s += t[i]
i += 1
return i - 2
nSteps = max_tour()
# c[i][j] is the jth customer (step) during the tour of the ith vehicle
c = VarArray(size=[nVehicles, nSteps], dom=range(nNodes))
# d[i][j] is the demand of the jth customer during the tour of the ith vehicle
d = VarArray(size=[nVehicles, nSteps], dom=demands)
satisfy(
AllDifferent(c, excepting=0),
# ensuring that all demands are satisfied
Cardinality(c, occurrences={0: nVehicles * nSteps - nNodes + 1} + {i: 1 for i in range(1, nNodes)}),
# no holes permitted during tours
[(c[i][j] != 0) | (c[i][j + 1] == 0) for i in range(nVehicles) for j in range(nSteps - 1)],
# computing the collected demands
[demands[c[i][j]] == d[i][j] for i in range(nVehicles) for j in range(nSteps)],
# not exceeding the capacity of each vehicle
[Sum(d[i]) <= capacity for i in range(nVehicles)],
# tag(symmetry-breaking)
Decreasing(c[:, 0])
)
minimize(
# minimizing the total traveled distance by vehicles
Sum(distances[0][c[i][0]] for i in range(nVehicles))
+ Sum(distances[c[i][j]][c[i][j + 1]] for i in range(nVehicles) for j in range(nSteps - 1))
+ Sum(distances[c[i][-1]][0] for i in range(nVehicles))
)