inverted indicator constraint in gurobipy - python

I am a beginner in gurobipy. I would like to add an inverted indicator constraint.
Indicator constraint is nothing but depending on a binary variable a constraint does or does not hold.
In gurobipy this is written as
model.addConstr((x == 1) >> (y + z <= 5))
where x is a binary variable, y and z are integer variables. This statement says that if x is True then the constraint y+z <= 5 holds.
But I would like to have an inverted constraint like this.
If y+z <= 5 then x == 1. But gurobi does not allow the lhs part of the statement to be an inequality. It can only be a binary variable equal to a constant (0 or 1).
So the inverted statement throws an error.
model.addConstr((y + z <= 5) >> (x == 1))
Any ideas how to rewrite such a conditional constraint in gurobipy?!

The implication
y+z ≤ 5 ⇒ x = 1
can be rewritten as:
x = 0 ⇒ y+z ≥ 6
This can be directly implemented as an indicator constraint.
This is based on propositional logic. This is called transposition:
A ⇒ B
⇔
not B ⇒ not A
So in theory we have
y+z ≤ 5 ⇒ x = 1
⇔
x = 0 ⇒ y+z > 5
If x and y are integers we can say x = 0 ⇒ y+z ≥ 6 If they are continuous variables you could do: x = 0 ⇒ y+z ≥ 5.0001 (in practice I would do: x = 0 ⇒ y+z ≥ 5 and keep things ambiguous at y+z = 5).
This is kind of a standard trick when using indicator constraints. It seems not everyone is aware of or appreciates this.

The indicator syntax is
binary expression >> linear constraint
So your constraint is invalid. You need a different model that forces x to 1 when y + z ≤ 5. Assuming y, z are non-negative integers, try 6x + y + z ≥ 6.

I think the best way to go with this one is to use the big-M approach
Let reconsider the problem you are trying to model
If y+z <= 5 then x == 1
It is equivalent to if y+z-5 <= 0 then x==1
From here we need a logic that will turn on and off the variable x depending on the condition on the y+z-5
y + z - 5 <= M(1-x)
will do the trick. Note that the x will need to be 1 for the relationship to hold if y+z-5 <= 0 which is what we want. Similarly, x will be turned off (set to 0) if y+z-5 >= 0
I hope this helps

Related

CVXPY set Z to 1 if B is positive

So here's the problem. I have this variable Z which follows the following rule:
I'm guessing Z should be defined as so:
Z = cvxpy.Variable(shape=shape_j_t, name="Z", boolean=True)
So Z is constrained(?) to the balance "B". How do I inform the solver that Z should be 1 if B is positive and 0 otherwise? Especially given that B itself is composed of other cvxpy.Variables.
The general approach, assuming a-priori knowledge about bounds (which are needed in general) on B looks like:
b <= UB * z
b >= LB * z
z in {0, 1}
which describes:
z = 0 <-> b = 0
z = 1 <-> LB <= b <= UB
But this is just something general and these things usually are designed having the full model in mind. Here we don't know what you are doing exactly. Sometimes we don't need equivalence but just implication (e.g. ignore the LB-constraint...)
Maybe it's not trivial to define the notion of positive balance as you only got inequalities and using LB=0 would express non-negativity, but not strict positiveness. For the latter, some a-priori definition of some epsilon (e.g. 0.001) would be needed.

MIP: Adding a Variable to Indicate Equality

I am trying to build a MIP model in the OR Tools Python API. I have two expressions x and y and want to make a variable b that is equal to 1 when x == y and 0 otherwise. What I've tried doing so far is adding the constraint that -M(1 - b) <= x - y <= M(1 - b) for some big value of M, which forces b to be 0 if x != y. Where I am stuck is adding a constraint that forces b to be 1 if x == y. I think I would want something such as x - y >= 1 - b or y - x >= 1 - b, but I don't know how to logically combine constraints like this. Any suggestions on how to do this? Or for some totally different approach?
I think the following expressions would work for you:
b <= x - y + 1
b <= y - x + 1
b >= 1-x + 1-y - 1
b >= y + x - 1
Please note that depending on the nature of the model, the CP-SAT solver could prove competitive. And it provides reification and half-reification natively.
Please have a look at
[Specific answer] https://github.com/google/or-tools/blob/master/ortools/sat/doc/channeling.md
[Introduction] https://developers.google.com/optimization/cp/cp_solver#cp-sat_example
[CP-SAT recipes] https://github.com/google/or-tools/blob/master/ortools/sat/doc/index.md

How to encode array comparison constraints in cvxopt

I want to use the python software cvxopt to solve a small testing problem I have (if the software is able to solve this problem, then my boss will be able to use it on a future project). However, I am having trouble figuring out from the documentation how I can encode some constraints that are not of the form Ax = b or Ax < b.
The problem statement is:
x is a numpy array (1-d). Find an array y such that:
(1) We minimize ||x-y||^2
(2) y is increasing throughout (y[k] <= y[k+1] for all k)
(3) the last element of y = the last element of x
(4) y[0] >= 0
I see how encoding conditions (3) and (4) can be done, but how can I encode condition (2)?
Thank you,
Christian
First a remark: there is no A<b in (continuous) convex-optimization, only A<=b.
Your condition (2) is just a pairwise-constraint on the neighbors like:
y[0] <= y[1]
y[1] <= y[2]
....
To bring it in standard-form:
y[0] <= y[1]
<=>
y[0] - y[1] <= 0
Now you can use the A<=b formulation:
A:
1 -1 0 0 ... meaning: y[0] <= y[1]
0 1 -1 0 ... y[1] <= y[2]
0 0 1 -1 ...
b:
0
0
0
...
If you are not using cvxopt's possibilities to tune KKT-calculations and co. i highly recommend using cvxpy (coming from the same academic institution) which is so much easier to use including a lot of functions like norm(x-y, 2) and more.... It can also use cvxopt as a solver if needed (but also other open-source solvers like ECOS, SCS).

0 is 0 == 0 (#evaluates to True?) [duplicate]

This question already has answers here:
Why does the expression 0 < 0 == 0 return False in Python?
(9 answers)
Closed 6 years ago.
This baffles me. Even without knowing the precedence order, one can check that the two possible ways to gather the expression would give False :
>>> (0 is 0) == 0
False
>>> 0 is (0 == 0)
False
But
>>> 0 is 0 == 0
True
How come?
You are using comparison operator chaining. The expression is interpreted as:
(0 is 0) and (0 == 0)
From the Comparisons documentation:
Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).
0 is 0 is true because Python interns small integers, an implementation detail, so you get (True) and (True) producing True.
When chaining comparison operators in Python, the operators aren't actually applied to the result of the other operators, but are applied to the operands individually. That is x ? y ?? z (where ? and ?? are supposed to stand in for some comparison operators) is neither equivalent to (x ? y) ?? z nor x ? (y ?? z), but rather x ? y and y ?? z.
This is particularly useful for > and co., allowing you to write things like min < x < max and have it do what you want rather than comparing a boolean to a number (which would happen in most other languages).

What is this operator *= -1

I'm going through some Python activities and was given example code with this operator: y *= -1
I had a look through the relevant Python docs, to no avail.
I know y += 1, for example, is short for y = y + 1. So is this y = y * -1 y equals y times -1 maybe?
Closest thing in Python docs I could find is this: x * y: product of x and y
Is this it?
In the vast majority of the cases
y *= <expr>
is the same as
y = y * <expr>
but in the general case, it is interpreted as:
y = imul(y, <expr>)
which is then equivalent to:
y = y.__imul__(<expr>)
if y's type overrides __imul__.
This means that if y's type overrides the inplace multiplication operator, y*=<expr> is performed inplace, while y=y*<expr> is not.
EDIT
It might not be immediately clear why the assignment is needed, i.e. why it is intrepreted as y = imul(y, <expr>), and not just imul(y, <expr>).
The reason is that it makes a lot of sense for the following two scenarios to give the same result:
c = a * b
and
c = a
c *= b
Now, this of course works if a and b are of the same type (e.g. floats, numpy arrays, etc.), but if they aren't, it is possible for the result of the operation to have the type of b, in which case the operation cannot be an inplace operation of a, thus the result needs to be assigned to a, in order to achieve the correct behavior.
For example, this works, thanks to the assignment:
from numpy import arange
a = 2
a *= arange(3)
a
=> array([0, 2, 4])
Whereas if the assignment is dropped, a remains unchanged:
a = 2
imul(a, arange(3))
=> array([0, 2, 4])
a
=> 2
Yes that's correct. It just means multiply the left-hand value by negative the right-hand value. They're both arithmetic operators that differ simply by operation and expression binding, so I believe +/* are parallel everywhere else in overloads.
y = y * -1

Categories

Resources