新闻中心
Pyomo中变量比较与二进制变量的条件建模:Big-M方法详解

本文深入探讨了在pyomo优化模型中如何正确处理涉及决策变量的条件逻辑。当尝试直接在python的`if`语句中使用pyomo变量进行比较时,会导致`typeerror`。针对此问题,本文详细介绍了如何利用big-m方法和辅助二进制变量,将复杂的条件逻辑转化为线性约束,从而在pyomo中实现变量间的有效比较与状态控制,并提供了具体的代码示例与原理分析。
在构建Pyomo优化模型时,经常需要根据模型中的决策变量(Var)的状态来触发或控制其他变量或约束。例如,当某个生产量达到一定阈值时,一个二进制变量需要被激活。然而,直接在Python的if语句中对Pyomo的Var对象进行比较,会导致TypeError: Relational expression used in an unexpected Boolean context。这是因为Pyomo变量是符号表达式,它们的值在模型求解之前是未知的,不能像普通Python数值一样直接进行布尔判断。
理解问题根源
考虑以下Pyomo约束定义中的条件语句:
def gen3_on_off(model, m):
# 这行代码会导致错误,因为model.gen1_use[m]和model.gen2_use[m]是Pyomo变量
if model.gen1_use[m] + model.gen2_use[m] <= 0.90 * model.load_profile[m]:
return model.gen3_status[m] == 1
else:
return model.gen3_status[m] == 0当Pyomo尝试构建gen3_on_off约束时,它会遍历model.m_index中的每个索引m。在每次迭代中,Python解释器会尝试评估if语句中的条件表达式。然而,model.gen1_use[m]和model.gen2_use[m]是pyomo.environ.Var类型的对象,它们代表了优化问题中的未知决策变量。对这些变量执行
解决方案:Big-M方法
解决这类问题的标准方法是使用Big-M(大M)方法,将条件逻辑转化为一组线性不等式。这通常需要引入一个辅助的二进制变量来表示条件的真假。
假设我们希望实现这样的逻辑: 如果 X >= T,则 Y = 1;否则,Y = 0。 其中 X 是一个或多个Pyomo变量的组合,T 是一个阈值,Y 是一个二进制变量(model.gen3_status[m])。
我们可以通过以下两个Big-M约束来实现这一条件逻辑:
-
约束1:当 Y=1 时,强制 X >= T + epsilonX >= T + epsilon - BigM * (1 - Y)
- 如果 Y = 1,则 X >= T + epsilon。这确保了只有当 X 严格大于 T 时,Y 才能为1。
- 如果 Y = 0,则 X >= T + epsilon - BigM。由于 BigM 是一个足够大的正数,这个约束在 Y=0 时几乎总是满足的,不会限制 X 的下限。
约束2:当 Y=0 时,强制 X X
- 如果 Y = 0,则 X
- 如果 Y = 1,则 X
参数说明:
Voicepods
Voicepods是一个在线文本转语音平台,允许用户在30秒内将任何书面文本转换为音频文件。
142
查看详情
- BigM:一个足够大的正数。它必须足够大,以至于当条件不激活时,它不会错误地限制变量的范围。然而,过大的BigM可能导致数值不稳定性,因此应选择一个合理的值,通常是问题中变量可能的最大范围。
- epsilon (eps):一个非常小的正数,用于处理严格不等式(> 或 = T + epsilon 确保 X 必须严格大于 T 才能满足条件。如果条件是 X >= T(包含等于),则可以省略 epsilon。
Pyomo中的实现
将上述Big-M方法应用于原问题,假设我们希望当 model.gen1_use[m] + model.gen2_use[m] 大于等于 0.30 * model.load_profile[m] 时,model.gen3_status[m] 为1,否则为0。
首先定义 eps 和 bigm 常量:
# 一些常量 eps = 1e-3 # 用于创建间隙,处理严格不等式 bigm = 1e3 # 选择一个足够大但不过大的值,避免数值不稳定性
然后,将原有的 gen3_on_off 约束替换为两个新的Big-M约束:
# 创建2个Big-M约束
def gen3_on_off_rule1(model, m):
# 逻辑:如果 gen1_use + gen2_use >= 0.30 * load_profile + eps,则 gen3_status 倾向于 1
return model.gen1_use[m] + model.gen2_use[m] >= 0.30 * model.load_profile[m] + eps - bigm * (1 - model.gen3_status[m])
def gen3_on_off_rule2(model, m):
# 逻辑:如果 gen1_use + gen2_use <= 0.30 * load_profile,则 gen3_status 倾向于 0
return model.gen1_use[m] + model.gen2_use[m] <= 0.30 * model.load_profile[m] + bigm * model.gen3_status[m]
model.gen3_on_off_bigm1 = Constraint(model.m_index, rule=gen3_on_off_rule1)
model.gen3_on_off_bigm2 = Constraint(model.m_index, rule=gen3_on_off_rule2)代码整合示例:
from pyomo.environ import *
import numpy as np
import pandas as pd
# 创建一个具体的模型
model = ConcreteModel()
idx = 20
np.random.seed(idx)
model.m_index = Set(initialize=list(range(idx)))
model.load_profile = Param(model.m_index, initialize=dict(zip(model.m_index, np.random.randint(10, 350, idx))))
model.solar_profile = Param(model.m_index, initialize=dict(zip(model.m_index, np.random.uniform(0, 0.6, idx))))
# 参数:发电机容量
model.gen1_cap = Param(initialize=100)
model.gen2_cap = Param(initialize=100)
model.gen3_cap = Param(initialize=100)
model.backup_cap = Param(initialize=300)
# 参数:发电机运行成本
model.gen1_cost = Param(initialize=10)
model.gen2_cost = Param(initialize=10)
model.gen3_cost = Param(initialize=10)
model.backup_cost = Param(initialize=-3)
# 变量:发电机输出能量
model.gen1_use = Var(model.m_index, domain=NonNegativeReals)
model.gen2_use = Var(model.m_index, domain=NonNegativeReals)
model.gen3_use = Var(model.m_index, domain=NonNegativeReals)
model.backup_use = Var(model.m_index, domain=NonNegativeReals)
# 二进制变量:发电机3的状态
model.gen3_status = Var(model.m_index, domain=Binary)
# 目标函数:最大化总成本
def production_cost(model):
total_cost = sum(
model.gen1_use[m] * model.gen1_cost +
model.gen2_use[m] * model.gen2_cost +
model.gen3_use[m] * model.gen3_cost * model.gen3_status[m] + # gen3成本与状态挂钩
model.backup_use[m] * model.backup_cost
for m in model.m_index)
return total_cost
model.obj = Objective(rule=production_cost, sense=maximize)
# Big-M 方法实现条件逻辑
# 一些常量
eps = 1e-3 # 用于创建间隙
bigm = 1e3 # 大M值
# 创建2个Big-M约束来控制gen3_status
# 条件:model.gen1_use[m] + model.gen2_use[m] >= 0.30 * model.load_profile[m]
# 结果:model.gen3_status[m] = 1 (如果条件满足) 或 0 (如果条件不满足)
def gen3_on_off_bigm_rule1(model, m):
# 如果 gen3_status[m] = 1,则 L.H.S >= R.H.S + eps
# 如果 gen3_status[m] = 0,则 L.H.S >= R.H.S + eps - bigm (几乎总是满足)
return model.gen1_use[m] + model.gen2_use[m] >= 0.30 * model.load_profile[m] + eps - bigm * (1 - model.gen3_status[m])
def gen3_on_off_big
m_rule2(model, m):
# 如果 gen3_status[m] = 0,则 L.H.S <= R.H.S
# 如果 gen3_status[m] = 1,则 L.H.S <= R.H.S + bigm (几乎总是满足)
return model.gen1_use[m] + model.gen2_use[m] <= 0.30 * model.load_profile[m] + bigm * model.gen3_status[m]
model.gen3_on_off_bigm1 = Constraint(model.m_index, rule=gen3_on_off_bigm_rule1)
model.gen3_on_off_bigm2 = Constraint(model.m_index, rule=gen3_on_off_bigm_rule2)
def energy_balance(model, m):
eq = model.gen1_use[m] + model.gen2_use[m] + model.gen3_use[m] + model.backup_use[m] >= model.load_profile[m]
return eq
model.energy_balance = Constraint(model.m_index, rule=energy_balance)
def gen1_max(model, m):
eq = model.gen1_use[m] <= model.gen1_cap
return eq
model.gen1_max = Constraint(model.m_index, rule=gen1_max)
def gen2_max(model, m):
eq = model.gen2_use[m] <= model.gen2_cap
return eq
model.gen2_max = Constraint(model.m_index, rule=gen2_max)
def gen3_max(model, m):
eq = model.gen3_use[m] <= model.gen3_cap * model.solar_profile[m] * model.gen3_status[m] # gen3容量也与状态挂钩
return eq
model.gen3_max = Constraint(model.m_index, rule=gen3_max)
def backup_max(model, m):
eq = model.backup_use[m] <= model.backup_cap
return eq
model.backup_max = Constraint(model.m_index, rule=backup_max)
# 求解器配置
Solver = SolverFactory('gurobi') # 确保Gurobi已安装并配置
Solver.options['LogFile'] = "gurobiLog"
print('\nConnecting to Gurobi Server...')
results = Solver.solve(model)
if (results.solver.status == SolverStatus.ok):
if (results.solver.termination_condition == TerminationCondition.optimal):
print("\n\n***Optimal solution found***")
print('obj returned:', round(value(model.obj), 2))
else:
print("\n\n***No optimal solution found***")
if (results.solver.termination_condition == TerminationCondition.infeasible):
print("Infeasible solution")
exit()
else:
print("\n\n***Solver terminated abnormally***")
exit()
# 结果提取与输出
load = []
gen1 = []
gen2 = []
gen3 = []
solar_profile = []
backup = []
gen3_status = []
for i in range(idx):
load.append(value(model.load_profile[i]))
gen1.append(value(model.gen1_use[i]))
gen2.append(value(model.gen2_use[i]))
gen3.append(value(model.gen3_use[i]))
solar_profile.append(value(model.solar_profile[i]))
backup.append(value(model.backup_use[i]))
gen3_status.append(value(model.gen3_status[i]))
df = pd.DataFrame({
'Load profile': load,
'Gen 1': gen1,
'Gen 2': gen2,
'Gen 3': gen3,
'Solar profile': solar_profile,
'Backup': backup,
'Gen 3 Status': gen3_status,
})
df.to_excel('binary.xlsx')
print(df)Big-M约束的详细分析
我们以一个具体数值为例,来理解这两个Big-M约束如何协同工作。 假设 0.30 * model.load_profile[m] 的值为 84.3。
情况一:期望 gen3_status[m] = 1 假设求解器决定 model.gen1_use[m] + model.gen2_use[m] 的和为 85 (大于 84.3),并且 gen3_status[m] 被设置为 1。
- 约束1: 85 >= 84.3 + 0.001 - 1000 * (1 - 1)85 >= 84.301 - 1000 * 085 >= 84.301 (满足)
- 约束2: 85
在这种情况下,两个约束都得到满足,并且 gen3_status[m] 被正确设置为 1。
情况二:期望 gen3_status[m] = 0 假设求解器决定 model.gen1_use[m] + model.gen2_use[m] 的和为 65 (小于 84.3),并且 gen3_status[m] 被设置为 0。
- 约束1: 65 >= 84.3 + 0.001 - 1000 * (1 - 0)65 >= 84.301 - 100065 >= -915.699 (满足)
- 约束2: 65
在这种情况下,两个约束都得到满足,并且 gen3_status[m] 被正确设置为 `
以上就是Pyomo中变量比较与二进制变量的条件建模:Big-M方法详解的详细内容,更多请关注其它相关文章!
# 倾向于
# 建设商城网站的书籍钱
# 无锡seo知识分享
# 营销推广分析案例分享会
# 诊所医生网站建设方案
# 小程序营销的推广方法
# 浙江信息化网站优化设计
# 网站关键词推广价格
# 如何营销展馆产品推广方案
# 新乡网站优化电池
# 优化网站设计方案模板
# 这一
# 文本文件
# excel
# 如何使用
# 在这种情况下
# 转化为
# 过大
# 转换为
# 设置为
# 是一个
# cos
# ai
# app
# python
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
黑鲨3Pro怎样在相册开漫画风滤镜_iPhone黑鲨3Pro相册开漫画风滤镜【趣味滤镜】
Win10怎么设置静态IP地址 Win10手动配置IP地址步骤【指南】
c++如何使用TBB库进行任务并行_c++ Intel线程构建模块
J*a里如何实现线程安全的懒加载单例_懒加载单例实现方法解析
在J*a里如何理解依赖关系的方向_依赖方向在模块结构中的作用
c++中的std::launder有什么实际用途_c++对象生命周期与指针优化
包子漫画官方网站阅读入口-包子漫画在线漫画官网直达链接
押井守高度称赞《辐射4》:玩了八年都停不下来!
win11如何卸载Windows更新补丁 Win11解决更新导致系统不稳定的问题【修复】
windows10怎么关闭系统提示音_windows10彻底静音设置方法
Web Components中自定义开关组件状态同步的常见陷阱与解决方案
响应式图片在网页设计中的正确实现方法
小米14应用无法联网原因分析_小米14网络权限修复
Python:递归比较文件夹内容并找出特定类型文件的差异
解决Bootstrap卡片顶部边距导致背景图下移的问题
在J*a中如何捕获IndexOutOfBoundsException_索引越界异常防护方法说明
高德地图沿途添加点失败如何解决 高德多点规划方法
Python中高效且防溢出的双曲正弦计算:基于对数空间的优化策略
ArrayList与LinkedList操作复杂度详解:遍历与修改
俄罗斯浏览器官网直达链接 俄罗斯浏览器最新在线入口导航
Log4j Console Appender性能瓶颈与高并发优化策略
腾讯视频怎么使用多账号家庭管理_腾讯视频家庭多账号统一管理与权限分配教程
J*aScriptWebpack优化_J*aScript构建工具实战
Win11如何开启讲述人功能 Win11屏幕阅读器(讲述人)开启与关闭【教程】
为什么我的微信朋友圈看不到别人的更新_微信朋友圈更新显示异常解决方法
J*aScript数组对象转换:按指定键分组与值收集
Golang如何实现状态模式管理对象状态_Golang State模式实现技巧
2025俄罗斯Yandex最新入口 官方网站地址及浏览器下载指南
TypeScript/J*aScript:高效查找数组中首个唯一ID对象
红果短剧网页版官网入口 官方最新网址发布
AO3官方可用镜像 Archive of Our Own网页版最新入口
处理Kafka消费者会话超时:深入理解消息处理语义与幂等性
Composer的 archive 命令怎么用_快速打包你的PHP项目及其Composer依赖
Golang如何使用context实现超时取消_Golang context超时取消模式实践
PHP 枚举:根据字符串获取枚举案例的策略与实现
LINUX的perf命令入门_LINUX官方性能分析工具的使用与解读
知音漫客正版漫画平台_知音漫客官网账号登录
Golang如何实现简单的Web表单_Golang表单提交与验证处理方法
在Go开发中优雅管理ListenAndServe进程:GoSublime集成方案
HuggingFaceEmbeddings中向量嵌入维度调整的限制与理解
优化LangChain文档加载与ChromaDB集成:解决多文档处理与分块问题
Mac怎么使用表情符号_Mac Emoji快捷键面板
Python类型检查:优化关联可选属性的Mypy推断策略
PostgreSQL海量数据高效导入策略:Python与Django实践指南
使用J*aScript检测输入元素是否包含在特定类中
邮政快递单号查询入口 邮政快递物流信息在线查询入口
铁路12306改签能改到更早的车次吗_铁路12306改签提前车次规则
在React函数组件中利用原生HTML5进行邮箱地址验证
J*aScript map 迭代中检测空数组元素的有效方法
印象笔记怎样用批量导出备知识库_印象笔记用批量导出备知识库【备份方法】


2025-12-02
浏览次数:次
返回列表
m_rule2(model, m):
# 如果 gen3_status[m] = 0,则 L.H.S <= R.H.S
# 如果 gen3_status[m] = 1,则 L.H.S <= R.H.S + bigm (几乎总是满足)
return model.gen1_use[m] + model.gen2_use[m] <= 0.30 * model.load_profile[m] + bigm * model.gen3_status[m]
model.gen3_on_off_bigm1 = Constraint(model.m_index, rule=gen3_on_off_bigm_rule1)
model.gen3_on_off_bigm2 = Constraint(model.m_index, rule=gen3_on_off_bigm_rule2)
def energy_balance(model, m):
eq = model.gen1_use[m] + model.gen2_use[m] + model.gen3_use[m] + model.backup_use[m] >= model.load_profile[m]
return eq
model.energy_balance = Constraint(model.m_index, rule=energy_balance)
def gen1_max(model, m):
eq = model.gen1_use[m] <= model.gen1_cap
return eq
model.gen1_max = Constraint(model.m_index, rule=gen1_max)
def gen2_max(model, m):
eq = model.gen2_use[m] <= model.gen2_cap
return eq
model.gen2_max = Constraint(model.m_index, rule=gen2_max)
def gen3_max(model, m):
eq = model.gen3_use[m] <= model.gen3_cap * model.solar_profile[m] * model.gen3_status[m] # gen3容量也与状态挂钩
return eq
model.gen3_max = Constraint(model.m_index, rule=gen3_max)
def backup_max(model, m):
eq = model.backup_use[m] <= model.backup_cap
return eq
model.backup_max = Constraint(model.m_index, rule=backup_max)
# 求解器配置
Solver = SolverFactory('gurobi') # 确保Gurobi已安装并配置
Solver.options['LogFile'] = "gurobiLog"
print('\nConnecting to Gurobi Server...')
results = Solver.solve(model)
if (results.solver.status == SolverStatus.ok):
if (results.solver.termination_condition == TerminationCondition.optimal):
print("\n\n***Optimal solution found***")
print('obj returned:', round(value(model.obj), 2))
else:
print("\n\n***No optimal solution found***")
if (results.solver.termination_condition == TerminationCondition.infeasible):
print("Infeasible solution")
exit()
else:
print("\n\n***Solver terminated abnormally***")
exit()
# 结果提取与输出
load = []
gen1 = []
gen2 = []
gen3 = []
solar_profile = []
backup = []
gen3_status = []
for i in range(idx):
load.append(value(model.load_profile[i]))
gen1.append(value(model.gen1_use[i]))
gen2.append(value(model.gen2_use[i]))
gen3.append(value(model.gen3_use[i]))
solar_profile.append(value(model.solar_profile[i]))
backup.append(value(model.backup_use[i]))
gen3_status.append(value(model.gen3_status[i]))
df = pd.DataFrame({
'Load profile': load,
'Gen 1': gen1,
'Gen 2': gen2,
'Gen 3': gen3,
'Solar profile': solar_profile,
'Backup': backup,
'Gen 3 Status': gen3_status,
})
df.to_excel('binary.xlsx')
print(df)