#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. Это работает! Большое спасибо.