软件工具 | Python调用运筹优化求解器(一):以CVRP&VRPTW为例

Python的求解器都有什么?并详细给出使用范围 Python 提供了丰富的求解器,可以处理从简单的线性方程到复杂的动态优化问题。根据具体需求,可以选择合适的库和方法来实现求解。选择时需考虑问题的性质(如线性或非线性、是否有约束等),以及求解的效率和精度等因素。 阅读详情
AI摘要

本文介绍了如何使用Python调用Gurobi、COPT和SCIP优化求解器来解决车辆路径问题(CVRP)和带有时间窗的车辆路径问题(VRPTW)。详细展示了模型构建、变量添加、目标函数和约束设置的步骤,并提供了完整的Python代码示例。测试结果显示Gurobi在求解质量和收敛性方面表现出色。


欢迎关注个人微信公众号:Python助力交通
在这里插入图片描述

1. 引言

优化求解器是解决复杂工程问题不可或缺的工具,可以帮助我们验证模型的正确性、理解决策变量的耦合关系、获取最优决策方案(合适规模条件下)。小编搜罗了网上关于各类常见(其实并不常见)的优化求解器介绍的帖子:

除了以上求解器外,还有一些针对特定问题而量身定制高效率求解器:

今天的主题是以CVRP和VRPTW问题为例,分享Python调用运筹优化求解器(Gurobi、COPT、SCIP)的教程。

2. 求解器介绍

(1)Gurobi
Gurobi是由美国 Gurobi Optimization 公司开发新一代大规模优化器,提供 C++, Java, Python, .Net, Matlab 和R等多种接口,支持求解以下模型:
(1)连续和混合整数线性问题
(2)凸目标或约束连续和混合整数二次问题
(3)非凸目标或约束连续和混合整数二次问题
(4)含有对数、指数、三角函数、高阶多项式目标或约束,以及任何形式的分段约束的非线性问题
(5)含有绝对值、最大值、最小值、逻辑与或非目标或约束的非线性问题

(2)COPT
杉数求解器COPT(Cardinal Optimizer)是杉数自主研发的针对大规模优化问题的高效数学规划求解器套件,也是支撑杉数端到端供应链平台的核心组件,是目前同时具备大规模混合整数规划、线性规划(单纯形法和内点法)、半定规划、(混合整数)二阶锥规划以及(混合整数)凸二次规划和(混合整数)凸二次约束规划问题求解能力的综合性能数学规划求解器,为企业应对高性能求解的需求提供了更多选择。COPT支持所有主流编程接口:C、C++、C#、Python、Julia、Java、AMPL、GAMS、Pyomo、PuLP、CVXPY。

(3)SCIP
SCIP起源于ZIB(Zuse Institute Berlin),由Tobias Achterberg奠定整个框架,是目前用于混合整数规划(MIP)和混合整数非线性规划(MINLP)的最快的非商业解算器之一,它允许用户对求解过程进行全面控制,支持自定义搜索树中的各个模块,在分支限界(Branch and Bound)过程中添加变量等功能。SCIP支持Python Java AMPL GAMS MATLAB等编程语言。

3. 基础语言

3.1 创建模型

# gurobi
cvrp_model = Model('cvrp')
# copt
env = Envr()
cvrp_model = env.createModel('cvrp')
# scip
cvrp_model = Model('cvrp')

3.2 添加变量

# gurobi
x = cvrp_model.addVar(vtype=GRB.BINARY, name='x') # 单个变量
X = cvrp_model.addVars(N, N, K, vtype=GRB.BINARY, name='X[i,j,k]') # 多个变量
# copt
x = cvrp_model.addVars(vtype=COPT.BINARY, name='x') # 单个变量
X = cvrp_model.addVars(N, N, K, vtype=COPT.BINARY, nameprefix='X[i,j,k]') # 多个变量
# scip
X[i,j,k] = cvrp_model.addVar(vtype="B", name=f"x({i},{j},{k})") # 单个变量(貌似只能添加单个变量)

3.3 添加目标函数

# gurobi
cvrp_model.setObjective( quicksum(X[i,j,k] * cost[i,j] for i in N for j in N for k in K), GRB.MINIMIZE)
# copt
cvrp_model.setObjective(quicksum(X[i, j, k] * cost[i, j] for i in N for j in N for k in K), sense=COPT.MINIMIZE)
# scip
cvrp_model.setObjective( quicksum(X[i,j,k] * cost[i,j] for i in N for j in N for k in K),'minimize' )

3.4 添加约束


# gurobi
cvrp_model.addConstr() # 单个约束
cvrp_model.addConstrs() # 多个约束
# copt
cvrp_model.addConstr() # 单个约束
cvrp_model.addConstrs() # 多个约束
# scip
cvrp_model.addCons() # 单个约束
cvrp_model.addConss()  # 多个约束

3.5 设置参数

# gurobi
cvrp_model.setParam(GRB.Param.LogFile, './gurobi_r101-31.log') # 保存日志
cvrp_model.Params.TimeLimit = 1200 # 设置求解时间
# copt
cvrp_model.setLogFile('./copt_r101-31.log')  # 保存日志
cvrp_model.param.timelimit = 1200 # 设置求解时间
# scip
cvrp_model.setLogfile('./scip_r101-31.log') # 保存日志
cvrp_model.setRealParam('limits/time', 1200)  # 设置求解时间

3.6 求解

# gurobi
cvrp_model.optimize()
# copt
cvrp_model.solve()
# scip
cvrp_model.optimize()

4. 数学模型

4.1 CVRP数学模型

在这里插入图片描述

4.2 VRPTW数学模型

在这里插入图片描述

5. 完整代码

5.1 Python调用Gurobi求解CVRP

import xlsxwriter
import math
import pandas as pd
import matplotlib.pyplot as plt
from gurobipy import Model,quicksum,GRB
def read_input(filename):
    """
    :param filename: 数据文件路径
    :return:
    """
    df = pd.read_csv(filename)
    x_coord = { df['id'][i]:df['x_coord'][i] for i in range(df.shape[0]) }       # 节点横坐标
    y_coord = { df['id'][i]:df['y_coord'][i] for i in range(df.shape[0]) }       # 节点纵坐标
    demand = { df['id'][i]:df['demand'][i] for i in range(df.shape[0]) }         # 节点需求
    cost = {}
    N = df['id'].tolist()
    for f_n in N:
        for t_n in N:
            dist = math.sqrt( (x_coord[f_n]-x_coord[t_n])**2 + (y_coord[f_n] - y_coord[t_n])**2 )
            cost[f_n,t_n] = dist
    return N,cost,demand,x_coord,y_coord

def build_model(N,K,depot,CAP,cost,demand):
    """
    :param N: 网络节点集合
    :param K: 车队集合
    :param depot: 配送中心id
    :param CAP: 车辆容量
    :param cost: 网络弧费用集合
    :param demand: 网络节点需求集合
    :return:
    """
    cvrp_model = Model('cvrp')
    # 添加变量
    X = cvrp_model.addVars(N, N, K, vtype=GRB.BINARY, name='X[i,j,k]')
    Y = cvrp_model.addVars(N, K, vtype=GRB.BINARY, name='Y[i,k]')
    U = cvrp_model.addVars(N, K, vtype=GRB.INTEGER, name='U[i,k]')
    # 设置目标函数
    cvrp_model.setObjective( quicksum(X[i,j,k] * cost[i,j] for i in N for j in N for k in K), GRB.MINIMIZE)
    # 添加约束
    #  需求覆盖约束
    cvrp_model.addConstrs( quicksum(Y[i,k] for k in K) == 1 for i in N[1:] )
    #  车辆启用约束
    cvrp_model.addConstr( quicksum(Y[depot,k] for k in K) == len(K) )
    #  车辆流平衡约束
    cvrp_model.addConstrs( quicksum(X[i,j,k] for j in N ) == quicksum(X[j,i,k] for j in N ) for i in N for k in K )
    #  车辆路径限制
    cvrp_model.addConstrs( quicksum(X[i,j,k] for j in N) == Y[i,k] for i in N for k in K )
    #  车辆容量约束
    cvrp_model.addConstrs( quicksum(Y[i,k] * demand[i] for i in N) <= CAP for k in K )
    #  破圈约束
    cvrp_model.addConstrs( U[i,k] - U[j,k] + CAP * X[i,j,k] <= CAP - demand[i] for i in N[1:] for j in N[1:] for k in K )
    cvrp_model.addConstrs( U[i,k] <=  CAP for i in N[1:] for k in K)
    cvrp_model.addConstrs( U[i,k] >= demand[i] for i in N[1:] for k in K )
    return cvrp_model,X,Y,U

def draw_routes(route_list,x_coord,y_coord):
    for route in route_list:
        path_x = []
        path_y = []
        for n in route:
            path_x.append(x_coord[n])
            path_y.append(y_coord[n])
        plt.plot(path_x, path_y,linewidth=0.5, marker='s',ms=5)
    plt.show()

def save_file(route_list,total_cost):
    wb = xlsxwriter.Workbook('路径方案.xlsx')
    ws = wb.add_worksheet()
    ws.write(0,0,'总费用')
    ws.write(0,1,total_cost)
    ws.write(1,0,'车辆')
    ws.write(1,1,'路径')
    row = 2
    for route in route_list:
        ws.write(row,0,route[0])
        route_str = [str(i) for i in route[1:]]
        ws.write(row,1,'-'.join(route_str))
        row += 1
    wb.close()

if __name__ == '__main__':
    filename = './datasets/CVRP/r101-31.csv'
    N, cost, demand, x_coord, y_coord = read_input(filename)
    depot = N[0]
    K = list(range(1,10))
    CAP = 80
    cvrp_model, X, Y, U = build_model(N, K, depot, CAP, cost, demand)
    cvrp_model.setParam(GRB.Param.LogFile, './gurobi_r101-31.log')
    cvrp_model.Params.TimeLimit = 1200
    cvrp_model.optimize()
    route_list = []
    for k in K:
        route = [depot]
        cur_node = depot
        cur_k = None
        for j in N[1:]:
            if X[depot, j, k].x > 0:
                cur_node = j
                cur_k = k
                route.append(j)
                N.remove(j)
                break
        if cur_k is None:
            continue
        while cur_node != depot:
            for j in N:
                if X[cur_node, j, cur_k].x > 0:
                    cur_node = j
                    route.append(j)
                    if j != depot:
                        N.remove(j)
                    break
        route_list.append(route)
    print("最优路径距离:", cvrp_model.objVal)
    print("最优路径使用车辆数:", len(route_list))
    draw_routes(route_list, x_coord, y_coord)
    save_file(route_list, cvrp_model.objVal)

5.2 Python调用Gurobi求解VRPTW

import math
import pandas as pd
import matplotlib.pyplot as plt
import xlsxwriter
from gurobipy import GRB,Model,quicksum,tupledict,tuplelist

def read_input(filename):
    """
    :param filename: 数据文件路径
    :return:
    """
    N = [] #所有节点
    Q = {} #节点需求
    TT = {} #节点旅行时间
    ET = {} #节点最早开始服务时间
    LT = {} #节点最晚结束服务时间
    ST = {} #节点服务时间
    x_coord = {} # 节点横坐标
    y_coord = {} # 节点纵坐标
    Cost={}
    df = pd.read_csv(filename)
    for i in range(df.shape[0]):
        id = df['id'][i]
        N.append(id)
        x_coord[id] = df['x_coord'][i]
        y_coord[id] = df['y_coord'][i]
        Q[id] = df['demand'][i]
        ET[id] = df['start_time'][i]
        LT[id] = df['end_time'][i]
        ST[id] = df['service_time'][i]
    for f_n in N:
        for t_n in N:
            dist = math.sqrt( (x_coord[f_n]-x_coord[t_n])**2 + (y_coord[f_n] - y_coord[t_n])**2 )
            Cost[f_n,t_n] = dist
            TT[f_n,t_n] = dist/1 # 假设速度为1
    return N,Q,TT,ET,LT,ST,Cost,x_coord,y_coord

def build_model(N,Q,TT,ET,LT,ST,Cost,CAP,K):
    """
    :param N: 所有节点集合,其中N[0]为车场
    :param Q: 节点需求集合
    :param TT: 旅行时间
    :param ET: 节点最早开始服务时间
    :param LT:节点最晚结束服务时间
    :param ST: 节点服务时间
    :param CAP: 车辆容量
    :param Cost: 旅行费用
    :param K: 车队
    :return:
    """
    C = N[1:] #需求节点
    M=10**5
    depot = N[0]
    # 创建模型
    vrptw_model=Model()
    # 添加变量
    X = vrptw_model.addVars(N,N,K,vtype=GRB.BINARY,name='X(i,j,k)')
    T = vrptw_model.addVars( N,K,vtype=GRB.CONTINUOUS,lb=0,name='T[i,k]')
    # 设置目标函数
    z1 = quicksum( Cost[i,j]*X[i,j,k] for i in N for j in N for k in K if i!=j)
    vrptw_model.setObjective(z1,GRB.MINIMIZE)
    # 车辆起点约束
    vrptw_model.addConstrs(quicksum(X[depot, j, k] for j in N) == 1 for k in K)
    # 车辆路径连续约束
    vrptw_model.addConstrs( quicksum(X[i,j,k] for j in N if j!=i)==quicksum(X[j,i,k] for j in N if j!=i) for i in C for k in K)
    # 车辆终点约束
    vrptw_model.addConstrs(quicksum(X[j, depot, k] for j in N) == 1 for k in K)
    # 需求服务约束
    vrptw_model.addConstrs( quicksum(X[i,j,k] for k in K for j in N if j!=i)==1 for i in C)
    # 车辆容量约束
    vrptw_model.addConstrs( quicksum(Q[i]*X[i,j,k] for i in C for j in N if i!=j)<=CAP for k in K )
    # 时间窗约束
    vrptw_model.addConstrs( T[i,k]+ST[i]+TT[i,j]-(1-X[i,j,k])*M<=T[j,k] for i in C for j in C for k in K if i!=j )
    vrptw_model.addConstrs( T[i,k] >= ET[i] for i in N for k in K)
    vrptw_model.addConstrs( T[i,k] <= LT[i] for i in N for k in K)
    return vrptw_model,X,T
def draw_routes(route_list,x_coord,y_coord):
    for route in route_list:
        path_x = []
        path_y = []
        for n in route:
            path_x.append(x_coord[n])
            path_y.append(y_coord[n])
        plt.plot(path_x, path_y,linewidth=0.5, marker='s',ms=5)
    plt.show()
def save_file(route_list,route_timetable,total_cost):
    wb = xlsxwriter.Workbook('路径方案.xlsx')
    ws = wb.add_worksheet()
    ws.write(0,0,'总费用')
    ws.write(0,1,total_cost)
    ws.write(1,0,'车辆')
    ws.write(1,1,'路径')
    ws.write(1,2,'时刻')
    row = 2
    for id,route in enumerate(route_list):
        ws.write(row,0,route[0])
        route_str = [str(i) for i in route[1:]]
        ws.write(row,1,'-'.join(route_str))
        timetable_str = [str(i) for i in route_timetable[id]]
        ws.write(row,2,'-'.join(timetable_str))
        row += 1
    wb.close()
if __name__=='__main__':
    filename = './data/r101.csv'
    N, Q, TT, ET, LT, ST, Cost,x_coord,y_coord = read_input(filename)
    depot = N[0]
    K = list(range(1, 30))
    CAP = 80
    vrptw_model,X,T = build_model(N,Q,TT,ET,LT,ST,Cost,CAP,K)
    vrptw_model.setParam(GRB.Param.LogFile, './log/gurobi_r101.log')
    vrptw_model.Params.TimeLimit = 1500
    vrptw_model.optimize()
    route_list = []
    route_timetable = []
    # 提取车辆路径
    for k in K:
        route = [depot]
        cur_node = depot
        cur_k = None
        for j in N[1:]:
            if X[depot, j, k].x > 0:
                cur_node = j
                cur_k = k
                route.append(j)
                N.remove(j)
                break
        if cur_k is None:
            continue
        while cur_node != depot:
            for j in N:
                if X[cur_node, j, cur_k].x > 0:
                    cur_node = j
                    route.append(j)
                    if j != depot:
                        N.remove(j)
                    break
        route.insert(0,k)
        route_list.append(route)
    # 提取车辆的时刻点
    for route in route_list:
        k = route[0]
        timetable = []
        for i in route[1:]:
            timetable.append(T[i,k].x)
        route_timetable.append(timetable)

    print("最优路径距离:", vrptw_model.objVal)
    print("最优路径使用车辆数:", len(route_list))
    draw_routes(route_list, x_coord, y_coord)
    save_file(route_list, route_timetable, vrptw_model.objVal)

5.3 Python调用COPT求解CVRP


import xlsxwriter
import math
import pandas as pd
import matplotlib.pyplot as plt
from coptpy import *
def read_input(filename):
    """
    :param filename: 数据文件路径
    :return:
    """
    df = pd.read_csv(filename)
    x_coord = { df['id'][i]:df['x_coord'][i] for i in range(df.shape[0]) }       # 节点横坐标
    y_coord = { df['id'][i]:df['y_coord'][i] for i in range(df.shape[0]) }       # 节点纵坐标
    demand = { df['id'][i]:df['demand'][i] for i in range(df.shape[0]) }         # 节点需求
    cost = {}
    N = df['id'].tolist()
    for f_n in N:
        for t_n in N:
            dist = math.sqrt( (x_coord[f_n]-x_coord[t_n])**2 + (y_coord[f_n] - y_coord[t_n])**2 )
            cost[f_n,t_n] = dist
    return N,cost,demand,x_coord,y_coord
def build_model(N,K,depot,CAP,cost,demand):
    # 创建求解环境
    env = Envr()
    # 创建求解模型
    cvrp_model = env.createModel('cvrp')
    # 添加决策变量
    X = cvrp_model.addVars(N, N, K, vtype=COPT.BINARY, nameprefix='X[i,j,k]')
    Y = cvrp_model.addVars(N, K, vtype=COPT.BINARY, nameprefix='Y[i,k]')
    U = cvrp_model.addVars(N, K, vtype=COPT.INTEGER, nameprefix='U[i,k]')
    # 设置目标函数
    cvrp_model.setObjective(quicksum(X[i, j, k] * cost[i, j] for i in N for j in N for k in K), sense=COPT.MINIMIZE)
    # 添加约束
    #  需求覆盖约束
    cvrp_model.addConstrs(quicksum(Y[i, k] for k in K) == 1 for i in N[1:])
    #  车辆启用约束
    cvrp_model.addConstr(quicksum(Y[depot, k] for k in K) == len(K))
    #  车辆流平衡约束
    cvrp_model.addConstrs(quicksum(X[i, j, k] for j in N) == quicksum(X[j, i, k] for j in N) for i in N for k in K)
    #  车辆路径限制
    cvrp_model.addConstrs(quicksum(X[i, j, k] for j in N) == Y[i, k] for i in N for k in K)
    #  车辆容量约束
    cvrp_model.addConstrs(quicksum(Y[i, k] * demand[i] for i in N) <= CAP for k in K)
    #  破圈约束
    cvrp_model.addConstrs(
        U[i, k] - U[j, k] + CAP * X[i, j, k] <= CAP - demand[i] for i in N[1:] for j in N[1:] for k in K)
    cvrp_model.addConstrs(U[i, k] <= CAP for i in N[1:] for k in K)
    cvrp_model.addConstrs(U[i, k] >= demand[i] for i in N[1:] for k in K)
    return cvrp_model, X, Y, U
def draw_routes(route_list,x_coord,y_coord):
    for route in route_list:
        path_x = []
        path_y = []
        for n in route:
            path_x.append(x_coord[n])
            path_y.append(y_coord[n])
        plt.plot(path_x, path_y,linewidth=0.5, marker='s',ms=5)
    plt.show()
def save_file(route_list,total_cost):
    wb = xlsxwriter.Workbook('路径方案.xlsx')
    ws = wb.add_worksheet()
    ws.write(0,0,'总费用')
    ws.write(0,1,total_cost)
    ws.write(1,0,'车辆')
    ws.write(1,1,'路径')
    row = 2
    for route in route_list:
        ws.write(row,0,route[0])
        route_str = [str(i) for i in route[1:]]
        ws.write(row,1,'-'.join(route_str))
        row += 1
    wb.close()
if __name__ == '__main__':
    filename = './datasets/CVRP/r101-31.csv'
    N, cost, demand, x_coord,y_coord = read_input(filename)
    depot = N[0]
    K = list(range(1,10))
    CAP = 80
    cvrp_model, X, Y, U = build_model(N, K, depot, CAP, cost, demand)
    cvrp_model.param.timelimit = 1200
    cvrp_model.setLogFile('./copt_r101-31.log')
    cvrp_model.solve()
    route_list = []
    for k in K:
        route = [depot]
        cur_node = depot
        cur_k = None
        for j in N[1:]:
            if X[depot, j, k].x > 0:
                cur_node = j
                cur_k = k
                route.append(j)
                N.remove(j)
                break
        if cur_k is None:
            continue
        while cur_node != depot:
            for j in N:
                if X[cur_node, j, cur_k].x > 0:
                    cur_node = j
                    route.append(j)
                    if j != depot:
                        N.remove(j)
                    break
        route_list.append(route)
    print("最优路径距离:", cvrp_model.objval)
    print("最优路径使用车辆数:", len(route_list))
    draw_routes(route_list, x_coord, y_coord)
    save_file(route_list, cvrp_model.objval)

5.4 Python调用COPT求解VRPTW


import math
import pandas as pd
import matplotlib.pyplot as plt
import xlsxwriter
from coptpy import Envr,COPT,quicksum

def read_input(filename):
    """
    :param filename: 数据文件路径
    :return:
    """
    N = [] #所有节点
    Q = {} #节点需求
    TT = {} #节点旅行时间
    ET = {} #节点最早开始服务时间
    LT = {} #节点最晚结束服务时间
    ST = {} #节点服务时间
    x_coord = {} # 节点横坐标
    y_coord = {} # 节点纵坐标
    Cost={}
    df = pd.read_csv(filename)
    for i in range(df.shape[0]):
        id = df['id'][i]
        N.append(id)
        x_coord[id] = df['x_coord'][i]
        y_coord[id] = df['y_coord'][i]
        Q[id] = df['demand'][i]
        ET[id] = df['start_time'][i]
        LT[id] = df['end_time'][i]
        ST[id] = df['service_time'][i]
    for f_n in N:
        for t_n in N:
            dist = math.sqrt( (x_coord[f_n]-x_coord[t_n])**2 + (y_coord[f_n] - y_coord[t_n])**2 )
            Cost[f_n,t_n] = dist
            TT[f_n,t_n] = dist/1 # 假设速度为1
    return N,Q,TT,ET,LT,ST,Cost,x_coord,y_coord
def build_model(N,Q,TT,ET,LT,ST,Cost,CAP,K):
    """
    :param N: 所有节点集合,其中N[0]为车场
    :param Q: 节点需求集合
    :param TT: 旅行时间
    :param ET: 节点最早开始服务时间
    :param LT:节点最晚结束服务时间
    :param ST: 节点服务时间
    :param CAP: 车辆容量
    :param Cost: 旅行费用
    :param K: 车队
    :return:
    """
    C = N[1:] #需求节点
    M=10**5
    depot = N[0]
    # 创建求解环境
    env = Envr()
    # 创建求解模型
    vrptw_model = env.createModel('vrptw')
    # 添加决策变量
    X = vrptw_model.addVars(N, N, K, vtype=COPT.BINARY, nameprefix='X[i,j,k]')
    T = vrptw_model.addVars( N,K,vtype=COPT.CONTINUOUS,lb=0,nameprefix='T[i,k]')
    # 设置目标函数
    vrptw_model.setObjective(quicksum(X[i, j, k] * Cost[i, j] for i in N for j in N for k in K), sense=COPT.MINIMIZE)
    # 车辆起点约束
    vrptw_model.addConstrs(quicksum(X[depot, j, k] for j in N) == 1 for k in K)
    # 车辆路径连续约束
    vrptw_model.addConstrs(
        quicksum(X[i, j, k] for j in N if j != i) == quicksum(X[j, i, k] for j in N if j != i) for i in C for k in K)
    # 车辆终点约束
    vrptw_model.addConstrs(quicksum(X[j, depot, k] for j in N) == 1 for k in K)
    # 需求服务约束
    vrptw_model.addConstrs(quicksum(X[i, j, k] for k in K for j in N if j != i) == 1 for i in C)
    # 车辆容量约束
    vrptw_model.addConstrs(quicksum(Q[i] * X[i, j, k] for i in C for j in N if i != j) <= CAP for k in K)
    # 时间窗约束
    vrptw_model.addConstrs(
        T[i, k] + ST[i] + TT[i, j] - (1 - X[i, j, k]) * M <= T[j, k] for i in C for j in C for k in K if i != j)
    vrptw_model.addConstrs(T[i, k] >= ET[i] for i in N for k in K)
    vrptw_model.addConstrs(T[i, k] <= LT[i] for i in N for k in K)
    return vrptw_model, X, T
def draw_routes(route_list,x_coord,y_coord):
    for route in route_list:
        path_x = []
        path_y = []
        for n in route:
            path_x.append(x_coord[n])
            path_y.append(y_coord[n])
        plt.plot(path_x, path_y,linewidth=0.5, marker='s',ms=5)
    plt.show()
def save_file(route_list,route_timetable,total_cost):
    wb = xlsxwriter.Workbook('路径方案.xlsx')
    ws = wb.add_worksheet()
    ws.write(0,0,'总费用')
    ws.write(0,1,total_cost)
    ws.write(1,0,'车辆')
    ws.write(1,1,'路径')
    ws.write(1,2,'时刻')
    row = 2
    for id,route in enumerate(route_list):
        ws.write(row,0,route[0])
        route_str = [str(i) for i in route[1:]]
        ws.write(row,1,'-'.join(route_str))
        timetable_str = [str(i) for i in route_timetable[id]]
        ws.write(row,2,'-'.join(timetable_str))
        row += 1
    wb.close()
if __name__=='__main__':
    filename = './data/r101.csv'
    N, Q, TT, ET, LT, ST, Cost,x_coord,y_coord = read_input(filename)
    depot = N[0]
    K = list(range(1, 30))
    CAP = 80
    vrptw_model,X,T = build_model(N,Q,TT,ET,LT,ST,Cost,CAP,K)
    vrptw_model.setLogFile('./log/copt_c201.log')
    vrptw_model.param.timelimit = 1500
    vrptw_model.solve()
    route_list = []
    route_timetable = []
    # 提取车辆路径
    for k in K:
        route = [depot]
        cur_node = depot
        cur_k = None
        for j in N[1:]:
            if X[depot, j, k].x > 0:
                cur_node = j
                cur_k = k
                route.append(j)
                N.remove(j)
                break
        if cur_k is None:
            continue
        while cur_node != depot:
            for j in N:
                if X[cur_node, j, cur_k].x > 0:
                    cur_node = j
                    route.append(j)
                    if j != depot:
                        N.remove(j)
                    break
        route.insert(0,k)
        route_list.append(route)
    # 提取车辆的时刻点
    for route in route_list:
        k = route[0]
        timetable = []
        for i in route[1:]:
            timetable.append(T[i,k].x)
        route_timetable.append(timetable)

    print("最优路径距离:", vrptw_model.objval)
    print("最优路径使用车辆数:", len(route_list))
    draw_routes(route_list, x_coord, y_coord)
    save_file(route_list, route_timetable, vrptw_model.objval)

5.5 Python调用SCIP求解CVRP


import xlsxwriter
import math
import pandas as pd
import matplotlib.pyplot as plt
from pyscipopt import Model, quicksum, multidict

def read_input(filename):
    """
    :param filename: 数据文件路径
    :return:
    """
    df = pd.read_csv(filename)
    x_coord = { df['id'][i]:df['x_coord'][i] for i in range(df.shape[0]) }       # 节点横坐标
    y_coord = { df['id'][i]:df['y_coord'][i] for i in range(df.shape[0]) }       # 节点纵坐标
    demand = { df['id'][i]:df['demand'][i] for i in range(df.shape[0]) }         # 节点需求
    cost = {}
    N = df['id'].tolist()
    for f_n in N:
        for t_n in N:
            dist = math.sqrt( (x_coord[f_n]-x_coord[t_n])**2 + (y_coord[f_n] - y_coord[t_n])**2 )
            cost[f_n,t_n] = dist
    return N,cost,demand,x_coord,y_coord

def build_model(N,K,depot,CAP,cost,demand):
    """
    :param N: 网络节点集合
    :param K: 车队集合
    :param depot: 配送中心id
    :param CAP: 车辆容量
    :param cost: 网络弧费用集合
    :param demand: 网络节点需求集合
    :return:
    """
    cvrp_model = Model('cvrp')
    # 添加变量
    X = {}
    Y = {}
    U = {}
    # 创建变量 X[i,j,k]
    for i in N:
        for j in N:
            for k in K:
                X[i,j,k] = cvrp_model.addVar(vtype="B", name=f"x({i},{j},{k})")
    # 创建变量 Y[i,k]
    for i in N:
        for k in K:
            Y[i,k] = cvrp_model.addVar(vtype="B", name=f"y({i},{k})")
    #  创建辅助变量U[i,k]
    for i in N:
        for k in K:
            U[i,k] = cvrp_model.addVar(vtype="I", name=f"u({i},{k})")
    # 设置目标函数
    cvrp_model.setObjective( quicksum(X[i,j,k] * cost[i,j] for i in N for j in N for k in K),'minimize' )
    # 添加约束
    #  需求覆盖约束
    cvrp_model.addConss( quicksum(Y[i,k] for k in K) == 1 for i in N[1:] )
    #  车辆启用约束
    cvrp_model.addCons( quicksum(Y[depot,k] for k in K) == len(K) )
    #  车辆流平衡约束
    cvrp_model.addConss( quicksum(X[i,j,k] for j in N ) == quicksum(X[j,i,k] for j in N ) for i in N for k in K )
    #  车辆路径限制
    cvrp_model.addConss( quicksum(X[i,j,k] for j in N) == Y[i,k] for i in N for k in K )
    #  车辆容量约束
    cvrp_model.addConss( quicksum(Y[i,k] * demand[i] for i in N) <= CAP for k in K )
    #  破圈约束
    cvrp_model.addConss( U[i,k] - U[j,k] + CAP * X[i,j,k] <= CAP - demand[i] for i in N[1:] for j in N[1:] for k in K )
    cvrp_model.addConss( U[i,k] <=  CAP for i in N[1:] for k in K)
    cvrp_model.addConss( U[i,k] >= demand[i] for i in N[1:] for k in K )
    return cvrp_model, X, Y, U

def draw_routes(route_list,x_coord,y_coord):
    for route in route_list:
        path_x = []
        path_y = []
        for n in route:
            path_x.append(x_coord[n])
            path_y.append(y_coord[n])
        plt.plot(path_x, path_y,linewidth=0.5, marker='s',ms=5)
    plt.show()
def save_file(route_list,total_cost):
    wb = xlsxwriter.Workbook('路径方案.xlsx')
    ws = wb.add_worksheet()
    ws.write(0,0,'总费用')
    ws.write(0,1,total_cost)
    ws.write(1,0,'车辆')
    ws.write(1,1,'路径')
    row = 2
    for route in route_list:
        ws.write(row,0,route[0])
        route_str = [str(i) for i in route[1:]]
        ws.write(row,1,'-'.join(route_str))
        row += 1
    wb.close()
if __name__ == '__main__':
    filename = './datasets/CVRP/r101-31.csv'
    N, cost, demand, x_coord, y_coord = read_input(filename)
    depot = N[0]
    K = list(range(1,10))
    CAP = 80
    cvrp_model, X, Y, U = build_model(N, K, depot, CAP, cost, demand)
    # cvrp_model.setRealParam('limits/gap', 0.1)  # 求解gap为10%
    cvrp_model.setRealParam('limits/time', 1200)  # 求解时间为1800s
    cvrp_model.setLogfile('./scip_r101-31.log')
    cvrp_model.optimize()
    route_list = []
    for k in K:
        route = [depot]
        cur_node = depot
        cur_k = None
        for j in N[1:]:
            if cvrp_model.getVal(X[depot, j, k]) > 0:
                cur_node = j
                cur_k = k
                route.append(j)
                N.remove(j)
                break
        if cur_k is None:
            continue
        while cur_node != depot:
            for j in N:
                if cvrp_model.getVal(X[cur_node, j, cur_k]) > 0:
                    cur_node = j
                    route.append(j)
                    if j != depot:
                        N.remove(j)
                    break
        route_list.append(route)
    print("最优路径距离:", cvrp_model.getObjVal())
    print("最优路径使用车辆数:", len(route_list))
    draw_routes(route_list, x_coord, y_coord)
    save_file(route_list, cvrp_model.getObjVal())

5.6 Python调用SCIP求解VRPTW


import math
import pandas as pd
import matplotlib.pyplot as plt
import xlsxwriter
from pyscipopt import Model, quicksum

def read_input(filename):
    """
    :param filename: 数据文件路径
    :return:
    """
    N = [] #所有节点
    Q = {} #节点需求
    TT = {} #节点旅行时间
    ET = {} #节点最早开始服务时间
    LT = {} #节点最晚结束服务时间
    ST = {} #节点服务时间
    x_coord = {} # 节点横坐标
    y_coord = {} # 节点纵坐标
    Cost={}
    df = pd.read_csv(filename)
    for i in range(df.shape[0]):
        id = df['id'][i]
        N.append(id)
        x_coord[id] = df['x_coord'][i]
        y_coord[id] = df['y_coord'][i]
        Q[id] = df['demand'][i]
        ET[id] = df['start_time'][i]
        LT[id] = df['end_time'][i]
        ST[id] = df['service_time'][i]
    for f_n in N:
        for t_n in N:
            dist = math.sqrt( (x_coord[f_n]-x_coord[t_n])**2 + (y_coord[f_n] - y_coord[t_n])**2 )
            Cost[f_n,t_n] = dist
            TT[f_n,t_n] = dist/1 # 假设速度为1
    return N,Q,TT,ET,LT,ST,Cost,x_coord,y_coord
def build_model(N,Q,TT,ET,LT,ST,Cost,CAP,K):
    """
    :param N: 所有节点集合,其中N[0]为车场
    :param Q: 节点需求集合
    :param TT: 旅行时间
    :param ET: 节点最早开始服务时间
    :param LT:节点最晚结束服务时间
    :param ST: 节点服务时间
    :param CAP: 车辆容量
    :param Cost: 旅行费用
    :param K: 车队
    :return:
    """
    C = N[1:] #需求节点
    M=10**5
    depot = N[0]
    # 创建模型
    vrptw_model=Model()
    X = {}
    T = {}
    # 创建变量 X[i,j,k]
    for i in N:
        for j in N:
            for k in K:
                X[i, j, k] = vrptw_model.addVar(vtype="B", name=f"x({i},{j},{k})")
    # 创建变量 T[i,k]
    for i in N:
        for k in K:
            T[i, k] = vrptw_model.addVar(vtype="I", name=f"t({i},{k})")
    # 设置目标函数
    vrptw_model.setObjective(quicksum(X[i, j, k] * Cost[i, j] for i in N for j in N for k in K), 'minimize')
    # 车辆起点约束
    # 车辆起点约束
    vrptw_model.addConss(quicksum(X[depot, j, k] for j in N) == 1 for k in K)
    # 车辆路径连续约束
    vrptw_model.addConss(
        quicksum(X[i, j, k] for j in N if j != i) == quicksum(X[j, i, k] for j in N if j != i) for i in C for k in K)
    # 车辆终点约束
    vrptw_model.addConss(quicksum(X[j, depot, k] for j in N) == 1 for k in K)
    # 需求服务约束
    vrptw_model.addConss(quicksum(X[i, j, k] for k in K for j in N if j != i) == 1 for i in C)
    # 车辆容量约束
    vrptw_model.addConss(quicksum(Q[i] * X[i, j, k] for i in C for j in N if i != j) <= CAP for k in K)
    # 时间窗约束
    vrptw_model.addConss(
        T[i, k] + ST[i] + TT[i, j] - (1 - X[i, j, k]) * M <= T[j, k] for i in C for j in C for k in K if i != j)
    vrptw_model.addConss(T[i, k] >= ET[i] for i in N for k in K)
    vrptw_model.addConss(T[i, k] <= LT[i] for i in N for k in K)
    return vrptw_model, X, T
def draw_routes(route_list,x_coord,y_coord):
    for route in route_list:
        path_x = []
        path_y = []
        for n in route:
            path_x.append(x_coord[n])
            path_y.append(y_coord[n])
        plt.plot(path_x, path_y,linewidth=0.5, marker='s',ms=5)
    plt.show()
def save_file(route_list,route_timetable,total_cost):
    wb = xlsxwriter.Workbook('路径方案.xlsx')
    ws = wb.add_worksheet()
    ws.write(0,0,'总费用')
    ws.write(0,1,total_cost)
    ws.write(1,0,'车辆')
    ws.write(1,1,'路径')
    ws.write(1,2,'时刻')
    row = 2
    for id,route in enumerate(route_list):
        ws.write(row,0,route[0])
        route_str = [str(i) for i in route[1:]]
        ws.write(row,1,'-'.join(route_str))
        timetable_str = [str(i) for i in route_timetable[id]]
        ws.write(row,2,'-'.join(timetable_str))
        row += 1
    wb.close()
if __name__=='__main__':
    filename = './data/c201.csv'
    N, Q, TT, ET, LT, ST, Cost,x_coord,y_coord = read_input(filename)
    depot = N[0]
    K = list(range(1, 30))
    CAP = 80
    vrptw_model,X,T = build_model(N,Q,TT,ET,LT,ST,Cost,CAP,K)
    vrptw_model.setLogfile('./log/scip_c101.log')
    vrptw_model.setRealParam('limits/time', 2000)  # 求解时间为1800s
    vrptw_model.optimize()
    route_list = []
    route_timetable = []
    # 提取车辆路径
    for k in K:
        route = [depot]
        cur_node = depot
        cur_k = None
        for j in N[1:]:
            if vrptw_model.getVal(X[depot, j, k]) > 0:
                cur_node = j
                cur_k = k
                route.append(j)
                N.remove(j)
                break
        if cur_k is None:
            continue
        while cur_node != depot:
            for j in N:
                if vrptw_model.getVal(X[cur_node, j, cur_k]) > 0:
                    cur_node = j
                    route.append(j)
                    if j != depot:
                        N.remove(j)
                    break
        route.insert(0,k)
        route_list.append(route)
    # 提取车辆的时刻点
    for route in route_list:
        k = route[0]
        timetable = []
        for i in route[1:]:
            timetable.append(vrptw_model.getVal(T[i,k]))
        route_timetable.append(timetable)

    print("最优路径距离:", vrptw_model.getObjVal())
    print("最优路径使用车辆数:", len(route_list))
    draw_routes(route_list, x_coord, y_coord)
    save_file(route_list, route_timetable, vrptw_model.getObjVal())

7. 测试案例

本期从solomon数据集中选择了c101,c201,cr101三个算例用于测评。
CVRP问题数据结构如下(保留30个节点):
在这里插入图片描述
VRPTW问题数据结构如下(保留100个节点):
在这里插入图片描述

8. 测试参数

软件版本号:

Gurbi:9.5.1
SCIP:8.0.0
COPT:5.0.1

CVRP相关参数设置:

车辆容量:80
车队规模:10
客户节点:30
求解时间:1200s

VRPTW相关参数设置:

车辆容量:80
车队规模:30
客户节点:100
求解时间:1500s

9. 测试结果

9.1 CVRP求解结果汇总

在这里插入图片描述
对于CVRP问题,在相同的求解时间下,Gurobi在求解质量方面有最好的表现,COPT比SCIP略差。

9.2 VRPTW求解结果汇总

在这里插入图片描述

对于VRPTW问题,在相同的求解时间下,Gurobi可以找到不错的优化解,而COPT和SCIP并未找到初始解。

9.3 上界下降曲线对比(以CVRP为例)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从上界下降曲线可以看出,Gurobi找到的初始可行解的质量最好,且收敛性最好,而COPT和SCIP的初始解质量相差不大,收敛性不如Gurobi。

9.5 车辆路径可视化(以CVRP为例)

c101-31(Gurobi)

在这里插入图片描述

c201-31(Gurobi)

在这里插入图片描述

r101-31(Gurobi)

在这里插入图片描述

10. 小节

根据以上测试结果,Gurobi的求解性能远优于SCIP和COPT,作为后起之秀COPT已经接近SCIP水平(最新版的COPT尚未测试,也许性能有更大提升)。
虽然求解器可以直接对数学模型进行求解,但仅在小规模案例上具有较好的性能,对于大规模问题仍需要设计更高效的算法。
小编后续将继续分享VRP问题系列求解算法,并将其求解效果与上述求解器进行比较。

HiGHS开源求解器Pyhton调用方法 目前发现HiGHS这一新的完全开源的求解器,在实际使用过程中比SCIP性能要好,但调用起来较为不方便,一是因为官方的教学文档没有写完,二是便捷的方法很少,例如quicksum、expr表达式等。那么在研究实际问题中,我们更关注求解时间,也就可以手动排除一些障碍,并且经常尝试一些新的东西。网络上除官方文档外对这个求解器的调用方法的相关描述几乎没有,所以我就有幸成为第一批吃螃蟹的人了。 阅读详情

相关推荐

运筹学经典问题(八):CVRP和VRP-TW

给定一个图,图上的点代表客户,边代表客户之间的路线,边的权重代表客户之间的距离,点上的数字代表每个用户的需求量。如果只是上面的模型,可能会出现下图这种解,: 假设我们的问题是车辆去客户那里取货,需要一个约束去消除这种不包含仓库的子环。这也是VRP建模的一个略难的约束。会有图上的哪些边被选中,形成。没有约束车辆的容量限制!

JESSIENOTCAR的博客 1989

CVRP建模与求解-基于粒子群算法(python实现)

本文为单配送中心、单车型、车辆封闭、非满载、需求不可拆分的VRP场景建立数学模型,并设计粒子群算法进行求解。

_2312 1万+

python调用求解器SCIP求解多维背包问题(MKP)

python调用求解器SCIP求解多维背包问题(MKP)

南军Opt的博客 2265

Python 数学建模——cvxpy 规划求解器

介绍了 Python 的 cvxpy 规划求解器,可以用于求解线性规划、非线性规划、整数规划,0-1 规划等常见的规划问题。

wr114514的博客 5205

Python QP 求解器

该 Python 库提供一站式 solve_qp 函数,用于求解凸二次规划:向量不等式逐个坐标应用。函数返回后端 QP 求解器找到的初等解,如果求解失败/问题不可行,则返回 None。所有求解器都要求问题是凸的,这意味着矩阵应该是半正定的。有些求解器还要求问题是严格凸的,这意味着应该是正定的。:还有一个 solve_problem 函数,它不仅能返回初等解,还能返回其对偶乘法器和后端求解器计算的所有其他相关量。

机器人控制与仿真应用 1864

【VRP问题】基于遗传结合粒子群求解VRPTW问题

一、粒子群算法简介 粒子群算法是在1995年由Eberhart博士和Kennedy博士一起提出的,它源于对鸟群捕食行为的研究。它的基本核心是利用群体中的个体对信息的共享从而使整个群体的运动在问题求解空间中产生从无序到有序的演化过程,从而获得问题的最优解。设想这么一个场景:一群鸟进行觅食,而远处有一片玉米地,所有的鸟都不知道玉米地到底在哪里,但是它们知道自己当前的位置距离玉米地有多远。那么找到玉米地的最佳策略,也是最简单有效的策略就是搜寻目前距离玉米地最近的鸟群的周围区域。 在PSO中,每个优化问题的..

qq_59747472的博客 437

【运筹优化】带时间窗约束的车辆路径规划问题(VRPTW)详解 + Python 调用 Gurobi 建模求解

车辆路径规划问题(Vehicle Routing Problem,VRP)一般指的是:对一系列发货点和收货点,组织调用一定的车辆,安排适当的行车路线,使车辆有序地通过它们,在满足指定的约束条件下(例如:货物的需求量与发货量,交发货时间,车辆容量限制,行驶里程限制,行驶时间限制等),力争实现一定的目标(如车辆空驶总里程最短,运输总费用最低,车辆按一定时间到达,使用的车辆数最小等)。下图给出了一个简单的VRP的例子最基本的VRP问题叫做带容量约束的车辆路径规划问题(Capacitated Vehicle Rou

知不足而奋进,望远山而前行 4万+

GA-VRPTW-python版本遗传算法求解带时间窗的路径规划问题(Python版本)

1、完整代码,可直接运行 ,包运行(如有疑问可私信) 2、擅长领域:路径规划、机器学习、数据爬虫、数据分析处理等 3、该资源有较为详尽的注解,非常方便大家阅读与理解。 GA-VRPTW-python版本 遗传算法求解带时间窗的路径规划问题(Python版本) 该资源适用于研究路径规划的同学,以及研究遗传算法的同学

基于遗传算法的CVRP建模求解(Python)

单向:纯取货/纯送货; 单配送中心:只有一个配送中心/车场; 单车型:只考虑一种车型, 需求不可拆分:客户需求只能有一辆车满足; 车辆封闭:完成配送任务的车辆需回到配送中心; 车辆充足:不限制车辆数量,即配送车辆需求均能满足; 非满载:任意客户点的需求量小于车辆最大载重;优化目标:最小化车辆启动成本和车辆行驶成本之和; 约束条件:车辆行驶距离约束,重量约束; 已知信息:配送中心位置、客户点位置、客户点需求、车辆最大载重、车辆最大行驶距离、车辆启动成本、车辆单位距离行驶成本;min⁡Z=C0K+C1∑i=0N

博客简介 1万+

DOTween回调函数的隐藏技巧:优化你的Unity动画流程

本文深入探讨了DOTween回调函数在Unity动画开发中的高级应用技巧,帮助开发者优化动画流程。通过分析回调机制、链式应用模式和大规模动画系统管理,提升性能与可维护性,特别适合需要高效处理复杂动画场景的Unity开发者。

weixin_27945229的博客 319

【脑电绘图教程 2】使用Brainstorm进行脑电处理及源定位

Brainstorm 是一个开源应用程序,支持MEG、EEG、fNIRS、ECoG、深度电极和其他电生理学的数据分析,尤其用于MEG、EEG的源定位。Brainstorm的主要优点是其简单直观的图形界面,不需要进行任何编程,即可上手MEG、EEG分析,此外,它还支持多种数据类型(基本上EEGLab支持的,它都支持),并且具有数据批量处理功能,可以很方便的分析自己的数据。

qq_40735196的博客 1万+

【亲测免费】 PyIpopt: 一个基于Python的优化求解器

PyIpopt: 一个基于Python的优化求解器 是一个强大的优化求解器,它基于开源的Ipopt算法,并提供了方便的Python接口。如果你正在寻找一种有效的工具来解决非线性优化问题,那么PyIpopt绝对值得一试。 什么是PyIpopt? PyIpopt是一个Python包,它是Ipopt的一个Python接口。Ipopt是一种流行的、用于求解连续非线性优化问题的内点方法求解器。PyIpopt...

gitblog_00050的博客 1889

H.264 入门篇 - 09 (帧间预测 - 参考帧列表)

短期和长期的关系和区别:在一个解码器中的 DPB(参考帧缓存)大小总是有限的,所以引入一个问题,什么样的参考帧会被保存到 DPB 中,什么样的参考帧会被移除出去,因此将分为长期和短期参考帧,所谓短期参考帧是这帧不会长期驻留在DPB中,如果参考帧缓存已满或者有其他特定的条件,那么短期参考帧就会被从DPB中移除;与之相对的长期参考帧,只要没有遇到某个指定的条件,遇到某个IDR帧, 遇到了清空整个DPB的指令等等,那么长期参考帧会长期在DPB中,不会因为有新的参考帧而被冲刷掉;(P帧是按照编码顺序)

StephenZhou 5104

Python 数独求解器

尽管还有其他解决方法,但使用回溯算法可以得到数独问题更准确的最终解,但它需要更多时间,因为其中包含许多迭代。然而,解决数独谜题可以提高一个人的逻辑思维能力,并且是一种有趣的消遣方式。

迹忆客 1113

【基金量化研究系列】基金绩效归因模型——Brinson多期归因模型之python实现

文章目录1. 引言2. Brinson多期归因模型的Python实现2.1 基准数据读取模块2.2 持仓数据读取模块2.3 持仓收益与基准计算模块2.4 Brinson多期归因模型核心算法Brinson_Multiple2.5 主函数模块3. 归因结果写在最后 1. 引言 在上文中,我们已经介绍了Brinson归因模型的基本思想。那么,就让我们动起手来,实现这一方法吧! 在Brinson多期归因模型实现的过程中,本文使用模块化方法,将整个实现过程划分为如下五个功能板块: Module 1: 基准数据读取模

Mikey_Sun的博客 2万+

ADRV9009学习资料保存:基于XC7Z100+ADRV9009的双收双发无线电射频板卡

ADRV9009学习资料保存:基于XC7Z100+ADRV9009的双收双发无线电射频板卡 一、板卡概述 基于XC7Z100+ADRV9009的双收双发无线电射频板卡是基于XilinxZYNQFPGA和ADI的无线收发芯片ADRV9009开发的专用功能板卡,用于5G小基站,无线图传,数据收发...

9377

【CVRP&VRPTW】Python+Gurobi求解运输问题建模实践二

采用Python+Gurobi实现车辆路径规划问题建模求解【CVRP&VRPTW】

Better.C的博客 1万+

docker安装fastdfs+nginx配置

docker安装fastdfs+nginx,实现图片或文件的上传与下载

weixin_47325126的博客 2193

运筹系列17:routing模型之CVRP问题

1. CVRP模型 CVRP指的是有容量(capacity)限制的VRP模型,是最常见的VRP模型。 2. 示例 依旧用上一章节的点,不同的是每个点多了一个送货需求。每辆车的最大容量是15,最小化总运输距离。 dimension可以使用AddDimensionWithVehicleCapacity方法,和AddDimension唯一的区别就是,第三个参数从一个固定值变成了一个列表,表示每一辆车有自...

kittyzc的博客 1万+

微信小程序 - 最新实现人脸识别认证功能,使用官方微信小程序人脸识别身份验证接口及常见的人脸核验、用户实名认证、身份证件与人脸是否匹配、是否活体、领取业务人脸认证等各种示例(验证活体人脸是否匹配源码)

微信小程序中实现人脸识别认证,微信小程序人脸识别认证-微信开放接口,如何为微信小程序添加人脸识别和身份验证功能,如何为微信小程序集成人脸识别与身份验证,微信人脸识别实名认证集成指南,识别失败,人脸识别接口怎么调用,前后端完整示例代码demo,微信小程序基于小程序实现人脸识别对比,人脸识别报错,微信人脸核身接口能力,微信小程序实名认证 人脸核验 人脸识别,微信小程序实名认证与人脸核身接口全解析,微信小程序-人脸识别+输出人脸匹配信息,微信小程序实名认证人脸核验人脸识别,微信小程序实名认证:wx.startFa

🏆 前端领域优质创作者 3277

【深度学习新浪潮】智能体在图像处理领域的技术突破与实践指南

智能体正在重构图像处理的技术版图:从多智能体分工的"专业化协作",到多模态统一的"极简架构",再到工具增强的"实战能力",技术突破不断降低开发门槛并拓展应用边界。对于开发者而言,2025年的核心机遇在于结合具体场景选择成熟框架(如医疗用IteR-MRL、工业用NVIDIA NIM),通过微调与工具集成快速落地解决方案。随着硬件成本下降与开源生态完善,图像处理智能体将从当前的"高端场景赋能"走向"千行百业普及",真正成为数字世界的"视觉感知与操作核心"。

专注:太空算力、AI infra、异构调度、大模型成本工程 439

VRPTW

带时间窗的VRP问题是在该基础上,还需要满足服务时间约束,即配送人员需要在一定的时间窗内到达客户需求点进行服务。带时间窗的VRP问题分为硬时间窗和软时间窗两种,硬时间窗是车辆一定要在时间窗范围内到达指定用户处,不能早于时间窗要求的最早时间,也不能晚于时间窗的最晚时间;VRP问题一般是指从物流配送中心用多辆车向多个客户需求点送货,每个客户需求点的位置和需求量是已知的,车辆的最大载质量是一定的,要求合理安排配送路线使得目标函数最优,并且满足以下条件:每个客户需求点只能被一辆车访问,并且只能访问一次;

FanSunshineboy的博客 2936

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

python中的优化器有哪些_Python SciPy 优化器(Optimizers)

1、SciPy优化器优化器是SciPy中定义的一组过程,它们可以找到函数的最小值或方程式的根。2、优化函数本质上,机器学习中的所有算法不过是一个复杂的方程式,需要借助给定的数据将其最小化。3、方程的根NumPy能够找到多项式和线性方程式的根,但无法找到非线性方程式的根,如下所示:x + cos(x)为此,可以使用SciPy的optimize.root函数。此函数接受两个必需的参数:fun-表示方程...

weixin_39586335的博客 1419

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

python调用开源求解器SCIP求解带时间窗车辆路径问题(VRPTW)

python调用开源求解器SCIP求解带时间窗车辆路径问题(VRPTW)

南军Opt的博客 1885

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

python求解带约束的优化问题

带约束的优化问题,在python中可以使用scipy的optimize包进行求解,具体求解函数为linprog

罗伯特祥的博客 5204

【运筹优化】网络最大流问题及三种求解算法详解 + Python代码实现

本文首先对最大流问题进行了介绍,然后分别介绍了三种求解最大流问题的算法Ford-Fulkerson算法、Edmons-Karp算法和 Dinic 算法,并给出了相应的 Python 代码。最后,对这三种算法进行了性能测试与分析。

知不足而奋进,望远山而前行 2万+
上一篇: 【改进篇】Python实现VRP常见求解算法——自适应大邻域算法(ALNS)
下一篇: 【改进篇】Python实现VRP常见求解算法——差分进化算法(DE)
Better.C
博客等级 码龄9年 1万+粉丝 72原创
评论 14
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Better.C

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值