Last active
July 26, 2018 07:20
-
-
Save 270ajay/154a1bdbd55aacb7b26bf2f5a411b55c to your computer and use it in GitHub Desktop.
Optimizing Vehicle Routing Problem with Time Windows using Mixed Integer Programming (BigM formulation). Uses PuLP library in python.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import csv | |
import pulp #This contains LP Modeling and solver | |
import time #This is used to see how much time for solving | |
####################################################################### | |
####################################################################### | |
NumberOfPoints = 10 # number of points/locations in the data | |
k = 5 # number of vehicles | |
BigM = 50 | |
StartTime = 12 #12 means 6am. 14 means 8am. half hour is 1 time unit. | |
EndTime = 44 #44 means 22:00 or 10pm. | |
ObjectiveWeightForVehicles = [50,100,150,200,250] #length of this list should be equal to k (number of vehicles) | |
####################################################################### | |
####################################################################### | |
assert len(ObjectiveWeightForVehicles) == k #checking if that condition satisfies. | |
#------------------------------------------------------------------------------------------------------ | |
# GETTING & PREPARING DATA | |
#------------------------------------------------------------------------------------------------------ | |
vehicleList = range(k) | |
Points = range(1,NumberOfPoints+1) | |
Nodes = range(0,NumberOfPoints+2) #there are 21 nodes as 0 and numberofpoints+1 are entry and exit depots respectively. | |
with open('travelTimes.csv') as csvfile: | |
data = list(csv.reader(csvfile)) | |
travelTimes = {} | |
for i in Points: | |
for j in Points: | |
if data[j][i].isdigit() and i!=j: | |
travelTimes[(i,j)] = float(int(data[j][i])/10) | |
#Addition of 0 and NumberOfPoints+1 points as they are depots in this model. | |
travelTimes[(0,NumberOfPoints+1)] = 0 | |
for i in Points: | |
travelTimes[(0,i)] = 0 | |
travelTimes[(i,(NumberOfPoints+1))] = 0 | |
#Addition of symmetrical travel times | |
for i in range(2,NumberOfPoints+1): | |
for j in range(1,i): | |
travelTimes[(i,j)] = travelTimes[(j,i)] | |
travelFrom,travelTo = zip(*list(travelTimes.keys())) | |
#----------------------------------------------------------------------------- | |
with open('locations.csv') as csvfile1: | |
data1 = list(csv.reader(csvfile1)) | |
LocationData = dict([(point,[]) for point in Points]) | |
for j in [1,6,7]: | |
for i in Points: | |
LocationData[i].append(data1[i][j]) | |
CapacityOfVehicle = float(data1[1][4]) | |
#------------------------------------------------------------------------------------------------------ | |
# LP MODELING | |
#------------------------------------------------------------------------------------------------------ | |
VRP = pulp.LpProblem("Assign_FromPointId_ToPointId_VehicleId, StartTime(S)_PointId_VehicleId", pulp.LpMinimize) | |
DecisionVar = pulp.LpVariable.dicts("Assign",(Nodes,Nodes,vehicleList),0,1,pulp.LpInteger) #Binary | |
TimeDecisionVar = pulp.LpVariable.dicts("Start",(Nodes,vehicleList),0,None, pulp.LpContinuous) | |
for point in Points: | |
for vehicle in vehicleList: | |
TimeDecisionVar[point][vehicle].bounds(float(LocationData[point][1]), float(LocationData[point][2])) | |
VRP += sum([float(travelTimes[From,To]) * ObjectiveWeightForVehicles[vehicle] * DecisionVar[From][To][vehicle] for From,To in zip(travelFrom,travelTo) | |
for vehicle in vehicleList]) | |
#Objective (2.1 in mip model.png) | |
for point in Points: | |
VRP += pulp.lpSum([DecisionVar[point][node][vehicle] for node in Nodes | |
for vehicle in vehicleList if point!=node]) == 1, "eachCustomerOnce"+str(point) | |
#constraint1 (2.2 in mip model.png) | |
for vehicle in vehicleList: | |
VRP += pulp.lpSum([float(LocationData[point][0]) * DecisionVar[point][node][vehicle] for point in Points | |
for node in Nodes if point!=node]) <= float(CapacityOfVehicle), "Capacity"+str(vehicle) | |
#constraint2 (2.3 in mip model.png) | |
for vehicle in vehicleList: | |
VRP += pulp.lpSum([DecisionVar[0][node][vehicle] for node in | |
Nodes if node!=0]) == 1, "entryDepotConnection"+str(vehicle) | |
#constraint3 (2.4 in mip model.png) | |
#there are 21 nodes as 0 and NumberOfPoints+1 are entry and exit depots respectively. | |
for vehicle in vehicleList: | |
VRP += pulp.lpSum([DecisionVar[node][NumberOfPoints+1][vehicle] for node in Nodes | |
if node!=NumberOfPoints+1]) == 1, "exitDepotConnection"+str(vehicle) | |
#constraint4 (2.6 in mip model.png) | |
for point in Points: | |
for vehicle in vehicleList: | |
VRP += pulp.lpSum([DecisionVar[node][point][vehicle] - DecisionVar[point][node][vehicle] for node in | |
Nodes if node!=point]) == 0, "forTrip"+str(point)+'k'+str(vehicle) | |
#constraint5 (2.5 in mip model.png) | |
for point in Points: | |
for vehicle in vehicleList: | |
VRP += DecisionVar[point][0][vehicle] == 0, "ToEntryDepot"+str(point)+str(vehicle) | |
VRP += DecisionVar[NumberOfPoints+1][point][vehicle] == 0, "FromExitDepot"+str(point)+str(vehicle) | |
#constraint6 - For constraint5 to work correctly. | |
for vehicle in vehicleList: | |
for node1 in Nodes: | |
if node1 == NumberOfPoints+1: | |
continue | |
else: | |
for node2 in Nodes: | |
if node2 == 0: | |
continue | |
else: | |
if (node1 != node2): | |
VRP += TimeDecisionVar[node1][vehicle] - TimeDecisionVar[node2][vehicle]\ | |
+ BigM * DecisionVar[node1][node2][vehicle] <= float(BigM - travelTimes[node1,node2]), \ | |
"timewindow"+str(vehicle)+'p'+str(node1)+'p'+str(node2) | |
for vehicle in vehicleList: | |
VRP += TimeDecisionVar[NumberOfPoints+1][vehicle] <= EndTime, "EndTime"+str(vehicle) | |
VRP += TimeDecisionVar[0][vehicle] >= StartTime, "StartTime"+str(vehicle) | |
VRP.writeLP("VRPLPModel.lp") | |
tic = time.time() | |
VRP.solve() | |
toc = time.time() | |
print("Time taken for solving is " + str(1000*(toc-tic)) + "ms") | |
print("") | |
for vehicle in vehicleList: | |
for node1 in Nodes: | |
for node2 in Nodes: | |
if DecisionVar[node1][node2][vehicle].value() == 1.0: | |
print("Point:"+ str(node1)+ " to Point:" + str(node2) + " by vehicle:" + str(vehicle)) | |
print("Objective value:",pulp.value(VRP.objective)) | |
print("See VRPOutput.csv and VRPLPModel.lp for more details.") | |
#------------------------------------------------------------------------------------------------------ | |
# PRINTING RESULTS INTO CSV | |
#------------------------------------------------------------------------------------------------------ | |
with open("VRPOutput.csv","w",newline='') as file: | |
datawriter = csv.writer(file) | |
datawriter.writerow(['PointTravelled','vehicle',"",'DecisionVar=1','TimeDecisionVar','StartTime']) | |
for vehicle in vehicleList: | |
for node1 in Nodes: | |
for node2 in Nodes: | |
if DecisionVar[node1][node2][vehicle].value() == 1.0: | |
#if node1 != 0: #to not print activity0. | |
datawriter.writerow(['Point'+str(node1),str(vehicle+1),"",str(DecisionVar[node1][node2][vehicle]), | |
str(TimeDecisionVar[node1][vehicle]),str(TimeDecisionVar[node1][vehicle].value())]) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
\* Assign_FromPointId_ToPointId_VehicleId, StartTime(S)_PointId_VehicleId *\ | |
Minimize | |
OBJ: 35 Assign_1_2_0 + 70 Assign_1_2_1 + 40 Assign_1_3_0 + 80 Assign_1_3_1 | |
+ 65 Assign_1_4_0 + 130 Assign_1_4_1 + 25 Assign_1_5_0 + 50 Assign_1_5_1 | |
+ 35 Assign_2_1_0 + 70 Assign_2_1_1 + 60 Assign_2_3_0 + 120 Assign_2_3_1 | |
+ 80 Assign_2_4_0 + 160 Assign_2_4_1 + 30 Assign_2_5_0 + 60 Assign_2_5_1 | |
+ 40 Assign_3_1_0 + 80 Assign_3_1_1 + 60 Assign_3_2_0 + 120 Assign_3_2_1 | |
+ 45 Assign_3_4_0 + 90 Assign_3_4_1 + 35 Assign_3_5_0 + 70 Assign_3_5_1 | |
+ 65 Assign_4_1_0 + 130 Assign_4_1_1 + 80 Assign_4_2_0 + 160 Assign_4_2_1 | |
+ 45 Assign_4_3_0 + 90 Assign_4_3_1 + 45 Assign_4_5_0 + 90 Assign_4_5_1 | |
+ 25 Assign_5_1_0 + 50 Assign_5_1_1 + 30 Assign_5_2_0 + 60 Assign_5_2_1 | |
+ 35 Assign_5_3_0 + 70 Assign_5_3_1 + 45 Assign_5_4_0 + 90 Assign_5_4_1 | |
Subject To | |
Capacity0: 33 Assign_1_0_0 + 33 Assign_1_2_0 + 33 Assign_1_3_0 | |
+ 33 Assign_1_4_0 + 33 Assign_1_5_0 + 33 Assign_1_6_0 + 47 Assign_2_0_0 | |
+ 47 Assign_2_1_0 + 47 Assign_2_3_0 + 47 Assign_2_4_0 + 47 Assign_2_5_0 | |
+ 47 Assign_2_6_0 + 10 Assign_3_0_0 + 10 Assign_3_1_0 + 10 Assign_3_2_0 | |
+ 10 Assign_3_4_0 + 10 Assign_3_5_0 + 10 Assign_3_6_0 + 25 Assign_4_0_0 | |
+ 25 Assign_4_1_0 + 25 Assign_4_2_0 + 25 Assign_4_3_0 + 25 Assign_4_5_0 | |
+ 25 Assign_4_6_0 + 34 Assign_5_0_0 + 34 Assign_5_1_0 + 34 Assign_5_2_0 | |
+ 34 Assign_5_3_0 + 34 Assign_5_4_0 + 34 Assign_5_6_0 <= 200 | |
Capacity1: 33 Assign_1_0_1 + 33 Assign_1_2_1 + 33 Assign_1_3_1 | |
+ 33 Assign_1_4_1 + 33 Assign_1_5_1 + 33 Assign_1_6_1 + 47 Assign_2_0_1 | |
+ 47 Assign_2_1_1 + 47 Assign_2_3_1 + 47 Assign_2_4_1 + 47 Assign_2_5_1 | |
+ 47 Assign_2_6_1 + 10 Assign_3_0_1 + 10 Assign_3_1_1 + 10 Assign_3_2_1 | |
+ 10 Assign_3_4_1 + 10 Assign_3_5_1 + 10 Assign_3_6_1 + 25 Assign_4_0_1 | |
+ 25 Assign_4_1_1 + 25 Assign_4_2_1 + 25 Assign_4_3_1 + 25 Assign_4_5_1 | |
+ 25 Assign_4_6_1 + 34 Assign_5_0_1 + 34 Assign_5_1_1 + 34 Assign_5_2_1 | |
+ 34 Assign_5_3_1 + 34 Assign_5_4_1 + 34 Assign_5_6_1 <= 200 | |
EndTime0: Start_6_0 <= 44 | |
EndTime1: Start_6_1 <= 44 | |
FromExitDepot10: Assign_6_1_0 = 0 | |
FromExitDepot11: Assign_6_1_1 = 0 | |
FromExitDepot20: Assign_6_2_0 = 0 | |
FromExitDepot21: Assign_6_2_1 = 0 | |
FromExitDepot30: Assign_6_3_0 = 0 | |
FromExitDepot31: Assign_6_3_1 = 0 | |
FromExitDepot40: Assign_6_4_0 = 0 | |
FromExitDepot41: Assign_6_4_1 = 0 | |
FromExitDepot50: Assign_6_5_0 = 0 | |
FromExitDepot51: Assign_6_5_1 = 0 | |
StartTime0: Start_0_0 >= 12 | |
StartTime1: Start_0_1 >= 12 | |
ToEntryDepot10: Assign_1_0_0 = 0 | |
ToEntryDepot11: Assign_1_0_1 = 0 | |
ToEntryDepot20: Assign_2_0_0 = 0 | |
ToEntryDepot21: Assign_2_0_1 = 0 | |
ToEntryDepot30: Assign_3_0_0 = 0 | |
ToEntryDepot31: Assign_3_0_1 = 0 | |
ToEntryDepot40: Assign_4_0_0 = 0 | |
ToEntryDepot41: Assign_4_0_1 = 0 | |
ToEntryDepot50: Assign_5_0_0 = 0 | |
ToEntryDepot51: Assign_5_0_1 = 0 | |
eachCustomerOnce1: Assign_1_0_0 + Assign_1_0_1 + Assign_1_2_0 + Assign_1_2_1 | |
+ Assign_1_3_0 + Assign_1_3_1 + Assign_1_4_0 + Assign_1_4_1 + Assign_1_5_0 | |
+ Assign_1_5_1 + Assign_1_6_0 + Assign_1_6_1 = 1 | |
eachCustomerOnce2: Assign_2_0_0 + Assign_2_0_1 + Assign_2_1_0 + Assign_2_1_1 | |
+ Assign_2_3_0 + Assign_2_3_1 + Assign_2_4_0 + Assign_2_4_1 + Assign_2_5_0 | |
+ Assign_2_5_1 + Assign_2_6_0 + Assign_2_6_1 = 1 | |
eachCustomerOnce3: Assign_3_0_0 + Assign_3_0_1 + Assign_3_1_0 + Assign_3_1_1 | |
+ Assign_3_2_0 + Assign_3_2_1 + Assign_3_4_0 + Assign_3_4_1 + Assign_3_5_0 | |
+ Assign_3_5_1 + Assign_3_6_0 + Assign_3_6_1 = 1 | |
eachCustomerOnce4: Assign_4_0_0 + Assign_4_0_1 + Assign_4_1_0 + Assign_4_1_1 | |
+ Assign_4_2_0 + Assign_4_2_1 + Assign_4_3_0 + Assign_4_3_1 + Assign_4_5_0 | |
+ Assign_4_5_1 + Assign_4_6_0 + Assign_4_6_1 = 1 | |
eachCustomerOnce5: Assign_5_0_0 + Assign_5_0_1 + Assign_5_1_0 + Assign_5_1_1 | |
+ Assign_5_2_0 + Assign_5_2_1 + Assign_5_3_0 + Assign_5_3_1 + Assign_5_4_0 | |
+ Assign_5_4_1 + Assign_5_6_0 + Assign_5_6_1 = 1 | |
entryDepotConnection0: Assign_0_1_0 + Assign_0_2_0 + Assign_0_3_0 | |
+ Assign_0_4_0 + Assign_0_5_0 + Assign_0_6_0 = 1 | |
entryDepotConnection1: Assign_0_1_1 + Assign_0_2_1 + Assign_0_3_1 | |
+ Assign_0_4_1 + Assign_0_5_1 + Assign_0_6_1 = 1 | |
exitDepotConnection0: Assign_0_6_0 + Assign_1_6_0 + Assign_2_6_0 | |
+ Assign_3_6_0 + Assign_4_6_0 + Assign_5_6_0 = 1 | |
exitDepotConnection1: Assign_0_6_1 + Assign_1_6_1 + Assign_2_6_1 | |
+ Assign_3_6_1 + Assign_4_6_1 + Assign_5_6_1 = 1 | |
forTrip1k0: Assign_0_1_0 - Assign_1_0_0 - Assign_1_2_0 - Assign_1_3_0 | |
- Assign_1_4_0 - Assign_1_5_0 - Assign_1_6_0 + Assign_2_1_0 + Assign_3_1_0 | |
+ Assign_4_1_0 + Assign_5_1_0 + Assign_6_1_0 = 0 | |
forTrip1k1: Assign_0_1_1 - Assign_1_0_1 - Assign_1_2_1 - Assign_1_3_1 | |
- Assign_1_4_1 - Assign_1_5_1 - Assign_1_6_1 + Assign_2_1_1 + Assign_3_1_1 | |
+ Assign_4_1_1 + Assign_5_1_1 + Assign_6_1_1 = 0 | |
forTrip2k0: Assign_0_2_0 + Assign_1_2_0 - Assign_2_0_0 - Assign_2_1_0 | |
- Assign_2_3_0 - Assign_2_4_0 - Assign_2_5_0 - Assign_2_6_0 + Assign_3_2_0 | |
+ Assign_4_2_0 + Assign_5_2_0 + Assign_6_2_0 = 0 | |
forTrip2k1: Assign_0_2_1 + Assign_1_2_1 - Assign_2_0_1 - Assign_2_1_1 | |
- Assign_2_3_1 - Assign_2_4_1 - Assign_2_5_1 - Assign_2_6_1 + Assign_3_2_1 | |
+ Assign_4_2_1 + Assign_5_2_1 + Assign_6_2_1 = 0 | |
forTrip3k0: Assign_0_3_0 + Assign_1_3_0 + Assign_2_3_0 - Assign_3_0_0 | |
- Assign_3_1_0 - Assign_3_2_0 - Assign_3_4_0 - Assign_3_5_0 - Assign_3_6_0 | |
+ Assign_4_3_0 + Assign_5_3_0 + Assign_6_3_0 = 0 | |
forTrip3k1: Assign_0_3_1 + Assign_1_3_1 + Assign_2_3_1 - Assign_3_0_1 | |
- Assign_3_1_1 - Assign_3_2_1 - Assign_3_4_1 - Assign_3_5_1 - Assign_3_6_1 | |
+ Assign_4_3_1 + Assign_5_3_1 + Assign_6_3_1 = 0 | |
forTrip4k0: Assign_0_4_0 + Assign_1_4_0 + Assign_2_4_0 + Assign_3_4_0 | |
- Assign_4_0_0 - Assign_4_1_0 - Assign_4_2_0 - Assign_4_3_0 - Assign_4_5_0 | |
- Assign_4_6_0 + Assign_5_4_0 + Assign_6_4_0 = 0 | |
forTrip4k1: Assign_0_4_1 + Assign_1_4_1 + Assign_2_4_1 + Assign_3_4_1 | |
- Assign_4_0_1 - Assign_4_1_1 - Assign_4_2_1 - Assign_4_3_1 - Assign_4_5_1 | |
- Assign_4_6_1 + Assign_5_4_1 + Assign_6_4_1 = 0 | |
forTrip5k0: Assign_0_5_0 + Assign_1_5_0 + Assign_2_5_0 + Assign_3_5_0 | |
+ Assign_4_5_0 - Assign_5_0_0 - Assign_5_1_0 - Assign_5_2_0 - Assign_5_3_0 | |
- Assign_5_4_0 - Assign_5_6_0 + Assign_6_5_0 = 0 | |
forTrip5k1: Assign_0_5_1 + Assign_1_5_1 + Assign_2_5_1 + Assign_3_5_1 | |
+ Assign_4_5_1 - Assign_5_0_1 - Assign_5_1_1 - Assign_5_2_1 - Assign_5_3_1 | |
- Assign_5_4_1 - Assign_5_6_1 + Assign_6_5_1 = 0 | |
timewindow0p0p1: 50 Assign_0_1_0 + Start_0_0 - Start_1_0 <= 50 | |
timewindow0p0p2: 50 Assign_0_2_0 + Start_0_0 - Start_2_0 <= 50 | |
timewindow0p0p3: 50 Assign_0_3_0 + Start_0_0 - Start_3_0 <= 50 | |
timewindow0p0p4: 50 Assign_0_4_0 + Start_0_0 - Start_4_0 <= 50 | |
timewindow0p0p5: 50 Assign_0_5_0 + Start_0_0 - Start_5_0 <= 50 | |
timewindow0p0p6: 50 Assign_0_6_0 + Start_0_0 - Start_6_0 <= 50 | |
timewindow0p1p2: 50 Assign_1_2_0 + Start_1_0 - Start_2_0 <= 49.3 | |
timewindow0p1p3: 50 Assign_1_3_0 + Start_1_0 - Start_3_0 <= 49.2 | |
timewindow0p1p4: 50 Assign_1_4_0 + Start_1_0 - Start_4_0 <= 48.7 | |
timewindow0p1p5: 50 Assign_1_5_0 + Start_1_0 - Start_5_0 <= 49.5 | |
timewindow0p1p6: 50 Assign_1_6_0 + Start_1_0 - Start_6_0 <= 50 | |
timewindow0p2p1: 50 Assign_2_1_0 - Start_1_0 + Start_2_0 <= 49.3 | |
timewindow0p2p3: 50 Assign_2_3_0 + Start_2_0 - Start_3_0 <= 48.8 | |
timewindow0p2p4: 50 Assign_2_4_0 + Start_2_0 - Start_4_0 <= 48.4 | |
timewindow0p2p5: 50 Assign_2_5_0 + Start_2_0 - Start_5_0 <= 49.4 | |
timewindow0p2p6: 50 Assign_2_6_0 + Start_2_0 - Start_6_0 <= 50 | |
timewindow0p3p1: 50 Assign_3_1_0 - Start_1_0 + Start_3_0 <= 49.2 | |
timewindow0p3p2: 50 Assign_3_2_0 - Start_2_0 + Start_3_0 <= 48.8 | |
timewindow0p3p4: 50 Assign_3_4_0 + Start_3_0 - Start_4_0 <= 49.1 | |
timewindow0p3p5: 50 Assign_3_5_0 + Start_3_0 - Start_5_0 <= 49.3 | |
timewindow0p3p6: 50 Assign_3_6_0 + Start_3_0 - Start_6_0 <= 50 | |
timewindow0p4p1: 50 Assign_4_1_0 - Start_1_0 + Start_4_0 <= 48.7 | |
timewindow0p4p2: 50 Assign_4_2_0 - Start_2_0 + Start_4_0 <= 48.4 | |
timewindow0p4p3: 50 Assign_4_3_0 - Start_3_0 + Start_4_0 <= 49.1 | |
timewindow0p4p5: 50 Assign_4_5_0 + Start_4_0 - Start_5_0 <= 49.1 | |
timewindow0p4p6: 50 Assign_4_6_0 + Start_4_0 - Start_6_0 <= 50 | |
timewindow0p5p1: 50 Assign_5_1_0 - Start_1_0 + Start_5_0 <= 49.5 | |
timewindow0p5p2: 50 Assign_5_2_0 - Start_2_0 + Start_5_0 <= 49.4 | |
timewindow0p5p3: 50 Assign_5_3_0 - Start_3_0 + Start_5_0 <= 49.3 | |
timewindow0p5p4: 50 Assign_5_4_0 - Start_4_0 + Start_5_0 <= 49.1 | |
timewindow0p5p6: 50 Assign_5_6_0 + Start_5_0 - Start_6_0 <= 50 | |
timewindow1p0p1: 50 Assign_0_1_1 + Start_0_1 - Start_1_1 <= 50 | |
timewindow1p0p2: 50 Assign_0_2_1 + Start_0_1 - Start_2_1 <= 50 | |
timewindow1p0p3: 50 Assign_0_3_1 + Start_0_1 - Start_3_1 <= 50 | |
timewindow1p0p4: 50 Assign_0_4_1 + Start_0_1 - Start_4_1 <= 50 | |
timewindow1p0p5: 50 Assign_0_5_1 + Start_0_1 - Start_5_1 <= 50 | |
timewindow1p0p6: 50 Assign_0_6_1 + Start_0_1 - Start_6_1 <= 50 | |
timewindow1p1p2: 50 Assign_1_2_1 + Start_1_1 - Start_2_1 <= 49.3 | |
timewindow1p1p3: 50 Assign_1_3_1 + Start_1_1 - Start_3_1 <= 49.2 | |
timewindow1p1p4: 50 Assign_1_4_1 + Start_1_1 - Start_4_1 <= 48.7 | |
timewindow1p1p5: 50 Assign_1_5_1 + Start_1_1 - Start_5_1 <= 49.5 | |
timewindow1p1p6: 50 Assign_1_6_1 + Start_1_1 - Start_6_1 <= 50 | |
timewindow1p2p1: 50 Assign_2_1_1 - Start_1_1 + Start_2_1 <= 49.3 | |
timewindow1p2p3: 50 Assign_2_3_1 + Start_2_1 - Start_3_1 <= 48.8 | |
timewindow1p2p4: 50 Assign_2_4_1 + Start_2_1 - Start_4_1 <= 48.4 | |
timewindow1p2p5: 50 Assign_2_5_1 + Start_2_1 - Start_5_1 <= 49.4 | |
timewindow1p2p6: 50 Assign_2_6_1 + Start_2_1 - Start_6_1 <= 50 | |
timewindow1p3p1: 50 Assign_3_1_1 - Start_1_1 + Start_3_1 <= 49.2 | |
timewindow1p3p2: 50 Assign_3_2_1 - Start_2_1 + Start_3_1 <= 48.8 | |
timewindow1p3p4: 50 Assign_3_4_1 + Start_3_1 - Start_4_1 <= 49.1 | |
timewindow1p3p5: 50 Assign_3_5_1 + Start_3_1 - Start_5_1 <= 49.3 | |
timewindow1p3p6: 50 Assign_3_6_1 + Start_3_1 - Start_6_1 <= 50 | |
timewindow1p4p1: 50 Assign_4_1_1 - Start_1_1 + Start_4_1 <= 48.7 | |
timewindow1p4p2: 50 Assign_4_2_1 - Start_2_1 + Start_4_1 <= 48.4 | |
timewindow1p4p3: 50 Assign_4_3_1 - Start_3_1 + Start_4_1 <= 49.1 | |
timewindow1p4p5: 50 Assign_4_5_1 + Start_4_1 - Start_5_1 <= 49.1 | |
timewindow1p4p6: 50 Assign_4_6_1 + Start_4_1 - Start_6_1 <= 50 | |
timewindow1p5p1: 50 Assign_5_1_1 - Start_1_1 + Start_5_1 <= 49.5 | |
timewindow1p5p2: 50 Assign_5_2_1 - Start_2_1 + Start_5_1 <= 49.4 | |
timewindow1p5p3: 50 Assign_5_3_1 - Start_3_1 + Start_5_1 <= 49.3 | |
timewindow1p5p4: 50 Assign_5_4_1 - Start_4_1 + Start_5_1 <= 49.1 | |
timewindow1p5p6: 50 Assign_5_6_1 + Start_5_1 - Start_6_1 <= 50 | |
Bounds | |
12 <= Start_1_0 <= 18 | |
12 <= Start_1_1 <= 18 | |
12 <= Start_2_0 <= 18 | |
12 <= Start_2_1 <= 18 | |
12 <= Start_3_0 <= 18 | |
12 <= Start_3_1 <= 18 | |
12 <= Start_4_0 <= 18 | |
12 <= Start_4_1 <= 18 | |
18 <= Start_5_0 <= 24 | |
18 <= Start_5_1 <= 24 | |
Binaries | |
Assign_0_1_0 | |
Assign_0_1_1 | |
Assign_0_2_0 | |
Assign_0_2_1 | |
Assign_0_3_0 | |
Assign_0_3_1 | |
Assign_0_4_0 | |
Assign_0_4_1 | |
Assign_0_5_0 | |
Assign_0_5_1 | |
Assign_0_6_0 | |
Assign_0_6_1 | |
Assign_1_0_0 | |
Assign_1_0_1 | |
Assign_1_2_0 | |
Assign_1_2_1 | |
Assign_1_3_0 | |
Assign_1_3_1 | |
Assign_1_4_0 | |
Assign_1_4_1 | |
Assign_1_5_0 | |
Assign_1_5_1 | |
Assign_1_6_0 | |
Assign_1_6_1 | |
Assign_2_0_0 | |
Assign_2_0_1 | |
Assign_2_1_0 | |
Assign_2_1_1 | |
Assign_2_3_0 | |
Assign_2_3_1 | |
Assign_2_4_0 | |
Assign_2_4_1 | |
Assign_2_5_0 | |
Assign_2_5_1 | |
Assign_2_6_0 | |
Assign_2_6_1 | |
Assign_3_0_0 | |
Assign_3_0_1 | |
Assign_3_1_0 | |
Assign_3_1_1 | |
Assign_3_2_0 | |
Assign_3_2_1 | |
Assign_3_4_0 | |
Assign_3_4_1 | |
Assign_3_5_0 | |
Assign_3_5_1 | |
Assign_3_6_0 | |
Assign_3_6_1 | |
Assign_4_0_0 | |
Assign_4_0_1 | |
Assign_4_1_0 | |
Assign_4_1_1 | |
Assign_4_2_0 | |
Assign_4_2_1 | |
Assign_4_3_0 | |
Assign_4_3_1 | |
Assign_4_5_0 | |
Assign_4_5_1 | |
Assign_4_6_0 | |
Assign_4_6_1 | |
Assign_5_0_0 | |
Assign_5_0_1 | |
Assign_5_1_0 | |
Assign_5_1_1 | |
Assign_5_2_0 | |
Assign_5_2_1 | |
Assign_5_3_0 | |
Assign_5_3_1 | |
Assign_5_4_0 | |
Assign_5_4_1 | |
Assign_5_6_0 | |
Assign_5_6_1 | |
Assign_6_1_0 | |
Assign_6_1_1 | |
Assign_6_2_0 | |
Assign_6_2_1 | |
Assign_6_3_0 | |
Assign_6_3_1 | |
Assign_6_4_0 | |
Assign_6_4_1 | |
Assign_6_5_0 | |
Assign_6_5_1 | |
End |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Location | Demand | TimeIn | TimeOut | ServiceTime | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Point1 | 23 | Vehicle Capacity | 200 | 12 | 18 | 2 | ||||
Point2 | 24 | 12 | 18 | 1 | ||||||
Point3 | 17 | 12 | 18 | 2 | ||||||
Point4 | 25 | 12 | 18 | 1 | ||||||
Point5 | 13 | 18 | 24 | 1 | ||||||
Point6 | 29 | 18 | 24 | 1 | ||||||
Point7 | 24 | 18 | 24 | 2 | ||||||
Point8 | 25 | 18 | 24 | 1 | ||||||
Point9 | 26 | 18 | 24 | 2 | ||||||
Point10 | 22 | 18 | 24 | 2 | ||||||
Point11 | 11 | 26 | 32 | 1 | ||||||
Point12 | 16 | 26 | 32 | 2 | ||||||
Point13 | 25 | 26 | 32 | 1 | ||||||
Point14 | 23 | 30 | 36 | 2 | ||||||
Point15 | 13 | 30 | 36 | 1 | ||||||
Point16 | 18 | 36 | 42 | 2 | ||||||
Point17 | 23 | 36 | 42 | 1 | ||||||
Point18 | 21 | 36 | 42 | 1 | ||||||
Point19 | 15 | 36 | 42 | 1 | ||||||
Point20 | 20 | 36 | 42 | 2 | ||||||
Point21 | 13 | 12 | 18 | 1 | ||||||
Point22 | 20 | 12 | 18 | 1 | ||||||
Point23 | 15 | 12 | 18 | 1 | ||||||
Point24 | 12 | 12 | 18 | 1 | ||||||
Point25 | 18 | 18 | 24 | 1 | ||||||
Point26 | 12 | 18 | 24 | 1 | ||||||
Point27 | 27 | 18 | 24 | 1 | ||||||
Point28 | 10 | 18 | 24 | 2 | ||||||
Point29 | 14 | 18 | 24 | 2 | ||||||
Point30 | 17 | 18 | 24 | 1 | ||||||
Point31 | 26 | 26 | 32 | 2 | ||||||
Point32 | 16 | 26 | 32 | 1 | ||||||
Point33 | 10 | 26 | 32 | 2 | ||||||
Point34 | 30 | 30 | 38 | 2 | ||||||
Point35 | 23 | 30 | 38 | 2 | ||||||
Point36 | 16 | 36 | 42 | 2 | ||||||
Point37 | 30 | 36 | 42 | 2 | ||||||
Point38 | 28 | 36 | 42 | 2 | ||||||
Point39 | 14 | 36 | 42 | 2 | ||||||
Point40 | 22 | 36 | 42 | 1 | ||||||
Point41 | 30 | 26 | 32 | 1 | ||||||
Point42 | 16 | 26 | 32 | 1 | ||||||
Point43 | 29 | 26 | 32 | 1 | ||||||
Point44 | 17 | 30 | 36 | 1 | ||||||
Point45 | 13 | 30 | 36 | 1 | ||||||
Point46 | 22 | 36 | 42 | 1 | ||||||
Point47 | 21 | 36 | 42 | 2 | ||||||
Point48 | 14 | 36 | 42 | 1 | ||||||
Point49 | 18 | 36 | 42 | 1 | ||||||
Point50 | 13 | 36 | 42 | 1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
driveTime | Point1 | Point2 | Point3 | Point4 | Point5 | Point6 | Point7 | Point8 | Point9 | Point10 | Point11 | Point12 | Point13 | Point14 | Point15 | Point16 | Point17 | Point18 | Point19 | Point20 | Point21 | Point22 | Point23 | Point24 | Point25 | Point26 | Point27 | Point28 | Point29 | Point30 | Point31 | Point32 | Point33 | Point34 | Point35 | Point36 | Point37 | Point38 | Point39 | Point40 | Point41 | Point42 | Point43 | Point44 | Point45 | Point46 | Point47 | Point48 | Point49 | Point50 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Point1 | 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||
Point2 | 7 | 0 | |||||||||||||||||||||||||||||||||||||||||||||||||
Point3 | 8 | 12 | 0 | ||||||||||||||||||||||||||||||||||||||||||||||||
Point4 | 13 | 16 | 9 | 0 | |||||||||||||||||||||||||||||||||||||||||||||||
Point5 | 5 | 6 | 7 | 9 | 0 | ||||||||||||||||||||||||||||||||||||||||||||||
Point6 | 8 | 12 | 15 | 19 | 17 | 0 | |||||||||||||||||||||||||||||||||||||||||||||
Point7 | 20 | 20 | 7 | 15 | 13 | 8 | 0 | ||||||||||||||||||||||||||||||||||||||||||||
Point8 | 8 | 9 | 20 | 17 | 10 | 12 | 16 | 0 | |||||||||||||||||||||||||||||||||||||||||||
Point9 | 18 | 5 | 17 | 13 | 17 | 13 | 13 | 12 | 0 | ||||||||||||||||||||||||||||||||||||||||||
Point10 | 9 | 19 | 9 | 6 | 6 | 18 | 11 | 6 | 8 | 0 | |||||||||||||||||||||||||||||||||||||||||
Point11 | 8 | 8 | 15 | 13 | 15 | 14 | 14 | 9 | 17 | 10 | 0 | ||||||||||||||||||||||||||||||||||||||||
Point12 | 5 | 6 | 6 | 17 | 18 | 5 | 10 | 7 | 17 | 15 | 14 | 0 | |||||||||||||||||||||||||||||||||||||||
Point13 | 10 | 13 | 8 | 11 | 11 | 20 | 10 | 13 | 13 | 9 | 12 | 19 | 0 | ||||||||||||||||||||||||||||||||||||||
Point14 | 10 | 18 | 14 | 15 | 6 | 18 | 11 | 8 | 6 | 7 | 14 | 10 | 8 | 0 | |||||||||||||||||||||||||||||||||||||
Point15 | 19 | 9 | 7 | 14 | 8 | 14 | 13 | 7 | 19 | 8 | 6 | 9 | 10 | 14 | 0 | ||||||||||||||||||||||||||||||||||||
Point16 | 6 | 14 | 13 | 16 | 18 | 16 | 12 | 13 | 13 | 15 | 9 | 6 | 12 | 13 | 10 | 0 | |||||||||||||||||||||||||||||||||||
Point17 | 11 | 11 | 8 | 18 | 7 | 8 | 15 | 9 | 10 | 5 | 12 | 18 | 16 | 14 | 7 | 19 | 0 | ||||||||||||||||||||||||||||||||||
Point18 | 5 | 9 | 6 | 13 | 8 | 14 | 6 | 8 | 17 | 11 | 11 | 13 | 8 | 12 | 14 | 9 | 18 | 0 | |||||||||||||||||||||||||||||||||
Point19 | 14 | 9 | 7 | 19 | 17 | 19 | 14 | 9 | 13 | 9 | 9 | 10 | 16 | 11 | 6 | 16 | 20 | 13 | 0 | ||||||||||||||||||||||||||||||||
Point20 | 15 | 16 | 9 | 13 | 7 | 15 | 7 | 19 | 9 | 19 | 8 | 13 | 18 | 18 | 10 | 20 | 13 | 17 | 7 | 0 | |||||||||||||||||||||||||||||||
Point21 | 17 | 10 | 8 | 8 | 20 | 14 | 7 | 19 | 12 | 17 | 6 | 10 | 12 | 11 | 9 | 10 | 9 | 5 | 8 | 9 | 0 | ||||||||||||||||||||||||||||||
Point22 | 7 | 11 | 18 | 7 | 16 | 8 | 18 | 13 | 7 | 11 | 19 | 9 | 8 | 13 | 5 | 12 | 16 | 17 | 6 | 6 | 6 | 0 | |||||||||||||||||||||||||||||
Point23 | 14 | 5 | 13 | 10 | 14 | 11 | 19 | 11 | 20 | 19 | 16 | 13 | 9 | 6 | 17 | 15 | 16 | 5 | 13 | 13 | 9 | 19 | 0 | ||||||||||||||||||||||||||||
Point24 | 19 | 15 | 13 | 18 | 19 | 17 | 14 | 19 | 11 | 11 | 14 | 11 | 11 | 15 | 14 | 8 | 15 | 14 | 18 | 5 | 17 | 19 | 19 | 0 | |||||||||||||||||||||||||||
Point25 | 9 | 7 | 5 | 11 | 7 | 18 | 9 | 5 | 9 | 10 | 15 | 6 | 6 | 6 | 15 | 16 | 5 | 11 | 6 | 5 | 12 | 9 | 17 | 16 | 0 | ||||||||||||||||||||||||||
Point26 | 10 | 20 | 16 | 13 | 10 | 16 | 14 | 13 | 18 | 12 | 14 | 11 | 16 | 13 | 9 | 5 | 8 | 6 | 6 | 11 | 6 | 11 | 14 | 20 | 14 | 0 | |||||||||||||||||||||||||
Point27 | 12 | 8 | 16 | 16 | 15 | 10 | 8 | 18 | 14 | 10 | 16 | 16 | 20 | 13 | 14 | 15 | 10 | 12 | 6 | 14 | 13 | 18 | 13 | 13 | 11 | 10 | 0 | ||||||||||||||||||||||||
Point28 | 20 | 8 | 11 | 19 | 15 | 19 | 10 | 14 | 9 | 19 | 12 | 11 | 10 | 15 | 15 | 12 | 15 | 9 | 8 | 17 | 9 | 8 | 8 | 20 | 7 | 7 | 16 | 0 | |||||||||||||||||||||||
Point29 | 5 | 14 | 9 | 17 | 15 | 10 | 17 | 6 | 10 | 15 | 19 | 13 | 15 | 20 | 15 | 6 | 9 | 6 | 16 | 12 | 15 | 19 | 7 | 16 | 15 | 7 | 10 | 5 | 0 | ||||||||||||||||||||||
Point30 | 13 | 13 | 18 | 11 | 8 | 20 | 18 | 19 | 12 | 9 | 15 | 8 | 19 | 16 | 20 | 17 | 20 | 16 | 17 | 17 | 20 | 13 | 8 | 5 | 19 | 6 | 9 | 12 | 15 | 0 | |||||||||||||||||||||
Point31 | 20 | 9 | 8 | 10 | 10 | 7 | 15 | 13 | 14 | 8 | 5 | 12 | 17 | 20 | 19 | 14 | 9 | 14 | 7 | 13 | 20 | 10 | 18 | 17 | 14 | 19 | 8 | 6 | 8 | 6 | 0 | ||||||||||||||||||||
Point32 | 6 | 7 | 6 | 6 | 19 | 13 | 18 | 17 | 12 | 13 | 7 | 16 | 18 | 13 | 17 | 11 | 13 | 13 | 9 | 18 | 18 | 17 | 16 | 16 | 15 | 12 | 15 | 11 | 13 | 18 | 14 | 0 | |||||||||||||||||||
Point33 | 15 | 6 | 5 | 7 | 19 | 19 | 6 | 11 | 10 | 18 | 19 | 18 | 19 | 15 | 20 | 17 | 10 | 7 | 13 | 8 | 18 | 16 | 16 | 8 | 8 | 8 | 10 | 13 | 5 | 11 | 7 | 16 | 0 | ||||||||||||||||||
Point34 | 8 | 5 | 18 | 10 | 10 | 7 | 10 | 6 | 6 | 18 | 17 | 19 | 19 | 11 | 6 | 19 | 13 | 16 | 19 | 12 | 15 | 17 | 20 | 19 | 7 | 7 | 19 | 14 | 18 | 10 | 14 | 20 | 11 | 0 | |||||||||||||||||
Point35 | 5 | 16 | 10 | 15 | 9 | 6 | 9 | 14 | 8 | 10 | 14 | 6 | 16 | 6 | 7 | 9 | 8 | 15 | 20 | 8 | 19 | 7 | 12 | 9 | 16 | 15 | 13 | 10 | 10 | 7 | 16 | 14 | 7 | 15 | 0 | ||||||||||||||||
Point36 | 19 | 14 | 19 | 18 | 14 | 7 | 8 | 16 | 6 | 12 | 19 | 8 | 11 | 16 | 17 | 10 | 12 | 8 | 8 | 20 | 8 | 10 | 18 | 5 | 17 | 6 | 9 | 16 | 8 | 20 | 5 | 10 | 18 | 9 | 19 | 0 | |||||||||||||||
Point37 | 11 | 8 | 14 | 16 | 13 | 8 | 8 | 18 | 8 | 18 | 15 | 9 | 7 | 18 | 19 | 8 | 11 | 15 | 5 | 17 | 9 | 18 | 17 | 9 | 5 | 13 | 7 | 5 | 8 | 18 | 15 | 18 | 5 | 17 | 13 | 11 | 0 | ||||||||||||||
Point38 | 5 | 17 | 15 | 16 | 12 | 12 | 14 | 6 | 20 | 15 | 10 | 8 | 15 | 17 | 9 | 8 | 8 | 10 | 20 | 9 | 18 | 13 | 6 | 20 | 6 | 12 | 19 | 8 | 5 | 8 | 8 | 10 | 18 | 7 | 11 | 11 | 13 | 0 | |||||||||||||
Point39 | 12 | 18 | 9 | 19 | 17 | 14 | 13 | 10 | 15 | 17 | 7 | 7 | 14 | 19 | 5 | 13 | 7 | 5 | 6 | 13 | 12 | 11 | 6 | 10 | 20 | 15 | 17 | 11 | 15 | 15 | 13 | 11 | 6 | 15 | 15 | 6 | 8 | 11 | 0 | ||||||||||||
Point40 | 19 | 14 | 9 | 14 | 20 | 7 | 19 | 12 | 19 | 6 | 18 | 8 | 18 | 18 | 20 | 12 | 12 | 17 | 14 | 12 | 19 | 13 | 9 | 11 | 6 | 17 | 16 | 9 | 11 | 14 | 7 | 11 | 11 | 15 | 12 | 19 | 10 | 17 | 5 | 0 | |||||||||||
Point41 | 6 | 15 | 8 | 6 | 17 | 7 | 7 | 17 | 11 | 7 | 19 | 6 | 13 | 20 | 12 | 17 | 6 | 12 | 15 | 10 | 8 | 18 | 20 | 10 | 9 | 13 | 14 | 8 | 20 | 16 | 5 | 17 | 19 | 6 | 16 | 18 | 5 | 19 | 14 | 14 | 0 | ||||||||||
Point42 | 10 | 15 | 11 | 9 | 6 | 19 | 19 | 15 | 13 | 6 | 18 | 19 | 8 | 15 | 12 | 19 | 18 | 11 | 18 | 20 | 17 | 15 | 9 | 16 | 12 | 11 | 14 | 19 | 7 | 12 | 10 | 14 | 13 | 17 | 6 | 5 | 10 | 18 | 17 | 7 | 20 | 0 | |||||||||
Point43 | 13 | 6 | 7 | 16 | 16 | 14 | 11 | 18 | 18 | 15 | 10 | 14 | 11 | 17 | 5 | 14 | 9 | 6 | 15 | 20 | 13 | 19 | 10 | 10 | 15 | 10 | 8 | 11 | 5 | 12 | 18 | 6 | 20 | 13 | 5 | 15 | 20 | 8 | 14 | 5 | 9 | 8 | 0 | ||||||||
Point44 | 5 | 12 | 5 | 15 | 17 | 16 | 6 | 10 | 5 | 6 | 5 | 8 | 9 | 11 | 19 | 20 | 18 | 6 | 8 | 20 | 12 | 16 | 20 | 6 | 17 | 7 | 7 | 8 | 16 | 10 | 14 | 13 | 20 | 13 | 20 | 14 | 19 | 14 | 11 | 10 | 12 | 7 | 15 | 0 | |||||||
Point45 | 18 | 11 | 6 | 17 | 6 | 9 | 19 | 8 | 12 | 9 | 9 | 10 | 17 | 13 | 13 | 17 | 18 | 17 | 6 | 12 | 18 | 10 | 16 | 18 | 18 | 5 | 10 | 20 | 14 | 10 | 9 | 10 | 18 | 16 | 12 | 17 | 9 | 13 | 10 | 7 | 5 | 7 | 17 | 16 | 0 | ||||||
Point46 | 13 | 9 | 11 | 9 | 14 | 17 | 18 | 10 | 10 | 8 | 20 | 9 | 7 | 20 | 8 | 20 | 20 | 19 | 7 | 7 | 8 | 12 | 19 | 14 | 15 | 16 | 17 | 7 | 18 | 7 | 16 | 15 | 10 | 19 | 9 | 9 | 7 | 16 | 17 | 7 | 12 | 14 | 18 | 9 | 6 | 0 | |||||
Point47 | 6 | 11 | 14 | 17 | 14 | 9 | 10 | 18 | 6 | 9 | 19 | 18 | 8 | 8 | 15 | 20 | 16 | 12 | 8 | 11 | 11 | 6 | 14 | 20 | 14 | 19 | 11 | 6 | 8 | 20 | 8 | 19 | 11 | 9 | 16 | 10 | 13 | 10 | 19 | 20 | 12 | 9 | 15 | 16 | 5 | 18 | 0 | ||||
Point48 | 14 | 18 | 18 | 12 | 10 | 9 | 6 | 14 | 14 | 10 | 10 | 18 | 14 | 18 | 10 | 14 | 12 | 13 | 20 | 19 | 14 | 7 | 8 | 8 | 12 | 7 | 18 | 7 | 14 | 16 | 12 | 12 | 8 | 14 | 20 | 9 | 15 | 11 | 17 | 12 | 13 | 16 | 19 | 15 | 18 | 13 | 8 | 0 | |||
Point49 | 9 | 18 | 20 | 13 | 13 | 13 | 12 | 17 | 14 | 16 | 19 | 12 | 11 | 18 | 12 | 20 | 19 | 6 | 12 | 19 | 17 | 16 | 12 | 6 | 7 | 13 | 7 | 15 | 5 | 20 | 5 | 17 | 7 | 13 | 10 | 15 | 14 | 13 | 14 | 18 | 15 | 11 | 18 | 10 | 11 | 17 | 17 | 18 | 0 | ||
Point50 | 19 | 14 | 11 | 17 | 12 | 10 | 5 | 15 | 18 | 10 | 17 | 19 | 9 | 19 | 7 | 15 | 11 | 15 | 7 | 18 | 15 | 18 | 13 | 20 | 8 | 18 | 20 | 7 | 10 | 5 | 15 | 8 | 8 | 12 | 18 | 11 | 6 | 18 | 15 | 14 | 5 | 20 | 16 | 12 | 12 | 6 | 5 | 11 | 12 | 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment