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

如何在Gurobi中添加取两个连续决策变量乘积下整值的约束

在Gurobi中实现v = floor(x * y)约束的方法

Gurobi不能直接定义v = floor(x * y)这类约束,因为它同时涉及双非线性项(连续变量x和y的乘积)和不连续的取整函数,属于非凸优化问题,而Gurobi默认只支持凸优化模型。不过你可以通过拆解约束、引入辅助变量的方式,让Gurobi能够处理这类需求。

约束拆解思路

要实现v = floor(x*y),可以把它拆成两个部分处理:

  • 先把连续变量的乘积转化为辅助变量
  • 再用整数变量和不等式约束表达取整逻辑

1. 引入辅助变量处理乘积项

添加一个连续辅助变量z,让z = x*y。这是双线性约束,Gurobi支持这类约束,但需要开启非凸求解模式(默认关闭)。

2. 用不等式表达取整逻辑

v = floor(z)等价于:

  • v ≤ z:保证v不大于z的整数部分
  • z < v + 1:保证z小于v的下一个整数
    同时要声明v为整数决策变量。

关键注意事项

  • 必须开启非凸参数:设置model.setParam('NonConvex', 2),否则Gurobi会拒绝求解包含双线性约束的非凸模型。
  • 非凸问题的局限性:这类问题无法保证找到全局最优解,只能得到局部最优;求解速度会远慢于凸优化问题,变量规模越大越明显。
  • 合理设置变量边界:给x、y、z设置明确的上下界,能帮助Gurobi的分支定界算法更高效地搜索解空间。

示例代码(Python)

import gurobipy as gp
from gurobipy import GRB

# 创建模型
model = gp.Model("floor_product_example")

# 定义决策变量
x = model.addVar(lb=0, ub=5, name="x")  # 给x设置0-5的边界
y = model.addVar(lb=0, ub=5, name="y")  # 给y设置0-5的边界
v = model.addVar(vtype=GRB.INTEGER, name="v")
z = model.addVar(lb=0, ub=25, name="z")  # x*y的最大可能值是25

# 添加约束
model.addConstr(z == x * y, "product_eq")
model.addConstr(v <= z, "floor_lower_bound")
model.addConstr(z < v + 1, "floor_upper_bound")

# 开启非凸求解模式
model.setParam('NonConvex', 2)

# 设置目标函数(示例:最大化v)
model.setObjective(v, GRB.MAXIMIZE)

# 求解模型
model.optimize()

# 输出结果
if model.status == GRB.OPTIMAL:
    print(f"最优解:")
    print(f"x = {round(x.X, 4)}")
    print(f"y = {round(y.X, 4)}")
    print(f"z = x*y = {round(z.X, 4)}")
    print(f"v = floor(z) = {int(v.X)}")
else:
    print("未找到最优解")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 18:13:25