Реализация ограничения «такое, что» в pyomo

#pyomo

Вопрос:

Я новичок в pyomo и хотел бы реализовать следующее ограничение усиления:

 param Tele=48;  set T=1..Tele; #set of epochs set A ordered; #set of appliances   var active{A,T}, binary;  param d{A}gt;=0;    subject to max_duration{a in A, t in T, ti in T:tgt;ti}: active[a,t]*t-active[a,ti]*tilt;=d[a]*(1- Tele*(active[a,t] active[a,ti]-2));   

Я в замешательстве относительно того, как реализовать условие ограничения «такое, что» t in T, ti in T:tgt;ti . Будет ли это связано с определением нового набора Tcomp в этом направлении (но не уверен, как справиться с этим else делом здесь):

 def tlarge_rule(m, t1, t2):  if t1 gt; t2:  return (t1,t2)  model.Tcomp = Set(model.T, model.T, initialize=tlarge_rule)  

Еще один мой запрос касается наиболее подходящего (с открытым исходным кодом) решателя pyomo для крупномасштабной оптимизации MILP (поскольку я не могу использовать Gurobi в своем проекте). Может GLPK ли или CBC справляться с такой оптимизацией (или есть другой более подходящий решатель с открытым исходным кодом)?

Большое спасибо за вашу помощь.

Ответ №1:

Добро пожаловать на сайт.

Подстановка «такое, что» может быть выполнена довольно легко pyomo . Вы не можете «похоронить» if оператор в своей модели, потому что эти значения неизвестны на момент построения модели…. Не уверен, как AMPL справляется с такими вещами. Хитрость заключается в том, чтобы использовать ядро python для построения произвольно сложных подмножеств и использовать их для построения вашей модели. К счастью, понимание списка/набора python чрезвычайно мощно и делает это довольно простым. Ниже приведен фрагмент, который показывает это. 2 метода… Ну, 2-е-это просто усовершенствование. Обратите внимание, что вам не обязательно включать подмножество в свою модель, но иногда это полезно для согласованности и T/S, а использование ключевого слова «внутри» в методе 2 позволяет проверять ошибки (предотвращение шутовства…). Обратите внимание, что 2 ограничения, построенные в модели, эквивалентны/избыточны… Просто показано для согласованности. [В стороне: active это ключевое слово в pyomo , поэтому я использовал act .]

Редактировать: Здесь, вероятно, есть законный 3-й метод, позволяющий использовать цикл for над нужными индексами (с внутренним циклом для t_prime управления циклом t с отдельными вызовами для создания ограничений для каждой комбинации, но это кажется намного более неуклюжим, чем создание собственного подмножества… вы бы просто воспроизводили заданное понимание. Кажется, уступает тому, что показано ниже…

Что касается решателей, GLPK и CBC они оба бесплатны и великолепны. Установка может быть немного сложной в зависимости от типа машины. На mac с домашним пивом это несложно.

 import pyomo.environ as pyo  tele = 4 appliances = ['fridge', 'tv']   m = pyo.ConcreteModel('subset_maker')  ### SETS  m.T = pyo.Set(initialize=range(1, tele   1)) m.A = pyo.Set(initialize=appliances)  ### VARIABLES m.act = pyo.Var(m.A, m.T, domain=pyo.Binary)  ### Method 1: Make subset on fly... c1_set = {(a, t, t_prime) for a in m.A for t in m.T for t_prime in m.T if t_prime lt; t} def C1(model, a, t, t_prime):  return model.act[a, t] * t_prime lt;= 10 # some nonsense... m.C1 = pyo.Constraint(c1_set, rule=C1)  ### Method 2: Bring that subset into the model (good for T/S and consistency...) m.C1_SET = pyo.Set(within=m.A*m.T*m.T, initialize=c1_set) m.C1_method_2 = pyo.Constraint(m.C1_SET, rule=C1)  m.pprint()  

Доходность:

 7 Set Declarations  A : Size=1, Index=None, Ordered=Insertion  Key : Dimen : Domain : Size : Members  None : 1 : Any : 2 : {'fridge', 'tv'}  C1_SET : Size=1, Index=None, Ordered=Insertion  Key : Dimen : Domain : Size : Members  None : 3 : C1_SET_domain : 12 : {('tv', 4, 1), ('fridge', 4, 3), ('fridge', 3, 2), ('fridge', 4, 2), ('tv', 2, 1), ('tv', 4, 3), ('tv', 3, 2), ('tv', 4, 2), ('fridge', 3, 1), ('fridge', 4, 1), ('fridge', 2, 1), ('tv', 3, 1)}  C1_SET_domain : Size=1, Index=None, Ordered=True  Key : Dimen : Domain : Size : Members  None : 3 : C1_SET_domain_index_0*T : 32 : {('fridge', 1, 1), ('fridge', 1, 2), ('fridge', 1, 3), ('fridge', 1, 4), ('fridge', 2, 1), ('fridge', 2, 2), ('fridge', 2, 3), ('fridge', 2, 4), ('fridge', 3, 1), ('fridge', 3, 2), ('fridge', 3, 3), ('fridge', 3, 4), ('fridge', 4, 1), ('fridge', 4, 2), ('fridge', 4, 3), ('fridge', 4, 4), ('tv', 1, 1), ('tv', 1, 2), ('tv', 1, 3), ('tv', 1, 4), ('tv', 2, 1), ('tv', 2, 2), ('tv', 2, 3), ('tv', 2, 4), ('tv', 3, 1), ('tv', 3, 2), ('tv', 3, 3), ('tv', 3, 4), ('tv', 4, 1), ('tv', 4, 2), ('tv', 4, 3), ('tv', 4, 4)}  C1_SET_domain_index_0 : Size=1, Index=None, Ordered=True  Key : Dimen : Domain : Size : Members  None : 2 : A*T : 8 : {('fridge', 1), ('fridge', 2), ('fridge', 3), ('fridge', 4), ('tv', 1), ('tv', 2), ('tv', 3), ('tv', 4)}  C1_index : Size=1, Index=None, Ordered=False  Key : Dimen : Domain : Size : Members  None : 3 : Any : 12 : {('fridge', 2, 1), ('fridge', 3, 1), ('fridge', 3, 2), ('fridge', 4, 1), ('fridge', 4, 2), ('fridge', 4, 3), ('tv', 2, 1), ('tv', 3, 1), ('tv', 3, 2), ('tv', 4, 1), ('tv', 4, 2), ('tv', 4, 3)}  T : Size=1, Index=None, Ordered=Insertion  Key : Dimen : Domain : Size : Members  None : 1 : Any : 4 : {1, 2, 3, 4}  act_index : Size=1, Index=None, Ordered=True  Key : Dimen : Domain : Size : Members  None : 2 : A*T : 8 : {('fridge', 1), ('fridge', 2), ('fridge', 3), ('fridge', 4), ('tv', 1), ('tv', 2), ('tv', 3), ('tv', 4)}  1 Var Declarations  act : Size=8, Index=act_index  Key : Lower : Value : Upper : Fixed : Stale : Domain  ('fridge', 1) : 0 : None : 1 : False : True : Binary  ('fridge', 2) : 0 : None : 1 : False : True : Binary  ('fridge', 3) : 0 : None : 1 : False : True : Binary  ('fridge', 4) : 0 : None : 1 : False : True : Binary  ('tv', 1) : 0 : None : 1 : False : True : Binary  ('tv', 2) : 0 : None : 1 : False : True : Binary  ('tv', 3) : 0 : None : 1 : False : True : Binary  ('tv', 4) : 0 : None : 1 : False : True : Binary  2 Constraint Declarations  C1 : Size=12, Index=C1_index, Active=True  Key : Lower : Body : Upper : Active  ('fridge', 2, 1) : -Inf : act[fridge,2] : 10.0 : True  ('fridge', 3, 1) : -Inf : act[fridge,3] : 10.0 : True  ('fridge', 3, 2) : -Inf : 2*act[fridge,3] : 10.0 : True  ('fridge', 4, 1) : -Inf : act[fridge,4] : 10.0 : True  ('fridge', 4, 2) : -Inf : 2*act[fridge,4] : 10.0 : True  ('fridge', 4, 3) : -Inf : 3*act[fridge,4] : 10.0 : True  ('tv', 2, 1) : -Inf : act[tv,2] : 10.0 : True  ('tv', 3, 1) : -Inf : act[tv,3] : 10.0 : True  ('tv', 3, 2) : -Inf : 2*act[tv,3] : 10.0 : True  ('tv', 4, 1) : -Inf : act[tv,4] : 10.0 : True  ('tv', 4, 2) : -Inf : 2*act[tv,4] : 10.0 : True  ('tv', 4, 3) : -Inf : 3*act[tv,4] : 10.0 : True  C1_method_2 : Size=12, Index=C1_SET, Active=True  Key : Lower : Body : Upper : Active  ('fridge', 2, 1) : -Inf : act[fridge,2] : 10.0 : True  ('fridge', 3, 1) : -Inf : act[fridge,3] : 10.0 : True  ('fridge', 3, 2) : -Inf : 2*act[fridge,3] : 10.0 : True  ('fridge', 4, 1) : -Inf : act[fridge,4] : 10.0 : True  ('fridge', 4, 2) : -Inf : 2*act[fridge,4] : 10.0 : True  ('fridge', 4, 3) : -Inf : 3*act[fridge,4] : 10.0 : True  ('tv', 2, 1) : -Inf : act[tv,2] : 10.0 : True  ('tv', 3, 1) : -Inf : act[tv,3] : 10.0 : True  ('tv', 3, 2) : -Inf : 2*act[tv,3] : 10.0 : True  ('tv', 4, 1) : -Inf : act[tv,4] : 10.0 : True  ('tv', 4, 2) : -Inf : 2*act[tv,4] : 10.0 : True  ('tv', 4, 3) : -Inf : 3*act[tv,4] : 10.0 : True  10 Declarations: T A act_index act C1_index C1 C1_SET_domain_index_0 C1_SET_domain C1_SET C1_method_2 [Finished in 413ms]  

Комментарии:

1. Это работает! Большое спасибо.