簡體   English   中英

如何根據pyomo中變量負值的數量來約束優化

[英]How to constrain optimization based on number of negative values of variable in pyomo

我正在使用 pyomo model(主要由其他人編寫,由我更新)優化電動汽車充電(即,車輛在給定時間步長輸入或輸出多少功率)。 優化變量 (u) 是功率,目標是在給定每個時間步長的充電成本的情況下最小化總充電成本。

我正在嘗試編寫一個新的優化 function 來限制 model 允許每輛車輸出功率的次數(即設置 u < 0)。 我編寫了一個名為 max_call_rule 的約束,它計算 u < 0 的次數,並將其約束為小於每輛車的給定值 (max_calls)。 (max_calls 是一個字典,其中每輛車的 label 與允許的呼叫次數的 integer 值配對。)

代碼很長,但我把核心部分放在下面:

model.u = Var(model.t, model.v, domain=Integers, doc='Power used')
model.max_calls = Param(model.v, initialize = max_calls)

def max_call_rule(model, v):
      return len([x for x in [model.u[t, v] for t in model.t] if x < 0]) <= model.max_calls[v]
model.max_call_rule = Constraint(model.v, rule=max_call_rule, doc='Max call rule')

這種方法不起作用——當我嘗試運行代碼時出現以下錯誤。

錯誤:為索引為 16 的約束 max_call_rule 生成表達式時規則失敗:ValueError:無法創建包含超過 3 個項的不等式表達式。

錯誤:從 data=None 構建組件“max_call_rule”失敗:ValueError:無法創建包含 3 個以上術語的不等式表達式。

我剛開始使用 pyomo,我懷疑這個錯誤意味着我正在嘗試做一些根本無法與優化程序一起工作的事情。 那么——有沒有更好的方法來限制我的變量 u 可以小於 0 的次數?

如果你想做的是盡量減少車輛輸出功率的次數,你可以引入一個允許/禁止車輛放電的二元變量。 您希望隨着時間和車輛對這個變量進行索引。

請注意,如果 model 的 rest 是 LP(線性,沒有任何 integer 變量),這將把它變成 MIP/MILP。 在求解所需的計算量以及您可以使用的求解器類型方面存在顯着差異。 問題越大,這將產生的差異就越大。 我不確定為什么u當前設置為Integers ,考慮到它代表權力,這似乎很奇怪。

model.allowed_to_discharge = Var(model.t, model.v, within=Boolean)

def enforce_vehicle_discharging_logic_rule(model, t, v):
    """
    When `allowed_to_discharge[t,v]` is 1, 
    this constraint doesn't have any effect.
    When `allowed_to_discharge[t,v]` is 1, u[t,v] >= 0.
    Note that 1e9 is just a "big M", i.e. any big number
    that you're sure exceeds the maximum value of `model.u`.
    """
    return model.u[t,v] >= 0 - model.allowed_to_discharge[t,v] * 1e9

model.enforce_vehicle_discharging_logic = Constraint(
    model.t, model.v, rule=enforce_vehicle_discharging_logic_rule
)

現在您有了二元變量,您可以計算事件,具體來說,您可以為此類事件分配成本並將其添加到您的目標 function(以防萬一,您只能有一個目標 function,所以您只需添加一個“組件”,而不是添加第二個目標函數)。

def objective_rule(model):
    return ( 
        ... # the same objective function as before
        + sum(model.u[t, v] for t in model.t for v in model.v) * model.cost_of_discharge_event
    )
model.objective = Objective(rule=objective_rule)

如果您添加到目標 function 中的是與車輛釋放的總能量相關的成本(而不是事件數),則您需要引入兩個單獨的充電和放電變量 - 均為非負,然后將 .net discharge”(現在你稱之為u )定義為一個Expression ,它是放電和充電之間的區別。

然后,您可以將成本構成添加到目標 function,即所有放電功率的總和,並將其乘以與之相關的成本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM