ORtools求解软时间窗车辆路径规划问题

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')

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
时间车辆路径问题(VRPTW)是一个重要的组合优化问题,它在实际中具有广泛的应用。Gurobi是一个高效的数学规划求解器,可以用来求解VRPTW问题。下面是一个基于Gurobi求解VRPTW问题的示例代码: ``` from gurobipy import * # 创建模型 m = Model('vrptw') # 参数设置 n = 20 # 客户数量 mdepot = 1 # 仓库数量 capacity = 100 # 车辆容量 Q = [0] + [random.randint(10, 20) for i in range(n)] # 每个客户的需求 c = [[random.randint(1, 100) for i in range(n + mdepot)] for j in range(n + mdepot)] # 距离矩阵 t = [[random.randint(1, 10) for i in range(n)] for j in range(n + mdepot)] # 时间矩阵 s = [0] + [random.randint(1, 5) for i in range(n)] # 每个客户的服务时间 e = [0] + [random.randint(10, 50) for i in range(n)] # 每个客户的最早开始时间 l = [0] + [random.randint(60, 100) for i in range(n)] # 每个客户的最晚结束时间 # 创建变量 x = {} for i in range(n + mdepot): for j in range(n + mdepot): x[i, j] = m.addVar(vtype=GRB.BINARY, name='x_{}_{}'.format(i, j)) # 创建约束 for i in range(n + mdepot): m.addConstr(quicksum(x[i, j] for j in range(n + mdepot)) == quicksum(x[j, i] for j in range(n + mdepot))) for i in range(n): m.addConstr(quicksum(x[i, j] for j in range(n + mdepot)) == 1) # 每个客户只被访问一次 for i in range(n + mdepot): m.addConstr(x[i, i] == 0) # 不可能存在自环 for i in range(1, n + mdepot): m.addConstr(quicksum(Q[j] * x[i, j] for j in range(n + mdepot)) <= capacity) # 车辆容量约束 for i in range(1, n + mdepot): for j in range(1, n + mdepot): m.addConstr((t[i][j - 1] + s[j] + c[i][j]) * x[i, j] - t[i][j - 1] <= l[j]) # 最晚结束时间约束 m.addConstr((t[i][j - 1] + s[j] + c[i][j]) * x[i, j] - t[i][j - 1] >= e[j]) # 最早开始时间约束 # 目标函数 obj = quicksum(c[i][j] * x[i, j] for i in range(n + mdepot) for j in range(n + mdepot)) m.setObjective(obj, GRB.MINIMIZE) # 求解模型 m.optimize() # 输出结果 if m.status == GRB.Status.OPTIMAL: print('最优目标函数值:{}'.format(m.objVal)) for i in range(n + mdepot): for j in range(n + mdepot): if x[i, j].x > 0.5: print('从{}到{}'.format(i, j)) else: print('求解失败') ``` 这段代码中,我们使用Gurobi求解一个含有20个客户和1个仓库的VRPTW问题。其中,我们通过随机数生成了距离矩阵、时间矩阵、需求量、服务时间、最早开始时间和最晚结束时间等参数。在创建模型后,我们使用addVar函数创建变量,使用addConstr函数创建约束,使用setObjective函数设置目标函数。最后,我们使用optimize函数求解模型,并输出最优解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值