Pyomo电池优化值错误:未初始化的NumericValue对象没有值

2024-10-02 20:33:38 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用Pyomo和glpk解算器为一个家用太阳能光伏板电池的运行编写优化。当没有多余的太阳能时,优化工作非常完美,但当太阳能太多时,我会得到一个未初始化的错误。 这是我的密码:

import numpy as np
import pandas as pd
from pyomo.environ import *
from pulp import *

power = pd.read_csv('Battery 2 Hourly Power flow for the month with time.csv')
solar_forecast = list(power['Solar_(W)'])
demand = list(power['Household_(W)']*(-1.0))
power['Time'] = np.arange(720)

以下是数据示例:

Hour     Grid_(W)    Household_(W)  Solar_(W)   Storage_(W)  Time
00:00    392.095000  -379.960833    0.0         -12.134167   0
01:00    205.441667  -193.115833    0.0         -12.325000   1
02:00    142.570000  -130.807500    0.0         -11.763333   2
03:00    96.456667   -84.829167     0.0         -11.632500   3
04:00    100.940833  -89.330833     0.0         -11.610833   4
05:00    132.357500  -120.559167    0.0         -11.797500   5
06:00    182.733333  -171.605833    0.000000    -11.126667   6
07:00    96.900833   -127.610000    42.106667   -11.397500  7
08:00    35.052500   -228.003333    304.839167  -111.890000 8
09:00    1.385833    -308.922500    489.586667  -182.050833 9
10:00    2086.825833 -2596.776667   492.475000  17.478333   10
11:00    959.740000  -1696.840833   846.346667  -109.245833 11
12:00    2648.243333 -3006.825000   374.156667  -15.579167  12
13:00    1826.446667 -2055.055833   240.062500  -11.453333  13
14:00    1410.041667 -1551.870000   153.488333  -11.658333  14
15:00    536.535000  -572.946667    48.553333   -12.143333  15
16:00    1079.993333 -1069.868333   0.890000    -11.016667  16
17:00    2269.711667 -2260.661667   0.000000    -9.050833   17

优化

model = ConcreteModel()

# Define model parameters
model.T = Set(initialize=power.Time.tolist(), ordered=True, doc='hour of week')
model.Ein = Param(initialize=2400, doc='Max rate of power flow (W) in')
model.Eout = Param(initialize=-2400, doc='Max rate of power flow (W) out')
model.Smax = Param(initialize=4800, doc='Max storage (Wh)')
model.Smin = Param(initialize=480, doc='Min storage (Wh)')
model.price = Param(initialize = 0.000124, doc = 'Hourly Price of Electricity')

#Decision Variables
model.E = Var(model.T, domain=Reals)  # Battery Power Flow
model.S = Var(model.T, domain=NonNegativeReals) # Battery State of Charge
model.excess_pv = Var(model.T, domain=Reals) # Excess PV Forecasted

## Set Constraints
def storage_state(model,t):
    'Storage changes with flows in/out'
    if t == model.T.first():
        return model.S[t] == (model.Smax + model.Smin)/2
    else:
        return model.S[t] == (model.S[t-1] - model.E[t-1])

model.charge_state = Constraint(model.T, rule = storage_state)

def max_charge(model,t):
    'Max hourly charge of the battery'
    return model.E[t] <= model.Ein

model.pos_charge = Constraint(model.T, rule = max_charge)

def max_discharge(model,t):
    'Max hourly discharge of the battery'
    return model.E[t] >= model.Eout

model.discharge = Constraint(model.T, rule = max_discharge)

def max_stateofcharge(model,t):
    'Max storage in the battery'
    return model.S[t] <= model.Smax

model.max_soc = Constraint(model.T, rule = max_stateofcharge)

def min_stateofcharge(model, t):
    'Min storage in the battery'
    return model.S[t] >= model.Smin

model.min_soc = Constraint(model.T, rule = min_stateofcharge)

def stop_final_discharge(model, t):
    'Prevents battery discharging in final hour'
    return model.E[t] <= model.S[t]

model.final = Constraint(model.T, rule = stop_final_discharge)

def excess_solar(model, t):
    'Calculating the excess solar if the battery is full'
    if model.S[t] == model.Smax:
        return model.excess_pv[t] == demand[t] - solar_forecast[t]
    else: 
        return model.excess_pv[t] == 0

model.solar_constraint = Constraint(model.T, rule = excess_solar)

def demand_cons(model, t):
    'Demand must be postive'
    if model.excess_pv[t] <= 0:
        return demand[t] - solar_forecast[t] - model.E[t] >= 0
    else:
        return demand[t] + model.excess_pv[t] - solar_forecast[t] - model.E[t] >= 0 

model.demand_constraint = Constraint(model.T, rule = demand_cons)

# objective
cost = sum(model.price*(demand[t] - solar_forecast[t] - model.E[t]) for t in model.T)
model.cost = Objective(expr = cost, sense=minimize)

# solve
solvername='glpk'
solverpath_folder='C:\\w64'
solverpath_exe='C:\\w64\\glpsol'
opt = SolverFactory(solvername,executable=solverpath_exe)

results = opt.solve(model)
print('Cost = €', round(value(model.cost()),2))

如果我没有多余的PV,我就不需要变量model.excess_pv = Var(model.T, domain=Reals),需求约束如下所示:

def demand_cons(model, t):
'Demand must be postive'
return demand[t] - solar_forecast[t] - model.E[t] >= 0

model.demand_constraint = Constraint(model.T, rule = demand_cons)

这就是我在尝试使用具有多余pv的数据运行代码时遇到的错误

 ERROR: evaluating object as numeric value: S[0]
        (object: <class 'pyomo.core.base.var._GeneralVarData'>)
    No value for uninitialized NumericValue object S[0]
ERROR: Rule failed when generating expression for constraint solar_constraint
    with index 0: ValueError: No value for uninitialized NumericValue object
    S[0]
ERROR: Constructing component 'solar_constraint' from data=None failed:
    ValueError: No value for uninitialized NumericValue object S[0]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-4-cd4b3e07af68> in <module>
     63         return Constraint.Skip
     64 
---> 65 model.solar_constraint = Constraint(model.T, rule = excess_solar)
     66 
     67 def demand_cons(model, t):

c:\users\stephen\python\lib\site-packages\pyomo\core\base\block.py in __setattr__(self, name, val)
    542                 # Pyomo components are added with the add_component method.
    543                 #
--> 544                 self.add_component(name, val)
    545             else:
    546                 #

c:\users\stephen\python\lib\site-packages\pyomo\core\base\block.py in add_component(self, name, val)
   1087                              _blockName, str(data))
   1088             try:
-> 1089                 val.construct(data)
   1090             except:
   1091                 err = sys.exc_info()[1]

c:\users\stephen\python\lib\site-packages\pyomo\core\base\constraint.py in construct(self, data)
    834                 for index in self.index_set():
    835                     self._setitem_when_not_present(
--> 836                         index, self.rule(block, index)
    837                     )
    838         except Exception:

c:\users\stephen\python\lib\site-packages\pyomo\core\base\util.py in __call__(self, parent, idx)
    302             return self._fcn(parent, *idx)
    303         else:
--> 304             return self._fcn(parent, idx)
    305 
    306 

<ipython-input-4-cd4b3e07af68> in excess_solar(model, t)
     58 def excess_solar(model, t):
     59     'Calculating the excess solar if the battery is full'
---> 60     if model.S[t] == model.Smax:
     61         return model.excess_pv[t] == demand[t] - solar_forecast[t]
     62     else:

pyomo\core\expr\logical_expr.pyx in pyomo.core.expr.logical_expr.EqualityExpression.__nonzero__()

pyomo\core\expr\numeric_expr.pyx in pyomo.core.expr.numeric_expr.ExpressionBase.__call__()

c:\users\stephen\python\lib\site-packages\pyomo\core\expr\visitor.py in evaluate_expression(exp, exception, constant)
   1052         visitor = _EvaluationVisitor()
   1053     try:
-> 1054         return visitor.dfs_postorder_stack(exp)
   1055 
   1056     except ( TemplateExpressionError, ValueError, TypeError,

c:\users\stephen\python\lib\site-packages\pyomo\core\expr\visitor.py in dfs_postorder_stack(self, node)
    582                 _sub = _argList[_idx]
    583                 _idx += 1
--> 584                 flag, value = self.visiting_potential_leaf(_sub)
    585                 if flag:
    586                     _result.append( value )

c:\users\stephen\python\lib\site-packages\pyomo\core\expr\visitor.py in visiting_potential_leaf(self, node)
    960 
    961         if node.is_numeric_type():
--> 962             return True, value(node)
    963         elif node.is_logical_type():
    964             return True, value(node)

pyomo\core\expr\numvalue.pyx in pyomo.core.expr.numvalue.value()

pyomo\core\expr\numvalue.pyx in pyomo.core.expr.numvalue.value()

ValueError: No value for uninitialized NumericValue object S[0]

有人知道我应该如何制定约束以解决此问题吗?我们将非常感谢您的帮助,并提前感谢您的帮助


Tags: theincoreselfmodelreturnvaluedef
1条回答
网友
1楼 · 发布于 2024-10-02 20:33:38

正如@Erwin所提到的,您不能在if语句中使用pyomo变量。因为在执行if语句时,变量的值是未知的。请参阅下面的代码注释,其中列出了有错误的行

def excess_solar(model, t):
    'Calculating the excess solar if the battery is full'
    if model.S[t] == model.Smax:  #here is the line with error
        return model.excess_pv[t] == demand[t] - solar_forecast[t]
    else: 
        return model.excess_pv[t] == 0

model.solar_constraint = Constraint(model.T, rule = excess_solar)

def demand_cons(model, t):
    'Demand must be postive'
    if model.excess_pv[t] <= 0: #error here too
        return demand[t] - solar_forecast[t] - model.E[t] >= 0
    else:
        return demand[t] + model.excess_pv[t] - solar_forecast[t] - model.E[t] >= 0 

model.demand_constraint = Constraint(model.T, rule = demand_cons)

我认为,如果你使用变量来确定约束是如何形成的,那么整个逻辑可能会有问题。我还没有讨论过您的示例,但我认为model.S应该是excess_solar约束的一部分,而不是用作if语句。过多的太阳能不会影响电池的最佳状态吗? 类似的情况也可能发生在demand constraint

对于excess solar约束,可能是这样的:

def excess_solar(model, t):
    'Calculating the excess solar if the battery is full'
     return model.excess_pv[t] + (model.S[t] - model.Smax) + (demand[t] - solar_forecast[t]) <= 0

如果要确保电池电量已满时model.excess_pv为0,可以在变量上设置一个界限,使其大于0。这只会导致约束松弛

相关问题 更多 >