Linear expression in Python MIP

189 views
Skip to first unread message

P

unread,
May 29, 2021, 6:46:02 PM5/29/21
to Python-MIP
Hello, I have just come across this package and it looks amazing. I am trying to implement a constraint, but I couldn't find much documentation on use of linear expression and add to expression. If I understand correctly, this packages does not support numpy arrays, so I will just specify pseudocode of the part I find difficult to code in Python MIP. 
Pseudocode for the constraint

Expr = L – c’ *x  # define a expression

Con[0] = Expr[0] / d[0] * d[0]

Con[k] = (Expr[k] *d[k] + Expr[k-1]) / d[k]  for k in 1 to 7 (use a loop to extend that expression)

Constraint => y >= Con[k] for k in 0 to 7

where L, c, d are data , and x and y are optimization variables defined in this package as shown in Python code below.

Can anyone please help me to code this constraint? My attempts at trying to implement this is shown at the bottom.

from mip import Model, xsum, minimize, CONTINUOUS 
p = [919, 199.2, 198.0, 100, 150]
c = [[40, 50, 21.5, 25, 41], [4, 5, 2.5, 5, 4], [4, 5, 2.5, 5, 4], [4, 5, 2.5, 5, 4], [4, 5, 102.5, 5, 4],[4, 5, 0, 105, 104],[4, 105, 0, 0, 0], [104, 0, 0, 0, 0]]
L = [2000, 550, 200, 600, 7000, 5000, 222, 10]
d= [0.99009901, 0.970661749, 0.950686094, 0.927477246, 0.90573081, 0.862296866, 0.829863942, 0.795567442]
n=5
m = Model() 
x = [ m.add_var(var_type=CONTINUOUS, lb=0, ub=1) for i in range(n) ]
y = m.add_var(var_type=CONTINUOUS,ub=0.02)
m.objective = minimize(xsum(p[i]*x[i] for i in range(n)))

# attempt to code the constraint
c= [*zip(*c)]   # take transpose of c
expr = m.add_constr(lin_expr = [[x[i] * j for j in sub] 
       for i, sub in enumerate(c)])
c= [*zip(*c)]
expr = m.add_constr(lin_expr = [[x[i] * j for j in sub] 
       for i, sub in enumerate(c)])
expr_update = [a_i - b_i for a_i, b_i in zip(L,expr)]   # create expression L -c'*x

Luciano Rigolin de Almeida

unread,
May 31, 2021, 7:23:49 AM5/31/21
to P, Python-MIP
Hi.

I didn't quite understand how you want your constraint.

Try saving your solution using:

m.write ('my_model.lp')

And see how your constraints look.

Att,

Luciano

--
You received this message because you are subscribed to the Google Groups "Python-MIP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python-mip+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python-mip/e62a046a-51f9-4d63-8091-f5590d9ee556n%40googlegroups.com.

MrP

unread,
May 31, 2021, 4:43:32 PM5/31/21
to Python-MIP
Thank you  Luciano

The difficulty is that  I don't know how to code this constraint in Python MIP. However, I have created the LP file on another platform to show what I am trying to do in Python MIP. For some reason I am unable to send any attachments, so I have copied over the LP file. I have shown detailed construction of this constraint below.

con[k=1] = (-40 x[1] - 50 x[2] - 21.5 x[3] - 25 x[4] - 41 x[5] + 2000) / 0.99009901  =>  con[1] : 40.399999995959995 x[1] + 50.499999994949995 x[2] + 21.7149999978285 x[3] + 25.249999997474998 x[4] + 41.409999995858996 x[5] + y >= 2019.9999997979999   

con[k=2] = ((-4 x[1] - 5 x[2] - 2.5 x[3] - 5 x[4] - 4 x[5] + 550) * 0.970661749 + con[k=1]) / 0.970661749  =>  con[2] : 45.2089999850195 x[1] + 56.511249981274375 x[2] + 24.64983749194798 x[3] + 30.755624990637187 x[4] + 46.239224984644984 x[5] + y >= 2610.449999250975   
and so on for con3...8  

Please let me know if this constraint is still not clear, and I would be happy to explain .

On the other platform I first create an expression, Expr (=L-c*x) 8-element vector expression
-40 x[1] - 50 x[2] - 21.5 x[3] - 25 x[4] - 41 x[5] + 2000
 -4 x[1] - 5 x[2] - 2.5 x[3] - 5 x[4] - 4 x[5] + 550
 -4 x[1] - 5 x[2] - 2.5 x[3] - 5 x[4] - 4 x[5] + 200
 -4 x[1] - 5 x[2] - 2.5 x[3] - 5 x[4] - 4 x[5] + 600
 -4 x[1] - 5 x[2] - 102.5 x[3] - 5 x[4] - 4 x[5] + 7000
 -4 x[1] - 5 x[2] - 105 x[4] - 104 x[5] + 5000
 -4 x[1] - 105 x[2] + 222
 -104 x[1] + 10
Then I use a loop to add to this expression as shown above.
con[k=1] = Expr[1] /d[1]
con[k=2] = (Expr[2]*d[2] +con[k=1]) / d[2]
Please note that here I am indexing starting at 1 (not 0 as it is required in Python)

LP file
minimize
obj: 919 x_1_ + 199.2 x_2_ + 198 x_3_ + 100 x_4_ + 150 x_5_
subject to
con_1_: 40.399999995959995 x_1_ + 50.499999994949995 x_2_ + 21.7149999978285 x_3_ + 25.249999997474998 x_4_ + 41.409999995858996 x_5_ + 1 y >= 2020
con_2_: 45.2089999850195 x_1_ + 56.511249981274375 x_2_ + 24.64983749194798 x_3_ + 30.755624990637187 x_4_ + 46.239224984644984 x_5_ + 1 y >= 2610.449999250975
con_3_: 50.1589238266485 x_1_ + 62.69865478331062 x_2_ + 27.66777569747433 x_3_ + 36.401856967732186 x_4_ + 51.21079573927163 x_5_ + 1 y >= 2865.3003319831873
con_4_: 55.41408220811489 x_1_ + 69.2676027601436 x_2_ + 30.86012389623626 x_3_ + 42.31276358988972 x_4_ + 56.49227577492505 x_5_ + 1 y >= 3537.0005490679173
con_5_: 60.74456448710186 x_1_ + 75.93070560887732 x_2_ + 134.10106999396433 x_3_ + 48.32868553406061 x_4_ + 61.84864529009453 x_5_ + 1 y >= 10621.923304508104
con_6_: 67.80427178312394 x_1_ + 84.75533972890491 x_2_ + 140.85574879904527 x_3_ + 155.76300427491057 x_4_ + 168.9639652012837 x_5_ + 1 y >= 16156.950207853359
con_7_: 74.45421315582355 x_1_ + 193.06776644477944 x_2_ + 146.36070396645817 x_3_ + 161.85056805974585 x_4_ + 175.56745182694056 x_5_ + 1 y >= 17010.399667990394
con_8_: 181.66389568767698 x_1_ + 201.39081776928722 x_2_ + 152.67023804061103 x_3_ + 168.82786214496693 x_4_ + 183.1360736604905 x_5_ + 1 y >= 17753.709179433714
Bounds
x_1_ <= 1
x_2_ <= 1
x_3_ <= 1
x_4_ <= 1
x_5_ <= 1
y <= 0.02
x_1_ >= 0
x_2_ >= 0
x_3_ >= 0
x_4_ >= 0
x_5_ >= 0
End


Luciano Rigolin de Almeida

unread,
Jun 1, 2021, 5:47:53 AM6/1/21
to MrP, Python-MIP
I understand what you want. You have to use xsum. The constraints you sent in the first email can be replaced by something like:

expr = m.add_constr(lin_expr = [[x[i] * j for j in sub]  for i, sub in enumerate(c)])

to

m.add_constr(xsum(j * x[i] for j in sub for i, sub in enumerate(c)) >= ????)

or:

for i, sub in enumerate(c):
     m.add_constr(xsum(j * x[i] for j in sub) >= ????)


See if you can solve it now and talk again.

Att,

Luciano

--
You received this message because you are subscribed to the Google Groups "Python-MIP" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python-mip+...@googlegroups.com.

MrP

unread,
Jun 1, 2021, 6:23:35 PM6/1/21
to Python-MIP
Thanks again! I get IndexError: list index out of range when I change the constraint to:
for i, sub in enumerate(c):
     m.add_constr(xsum((L[j]- j * x[i])/d[j] for j in sub) <= y)

Even if we sort out this error, I am not sure if this is equivalent to the constraint I have shown in my last email.  I have also given the full code below. Any help will be much appreciated! 

from mip import Model, xsum, minimize, CONTINUOUS 
p = [919, 199.2, 198.0, 100, 150]
c = [[40, 50, 21.5, 25, 41], [4, 5, 2.5, 5, 4], [4, 5, 2.5, 5, 4], [4, 5, 2.5, 5, 4], [4, 5, 102.5, 5, 4],[4, 5, 0, 105, 104],[4, 105, 0, 0, 0], [104, 0, 0, 0, 0]]
L = [5000, 7000, 7000, 6000, 8000, 7000, 20000, 0]
d= [0.99009901, 0.970661749, 0.950686094, 0.927477246, 0.90573081, 0.862296866, 0.829863942, 0.795567442]

n=5
m = Model() 
x = [ m.add_var(var_type=CONTINUOUS, lb=0, ub=1) for i in range(n) ]
y = m.add_var(var_type=CONTINUOUS,ub=0.02)
m.objective = minimize(xsum(p[i]*x[i] for i in range(n)))

c= [*zip(*c)]
for i, sub in enumerate(c):
     m.add_constr(xsum((L[j]- j * x[i])/d[j] for j in sub) <= y)


Luciano Rigolin de Almeida

unread,
Jun 2, 2021, 3:28:27 AM6/2/21
to MrP, Python-MIP
Your problem there is that there is no L[j]. Look:

c= [*zip(*c)]
for i, sub in enumerate(c):
    for j in sub:
        print(L[j])
       #m.add_constr(xsum((L[j]- j * x[i])/d[j] for j in sub) <= y)

You can try to do something like:

for i, sub in enumerate(c):  
    m.add_constr(xsum((L[j]- j * x[i])/d[j] for j in range(len(sub))) <= y)


I didn't try to assemble the constraint you need here, but the way is out there, with xsum.

Message has been deleted

Luciano Rigolin de Almeida

unread,
Jun 4, 2021, 9:01:14 AM6/4/21
to Sheikh Yasir, Python-MIP
Hello.

I understand what you want. I would make a cost matrix of your variable x. And then I would use that matrix to assemble the constraints.

Something like:

from mip import *

p = [919, 199.2, 198.0, 100, 150]
c = [[40, 50, 21.5, 25, 41], [4, 5, 2.5, 5, 4], [4, 5, 2.5, 5, 4], [4, 5, 2.5, 5, 4], [4, 5, 102.5, 5, 4],[4, 5, 0, 105, 104],[4, 105, 0, 0, 0], [104, 0, 0, 0, 0]]
L = [5000, 7000, 7000, 6000, 8000, 7000, 20000, 0]
d= [0.99009901, 0.970661749, 0.950686094, 0.927477246, 0.90573081, 0.862296866, 0.829863942, 0.795567442]

n=5
#m = Model()
m = Model(solver_name=CBC)
x = [ m.add_var(name='x_{}'.format(i+1), var_type=CONTINUOUS, lb=0, ub=1) for i in range(n) ]
y = m.add_var(name='y', var_type=CONTINUOUS,ub=0.02)

m.objective = minimize(xsum(p[i]*x[i] for i in range(n)))

#These values I copied from the example you sent.
cost = [[40.399999995959995 , 50.499999994949995 , 21.7149999978285 , 25.249999997474998 , 41.409999995858996 ,  2020],
[45.2089999850195 , 56.511249981274375 , 24.64983749194798 , 30.755624990637187 , 46.239224984644984 ,  2610.449999250975],
[50.1589238266485 , 62.69865478331062 , 27.66777569747433 , 36.401856967732186 , 51.21079573927163 ,  2865.3003319831873],
[55.41408220811489 , 69.2676027601436 , 30.86012389623626 , 42.31276358988972 , 56.49227577492505 ,  3537.0005490679173],
[60.74456448710186 , 75.93070560887732 , 134.10106999396433 , 48.32868553406061 , 61.84864529009453 ,  10621.923304508104],
[67.80427178312394 , 84.75533972890491 , 140.85574879904527 , 155.76300427491057 , 168.9639652012837 ,  16156.950207853359],
[74.45421315582355 , 193.06776644477944 , 146.36070396645817 , 161.85056805974585 , 175.56745182694056 ,  17010.399667990394],
[181.66389568767698 , 201.39081776928722 , 152.67023804061103 , 168.82786214496693 , 183.1360736604905 ,  17753.709179433714]]

for c in cost:
     m.add_constr(xsum(c[i] * x[i] for i in range(n)) + y >= c[5])

m.write('model1.lp')

What you have to do is create your cost matrix based on the values you need.

Att,

Luciano

Em qua., 2 de jun. de 2021 às 23:05, Sheikh Yasir <syas...@gmail.com> escreveu:
Thanks for you help

for i, sub in enumerate(c):  
    m.add_constr(xsum((L[j]- j * x[i])/d[j] for j in range(len(sub))) <= y)

This does not do what I want from the constraint. My constraint is cumulative in the sense that the expression at the previous period gets added to the following period. 

I will just give up on this.
Reply all
Reply to author
Forward
0 new messages