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

如何在Gurobi中实现含求和项的二次优化目标函数?

如何在Gurobi目标函数中加入含整数变量的求和项?

我尝试使用Python的Gurobi库优化含求和项的二次方程,但求和项报错,推测原因是其无法接受整数变量,仅支持常量整数。请问如何在目标函数中加入求和项?

我的代码如下:

from gurobipy import *
import sympy as sy

op1=sy.Symbol('op1')
op2=sy.Symbol('op2')

# Create a model
quadratic_model = Model('quadratic')

# Define decision variables
n = quadratic_model.addVar(vtype=GRB.INTEGER, lb=0, name='n')
t = quadratic_model.addVar(vtype=GRB.INTEGER, lb=0, name='t')
temp = quadratic_model.addVar(vtype=GRB.INTEGER, lb=0, name='temp')

# Define objective function
obj_fn = (1256*80/12.5)*n*t + 25*5*n*t + sy.summation(5*t*50*(365//n)*op1,(op1,1,n)) + sy.summation(5*24*op2,(op2,1,365))
quadratic_model.setObjective(obj_fn, GRB.MINIMIZE)

# Add constraints
quadratic_model.addConstr(50*n*t >= 4320)
quadratic_model.addConstr(n>=1)
quadratic_model.addConstr(t>=1)
quadratic_model.addConstr(n<=6*30/4)            

# Solve model
quadratic_model.setParam('NonConvex', 2)
quadratic_model.optimize()

# Print results
for v in quadratic_model.getVars():
    print('---------------------------------------')
    print('%s : %g' % (v.varName, v.x)) 

print("minimized solution for the equation is:", quadratic_model.objVal)

我尝试了两种方案仍未解决问题:

  • 使用temp变量替代365//n并添加约束temp == 365//n,但仍无法解决;
  • 使用for循环,却出现‘module 'gurobipy' has no attribute 'INTEGER'’的异常,此前使用Gurobi求解二次问题时未出现该问题。

问题分析与解决方法

核心问题

  1. SymPy求和不兼容Gurobi变量:SymPy的sy.summation是符号计算工具,仅能处理常量上限的求和,无法识别Gurobi变量n作为求和上限,且Gurobi不能直接接受SymPy表达式作为目标函数。
  2. 整数除法的非线性限制:365//n属于非线性操作,Gurobi默认不支持直接建模,需转化为线性约束。
  3. for循环报错原因:大概率是导入方式冲突,from gurobipy import *可能导致GRB.INTEGER未被正确加载,建议显式导入GRB类。

具体解决方案

1. 手动展开求和项,替换为代数表达式

直接推导求和结果,不再依赖SymPy:

  • sy.summation(op1, (op1,1,n))的求和结果为n*(n+1)/2,因n是整数,可直接写入目标函数;
  • sy.summation(op2, (op2,1,365))是常量求和,直接计算为5*24*(365*366//2)。
2. 用线性约束实现整数除法

引入整数变量k替代365//n,通过以下线性约束定义k:

k * n ≤ 365 < (k+1)*n
k ≥ 0
3. 修正后的完整代码
from gurobipy import Model, GRB

# 创建模型
quadratic_model = Model('quadratic')

# 定义决策变量
n = quadratic_model.addVar(vtype=GRB.INTEGER, lb=1, name='n')  # 直接设lb=1,避免n=0报错
t = quadratic_model.addVar(vtype=GRB.INTEGER, lb=1, name='t')
k = quadratic_model.addVar(vtype=GRB.INTEGER, lb=0, name='k')  # 替代365//n

# 预计算常量求和项
sum_op2 = 5 * 24 * (365 * 366 // 2)

# 定义目标函数
obj_fn = (1256*80/12.5)*n*t + 25*5*n*t + 5*t*50*k*(n*(n+1)//2) + sum_op2
quadratic_model.setObjective(obj_fn, GRB.MINIMIZE)

# 添加约束
quadratic_model.addConstr(50*n*t >= 4320, name='demand_constraint')
quadratic_model.addConstr(k * n <= 365, name='div_constraint_lower')
quadratic_model.addConstr((k + 1) * n > 365, name='div_constraint_upper')
quadratic_model.addConstr(n <= 6*30//4, name='n_upper_limit')  # 转为整数上限,避免浮点误差

# 求解模型
quadratic_model.setParam('NonConvex', 2)
quadratic_model.optimize()

# 输出结果
for v in quadratic_model.getVars():
    print('---------------------------------------')
    print('%s : %g' % (v.varName, v.x)) 

print("minimized solution for the equation is:", quadratic_model.objVal)
4. 关键说明
  • 显式导入Model和GRB可避免INTEGER属性找不到的问题,规避from gurobipy import *的导入冲突;
  • 所有求和项均转化为Gurobi支持的变量表达式或常量,不再依赖SymPy;
  • 整数除法通过辅助变量k和线性约束实现,符合Gurobi的建模规则。

内容的提问来源于stack exchange,提问作者Karas0u

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 19:10:41