Pyomo中决策变量间除法约束的线性化实现方案咨询
Pyomo中含实型变量/整型变量约束的线性化方法
所有线性化方法都要求整型除数变量不会取0,以下默认除数为正整数变量,若除数允许取负值可参考逻辑扩展调整。
场景1:除法仅出现在不等式约束中
比如原约束形式为 x / y ≤ C 或 x / y ≥ C,其中x为实型变量,y为正整型变量,C为常数/固定参数。
- 直接利用不等式乘法规则变形即可,不需要额外引入决策变量:
x / y ≤ C→x ≤ C * yx / y ≥ C→x ≥ C * y
- 该变形完全等价,没有精度损失。
- 如果y允许取负值,需要先引入0-1变量标记y的正负,分情况对不等式变形后用大M法合并约束即可,核心逻辑和正整数场景一致。
场景2:除法结果为独立决策变量
即原约束形式为 z = x / y,其中z为实型变量,x为实型变量,y为正整型变量,属于双线性非线性约束,需要引入辅助变量线性化,步骤如下:
- 提前确定各变量的可行域上下界:
- y的整数上下界:
Y_L ≤ y ≤ Y_U - z的上下界:
Z_L ≤ z ≤ Z_U - x的上下界:
X_L ≤ x ≤ X_U
- y的整数上下界:
- 引入辅助0-1变量集合
b,b[k]对应y取k值的标记,k的取值范围为[Y_L, Y_U]的所有整数 - 加入以下线性约束:
- 保证y只能取唯一值:
sum(b[k] for k in range(Y_L, Y_U+1)) == 1 - y的取值关联:
y == sum(k * b[k] for k in range(Y_L, Y_U+1)) - 双线性项等价约束,M取足够大的常数,推荐值为
max(abs(Z_U*k - X_U), abs(Z_L*k - X_L))即可:for k in range(Y_L, Y_U+1): x >= k*z - M*(1 - b[k]) x <= k*z + M*(1 - b[k])
- 保证y只能取唯一值:
Pyomo代码示例
import pyomo.environ as pyo model = pyo.ConcreteModel() # 变量定义 model.x = pyo.Var(within=pyo.Reals, bounds=(0, 100)) # 实型变量x model.y = pyo.Var(within=pyo.Integers, bounds=(1, 10)) # 正整型变量y,下界为1避免取0 model.z = pyo.Var(within=pyo.Reals, bounds=(0, 20)) # 除法结果变量z Y_L = 1 Y_U = 10 # 辅助0-1变量 model.b = pyo.Var(range(Y_L, Y_U+1), within=pyo.Binary) M = 200 # 根据变量上下界计算的足够大的常数 # 线性化约束 model.b_sum = pyo.Constraint(expr=sum(model.b[k] for k in range(Y_L, Y_U+1)) == 1) model.y_def = pyo.Constraint(expr=model.y == sum(k * model.b[k] for k in range(Y_L, Y_U+1))) def _x_low_rule(model, k): return model.x >= k * model.z - M * (1 - model.b[k]) model.x_low = pyo.Constraint(range(Y_L, Y_U+1), rule=_x_low_rule) def _x_high_rule(model, k): return model.x <= k * model.z + M * (1 - model.b[k]) model.x_high = pyo.Constraint(range(Y_L, Y_U+1), rule=_x_high_rule)
内容的提问来源于stack exchange,提问作者Unziello
相关产品推荐
相关产品推荐

