Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I write an IF condition for my decision variable for Mixed Integer Linear Programming (MILP) using PuLP GLPK on Python?

Tags:

python

glpk

pulp

I am trying to solve an optimization problem using mixed integer linear programming on PuLP with GLPK solver on Python. So far I have been successful solving basic optimization problems with constraints, such as:

prob = LpProblem("MILP", LpMinimize)
x1 = LpVariable("x1",lowBound=0, cat = 'Binary')
x2 = LpVariable("x2", cat = 'Continuous')
prob += 4*x1 + x2, "Objective Function"
prob += x2 - 4*x1 <= 0
prob += x2 - 2*x1 >= 0
status = prob.solve()
LpStatus[status]
value(x1), value(x2), value(prob.objective)

This gives an optimum result where x1 = 1.0, x2 = 3.0 and Objective Function = 7.0

What I'm trying to figure out is how can I solve an optimization problem with an if condition in, for example, the following constraint:

x1 > 0 IF x2 > 2

or something like:

x1 > 0 IF x2 == 3

Bascially, how can I integrate an if conditional statement into the MILP constraints.

like image 996
Muhammad Ali Avatar asked Nov 12 '19 19:11

Muhammad Ali


People also ask

How do I use the PuLP library in Python?

Line 1-2: First import the library pulp as p. Line 4-5: Define the problem by giving a suitable name to your problem, here I have given the name 'Problem'. Also, specify your aim for the objective function of whether to Maximize or Minimize. Line 7-9: Define LpVariable to hold the variables of the objective functions.

Is MIP a linear programming problem?

This can not be formulated as a linear programming problem. We need extra binary variables and end up with a MIP. (in practice I would drop the 0.001 term). Many modern MIP solvers have indicator constraints.

Why should I use pulp with integer variables?

Memory and solution time may rise exponentially as you add more integer variables. Fortunately, PuLP can solve an optimization problem with this kind of restrictions too. The code is almost identical as before, so it is not repeated here.

How can we write a linear program without Multiplying d and E?

If a > b then c = d else c = e d, e are variables. How can we write a linear program without multiplying d and e with binary variables? But we can use binary variables. Show activity on this post. This can not be formulated as a linear programming problem. We need extra binary variables and end up with a MIP.

What is the problem of linear programming language (LP)?

Essentially, in a casual mathematical language, the problem is, Notice that the inequality relations are all linear in nature i.e. the variables f are multiplied by constant coefficients and the resulting terms are bounded by constant limits and that’s what makes this problem solvable by an LP technique.


1 Answers

The search term you are looking for is "indicator variable", or "big-M constraint".

As far as I know PULP doesn't directly support indicator variables, so a big-M constraint is the way to go.

A Simple Example: x1 <= 0 IF x2 > 2

from pulp import *

prob = LpProblem("MILP", LpMaximize)
x1 = LpVariable("x1", lowBound=0, upBound=10, cat = 'Continuous')
x2 = LpVariable("x2", lowBound=0, upBound=10, cat = 'Continuous')

prob += 0.5*x1 + x2, "Objective Function"

b1 = LpVariable("b1", cat='Binary')

M1 = 1e6
prob += b1 >= (x1 - 2)/M1

M2 = 1e3
prob += x2 <= M2*(1 - b1)

status = prob.solve()
print(LpStatus[status])
print(x1.varValue, x2.varValue, b1.varValue, pulp.value(prob.objective))

We want a constraint x1 <= 0 to exist when x2 > 2. When x2 <= 2 no such constraint exists (x1 can be either positive or negative).

First we create a binary variable:

b1 = LpVariable("b1", cat='Binary')

Choose this to represent the condition x2 > 2. The easiest way to achieve this adding a constraint:

M1 = 1e6
prob += b1 >= (x2 - 2)/M1

Here M1 is the big-M value. It needs to be chosen such that for the largest possible value of x2 the expression (x2-2)/M is <=1. It should be as small as possible to avoid numerical/scaling issues. Here a value of 10 would work (x2 has upper bound of 10).

To understand how this contraint works, think of the cases, for x2<=2 the right-hand-side is at-most 0, and so has no effect (lower bound of a binary variable already set to 0). However if x2>2 the right hand side will force b1 to be more than 0 - and as a binary variable it will be forced to be 1.

Finally, we need to build the required constraint:

M2 = 1e3
prob += x1 <= M2*(b1 - 1)

Again to understand how this constraint works, consider the cases, if b1 is true (1) the constraint is active and becomes: x1 <= 0. If b1 is false ('0') the constraint becomes x1 <= M2, provided M2 is large enough this will have no effect (here it could be as small as 10 as x1 already has an upper bound of 10.

In the full code above if you vary the coefficient of x1 in the objective function you should notice that b1 is activated/de-activated and the additional constraint applied to x1 as expected.

like image 82
kabdulla Avatar answered Oct 20 '22 01:10

kabdulla