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

如何解决Gurobi报错‘Divisor must be a constant’并正确实现目标函数?

问题分析与解决方案

1. 错误根源:变量做除数违反Gurobi规则

Gurobi作为线性/整数规划求解器,绝对不允许把决策变量(比如你的x[i,j])当作除数——这就是你看到Divisor must be a constant报错的直接原因。另外你目标函数里的if x!=0条件判断,也没法直接在Gurobi的线性表达式里实现,这种离散逻辑需要特殊处理,但其实你的需求根本不需要这么做。

2. 目标函数的等价线性转换

从你的代码逻辑推断,你应该是想最大化「总运输成本节约量」:对每一笔从工厂到客户的运输,计算D - d[i,j](单位运输量的节约值),再乘以运输量x[i,j],最后求和。

我们可以通过数学推导把你原本的目标逻辑转化为完全线性的形式:
假设你原本想对每个工厂i计算D - (Σ(d[i,j]x[i,j]) / Σx[i,j]),再乘以该工厂的总运输量Σx[i,j],最后把所有工厂的结果加起来。展开后就是:

Σ[ D*Σx[i,j] - Σ(d[i,j]x[i,j]) ] = ΣΣ( (D - d[i,j]) * x[i,j] )

这个线性表达式完全符合Gurobi的要求,不需要任何除法操作。

3. 代码修改细节

(1)修复目标函数

把原来的目标函数替换成下面的线性版本:

model.setObjective(quicksum((D - d[i,j]) * x[i,j] for i in P for j in W), GRB.MAXIMIZE)

(2)删除冗余约束

你写的这个约束完全是多余的,删掉它能减少不必要的计算开销:

# 这个约束可以直接删除,因为d[i,j]最大是5,D=100,5*x[i,j] <=100*x[i,j]恒成立
for i in P:
    for j in W:
        model.addConstr(d[i,j]*x[i,j],"<=",D*x[i,j])

(3)修正变量名冲突(可选但推荐)

你用import pandas as p,同时又用P,p=multidict(...),这会导致p被覆盖。建议把pandas的导入改成import pandas as pd,避免变量名冲突。

(4)修正输出的工厂/客户顺序

你的输出语句里工厂和客户的顺序搞反了,而且要获取变量的最优值需要用.X属性:

print("sending quantity %10.2f from factory %3s to customer %3s" %(x[i,j].X, i, j))

完整修改后的代码

from gurobipy import *
import pandas as pd  # 修正变量名冲突
import numpy as np

d={ (1,1):2,(1,2):3,(1,3):3,(1,4):5,
    (2,1):2,(2,2):3,(2,3):3,(2,4):5,
    (3,1):2,(3,2):3,(3,3):3,(3,4):5,
    (4,1):2,(4,2):3,(4,3):3,(4,4):5,
    (5,1):2,(5,2):3,(5,3):3,(5,4):5,
}
P,p_cap=multidict({1:1,2:1,3:2,4:2,5:2})  # 改名p为p_cap,避免冲突
W,w_demand=multidict({1:2,2:2,3:2,4:2})  # 改名w为w_demand,更清晰
D=100
total_p=sum([i for i in p_cap.values()])
total_w=sum([j for j in w_demand.values()])
if total_w/total_p<1:
    R= total_w/total_p
else :
    R=1
print(R)

model=Model("keibi optimizer")
x={}
for i in P:
    for j in W:
        x[i,j]=model.addVar(vtype="C",name="x(%s,%s)"%(i,j))
model.update()

# 需求约束
for j in W:
    model.addConstr(quicksum(x[i,j] for i in P) == w_demand[j],name='Demand(%s)' %j)
# 产能约束
for i in P:
    model.addConstr(quicksum(x[i,j] for j in W) <= p_cap[i],name='Capacity(%s)' %i)

# 修正后的线性目标函数
model.setObjective(quicksum((D - d[i,j]) * x[i,j] for i in P for j in W), GRB.MAXIMIZE)
model.optimize()

print("Optimal value:", model.ObjVal/(total_p*D))
for(i,j) in x:
    # 用.X获取最优值,修正工厂和客户的顺序
    print("sending quantity %10.2f from factory %3s to customer %3s" %(x[i,j].X, i, j))

验证说明

修改后的代码:

  • 完全符合Gurobi的线性规划要求,不会再出现除数错误
  • 目标函数等价于你原本想实现的逻辑(最大化总节约值)
  • 修复了变量名冲突和输出顺序的问题
  • 删除了冗余约束,提升求解效率

内容的提问来源于stack exchange,提问作者炎天下修羅

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 14:19:06