ORTools本身有求解CVRP和加入硬时间窗的方法,如果需要求解软时间窗的,在原本CVRP基础上难以修改,所以可以自己建模~相关语法比较少,小公主这里用python调包辣,java的maven配了半天还是不行,所以用了python,体验还不错嘻嘻嘻。
import math
import re
from ortools.linear_solver import pywraplp
solver = pywraplp.Solver('SolveVRPSTW',
pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)
class Data:
customerNum = 0
nodeNum = 0
vehicleNum = 0
capacity = 0
cor_X = []
cor_Y = []
demand = []
serviceTime = []
readyTime = []
dueTime = []
disMatrix = [[]] # 读取数据
# function to read data from .txt files
def readData(data, path, customerNum):
data.customerNum = customerNum
data.nodeNum = customerNum + 2
f = open(path, 'r')
lines = f.readlines()
count = 0
# read the info
for line in lines:
count = count + 1
if (count == 5):
line = line[:-1].strip()
str = re.split(r" +", line)
data.vehicleNum = float(str[0])
data.capacity = float(str[1])
elif (count >= 10 and count <= 10 + customerNum):
line = line[:-1]
str = re.split(r" +", line)
data.cor_X.append(float(str[2]))
data.cor_Y.append(float(str[3]))
data.demand.append(float(str[4]))
data.readyTime.append(float(str[5]))
data.dueTime.append(float(str[6]))
data.serviceTime.append(float(str[7]))
# data.cor_X.append(float(str[1]))
# data.cor_Y.append(float(str[2]))
# data.demand.append(float(str[3]))
# data.readyTime.append(float(str[4]))
# data.dueTime.append(float(str[5]))
# data.serviceTime.append(float(str[6]))
data.cor_X.append(data.cor_X[0])
data.cor_Y.append(data.cor_Y[0])
data.demand.append(data.demand[0])
data.readyTime.append(data.readyTime[0])
data.dueTime.append(data.dueTime[0])
data.serviceTime.append(data.serviceTime[0])
# compute the distance matrix
data.disMatrix = [([0] * data.nodeNum) for p in range(data.nodeNum)] # 初始化距离矩阵的维度,防止浅拷贝
# data.disMatrix = [[0] * nodeNum] * nodeNum]; 这个是浅拷贝,容易重复
for i in range(0, data.nodeNum):
for j in range(0, data.nodeNum):
temp = (data.cor_X[i] - data.cor_X[j]) ** 2 + (data.cor_Y[i] - data.cor_Y[j]) ** 2
data.disMatrix[i][j] = math.sqrt(temp)
temp = 0
return data
def printData(data, customerNum):
print("下面打印数据\n")
print("vehicle number = %4d" % data.vehicleNum)
print("vehicle capacity = %4d" % data.capacity)
for i in range(len(data.demand)):
print('{0}\t{1}\t{2}\t{3}'.format(data.demand[i], data.readyTime[i], data.dueTime[i], data.serviceTime[i]))
print("-------距离矩阵-------\n")
for i in range(data.nodeNum):
for j in range(data.nodeNum):
# print("%d %d" % (i, j));
print("%6.2f" % (data.disMatrix[i][j]), end=" ")
print()
# # Read Data
# reading data
data = Data()
path = 'c101.txt'
customerNum = 20
readData(data, path, customerNum)
data.vehicleNum = 5
#printData(data, customerNum)
# # Build and solve VRPTW
BigM = 100000
x = {}
s = {}
Ve = {}
CoA = {}
CoB = {}
for i in range(data.nodeNum):
for k in range(data.vehicleNum):
name = 's_' + str(i) + '_' + str(k)
s[i,k] = solver.NumVar(0,1500,name)
for j in range(data.nodeNum):
if (i != j):
name = 'x_' + str(i) + '_' + str(j) + '_' + str(k)
x[i, j, k] = solver.BoolVar(name)
for i in range(data.vehicleNum):
name = 've'+str(i)
Ve[i] = solver.BoolVar(name)
for i in range(data.nodeNum):
name = 'CoA' + str(i)
CoA[i] = solver.NumVar(0,10,name)
name = 'CoB' + str(i)
CoB[i] = solver.NumVar(0,10,name)
objective = solver.Objective()
for i in range(data.nodeNum):
for k in range(data.vehicleNum):
for j in range(data.nodeNum):
if (i != j):
objective.SetCoefficient(x[i,j,k],data.disMatrix[i][j])
for i in range(1,data.nodeNum-1):
objective.SetCoefficient(CoB[i],1)
objective.SetCoefficient(CoA[i],1)
objective.SetMinimization()
for k in range(data.vehicleNum):
solver.Add( Ve[k] == sum(x[0,j,k] for j in range(1,data.nodeNum)))
for k in range(data.vehicleNum):
for h in range(1, data.nodeNum - 1):
solver.Add(sum(x[i,h,k] for i in range(data.nodeNum-1) if i !=h)==sum(x[h,j,k] for j in range(1,data.nodeNum) if j!=h))
for k in range(data.vehicleNum):
solver.Add(Ve[k] == sum(x[i, data.nodeNum-1, k] for i in range(1, data.nodeNum-1)))
for i in range(1, data.nodeNum - 1):
solver.Add((sum(x[i,j,k] for k in range(data.vehicleNum) for j in range(1,data.nodeNum) if (i!=j)))==1)
for k in range(data.vehicleNum):
for i in range(1, data.nodeNum - 1):
solver.Add(sum(x[i,j,k] for j in range(1,data.nodeNum) if i!=j )<= data.capacity)
for k in range(data.vehicleNum):
for i in range(data.nodeNum):
for j in range(data.nodeNum):
if (i != j):
solver.Add(s[i, k] + data.disMatrix[i][j] + data.serviceTime[i] - s[j, k]
- BigM + BigM * x[i, j, k] <= 0)
for i in range(1, data.nodeNum - 1):
for k in range(data.vehicleNum):
solver.Add(CoB[i] - s[i,k] + data.dueTime[i] >= 0)
solver.Add(CoA[i]-data.readyTime[i]+s[i,k]>=0)
solver.Solve()
print(solver.Objective().Value())
for k in range(data.vehicleNum):
for i in range(data.nodeNum):
for j in range(data.nodeNum):
if i!=j and x[i,j,k].solution_value() > 0:
print(str(i)+'_'+str(j)+'_'+str(k)+'=1')