Какой тип оптимизации следует настроить, если мне нужно иметь условное ограничение с использованием переменной в Pyomo? - PullRequest
0 голосов
/ 01 февраля 2019

Я создаю объект оптимизации, используя Pyomo в Python 3.7.Я сталкиваюсь с несколько фундаментальной проблемой, когда мне нужно создать ограничение, в котором есть условное выражение для переменной решения.Я видел, что Pyomo не поддерживает использование переменных решения в условных выражениях в объекте ограничения, но я не уверен, какую методологию использовать, чтобы обойти эту проблему.

Короче говоря, основная проблема проистекает из одного ограничения, где ограничение изменяется в зависимости от знака переменной решения.Ограничение устанавливается следующим образом:

def ex_rule(mdl,h,i)
   if mdl.x[h,i]>0:
      return mdl.y[h,i-1]+mdl.x[h,i-1]*mdl.eff=mdl.y[h,i]
   elif mdl.x[h,i]<0:
      return mdl.y[h,i-1]+mdl.x[h,i-1]/mdl.eff=mdl.y[h,i]

mdl.cons1=Constraint(mdl.hours,mdl.resources,rule=ex_rule)

Где mdl.y и mdl.x являются переменными решения, а mdl.eff является параметром.По сути, основное отличие состоит в том, что знак mdl.x должен определять, включено ли умножение или деление в ограничение.Когда я запускаю свой текущий код, я получаю следующую ошибку (как и ожидалось):

Выражение неравенства: 0.0

Я знаю, что на самом деле не могу сделать это так, как я его настроил, но я не уверен, как изменить мою задачу оптимизации, чтобы иметь возможность делатьэтот.Любые советы будут полезны!Спасибо!

--- ОБНОВЛЕНИЕ --- Для тех, кто заинтересован, я думаю, что нашел способ обойти это, используя двоичную переменную индикатора, чтобы повлиять на работу члена эффективности.Теперь код выглядит примерно так:

mdl.bi_ind=Var(mdl.h,mdl.i,within=binary)
def ex_rule(mdl,h,i)
    return (mdl,y[h,i-1]+mdl.x[h,i-1]*(1-(1-mdl.eff)*mdl.bi_ind)*(1/(1-(1- \
             mdl.eff)*mdl.bi_ind))==mdl.x[h,i]

mdl.cons1=Constraint(mdl.hours,mdl.resources,rule=ex_rule)

Теперь я считаю, что мне нужно преобразовать задачу для Pyomo в создание объекта MILP, если я не ошибаюсь ...

1 Ответ

0 голосов
/ 15 февраля 2019

Использование бинарной переменной здесь, безусловно, путь.Чтобы улучшить ясность модели, вы можете разделить переменную x на две отдельные переменные, которые представляют решение в противоположных направлениях.

from pyomo import environ as pe
M = 1e6 # make sure this is large enough
...

mdl.x_charge = pe.Var(m.hours, m.resources, within=pe.NonNegativeReals)
mdl.x_discharge = pe.Var(m.hours, m.resources, within=pe.NonNegativeReals)
mdl.bi_ind=Var(mdl.h,mdl.i,within=pe.Binary)

mdl.only_charge_if = pe.Constraint(m.hours, m.resources,
    rule = lambda h,i: m.x_charge[h,i] <= M * m.bi[h,i], 
    doc = "Only charge if `bi` is 1")

mdl.only_discharge_if = pe.Constraint(m.hours, m.resources,
    rule = lambda h,i: m.x_discharge[h,i] <= M * (1 - m.bi[h,i]), 
    doc = "Only discharge if `bi` is 0")

def ex_rule(mdl,h,i)
    return (mdl,y[h,i-1] + mdl.x_charge[h,i-1] * mdl.eff - mdl.x_discharge[h,i-1] / 
            mdl.eff == mdl.x[h,i])

mdl.cons1=Constraint(mdl.hours,mdl.resources,rule=ex_rule)

Если у вас есть максимальное значение для x_charge и x_discharge (например, что-то, что вы устанавливаете в качестве верхней границы), тогда вы можете использовать это вместо M.

...