1

I'm looking to satisfy a set of constraints using PuLP and I'm not exactly sure how to set up the variables to do so.

For example, how would I set up variables for the following constraint:

((x_1 < x_2) AND (x_1 < x_3)) OR ((x_1 > x_2) AND (x_1 > x_3))

A variable x_1 is either less or greater than both, x_2 and x_3.

Any help would be appreciated. Thanks!

1

2 Answers 2

4

The constraint

 ((x1 <= x2) AND (x1 <= x3)) OR ((x1 >= x2) AND (x1 >= x3))

can be formulated with just one extra binary variable:

 x1 <= x2 + delta*M
 x1 <= x3 + delta*M
 x1 >= x2 - (1-delta)*M
 x1 >= x3 - (1-delta)*M
 delta in {0,1}

Most advanced solvers have indicator constraints, allowing us to write this without big-M's:

 delta = 0 -> x1 <= x2
 delta = 0 -> x1 <= x3
 delta = 1 -> x1 >= x2
 delta = 1 -> x1 >= x3
 delta in {0,1}
Sign up to request clarification or add additional context in comments.

1 Comment

I had to read through and implement the other answer first before I could understand this simplified answer. This is clean and helps a lot. Thank you! Even though LP doesn't generally handle inequalities I'm guessing this can be correct with some small constant value c? For example: x1 + c<= x2 + delta M; x1 + c<= x3 + delta M; x1 >= c + x2 - (1-delta)M; x1 >= c + x3 - (1-delta)M; delta in {0,1}
3

First a remark: there is no < operator in Linear-programming. There is only <=. This means: if you want strict inequalities, you will need to add some small constant epsilon!

Now let's assume your task looks like: ((x1<=x2) && (x1<=x3)) || ((x1>x2) && (x1>x3)) (> is the logical negation of <= here which will make this work despite the above).

Let's call (x1>x2) = z1 and (x1>x3) = z2. Then this can be simplified to: (!z1 || z2) && (z1 || !z2) (i used the names A and B in the link).

  • Introduce two new binary-variables z1, z2
  • Use a bigM-based formulation like this page 4 to create an indicator for your relation:
    • x1 <= x2 + M * z1 where M is a big constant; (z1=0) -> x1 <= x2
    • x1 <= x3 + M * z2 where M is another big constant; (z2=0) -> x1 <= x3
  • Now we need the above: (!z1 || z2) && (z1 || !z2)
    • This is basically a !(z1 xor z2), here 1-(z1 xor z2) (look at the truth-table in the "simplified" link above ) and you can follow a very active Stackoverflow-user here to linearize the xor:
      • Introduce another binary-variable z3
      • Add linear constraints
        • z3 <= (1-z1) + (1-z2)
        • z3 >= (1-z1) - (1-z2)
        • z3 >= (1-z2) - (1-z1)
        • z3 <= 2 - (1-z1) - (1-z2)
    • z3 is now z1 xor z2
    • Add constraint: z3 == 0

(There might be some error in the above, but the concept should be ok. With code at hands you should be able to make it work)

1 Comment

This is awesome! So we know that z3 = !(z1 XOR z2). What's the difference (1) introducing z3 and the additional constraints to linearize XOR, and (2) just adding the constraint that z1 == z2?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.