Pyomo KeyError:"访问索引组件时出错:索引' 0'对数组组件无效' li_f_inv'"

时间:2018-04-16 16:05:25

标签: pyomo

我试图在Pyomo上运行以下代码。使用具体模型是一个简单的传输扩展问题。

谢谢jsiirola。我其实只是在学习Pyomo,这就是为什么我可能犯了愚蠢的错误。我实施了你所建议的所有内容,如下所示:

from pyutilib.misc import import_file
from pyomo.environ import *
import networkx as nx

model = ConcreteModel() 
model.name = "DTEPM_trial_concrete"

#Sets
#Epoch
model.E = Set(initialize = [0, 1, 2, 3])
model.E_n = Set(model.E, initialize = {0:[1,2,3,4,5], 1:[6,7,8,9,10], 2:[11,12,13,14,15], 3:[16,17,18,19,20]})

#System nodes
model.N = ['N1', 'N2', 'N3']
model.n_name= Param(model.N, within = Integers)

#T = Set()
model.G = ['G1', 'G2', 'G3']
model.LI = ['L1', 'L2', 'L3']

#Scalar Parameters
model.int_rate = 0.05
model.vll = 3000
model.tau_period = 8760

def R_discount_inv_init(model, i):
    return sum(1 / (1 + model.int_rate)**(i - 1) for i in model.E)
model.cum_disc_inv_cost = Param(model.E, initialize = R_discount_inv_init)

def R_discount_op_init(model, i):
    for index in model.E_n:
        return sum(1 / (1 + model.int_rate)**(i - 1) for i in model.E_n[index])
model.cum_disc_op_cost = Param(model.E, initialize = R_discount_op_init)

#Demand Periods
model.t_demand = {'N1': 1.05, 'N2': 2.10, 'N3': 7.35}
model.demand_curtailed = Var(model.E, model.N, within = NonNegativeReals)

#Generation Units  

model.ge_max = {'G1': 2.00, 'G2': 2.00, 'G3': 7.35}

model.ge_marginal_cost = {'G1': 30, 'G2': 35, 'G3': 40}

model.B = {('N1','G1'): 1, ('N1','G2'): 0, ('N1','G3'): 0, ('N2','G1'): 0, ('N2','G2'): 1, ('N2','G3'): 0, ('N3','G1'): 0, ('N3','G2'): 0, ('N3','G3'): 1,}

#Transmission lines
model.li_x = {'L1': 0.2, 'L2': 0.2, 'L3': 0.2}
model.li_max_f = 1.50
model.li_f = {'L1': 1.00, 'L2': 1.00, 'L3': 1.00} 
model.li_sending_bus = {'L1': 'N1', 'L2': 'N1', 'L3': 'N2'}
model.li_receiving_bus = {'L1': 'N2', 'L2': 'N3', 'L3': 'N3'}
model.li_length = {'L1': 100, 'L2': 100, 'L3': 100}

#Expansion Options
model.inv_cost_var = 4000000


nodes = ['N1', 'N2', 'N3']
edges = [['N1', 'N2'], ['N1', 'N3'], ['N2', 'N3']]
I = nx.DiGraph()
I.add_nodes_from(nodes)
I.add_edges_from(edges)

model.I = -nx.incidence_matrix(I, oriented=True) # this returns a scipy sparse matrix

#Variables

#Transmission line power flow limits
def fl_inv(model, i, l):
    return (0, model.li_max_f)
model.li_f_inv = Var(model.E, model.LI, bounds = fl_inv)

#Transmission line investment and operation contraints
model.f = Var(model.LI, model.E, initialize=0)
def fl_rule(model, l, j, i):
    if i:
        return model.f[l,j] >= -(model.li_f_inv[j,l] + model.li_f[l])
    else:
        return model.f[l,j] <= (model.li_f_inv[j,l] + model.li_f[l])
model.bound_f = Constraint(model.LI, model.E, [0,1], rule=fl_rule)

#generation limit
def fg(model, i, g):
    return (0, model.ge_max[g])
model.ge_output = Var(model.G, model.E, initialize = 0, bounds = fg)

#phase angles for the nodes
model.theta = Var(model.E, model.N, within = NonNegativeReals)

def line_equation(model, e, l):
    return model.bound_f[l] == (1/model.li_x(l) for l in model.LI) *(sum(model.theta[n] for n in model.N if model.n_name[n] == model.li_sending_bus[l]) - sum(model.theta[n] for n in model.N if model.n_name[n] == model.li_receiving_bus[l]))
model.line_equation = Constraint(model.LI, model.E, rule = line_equation)


def system_balance(model, e, n):
    return sum(model.b[n, g] * model.ge_output[g] for g in model.G) \
           + sum(model.I[n, l] * model.f[l] for l in model.LI) \
           - sum(model.t_demand[n] - model.demand_curtailed[n]) == 0

model.SystemBalance = Constraint(model.E, model.N, rule=system_balance)

#OBJECTIVE FUNCTION
def objective_mincost(model):
    return sum( model.cum_disc_inv_cost[e] for e in model.E * sum (model.li_f_inv[l] * model.inv_cost_var[l] * model.li_length[l]) + model.cum_disc_op_cost[e] * (model.tau_period * (sum(model.ge_max[g] * (model.ge_marginal_cost[g])) + sum(model.demand_curtailed[n] * model.vll)))) 
model.objective = Objective(rule = objective_mincost, sense = minimize) 

opt = SolverFactory('gurobi')
results = opt.solve(model) # solves and updates instance
model.display()

但收到以下新错误消息:

错误:为索引(&#39; L3&#39;,0)生成约束line_equation的表达式时规则失败:         KeyError:&#34;访问索引组件时出错:索引&#39; L3&#39;对于数组组件&#39; bound_f&#39;&#34;无效 错误:构建组件&line -equation&#39;来自data =无失败:         KeyError:&#34;访问索引组件时出错:索引&#39; L3&#39;对于数组组件&#39; bound_f&#39;&#34;

无效

请问您认为可能出错了什么?

谢谢

1 个答案:

答案 0 :(得分:1)

如错误所示,您没有将有效索引传递给model.li_f_inv规则中的model.f。您的Var model.li_f_inv声明为:

model.li_f_inv = Var(model.E, model.LI, bounds = fl_inv)

model.f的当前规则只是将一个索引传递给model.li_f_inv,这是无效的。这意味着您需要更新model.f的规则以传递正确的索引:

#Transmission line investment and operation contraints
model.f = Var(model.LI, model.E, initialize=0)
def fl_rule(model, l, j, i):
    if i:
        return model.f[l,j] >= -(model.li_f_inv[j,l] + model.li_f[l])
    else:
        return model.f[l,j] <= (model.li_f_inv[j,l] + model.li_f[l])
model.bound_f = Constraint(model.LI, model.E, [0,1], rule=fl_rule)

另请注意,您要在model.f的定义和fl_rule函数隐含的集合之间转置索引集。

编辑:我没注意到在你的原始帖子中,你试图在另一个变量(li_f_inv)的边界中使用变量(f)。这不是一个有效的数学程序(更不用说,不是有效的Pyomo)。您需要将变量边界表示为约束。此外,虽然Pyomo允许您表达范围约束(lb <= body <= ub),但lbub都不可能是可变的。由于这不是这种情况,因此必须单独表达两个边界约束。