我是一个新手,尤其是pyomo,所以我为新手的错误提前道歉。
我已经定义了一个简单的单元提交练习([1]中的示例3.1),使用[2]作为起点。我得到了正确的结果,我的代码运行,但我有一些关于如何访问东西的问题。
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import shutil
import sys
import os.path
import pyomo.environ as pyo
import pyomo.gdp as gdp #necessary if you use booleans to select active and inactive units
def bounds_rule(m, n, param='Cap_MW'):
# m because it pases the module
# n because it needs a variable from each set, in this case there was only m.N
return (0, Gen[n][param]) #returns lower and upper bounds.
def unit_commitment():
m = pyo.ConcreteModel()
m.dual = pyo.Suffix(direction=pyo.Suffix.IMPORT_EXPORT)
N=Gen.keys()
m.N = pyo.Set(initialize=N)
m.Pgen = pyo.Var(m.N, bounds = bounds_rule) #amount of generation
m.Rgen = pyo.Var(m.N, bounds = bounds_rule) #amount of generation
# m.OnOff = pyo.Var(m.N, domain=pyo.Binary) #boolean on/off marker
# objective
m.cost = pyo.Objective(expr = sum( m.Pgen[n]*Gen[n]['energy_$MWh'] + m.Rgen[n]*Gen[n]['res_$MW'] for n in m.N), sense=pyo.minimize)
# demand
m.demandP = pyo.Constraint(rule=lambda m: sum(m.Pgen[n] for n in N) == Demand['ener_MWh'])
m.demandR = pyo.Constraint(rule=lambda m: sum(m.Rgen[n] for n in N) == Demand['res_MW'])
# machine production limits
# m.lb = pyo.Constraint(m.N, rule=lambda m, n: Gen[n]['Cap_min']*m.OnOff[n] <= m.Pgen[n]+m.Rgen[n] )
# m.ub = pyo.Constraint(m.N, rule=lambda m, n: Gen[n]['Cap_MW']*m.OnOff[n] >= m.Pgen[n]+m.Rgen[n])
m.lb = pyo.Constraint(m.N, rule=lambda m, n: Gen[n]['Cap_min'] <= m.Pgen[n]+m.Rgen[n] )
m.ub = pyo.Constraint(m.N, rule=lambda m, n: Gen[n]['Cap_MW'] >= m.Pgen[n]+m.Rgen[n])
m.rc = pyo.Suffix(direction=pyo.Suffix.IMPORT)
return m
Gen = {
'GenA' : {'Cap_MW': 100, 'energy_$MWh': 10, 'res_$MW': 0, 'Cap_min': 0},
'GenB' : {'Cap_MW': 100, 'energy_$MWh': 30, 'res_$MW': 25, 'Cap_min': 0},
} #starting data
Demand = {
'ener_MWh': 130, 'res_MW': 20,
} #starting data
m = unit_commitment()
pyo.SolverFactory('glpk').solve(m).write()
m.display()
df = pd.DataFrame.from_dict([m.Pgen.extract_values(), m.Rgen.extract_values()]).T.rename(columns={0: "P", 1: "R"})
print(df)
print("Cost Function result: " + str(m.cost.expr()) + "$.")
print(m.rc.display())
print(m.dual.display())
print(m.dual[m.demandR])
da= {'duals': m.dual[m.demandP],
'uslack': m.demandP.uslack(),
'lslack': m.demandP.lslack(),
}
db= {'duals': m.dual[m.demandR],
'uslack': m.demandR.uslack(),
'lslack': m.demandR.lslack(),
}
duals = pd.DataFrame.from_dict([da, db]).T.rename(columns={0: "demandP", 1: "demandR"})
print(duals)
字符串
以下是我的问题:
- Duals/shadow-price:根据定义,影子价格是约束条件的对偶变量(m.demandP和m.demandR).有没有一种方法可以访问这些值并将它们放入一个嵌套框架中,而不用做我做的“糟糕”的事情?我的意思是手动定义da和db,然后在两个字典连接时创建嵌套框架?我想做一些更干净的东西,比如保存系统中每个生成器的P和R结果的df。
1.通常,在机组组合问题中,使用二进制变量来“标记”或“选择”活动和非活动机组。(注解行)。对于我在[3]中发现的,在包含二进制变量的模型中不存在二进制变量。之后,我重写了这个问题,没有包含二进制变量。在这个简单的练习中,所有单元都运行,这不是一个问题,但是对于更大的问题。我需要能够让优化决定哪些单元将运行,哪些单元将不运行,我仍然需要影子价格。在包含二进制变量的问题中,有没有一种方法可以获得影子价格/影子价格?
我让基于二进制变量的约束定义也在那里,以防有人发现它有用。
注意事项:代码也运行二进制变量,并得到正确的结果,但我不知道如何得到影子价格。因此,我的问题。
[1]Morales,J. M.,Conejo,A. J.,Madsen,H.,Pinson,P.,& Zugno,M.(2013). Integrating renewables in electricity markets:operational problems(Vol. 205). Springer Science & Business Media.
[2][https://jckantor.github.io/ND-Pyomo-Cookbook/04.06-Unit-Commitment.html](https://jckantor.github.io/ND-Pyomo-Cookbook/04.06-Unit-Commitment.html)
[3][Dual Variable Returns Nothing in Pyomo](https://stackoverflow.com/questions/64160458/dual-variable-returns-nothing-in-pyomo)的
1条答案
按热度按时间hjzp0vay1#
要回答1,您可以使用
model.component_objects(pyo.Constraint)
从模型中动态获取约束对象,它将返回约束的迭代器,这使您不必硬编码约束名称。对于索引变量来说,这很棘手,因为您必须执行一个额外的步骤来获取每个索引的松弛,而不仅仅是约束对象。你可以遍历keys
属性来检索这些值。字符串
关于2,我同意@Erwin关于用二进制变量求解以获得最优解的评论,然后去除二进制限制,但将变量固定为最优值以获得一些对偶变量值。