You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中Pulp变量出现NoneType与int比较错误的求助

TSP求解变量值为None的问题分析与解决

问题描述

使用Python结合Pulp库求解旅行商问题(TSP),循环处理不同规模的TSP文件时,前3个小文件运行正常,但处理第4个及更大规模文件时,print_prob函数中执行v.varValue >= 1时触发错误:'>=' not supported between instances of 'NoneType' and 'int',即变量的varValue属性为None。需明确问题原因并给出解决建议。


相关代码

触发错误的print_prob函数

def print_prob(prob, timelimit):
    for v in prob.variables():
        if (v.varValue >= 1):
            print(v.name, "=", v.varValue)

    print(value(prob.objective))

    if timelimit >= 0:
        print("剩余执行时间:", timelimit)
        print("总执行时间:", max_time - timelimit)
    else:
        print("在给定时间内未找到最优解。")
    #print(prob)

    return

全局处理逻辑

def testing_all_3(i):
    # 文件名列表
    file = ['wi29', 'dj38', 'qa194', 'uy734', 'zi929', 'lu980', 'rw1621', 'mu1979', 'nu3496', 'ca4663']
    print("===============")
    print("测试文件", file[i] + ".tsp")
    # 使用专用函数打开TSP文件(TSP格式有对应的处理库)
    bench = _tspfile(file[i] + ".tsp")
    n = bench.dimension
    # 根据文件数据生成节点列表(用数字表示)
    cidades, destinos = _append(n)
    # 将节点权重转换为Pulp可用的字典格式
    costs = _tsp(n, bench)
    costs = makeDict([cidades, destinos], costs, 0)

    # 调用两个类似的求解函数
    print("使用MTZ方法求解")
    solvingMTZ(cidades, destinos, n, costs, file[i])
    print("===============")
    print("测试文件", file[i] + ".tsp")
    print("使用DL方法求解")
    solvingDL(cidades, destinos, n, costs, file[i])

for i in range(5,10):
    # 原本会遍历0到9,但第4个及之后的文件才会报错
    testing_all_3(i)

核心MTZ求解函数

def solvingMTZ(cidades, destinos, n, costs, file):
    prob = LpProblem("Teste", LpMinimize)
    road = [(cid_i, cid_j) for cid_i in cidades for cid_j in destinos]
    var = LpVariable.dicts("Road", (cidades, destinos), 0, 1, LpInteger)

    # 目标函数
    prob += lpSum([var[cid_i][cid_j] * costs[cid_i][cid_j] for (cid_i, cid_j) in road])

    # 约束:每个节点仅出一次
    for i in cidades:
        prob += lpSum([var[i][cid_j] for cid_j in destinos if i != cid_j]) == 1

    # 约束:每个节点仅入一次
    for j in destinos:
        prob += lpSum([var[cid_i][j] for cid_i in cidades if j != cid_i]) == 1

    prob = mtz(n, prob, cidades, var)
    timelimit = max_time
    start = time.time()
    prob.solve(GUROBI_CMD(timeLimit=timelimit, msg=1, gapRel=0))
    end = time.time()
    timelimit = timelimit - end + start
    print(timelimit)

    # 打印变量值和最终结果
    print_prob(prob, timelimit)
    make_node_fileMTZ(prob, file, timelimit)
    return

# MTZ约束生成函数(DL方法的求解函数几乎完全相同,此处省略)
def mtz(n, prob, cidades, var):
    u = LpVariable.dicts('u', (i for i in cidades), 1, n-1, LpInteger)
    for i in cidades[1:]:
        for j in cidades[1:]:
            # if i != j:
            prob += u[i] - u[j] + (n - 1) * var[i][j] <= n - 2
    return prob

问题原因

  1. 求解超时无可行解:大规模TSP的变量数和约束数随节点数呈指数增长,当前设置的timeLimit不足以让Gurobi找到可行解。小问题求解速度快,能在时限内完成,变量有有效值;大问题超时后,求解器未返回任何可行解,变量varValue保持为None。
  2. 未检查求解状态:代码直接访问变量值,未判断求解是否成功。Pulp中prob.solve()返回状态码,超时情况下状态通常为LpStatusNotSolved或LpStatusTimeLimit,此时变量无有效值。
  3. MTZ约束效率低下:MTZ约束数量为O(n²),节点数增大后约束暴增,不仅减慢求解速度,还可能导致求解器在时限内无法找到可行解,甚至引发数值稳定性问题。

解决建议

1. 先检查求解状态再访问变量

在print_prob中先判断求解状态,仅当有可行解时才遍历变量:

def print_prob(prob, timelimit):
    status = LpStatus[prob.status]
    # 仅处理最优或可行状态
    if status not in ["Optimal", "Feasible"]:
        print(f"求解状态:{status},无有效变量值")
        obj_val = value(prob.objective) if prob.objective else "N/A"
        print(f"目标函数值:{obj_val}")
        if timelimit < 0:
            print("在给定时间内未找到最优解。")
        else:
            print("剩余执行时间:", timelimit)
            print("总执行时间:", max_time - timelimit)
        return

    # 遍历变量时增加None判断
    for v in prob.variables():
        if v.varValue is not None and v.varValue >= 1:
            print(v.name, "=", v.varValue)

    print("目标函数值:", value(prob.objective))
    # 时间打印逻辑
    if timelimit >= 0:
        print("剩余执行时间:", timelimit)
        print("总执行时间:", max_time - timelimit)
    else:
        print("在给定时间内未找到最优解。")

2. 调整求解器参数

  • 增大timeLimit,给大规模问题足够的求解时间;
  • 放宽gapRel参数(如设为0.05),允许求解器在找到接近最优的可行解时提前终止,避免超时无结果;
  • 开启多线程加速,如GUROBI_CMD(timeLimit=timelimit, msg=1, gapRel=0.05, threads=4)。

3. 优化TSP模型

MTZ模型不适用于大规模TSP(n>500),建议:

  • 使用Gurobi内置的TSP求解接口(更高效,针对TSP做了优化);
  • 改用启发式算法(如遗传算法、模拟退火)快速得到可行解,再结合整数规划做局部优化;
  • 选择更高效的整数规划模型(如基于子回路消除的分支定界模型)。

4. 变量访问时增加None判断

即使求解状态正常,个别变量可能因数值问题未赋值,因此必须先判断v.varValue is not None再做比较。


内容的提问来源于stack exchange,提问作者Gabriel Sanches da Silva

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 07:40:23