Jupyter Snippet P4M 09
Jupyter Snippet P4M 09
Integer & Linear Programming
An example
Setting up data: cost matrix, demand, supply
F = range(2) # 2 factories
R = range(12) # 12 retailers
C = [[1,2,2,1,3,4,5,7,5,2,3,2],
[4,5,5,4,1,3,1,2,1,2,4,6]]
demand = [9,4,2,6,4,5,7,8,3,6,9,5]
print('Total demand =',sum(demand))
supply = [ 34, 45]
Total demand = 68
Now we can define a linear program $$\min \sum_{i\in F}\sum_{j\in R} c_{ij} x_{ij}$$ Subject To $$\sum_{r\in R} x_{fr} \le s_r\quad\forall f\in F$$ $$\sum_{f\in F} x_{fr} = d_f\quad\forall r\in R$$ $$x \ge 0$$
from mymip.mycplex import Model
lp = Model()
# define double indexed variables and give them a meaningful names
x = [ [lp.variable('x%dto%d'%(i,j)) for j in R]
for i in F ]
lp.min( sum( C[i][j] * x[i][j] for i in F for j in R))
# constraints can be given names too:
lp.SubjectTo({"Supply%d"%f: sum(x[f][r] for r in R) <= supply[f] for f in F})
lp.SubjectTo(("Demand%02d"%r, sum(x[f][r] for f in F) == demand[r] ) for r in R)
for f in F:
for r in R: x[f][r] >= 0 # all variables non-negative
lp.param["SCRIND"]=1 # set parameter to show CPLEX output
lp.optimise()
print("The minimum cost is",lp.objective())
for r in R:
for f in F:
if x[f][r].x > 0: # amount is not zero
print("%.1f from F%d to R%02d"%(x[f][r].x,f,r))
Tried aggregator 1 time.
LP Presolve eliminated 0 rows and 4 columns.
Aggregator did 12 substitutions.
Reduced LP has 2 rows, 8 columns, and 16 nonzeros.
Presolve time = 0.01 sec. (0.02 ticks)
Iteration log . . .
Iteration: 1 Dual objective = 122.000000
The minimum cost is 122.0
9.0 from F0 to R00
4.0 from F0 to R01
2.0 from F0 to R02
6.0 from F0 to R03
4.0 from F1 to R04
5.0 from F1 to R05
7.0 from F1 to R06
8.0 from F1 to R07
3.0 from F1 to R08
6.0 from F1 to R09
8.0 from F0 to R10
1.0 from F1 to R10
5.0 from F0 to R11
To see how the solve sees this problem, try writing it out to file and printing the contents of the file:
lp.write("myfirst.lp")
print(open("myfirst.lp","r").read())
\ENCODING=ISO-8859-1
\Problem name: Model
Minimize
obj: x0to0 + 2 x0to1 + 2 x0to2 + x0to3 + 3 x0to4 + 4 x0to5 + 5 x0to6 + 7 x0to7
+ 5 x0to8 + 2 x0to9 + 3 x0to10 + 2 x0to11 + 4 x1to0 + 5 x1to1 + 5 x1to2
+ 4 x1to3 + x1to4 + 3 x1to5 + x1to6 + 2 x1to7 + x1to8 + 2 x1to9
+ 4 x1to10 + 6 x1to11
Subject To
Supply0: x0to0 + x0to1 + x0to2 + x0to3 + x0to4 + x0to5 + x0to6 + x0to7
+ x0to8 + x0to9 + x0to10 + x0to11 <= 34
Supply1: x1to0 + x1to1 + x1to2 + x1to3 + x1to4 + x1to5 + x1to6 + x1to7
+ x1to8 + x1to9 + x1to10 + x1to11 <= 45
Demand00: x0to0 + x1to0 = 9
Demand01: x0to1 + x1to1 = 4
Demand02: x0to2 + x1to2 = 2
Demand03: x0to3 + x1to3 = 6
Demand04: x0to4 + x1to4 = 4
Demand05: x0to5 + x1to5 = 5
Demand06: x0to6 + x1to6 = 7
Demand07: x0to7 + x1to7 = 8
Demand08: x0to8 + x1to8 = 3
Demand09: x0to9 + x1to9 = 6
Demand10: x0to10 + x1to10 = 9
Demand11: x0to11 + x1to11 = 5
End
Advanced Usage
All of the raw CPLEX callable library functions as per the can be accessed if required using C interface (see IBM’s CPLEX documentation) can be accessed by using the cplex
object.
For example to identify a minimal conflict set leading to infeasiblity of the problem we can use the CPXrefineconflict and write out the conflict set using CPXclpwrite
from mymip.mycplex import cplex
lp.SubjectTo(x[0][0]+x[1][1] >= 50) # make it infeasible
lp.optimise() # error!
cplex.CPXrefineconflict(lp.Env,lp.LP,0,0) # 2 null pointers
cplex.CPXclpwrite(lp.Env,lp.LP,b"conflict.lp") # note binary (ascii) string
print("#"*10,"Conflict LP","#"*10)
print(open("conflict.lp","r").read())
Iteration log . . .
Iteration: 1 Dual objective = 204.000000
########## Conflict LP ##########
\ENCODING=ISO-8859-1
\Problem name: Model_conflict
Minimize
obj:
Subject To
Demand00: x0to0 + x1to0 = 9
Demand01: x0to1 + x1to1 = 4
C15: x0to0 + x1to1 >= 50
\Sum of equality rows in the conflict:
\ sum_eq: x0to0 + x0to1 + x1to0 + x1to1 = 13
Bounds
x0to0 Free
x1to1 Free
End