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

Python Gurobi 实现依赖决策变量的分段费率目标函数建模咨询

解决方案

你需要实现的是基于决策变量区间取值的分段费率目标函数,本质为目标关于y_t的分段线性函数,Gurobi Python接口有两种常用实现方案:

方案1:使用原生分段线性约束(推荐)

该方案利用Gurobi内置的addGenConstrPWL接口直接定义分段函数,无需手动引入二进制变量,求解效率更高,尤其适合当前凸成本的场景(费率随y_t增大递增,成本函数为凸,Gurobi有专门优化逻辑)。

实现代码示例:

import gurobipy as gp
from gurobipy import GRB

# 预设参数
T = 10  # 时间段总数
p = [100, 120, 90, ...]  # 各时间段的价格,长度为T
b = [0, 50, 100, 150, 200]  # 数量区间边界
r_list = [0, 0.05, 0.1, 0.15, 0.2]  # 各区间对应附加费率

# 初始化模型
m = gp.Model("piecewise_cost_opt")

# 定义决策变量:各时间段的采购/生产数量y_t
y = m.addVars(T, lb=0, name="y")
# 定义辅助变量:各时间段的对应成本
cost = m.addVars(T, lb=0, name="cost")

# 为每个时间段添加分段线性约束
for t in range(T):
    # 计算每个区间断点对应的成本值:成本 = 单位价格*(1+对应费率)* 断点数量值
    point_cost = [p[t] * (1 + r_list[k]) * b[k] for k in range(len(b))]
    # 建立y[t]到cost[t]的分段线性映射
    m.addGenConstrPWL(y[t], cost[t], b, point_cost, name=f"pwl_cost_t{t}")

# 设置目标:最小化全周期总成本
m.setObjective(gp.quicksum(cost[t] for t in range(T)), GRB.MINIMIZE)

# 求解模型
m.optimize()

方案2:二进制指示变量实现

如果你的业务逻辑需要额外用到区间归属的标记变量,可采用该方案手动引入二进制变量标记区间归属,再关联费率计算。

实现代码示例:

import gurobipy as gp
from gurobipy import GRB

# 预设参数
T = 10
p = [100, 120, 90, ...]
b = [0, 50, 100, 150, 200]
r_list = [0, 0.05, 0.1, 0.15, 0.2]
K = len(b) - 1  # 区间总数
M = 1000  # y_t的最大上界,可根据业务场景调整

# 初始化模型
m = gp.Model("indicator_cost_opt")

# 决策变量
y = m.addVars(T, lb=0, name="y")
# 二进制变量:z[t][k]=1代表时间段t的y_t落在第k个区间[b[k], b[k+1]]
z = m.addVars(T, K, vtype=GRB.BINARY, name="z")
# 辅助变量:各时间段的附加费率
r = m.addVars(T, lb=0, ub=max(r_list), name="r")

# 约束1:每个时间段只能归属一个区间
m.addConstrs((gp.quicksum(z[t, k] for k in range(K)) == 1 for t in range(T)), name="single_interval")

# 约束2:y_t的区间范围限制
for t in range(T):
    for k in range(K):
        m.addConstr(y[t] >= b[k] * z[t, k], name=f"y_lb_t{t}_k{k}")
        m.addConstr(y[t] <= b[k+1] * z[t, k] + M * (1 - z[t, k]), name=f"y_ub_t{t}_k{k}")

# 约束3:费率关联区间归属
m.addConstrs((r[t] == gp.quicksum(r_list[k] * z[t, k] for k in range(K)) for t in range(T)), name="r_calc")

# 设置目标函数
m.setObjective(gp.quicksum(p[t] * (1 + r[t]) * y[t] for t in range(T)), GRB.MINIMIZE)

# 求解
m.optimize()

注意:方案2引入了二进制变量,求解复杂度高于方案1,无特殊需求优先选择方案1。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 06:09:04