TypeError: unsupported operand type(s) for *: 'float' and 'NoneType' when building pyomo model

TypeError: unsupported operand type(s) for *: 'float' and 'NoneType' when building pyomo model

我对 pyomo 模型有疑问,这里已经部分回答了这个问题:

但是,首先我并不真正理解这个问题,如果我应用建议的修复程序,我会收到另一个错误。

所以在这里我将向您提供我的一些代码。我有一个有一些限制的光伏模型和一个有一些限制的太阳能热模型,理论上可以争夺相同的可用区域:

#total PV power generation from ground/tilt roof/wall at teach timestep
m.pv_groundGen = Var(year_i, ts_i, within = NonNegativeReals, initialize = 0)
m.pv_roofGen = Var(year_i, ts_i, within = NonNegativeReals, initialize = 0)

#PV covered roof area at different angles
m.pv_roofPanelArea = Var(r_az, r_tilt, within = NonNegativeReals, initialize = 0)
m.pv_groundPanelArea = Var(within = NonNegativeReals, initialize = 0)
if "pv_ground" in ders_df.index.values:
    
    # Relation between installed capacity and panel area        
    def pv_groundPanelAreaRule(m):
        return m.c_c["pv_ground"] == m.pv_groundPanelArea * pv_eff
    m.const_pvGroundArea = Constraint(rule = pv_groundPanelAreaRule) 

    #Some constraints describing pv generation cut for visibility

    #Limits the area available for ground and flat roof pv
    
    if "solar_thermal_ground" not in ders_df.index.values: 
        def panel_groundAreaLimit(m):
            return m.pv_groundPanelArea <= pv_groundareaAvail * pv_gcr_ground
        m.const_panelGroundAreaLimit = Constraint(rule = panel_groundAreaLimit)
    
if "pv_roof" in ders_df.index.values:
    
    # Relation between installed capacity and panel area
    def pv_roofPanelAreaRule(m):
        return m.c_c["pv_roof"] == sum(m.pv_roofPanelArea[az, tilt] for az in r_az \
            for tilt in r_tilt) * pv_eff
    m.const_pvRoofArea = Constraint(rule = pv_roofPanelAreaRule)
    
    #Some constraints describing pv generation cut for visibility
    
    #Limits the area available for ground and flat roof pv
    if "solar_thermal_roof" not in ders_df.index.values:
        def panel_roofAreaLimit(m, az, tilt):
            return m.pv_roofPanelArea[az, tilt] <= pv_roofwallareaAvail.at[az, tilt] * pv_gcr_roof
        m.const_panelRoofAreaLimit = Constraint(r_az, r_tilt, rule = panel_roofAreaLimit)

m.st_groundPanelArea = Var(within = NonNegativeReals, initialize = 0)
m.st_roofPanelArea = Var(r_az, r_tilt, within = NonNegativeReals, initialize = 0)

if "solar_thermal_ground" in ders_df.index.values:
    
    def stUsefulHeatG_rule(m,y,ts):          
        return sum(m.heat["solar_thermal_ground", hCons, y, ts] for hCons in hIn) == \
            (st_eff_0*irrad_tilt_flat[ts] *1000 - st_a1*(st_Tf-temp[ts]) - \
            st_a2*((st_Tf-temp[ts])**2)) * m.st_groundPanelArea
    m.const_stUsefulHeatG = Constraint(year_i,ts_i,rule = stUsefulHeatG_rule)
        
    def stpanelAreaG_rule(m):
        return m.c_c["solar_thermal_ground"] == m.st_groundPanelArea * 0.717 # official conversion factor 
    m.const_stpanelAreaG = Constraint(rule = stpanelAreaG_rule)
    
    if "pv_ground" in ders_df.index.values:
        def panel_groundAreaLimit(m):
            return m.pv_groundPanelArea/pv_gcr_ground + m.st_groundPanelArea*1.7 <= pv_groundareaAvail
        m.const_panelGroundAreaLimit = Constraint(rule = panel_groundAreaLimit)
    else:
        def panel_groundAreaLimit(m):
            return m.st_groundPanelArea*1.7 <= pv_groundareaAvail
        m.const_panelGroundAreaLimit = Constraint(rule = panel_groundAreaLimit)
    
if "solar_thermal_roof" in ders_df.index.values:
    
    def stUsefulHeatR_rule(m,y,ts):          
        return sum(m.heat["solar_thermal_roof", hCons, y, ts] for hCons in hIn) == \
            sum((st_eff_0*irrad_tilt_tilt_df.at[az,tilt][ts] *1000-st_a1*(st_Tf-temp[ts]) - \
            st_a2*((st_Tf-temp[ts])**2)) * m.st_roofPanelArea[az, tilt] for az in r_az for tilt in r_tilt)
    m.const_stUsefulHeatR = Constraint(year_i,ts_i,rule = stUsefulHeatR_rule)
        
    def stpanelAreaR_rule(m):
        return m.c_c["solar_thermal_roof"] == sum(m.st_roofPanelArea[az, tilt] \
                for az in r_az for tilt in r_tilt) * 0.717 # official conversion factor 
    m.const_stpanelAreaR = Constraint(rule = stpanelAreaR_rule)
    
    if "pv_roof" in ders_df.index.values:
        def panel_roofAreaLimit(m, az, tilt):
            return m.pv_roofPanelArea[az, tilt]/pv_gcr_roof + m.st_roofPanelArea[az, tilt] * \
                1.7 <= pv_roofwallareaAvail.at[az, tilt]
        m.const_panelRoofAreaLimit = Constraint(r_az, r_tilt, rule = panel_roofAreaLimit)
    else:
        def panel_roofAreaLimit(m, az, tilt):
            return m.st_roofPanelArea[az, tilt] * 1.7 <= pv_roofwallareaAvail.at[az, tilt]
        m.const_panelRoofAreaLimit = Constraint(r_az, r_tilt, rule = panel_roofAreaLimit)

现在的问题是,如果我构建模型(包括我在此处发布的部分),我会收到此错误:

TypeError:* 不支持的操作数类型:'float' 和 'NoneType'(向我显示此 line st_a2*((st_Tf-temp[ts])**2)) * m.st_groundPanelArea 在处理上述异常的过程中,又出现了一个异常: 类型错误:stUsefulHeatG_rule() 缺少 2 个必需的位置参数:'y' 和 'ts'

现在,如果我接受上面 link 的建议并创建变量 m.st_groundPanelArea,这似乎是 Set [1,] 的麻烦制造者,我会收到一个新错误: AttributeError: 'numpy.ndarray' 对象没有属性 'is_expression_type'

阅读其他线程和错误代码我认为这一切都与 numpy 和 pyomo 的交互问题有关,但我真的不明白为什么我对 m.pv_groundGen 没有同样的问题例子

非常感谢,祝一切顺利:)

您的 post 没有定义所有的变量来真正解决这个问题。如果以下没有回答您的问题,您应该通过删除模型中不必要的部分来编辑您的 post 并包括变量定义和示例数据片段以 重现错误。

就是说,我认为您对同一问题的另一种表现感到厌恶,该问题是关于非索引 pyomo 变量与 numpy 数据类型的交互。我认为 pyomonumpy 都试图覆盖一些基本的代数函数以产生一致的数据类型。 pyomo 正在尝试创建 pyomo.expressions,而 numpy 正在尝试维护 ndarray。 (在关于此问题的 pyomo 错误报告中可能对此问题有更全面的描述,但我认为,这会让您感到厌烦。)

我的建议,尤其是,当你有一个单例 pyomo 变量时,不要 使用 numpy 数组或变量在你的模型中。只需强制将它们转换为基本 python 类型,就可以了。 (如图链接post。)

如果你想坚持现在的方式,你应该把方程从你的约束中拉出来,在定义所有变量并确保它计算后修改它到 pyomo 表达式。当变量是单例时,与 numpy 数组交互时顺序很重要。是的,这很丑陋。所以强烈建议索引 所有 变量或将所有内容转换为基本类型,这很容易。

In [57]: import numpy as np                                                                                            

In [58]: from pyomo.environ import *                                                                                   

In [59]: m = ConcreteModel()                                                                                           

In [60]: s = Set(initialize=[1,2,3])                                                                                   

In [61]: m.x = Var(s)                                                                                                  

In [62]: m.y = Var()   # a non-indexed variable!                                                                       

In [63]: temp = np.array([1.5, 2.5])                                                                                   

In [64]: type(m.x[1] * temp[1])                                                                                        
Out[64]: pyomo.core.expr.numeric_expr.MonomialTermExpression

In [65]: type(temp[1] * m.x[1])                                                                                        
Out[65]: pyomo.core.expr.numeric_expr.MonomialTermExpression

In [66]: #  All is good.... these above evaluated to pyomo expressions                                                 

In [67]: type(m.y * temp[1])                                                                                           
Out[67]: pyomo.core.expr.numeric_expr.MonomialTermExpression

In [68]: type(temp[1] * m.y)                                                                                           
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-68-e1ff132af45b> in <module>
----> 1 type(temp[1] * m.y)

TypeError: unsupported operand type(s) for *: 'float' and 'NoneType'

In [69]: type(temp[1] * Var())                                                                                         
Out[69]: numpy.ndarray

In [70]: # noted that when the variable is not constructed in a model, the behavior evaluates to an ndarray