简体   繁体   中英

Linked variables in optimization problem using pyomo piecewise

I am struggling with "linked" variables in a cost optimization problem. Overall I have four variables: varX1 , varX2 , varY1 and varY2 which are paired in the following manner:

if 0 <= varX1 < 1 then varY1 = 0
if 1 <= varX1 <= 6 then varY1 = 1

and

if 0 <= varX2 < 1 then varY2 = 0 
if 1 <= varX2 <= 5 then varY2 = 1 

I have tried to model the relationship of varX1 and varY1 as well as varX2 and varY2` using pyomos piecewise trying to recreate the example from https://github.com/Pyomo/pyomo/blob/main/examples/pyomo/piecewise/step.py .

Full model code is:

import pyomo.environ as po

costsX1 = 4
costsX2 = 6

costsY1 = 2
costsY2 = 1

a1 = 4
a2 = 3

model = po.ConcreteModel()

model.VarX1 = po.Var(bounds=(0,6))
model.VarX2 = po.Var(bounds=(0,5))

model.VarY1 = po.Var(within=po.Binary)
model.VarY2 = po.Var(within=po.Binary)

model.cons1 = po.Constraint(expr=model.VarX1+model.VarX2==5)
model.cons2 = po.Constraint(expr=a1*model.VarY1+ a2*model.VarY2>=3)

model.obj = po.Objective(expr=costsX1*model.VarX1+costsY1*a1*model.VarY1+costsX2*model.VarX2+costsY2*a2*model.VarY2,
                         sense=po.minimize)

DOMAIN_PTS_X1 = [0, 1, 1, 6]
RANGE_PTS_Y1  = [0, 0, 1, 1]

DOMAIN_PTS_X2 = [0, 1, 1, 5]
RANGE_PTS_Y2  = [0, 0, 1, 1]

model.piece1 = po.Piecewise(model.VarX1, model.VarY1,
                            pw_pts=DOMAIN_PTS_X1,
                            pw_constr_type='LB',
                            f_rule=RANGE_PTS_Y1,
                            pw_repn='INC')

model.piece2 = po.Piecewise(model.VarX2, model.VarY2,
                            pw_pts=DOMAIN_PTS_X2,
                            pw_constr_type='LB',
                            f_rule=RANGE_PTS_Y2,
                            pw_repn='INC')

opt = po.SolverFactory('cbc')
result_obj = opt.solve(model, tee=True)

model.pprint()

I get the following result

4 Var Declarations
    VarX1 : Size=1, Index=None
        Key  : Lower : Value : Upper : Fixed : Stale : Domain
        None :     0 :   5.0 :     6 : False : False :  Reals
    VarX2 : Size=1, Index=None
        Key  : Lower : Value : Upper : Fixed : Stale : Domain
        None :     0 :   0.0 :     5 : False : False :  Reals
    VarY1 : Size=1, Index=None
        Key  : Lower : Value : Upper : Fixed : Stale : Domain
        None :     0 :   0.0 :     1 : False : False : Binary
    VarY2 : Size=1, Index=None
        Key  : Lower : Value : Upper : Fixed : Stale : Domain
        None :     0 :   1.0 :     1 : False : False : Binary

As one can see, there is no pairing of varX1 and varY1 .

Can anyone help me with that?


Solution:

With the help of AirSquid I was able to find a simple solution for my problem. I gave up on using pyomos piecewise function and introduced additional constraints to the model. The following model works as desired

import pyomo.environ as po

costsX1 = 4
costsX2 = 6

costsY1 = 2
costsY2 = 1

a1 = 4
a2 = 3

model = po.ConcreteModel()

model.VarX1 = po.Var(bounds=(0,6))
model.VarX2 = po.Var(bounds=(0,5))

model.VarY1 = po.Var(within=po.Binary)
model.VarY2 = po.Var(within=po.Binary)

model.cons1 = po.Constraint(expr=model.VarX1+model.VarX2==5)
model.cons2 = po.Constraint(expr=a1*model.VarY1+ a2*model.VarY2>=3)

model.con3 = po.Constraint(expr=model.VarY1 <= model.VarX1)
model.con4 = po.Constraint(expr=model.VarY1 >= model.VarX1/6)

model.con5 = po.Constraint(expr=model.VarY2 <= model.VarX2)
model.con6 = po.Constraint(expr=model.VarY2 >= model.VarX2/5)

model.obj = po.Objective(expr=costsX1*model.VarX1+costsY1*a1*model.VarY1+costsX2*model.VarX2+costsY2*a2*model.VarY2,
                         sense=po.minimize)

opt = po.SolverFactory('cbc')
result_obj = opt.solve(model, tee=True)

model.pprint()

Think about this differently. Consider y to be an "indicator" variable. In this case it indicates which range x is in, or more precisely, it indicates the upper and lower bounds on x. So, now the task is to do a little algebra with binary numbers to make that work...

Let's think about the low....

x >= 1 * y

Works for both values of y in {0, 1}

And the high... if y=0 we want 1, if y=1, we want 6... A little algebra:

x <= 1 + 5 * y

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM