使用以下简化模型:
model = ConcreteModel()
model.WEEKS = Set(initialize = [1,2,3])
model.PRODS = Set(initialize = ['Q24','J24','F24'])
model.MONTHS = Set(initialize = ['J24','F24'])
model.volume = Var(model.WEEKS,model.PRODS, within = NonNegativeIntegers)
model.auction = Var(model.WEEKS,model.PRODS, within = Binary)
model.HedgeMin = Param(model.WEEKS,model.MONTHS, within = NonNegativeIntegers, initialize = {(1,'J24'):45,(1,'F24'):45,
(2,'J24'):90,(2,'F24'):90,
(3,'J24'):135,(3,'F24'):135})
model.HedgeMax = Param(model.WEEKS,model.MONTHS, within = NonNegativeIntegers, initialize = {(1,'J24'):60,(1,'F24'):60,
(2,'J24'):120,(2,'F24'):120,
(3,'J24'):180,(3,'F24'):180})
我正在尝试构建一个约束,将累积边界应用于
auction
中每周和 volume
中每月的 model.WEEKS
* model.MONTHS
的乘积。使用@AirSquid对此post的回复的有用指导,我构建了以下内容:
def hedge_rule(model, i,j):
subset = {x for x in model.WEEKS if x <= i}
return (model.HedgeMin[i,j],
sum(model.auction[i,j] * model.volume[i,j] for i in subset for j in model.MONTHS)
model.HedgeMax[i,j])
model.hedge_const = Constraint(model.WEEKS,model.MONTHS, rule = hedge_rule)
这会产生以下约束:
hedge_const : Size=6, Index=hedge_const_index, Active=True
Key : Lower : Body : Upper : Active
(1, 'F24') : 45.0 :auction[1,J24]*volume[1,J24] + auction[1,F24]*volume[1,F24] : 60.0 :True
(1, 'J24') : 45.0 :auction[1,J24]*volume[1,J24] + auction[1,F24]*volume[1,F24] : 60.0 :True
(2, 'F24') : 90.0 :auction[1,J24]*volume[1,J24] + auction[1,F24]*volume[1,F24] + auction[2,J24]*volume[2,J24] + auction[2,F24]*volume[2,F24] : 120.0 : True
(2, 'J24') : 90.0 :auction[1,J24]*volume[1,J24] + auction[1,F24]*volume[1,F24] + auction[2,J24]*volume[2,J24] + auction[2,F24]*volume[2,F24] : 120.0 : True
(3, 'F24') : 135.0 : auction[1,J24]*volume[1,J24] + auction[1,F24]*volume[1,F24] + auction[2,J24]*volume[2,J24] + auction[2,F24]*volume[2,F24] + auction[3,J24]*volume[3,J24] + auction[3,F24]*volume[3,F24] : 180.0 : True
(3, 'J24') : 135.0 : auction[1,J24]*volume[1,J24] + auction[1,F24]*volume[1,F24] + auction[2,J24]*volume[2,J24] + auction[2,F24]*volume[2,F24] + auction[3,J24]*volume[3,J24] + auction[3,F24]*volume[3,F24] : 180.0 : True
我相信,因为我对集合
auction[i,j]*volume[i,j]
求和 model.MONTHS
,所以 J24
和 F24
都包含在每个集合声明中。因此,例如:(1, 'F24')
=45.0 :auction[1,J24]*volume[1,J24] + auction[1,F24]*volume[1,F24] : 60.0
.
但是,我希望每个键仅包含相关月份。即
(1, 'F24')
=45.0 :auction[1,F24]*volume[1,F24] : 60.0
(1, 'J24')
=45.0 :auction[1,J24]*volume[1,J24] : 60.0
(2, 'F24')
=90.0 :auction[1,F24]*volume[1,F24] + auction[2,F24]*volume[2,F24] : 120.0
(2, 'J24')
=90.0 :auction[1,J24]*volume[1,J24] + auction[2,J24]*volume[2,J24] : 120.0
等等
我的问题是,这是否可以通过
model.hedge_rule
的单一定义来实现?我想该解决方案需要为 MONTHS
中的每个元素创建单独的集合,但我不太确定如何实现它。
一如既往,非常感谢帮助和指导!
尚不完全清楚
MONTHS
是什么,但您绝对应该避免重复那里的另一组值,除非它是某种子集。
我认为您对特定产品与某些周有某种关联,因此以下是我将采取的方法。您有效地制作了一组稀疏的
WEEKS * PRODS
并使用它,这很好。
您可以搜索我的其他答案“索引集”,我已经发布了其他类似的建议。
OBTW:您似乎(无意中?)构建了一个非线性(因为您正在乘以变量)整数程序,这将很难解决。如果可能的话,您应该考虑重新制定 MILP。如果这是可接受的简化,则可以考虑将
volume
设为连续变量而不是整数。也许考虑制定一个大 M 约束而不是乘以变量。
from pyomo.environ import ConcreteModel, Set, Var, Constraint
weekly_products = {
1: ['Q24', 'J24'],
2: ['Q24', 'F24'],
3: ['F24']
}
model = ConcreteModel()
model.WEEKS = Set(initialize = [1,2,3])
model.PRODS = Set(initialize = ['Q24','J24','F24'])
# model.MONTHS = Set(initialize = ['J24','F24']) <-- don't do this. :)
# this is an "indexed set" which is a set of sets, indexed in this case by WEEKS
model.WEEK_PROD = Set(model.WEEKS, initialize=weekly_products)
model.WEEK_PROD_flat = Set(initialize=[(w, p) for w in model.WEEKS for p in model.WEEK_PROD[w]])
# initializing X with this reduced flat set will reduce errors and build a more compact
# model instead of |weeks| * |products| if there are only sparse legal combinations to consider:
model.X = Var(model.WEEK_PROD_flat)
def limit_rule(m, week):
return (5, sum(m.X[week, product] for product in m.WEEK_PROD[week]), 10)
model.C1 = Constraint(model.WEEKS, rule=limit_rule)
model.pprint()
4 Set Declarations
PRODS : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 3 : {'Q24', 'J24', 'F24'}
WEEKS : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 3 : {1, 2, 3}
WEEK_PROD : Size=3, Index=WEEKS, Ordered=Insertion
Key : Dimen : Domain : Size : Members
1 : 1 : Any : 2 : {'Q24', 'J24'}
2 : 1 : Any : 2 : {'Q24', 'F24'}
3 : 1 : Any : 1 : {'F24',}
WEEK_PROD_flat : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 2 : Any : 5 : {(1, 'Q24'), (1, 'J24'), (2, 'Q24'), (2, 'F24'), (3, 'F24')}
1 Var Declarations
X : Size=5, Index=WEEK_PROD_flat
Key : Lower : Value : Upper : Fixed : Stale : Domain
(1, 'J24') : None : None : None : False : True : Reals
(1, 'Q24') : None : None : None : False : True : Reals
(2, 'F24') : None : None : None : False : True : Reals
(2, 'Q24') : None : None : None : False : True : Reals
(3, 'F24') : None : None : None : False : True : Reals
1 Constraint Declarations
C1 : Size=3, Index=WEEKS, Active=True
Key : Lower : Body : Upper : Active
1 : 5.0 : X[1,Q24] + X[1,J24] : 10.0 : True
2 : 5.0 : X[2,Q24] + X[2,F24] : 10.0 : True
3 : 5.0 : X[3,F24] : 10.0 : True
6 Declarations: WEEKS PRODS WEEK_PROD WEEK_PROD_flat X C1