Searching for MILP constraint to prevent alternation of integer variable - optimization

Here is precisely my case:
Let's assume a variable x[t] which is a NonNegativeInteger smaller or equal than 3.
So x[t] can be {0,1,2,3}. It's indexed by a time serie.
I would like to prevent x[t] from alternating.
Means I would like to disallow
x[0] = 0
x[1] = 1
x[2] = 0
but also
x[0] = 1
x[1] = 2
x[2] = 1
and
x[0] = 2
x[1] = 3
x[2] = 2
I am looking for a constraint to disallow this. Three time steps must be involved in that constraint.
I've tried a couple of constraints. I am not sure if this is even possible with a simple constraint.
Maybe I have to add a variable to make this work. Do you have any experience with that kind of problem?
Thank you in advance!

You can ensure increasing or decreasing order with below constraints:
x[t] + M(y-1) <= x[t+1]
x[t] + My >= x[t+1]
y:Binary variable (same y is used at all equations)
M:Big number (bigger than possible the biggest value)

Related

Constraint Programming, how to add x[i] <= (max(x[:i]) + 1)

I'm building a model using or-tools CP tools. The values I want to find are placed in a vector X, and I want to add a constraint that says up to each position of X, the next position cannot have as a value something bigger than the maximum found until X[:i] + 1
It would be something like this:
X[i] <= (max(X[:i]) + 1)
Of course, I cannot add this as a linear constraint with a max(), and creating one extra feature for each value of X upper bound seems excessive and also I would need to minimize each one to make it the "max", otherwise those are just upper bounds that could be huge and not prune my search space (and I already have an objective function).
I already have an objective function.
I know that one trick to add for instance a min-max (min(max(x[i])) problem is to create another variable that is an upper bound of each x and minimize that one. It would be sth like this:
model = cp_model.CpModel()
lb =0; ub=0
model.NewIntVar(z, lb, ub)
for i in domain(X):
model.NewIntVar(X[i], lb, up)
model.Add(X[i] <= z)
model.Minimize(z)
In case you don't want to program this you can use the method in or-tools:
model.AddMaxEquality(z, X)
Now I want to add a constraint that at each value of X sets an upper limit which is the maximum value found until the previous x. It would be something like this:
X[i] <= max(X[:i]) + 1
I was thinking of replicating the previous idea but that would require creating a "z" for each x... not sure if that is the best approach and how much it will reduce my space of solutions. At the same time couldn't find a method in or-tools to do this.
Any suggestions, please?
PS: I already have as an objective function min(z) like it is in the example presented.
Example:
For instance, you can have as a result of the model:
[0, 1, 2, 0, 2, 3]
But you shouldn't have:
[0, 1, 1, 2, 4]
Since the max until X[:3] is 2, so the ub of X[4] should be 2 + 1.
Thanks!
I have no specific hints except:
you need to experiment. One modeling trick may work on one kind of model and not on the other
make sure to use reuse the max variable at index i - 1. With X the array of variables and M the array of max, i.e. M[i] = max(X[0], .., X[i - 1])
M[i] = max(M[i - 1], X[i - 1])
X[i] <= M[i] + 1

How to convert the following if conditions to Linear integer programming constraints?

These are the conditions:
if(x > 0)
{
y >= a;
z <= b;
}
It is quite easy to convert the conditions into Linear Programming constraints if x were binary variable. But I am not finding a way to do this.
You can do this in 2 steps
Step 1: Introduce a binary dummy variable
Since x is continuous, we can introduce a binary 0/1 dummy variable. Let's call it x_positive
if x>0 then we want x_positive =1. We can achieve that via the following constraint, where M is a very large number.
x < x_positive * M
Note that this forces x_positive to become 1, if x is itself positive. If x is negative, x_positive can be anything. (We can force it to be zero by adding it to the objective function with a tiny penalty of the appropriate sign.)
Step 2: Use the dummy variable to implement the next 2 constraints
In English: if x_positive = 1, then y >= a
However, if x_positive = 0, y can be anything (y > -inf)
y > a - M (1 - x_positive)
Similarly,
if x_positive = 1, then z <= b
z <= b + M * (1 - x_positive)
Both the linear constraints above will kick in if x>0 and will be trivially satisfied if x <=0.

Constraint saying all elements of vector has to be >= 0 in scipy optimization

The input vector is x, which contains 5 elements and I want to optimize (minimize) a function with a constraint that all elements of x should be greater than or equal to 0.
ie., x[i] >= 0 for 1 <= i <= 5
In one of the answer I saw this and used in my code, but the answer is returning negative values also
def constraint2(x):
"""constrain all elements of a to be >= 0"""
return x
cons2 = {'type': 'ineq', 'fun': constraint2}
Where am I going wrong? How to enforce the constraint?
all(ele >= 0 for ele in x)
Try this

AMPL double conditions in constraints

I'm working on an optimization project and I'm using AMPL with CPLEX for this.
My problem is somehow simple but I couldn't do it without using some additional "useless" variables.
So assume I have the following code:
set A:= a b c;
set B:= 1 2 3;
var x{A,B} binary;
now I want a constraint to be processed under 2 conditions, for example:
if x[a,1] = 1 and x[a,2] = 1 then (some constraint).
Unfortunately, CPLEX won't let me use the syntax:
s.t const: x[a,1] = 1 and x[a,2] = 1 ==> (some constraint)
it says "logical constraint _slogcon[1] is not an indicator constraint.
Now the way I did it was by introducing a new variable.
var dummyVar{A,A,B,B} binary;
this variable is equal to 1 if both x[a,1] = 1 and x[a,2] = 1.
subject to condition: 2*dummyVar[a,a,1,2] <= x[a,1] + x[a,2]
My problem is with the large model I'm working with. In my case, this dummyVar is not simply a small set, it contains a set of sets. When AMPL is processing the code (translating it to be read by CPLEX), it crashes due to lack of memory.
Is there any simple way to write something like
s.t const: x[a,1] = 1 and x[a,2] = 1 ==> (some constraint)
without introducing any additional variables? Thanks in advance.
To model this effectively, you should consider two things
'some-constraint' is linear or quadratic.
if either x[a,1] or x[a,2] are 1, then the constraint can be violated.
On point 1, your some-constraint is of the form
l <= f(x) <= u
where f(x) is a quadratic of linear function and l and u are constraints. If you let f_max and f_min be the upper and lower bounds of the function f(x) over all feasible values of x then you can write your conditional constraint as
l - (l - f_min) (x[a,1] + x[a,2]) <= f(x) <= u + (f_max - u)(x[a,1] + x[a,2])
If either x[a,1] or x[a,2] are 1 then the constraint becomes
f_min <= f(x) <= f_max
or looser if both x[a,1] and x[a,2] are both 1. If both are 0, then the original constraint is enforced.

AMPL "Locking" a derived variable to a value

I want to investigate whether it is profitable to invest in an additional production facility, and hence I have to account for an capitilization in my objective function.
As such I am wondering if it is possible to, say, if y[t] = 1, then y[g] = 1
for g != t, g > t and where g,t is a subset of the time interval set T.
My first thought was to have:
subject to Constraint1:
y[t] = y[t-1] for all t in T
But that must surely render the solution of y to become the start value in y[0] which is something I obviously do not want.
For clarification. Assume that y[t] is a binary variable whose value is 1 if the investment is undertaken in time t, otherwise 0.
Hope anyone can shed some light into this!
Regards
The constraint y[t] = 1, then y[g] = 1 for g != t, g > t can be represented in AMPL as something like:
s.t. c{t in T: t != t0}: y[t + 1] >= y[t];
where t0 is the first element of set T. Note the use of >= instead of =. If y[t] is 1 for some t, it will drive y for all subsequent values of t to 1.