总结使用Pyomo解决优化问题的一般方式

ops/2024/10/18 14:15:44/

总结使用Pyomo解决优化问题的一般方式

首先当然要import pyomo.environ as pe,以及定义m = pe.Concretemodel()

已知12个时刻的电价price_schedule,以及12个时刻的充电量charge_schedule

求解目标是需要找到最好的售卖电量的方式 w t w_t wt使得总的利润 ∑ t = 1 T p t w t \sum_{t=1}^{\mathcal{T}}p_t w_t t=1Tptwt最大,其中 p t p_t pt已知。

我在这里总结一下使用pyomo解答优化问题的关键要素。
1.定义参数的参数。这一部分包括总长度以及集合,规定了集合的总长度和形状。

m.nt = pe.Param(initialize=len(price_schedule), domain=pe.integers)

定义总长度之后,这只是一个数,print以后可以得到12

用这个参数来定义时间集合T,这是一个顺次生成的集合,其值为range(m.nt())

m.T = pe.Set(initialize=range(m.nt()))

有多少个总长度以及集合,上述过程就要重复多少次。当然,除外的情况为:这几个集合长度参数相同,因此只需要导入一个长度参数即可。但为了熟练多写几个长度参数也不是不可以。

2.定义参数。

在本问题中,包括 P t P_t Pt Q t Q_t Qt S 0 S_0 S0 w m a x w_{max} wmax四个参数。其中, P t P_t Pt Q t Q_t Qt两个参数形状为m.T*1,所以在pe.Param中,应该加入对形状的说明,即m.T即如下:

m.price = pe.Param(m.T, initialize=price_schedule)
m.charge = pe.Param(m.T, initialize=charge_schedule)
m.S0 = pe.Param(initialize=500.)
m.wmax = pe.Param(initialize=150.)

由于range(m.nt())就是m.T的值,所以可以range(m.nt())用来指代m.T

3.定义变量。

这一段和往常相同,定义变量的内容使用pe.Var即可。参数因为具有形状要求,应该加上range(m.nt())或者m.T

m.w = pe.Var(m.T, domain=pe.NonNegativeReals)
m.s = pe.Var(m.T, domain=pe.NonNegativeReals)

4.定义目标

目标的表达式为
max ⁡ w t , s t ∑ t ∈ T ( p t w t ) \begin{align} \max_{w_t, s_t}\quad& \sum_{t\in \mathcal{T}}(p_tw_t)\\ \end{align} wt,stmaxtT(ptwt)
目标为 max ⁡ w t , s t ∑ t ∈ T ( p t w t ) \max_{w_t, s_t} \sum_{t\in \mathcal{T}}(p_tw_t) maxwt,sttT(ptwt),也就是 p t p_t pt w t w_t wt的对应项相乘。

原来的时候,目标使用m.o = pe.Objective(rule=lambda m:[optimization problem format], sense=maximize/minimize)的形式定义。但是由于函数形式变长,这种定义形式变得繁琐,使用先定义优化函数,后定义目标的形式。

# 定义函数
def objective_func(model):return sum(m.price[t]*m.w[t] for t in m.T)
m.o = pe.Objective(rule=objective_func, sense=maximize)

5.定义约束

定义约束有
w t ≤ w m a x , ∀ t ∈ T S t ≤ S 0 , ∀ t ∈ T S t − S t − 1 = Q t − w t . ∀ t ∈ T , t ≥ 2 S t − S 0 = Q 1 − w 1 . \begin{align*} \quad & w_t\leq w_{max}, \forall t\in \mathcal{T}\\ & S_t\leq S^0 , \forall t\in \mathcal{T}\\ & S_{t}-S_{t-1}=Q_t-w_t. \forall t\in \mathcal{T},t\geq2\\ & S_{t}-S^0=Q_1-w_1. \end{align*} wtwmax,tTStS0,tTStSt1=Qtwt.∀tT,t2StS0=Q1w1.
在原来的时候,约束使用m.c = pe.ConstraintList()形成约束列表,然后使用m.c.add()的形式逐个写入约束。缺点是繁琐。

现在,先定义条件的函数def,然后再使用model.[name of the def]=pe.Constriant()导入约束条件。

  1. 可以用循环的形式理解这个代码,这里在函数调用过程中的t可以理解为循环单元,可以理解为类似于函数定义之类的东西,传入的是for t in T里面的t之类的东西。
  2. pe.Constraint中,等于对前面函数提到的t进行迭代定义,从而得到一系列约束。再说一遍,m.T即为range(m.nt()),也就是从1m.nt()的一个序列。
# 定义约束
def w_less_than_max(model, t):return m.w[t]<=m.wmax 
m.w_less_than_max = pe.Constraint(m.T, rule=w_less_than_max)

类似地,定义第二个式子:

def Q_less_than_S0(model, t):return m.s[t]<=m.S0
m.Q_less_than_S0 = pe.Constraint(m.T, rule=Q_less_than_S0)

第三个式子有点复杂,分为2种情况,一种是t=1的时候,一种则是其余时候

def Two_type_for_Storage(model,t):if t==0:return m.s[t]-m.s0==m.charge[t]*m.S0-m.w[t]else:return m.s[t]-m.s[t-1]==m.charge[t]*m.S0-m.w[t]
m.Two_type_for_Storage = pe.Constraint(m.T, rule=Two_type_for_Storage)

6.求解式子

和往常一样求解即可。

solver = pe.SolverFactory('gurobi')
results = solver.solve(model)

7.输出结果

# print(model.display())
print(f"time\tprice\tpower\tstorage")
for t in model.T:print(f"{t}\t{model.price[t]:.2f}\t{model.w[t]():>5.1f}\t{model.s[t]():>5.1f}")

也可以画图输出结果。这里就不赘述了。


http://www.ppmy.cn/ops/94268.html

相关文章

我在高职教STM32——I2C通信入门(2)

大家好,我是老耿,高职青椒一枚,一直从事单片机、嵌入式、物联网等课程的教学。对于高职的学生层次,同行应该都懂的,老师在课堂上教学几乎是没什么成就感的。正是如此,才有了借助CSDN平台寻求认同感和成就感的想法。在这里,我准备陆续把自己花了很多心思设计的教学课件分…

SpringBoot快速入门(自动创建)

目录 前言 步骤 1 创建项目 2 选择生成器springBoot 3 修改后&#xff0c;如图所示 4 点击下一步 5 点击Web----SpringWeb 6 点击创建 6.1 如果发生报错如: 6.2 替换合适版本&#xff0c;等待重新加载 7 添加contronller类 7.1 添加HelloController 类 8 ​​创建…

什么是开源什么是闭源?以及它们之间的关系

开源软件&#xff08;Open Source Software&#xff09; 定义&#xff1a;开源软件是指其源代码可以被公众访问和使用的软件。用户可以查看、修改和增强软件的源代码。 许可&#xff1a;通常遵循特定的开源许可证&#xff0c;如GNU通用公共许可证&#xff08;GPL&#xff09;、…

什么情况下mysql 会索引失效?

MySQL 中索引失效的情况通常与查询条件、表结构以及数据访问模式有关。了解索引失效的原因可以帮助我们更有效地使用索引来提高查询性能。以下是一些可能导致 MySQL 索引失效的常见情形&#xff1a; 使用不等于操作符&#xff08;! 或 < >&#xff09;: 如果查询条件包含…

仿RabbitMq实现简易消息队列正式篇(消费者篇)

TOC消费者管理模块 客户端由两种&#xff1a;发布消息&#xff0c;订阅消息 因此订阅了指定队列消息的客户端才是一个消费者。 消费者数据存在的意义&#xff1a;当指定队列有了消息以后&#xff0c;就需要将消息推送给这个消费者客户端&#xff08;推送的时候就需要找到这个…

【数据结构】顺序表实现

0. 前言 小伙伴们大家好&#xff0c;从今天开始&#xff0c;我们就开始学习《数据结构》这门课程~ 首先想给大家讲讲什么是数据结构&#xff1f; 0.1 数据结构是什么&#xff1f; 数据结构是由“数据”和“结构”两词组合⽽来。 什么是数据&#xff1f; 比如常⻅的数值1、…

动手学深度学习(pytorch)学习记录7-线性回归的从零开始实现[学习记录]

注&#xff1a;本代码在jupyter notebook上运行 封面图片来源 1、生成数据集 %matplotlib inline import random import torch from d2l import torch as d2l构造数据集&#xff1a;生成一个包含1000个样本的数据集&#xff0c; 每个样本包含从标准正态分布中采样的2个特征。…

八股面试大总结⑤ —— Redis篇

5.1 什么是Redis 内存型数据库&#xff0c;读写速度快有多种数据类型用于不同业务执行命令由单线程完成&#xff0c;不存在并发竞争 5.2 为什么用redis做mysql的缓存 redis高性能&#xff1a;用户第一次访问mysql的数据会从硬盘读取比较慢&#xff0c;之后会将数据缓存在red…