首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Pyomo中对两阶段随机规划中的情景进行适当的索引?

如何在Pyomo中对两阶段随机规划中的情景进行适当的索引?
EN

Stack Overflow用户
提问于 2022-10-03 09:50:40
回答 1查看 83关注 0票数 0

的主要问题是:如何定义风场景参数,以便为场景集S中的不同概率提供不同的风场景。

当运行场景集S= 1,2,3的随机代码时,...10和相应的概率Prob = 0.1、0.1、……、0.1。T= 1,2,.,48,具有相应的风速m.wind。

我尝试了以下选项来为下面的目标函数创建一个(s*t)矩阵。

目标函数

选项1: m.wind = dict{: 48 },这是在确定性模型中使用的风速为48步的dict

选项2: m. wind = {ndarray:( 10 , 48 )} =数组([.,.]),在这篇文章中,我构造了一个由10个场景的风速组成的数组,每个场景在48个时间步。

选项3: m.windd = {list:10} =array(.)、.、(.),在这个选项中,我在读了Pyomo有时不识别方括号之后,在括号之间放置了不同的场景。

选项4:最后一种构造风场景集的方法是创建一个(x*t)字典。

所有选项导致错误:错误:索引'0‘实际上对组件'wind’无效

您知道如何解决这个错误,以及如何正确地索引风吗?

`

代码语言:javascript
复制
def build_model(price_data, horizon_length, scenario_length, load_calc, park_calc):

m = pyo.ConcreteModel()

### BEGIN SOLUTION

# test vector
vector = np.array([0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1])
vector = vector.reshape(10,1)

## Sets

# Save the number of timesteps
m.N = horizon_length
m.S = len(scenario_length)

# Define the horizon set starting at hour 1 until horizon length +1
m.HORIZON = pyo.Set(initialize=range(1, m.N + 1))

# Define scenario set
m.SCENARIO = pyo.Set(initialize=range(1, m.S + 1))

## Parameters

# Round trip efficiency
m.teta = pyo.Param(initialize=0.95)

# Energy [MWh] in battery at t=0
m.E0 = pyo.Param(initialize=2.0, mutable=True)

# Guarantee of origin for local wind [€/MWh]
m.goNL = pyo.Param(initialize=5)

# Guarantee of origin for grid power [€/MWh]
m.goBE = pyo.Param(initialize=150)

# Maximum discharge power
m.d_max = pyo.Param(initialize=5)

# Maximum charge power
m.c_max = pyo.Param(initialize=5)

# Maximum export power
m.im_max = pyo.Param(initialize=10)

# Maximum import power
m.ex_max = pyo.Param(initialize=100)

## CREATE DICTS FOR DATA: Price, Load & Calc
# Create empty dictionary
price_data_dict = {}

# Loop over Price data elements of numpy array
for i in range(0, len(price_data)):
    # Add element to data_dict
    price_data_dict[i + 1] = price_data[i]

# Create empty dictionary
load_data_dict = {}

# Loop over Load data elements of numpy array
for i in range(0, len(load_calc)):
    # Add element to data_dict
    load_data_dict[i + 1] = load_calc[i]

# Create empty dictionary
park_data_dict = {}

# Loop over Wind park data elements of numpy array
for i in range(0, len(park_calc)):
    # Add element to data_dict
    park_data_dict[i + 1] = park_calc[i]

# Create empty dictionary
prob_dict = {}

# Loop over probability data elements of numpy array
for i in range(0, len(vector)):
    # Add element to prob_dict
    prob_dict[i + 1] = vector[i]

# Repeat the wind data to a matrix for 10 similar scenario's
wind_matrix = np.tile(park_calc, (10, 1))
# wind_matrix = np.tile(park_calc, (10, 1)) * vector

park_data_dict_2 = {1: park_data_dict, 2: park_data_dict, 3: park_data_dict, 4: park_data_dict, 5: park_data_dict,
                    6: park_data_dict, 7: park_data_dict, 8: park_data_dict, 9: park_data_dict, 10: park_data_dict}

# Price data
m.price = pyo.Param(m.HORIZON, initialize=price_data_dict, domain=pyo.Reals, mutable=True)

# Load data
m.Load = pyo.Param(m.HORIZON, initialize=load_data_dict, domain=pyo.Reals, mutable=True)

# Wind park data
m.wind = pyo.Param(m.SCENARIO, m.HORIZON, initialize=park_data_dict_2, mutable=True) #park_data_dict

# Scenario probability
m.prob = pyo.Param(m.SCENARIO, initialize=vector)  # Was Scen_prob

# # New description of wind in 10 different scenarios
# m.wind = pyo.Param(m.SCENARIO, m.HORIZON, initialize=wind_matrix_2) #  initialize=wind_matrix_2

## Variables

## Battery related variables
# Charging rate [MW]
m.c = pyo.Var(m.HORIZON, initialize=0.0, bounds=(0, 10), domain=pyo.NonNegativeReals)

# Discharging rate [MW]
m.d = pyo.Var(m.HORIZON, initialize=0.0, bounds=(0, 10), domain=pyo.NonNegativeReals)

# Battery power
m.Bat = pyo.Var(m.HORIZON, initialize=0.0, domain=pyo.NonNegativeReals)

# Binary variables charging and grid
m.u = pyo.Var(m.HORIZON, initialize=0.0, domain=pyo.Binary)
m.v = pyo.Var(m.HORIZON, initialize=0.0, domain=pyo.Binary)

# Energy (state-of-charge) [MWh]
m.E = pyo.Var(m.HORIZON, initialize=2.0, bounds=(0, 5), domain=pyo.NonNegativeReals)
m.G_im = pyo.Var(m.HORIZON, initialize=0, bounds=(0, 10), domain=pyo.NonNegativeReals)
m.G_ex = pyo.Var(m.HORIZON, initialize=0, bounds=(0, 100), domain=pyo.NonNegativeReals)
m.grid = pyo.Var(m.HORIZON, initialize=m.Load, bounds=(0, 10), domain=pyo.NonNegativeReals)

# Objective function

# def objfun(model):
#     return sum((m.price[t] + m.goNL) * m.wind[t] + (m.price[t] + m.goBE) * m.G_im[t] for t in m.HORIZON)

def objfun(model):
    return sum((m.price[t] + m.goBE) * m.G_im[t] + (m.price[t] + m.goNL) * sum(m.prob[s] * m.wind[s, t] for s in m.SCENARIO) for t in m.HORIZON)

m.OBJ = pyo.Objective(rule=objfun, sense=pyo.minimize)

def PowerBalance(m, t):
    return m.Load[t] + m.c[t] == m.grid[t] + m.d[t]

# Define Energy Balance constraints. [MWh] = [MW]*[1 hr]
# Note: assume 1-hour timestep in price data and control actions.
def EnergyBalance(m, t):
    # First timestep
    if t == 1:
        return m.E[t] == m.E0 + m.c[t] * m.teta - m.d[t] / m.teta

        # Subsequent timesteps
    else:
        return m.E[t] == m.E[t - 1] + m.c[t] * m.teta - m.d[t] / m.teta

# def ColdIroning(m, t):
#     return m.c[t] + m.d[t] + m.Load[t] <= m.CI

def GridBalance(m, t, s):
    return m.grid[t] == m.wind[t, s] + m.G_im[t] - m.G_ex[t]

def ImMax(m, t):
    return m.G_ex[t] - m.v[t] * m.ex_max <= 0

def ExMax(m, t):
    return m.G_im[t] + m.v[t] * m.im_max <= m.im_max

# def BatteryBalance(m, t):
#     return m.Bat[t] - m.d[t] + m.c[t] == 0
#
def ChargeMax(m, t):
    return m.d[t] - m.u[t] * m.d_max <= 0

def DischargeMax(m, t):
    return m.c[t] + m.u[t] * m.c_max <= m.c_max

m.EnergyBalance_Con = pyo.Constraint(m.HORIZON, rule=EnergyBalance)
m.PowerBalance_Con = pyo.Constraint(m.HORIZON, rule=PowerBalance)
# m.ColdIroning_Con = pyo.Constraint(m.HORIZON, rule=ColdIroning)
m.GridBalance_Con = pyo.Constraint(m.HORIZON, m.SCENARIO, rule=GridBalance)
# m.BatteryBalance_Con = pyo.Constraint(m.HORIZON, rule=BatteryBalance)
m.ChargeMax_Con = pyo.Constraint(m.HORIZON, rule=ChargeMax)
m.DischargeMax_Con = pyo.Constraint(m.HORIZON, rule=DischargeMax)
m.ImMax_Con = pyo.Constraint(m.HORIZON, rule=ImMax)
m.ExMax_Con = pyo.Constraint(m.HORIZON, rule=ExMax)
## END SOLUTION

return m`
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-10-03 15:27:40

嗨,托马斯,欢迎来到现场。

在我们谈论风之前,你的模型上有一些快速的东西.

您不需要(也可能不应该)初始化变量,只需让求解者完成它的工作。

在您的t,s约束中有一个异常错误的GridBalance,这将是一个很难找到的问题。

你没说风数据是什么格式的。也许你只是用手干扰了一些表格数据。所以让我们从pyomo想要的开始..。它需要一个元组索引字典来初始化参数。这意味着字典的键值是(s,t)值的元组。这也被称为“平面”数据结构,其中所有的键都被枚举,感兴趣的数据值在1列中(例如,一种矩阵格式或其他)。因此,您希望从以下内容初始化您的参数:

代码语言:javascript
复制
import pyomo.environ as pyo

# what we want: a "flat" dictionary

#         s, t : w
wind = { (1, 1): 12,
         (1, 2): 11,
         (1, 3): 10,
         (2, 1): 9,
         (2, 2): 13,
         (2, 3): 14}

m = pyo.ConcreteModel()

# SETS
m.S = pyo.Set(initialize=[1, 2])
m.T = pyo.Set(initialize=[1, 2, 3])

# PARAMS

m.wind = pyo.Param(m.S, m.T, initialize=wind)

m.pprint()

输出:

代码语言:javascript
复制
3 Set Declarations
    S : Size=1, Index=None, Ordered=Insertion
        Key  : Dimen : Domain : Size : Members
        None :     1 :    Any :    2 : {1, 2}
    T : Size=1, Index=None, Ordered=Insertion
        Key  : Dimen : Domain : Size : Members
        None :     1 :    Any :    3 : {1, 2, 3}
    wind_index : Size=1, Index=None, Ordered=True
        Key  : Dimen : Domain : Size : Members
        None :     2 :    S*T :    6 : {(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3)}

1 Param Declarations
    wind : Size=6, Index=wind_index, Domain=Any, Default=None, Mutable=False
        Key    : Value
        (1, 1) :    12
        (1, 2) :    11
        (1, 3) :    10
        (2, 1) :     9
        (2, 2) :    13
        (2, 3) :    14

4 Declarations: S T wind_index wind

显然,有几种技术可以根据源数据的结构从数据生成元组索引字典。不过,在此之前,我看到您将列表转换为带循环的切块。当然可行,或者您可以使用带有枚举的快捷方式,它生成索引:值对并将其传递给字典构造函数。注意,如果您喜欢您的数据1-索引副0,枚举使用一个可选的开始参数。

代码语言:javascript
复制
prices = [3.5, 4.2, 9.8]
price_dict = dict(enumerate(prices, start=1))

print(price_dict)

# {1: 3.5, 2: 4.2, 3: 9.8}

因此,如果你纯粹是手工干扰的值,你可以键入一个平面字典,如上面所示,或者如果你有一个列表(也就是矩阵)风数据,你可以转换它几种方式,取决于你的舒适度与字典的理解等。下面的所有这些都生成了同一个平面字典,可在您的模型中使用:

代码语言:javascript
复制
raw_wind_data = [[4, 5, 9],
                 [3, 0, 12]]

wind_1 = {}
for i in range(len(raw_wind_data)):
    for j in range(len(raw_wind_data[0])):
        wind_1[(i+1, j+1)] = raw_wind_data[i][j]

wind_2 = { (r+1, c+1) : raw_wind_data[r][c] 
                    for r in range(len(raw_wind_data)) 
                    for c in range(len(raw_wind_data[0]))}

wind_3 = {(r_idx, c_idx): w 
            for r_idx, row in enumerate(raw_wind_data, 1)
            for c_idx, w   in enumerate(row, 1)}

print(wind_1)
print(wind_2)
print(wind_3)

# {(1, 1): 4, (1, 2): 5, (1, 3): 9, (2, 1): 3, (2, 2): 0, (2, 3): 12}
# {(1, 1): 4, (1, 2): 5, (1, 3): 9, (2, 1): 3, (2, 2): 0, (2, 3): 12}
# {(1, 1): 4, (1, 2): 5, (1, 3): 9, (2, 1): 3, (2, 2): 0, (2, 3): 12}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73933729

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档