AMPL double conditions in constraints - optimization

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.

Related

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.

How to set up simple two domain constraint on a variable in Pyomo?

I am working on a supply chain optimisation problem using Pyomo and I need to set up a constraint on specific variables in the model. The constraint is that the variable should be within the set (0,1) or (200, to infinity). However, when I try to set up that constraint I am getting a TypeError, here is my code:
def rail_rule(model):
for route in routes:
if "rail" in route[0].lower():
dest = route[0]
dg = route[1]
sg = route[2]
site = route[3]
return model.x[dest, dg, sg, site]>=200 or model.x[dest, dg, sg, site]<=1
model.railconst = Constraint(rule = rail_rule)
I get this error when I run it :
TypeError: Relational expression used in an unexpected Boolean context.
The inequality expression:
200.0 <= x[RAIL - KENSINGTON,8,8,BROCKLESBY]
contains non-constant terms (variables) that were evaluated in an
unexpected Boolean context at
File '<ipython-input-168-901363ebc86f>', line 8:
return model.x[dest, dg, sg, site]>=200 or model.x[dest, dg, sg, site]<=1
Evaluating Pyomo variables in a Boolean context, e.g.
if expression <= 5:
is generally invalid. If you want to obtain the Boolean value of the
expression based on the current variable values, explicitly evaluate the
expression using the value() function:
if value(expression) <= 5:
or
if value(expression <= 5):
So my understanding is that I cant give Pyomo a boolean expression as a constraint, but I am quite new to Pyomo and not too sure if that's what my issue is or if I am doing it correctly.
This constraint could also be implemented in the variable intialisation as boundaries, but I cant find a way to set up two boundaries on a single variable in Pyomo.
Thanks !
There are different ways to handle this:
(1) Use binary variables. Assume you have a good upper bound on x, i.e., x ∈ [0, U]. Then formulate the constraints
x ≤ 1 + (U-1) δ
x ≥ 200 δ
δ ∈ {0,1} (binary variable)
This is the easiest way.
(2) If you don't have a good upper bound on x, you can use a SOS1 set. (SOS1 means Special Ordered Set of type 1). Assume x,s1,s2 ≥ 0.
x ≤ 1 + s1
x ≥ 200 - s2
s1,s2 ∈ SOS1 (s1,s2 form a SOS1 set)
(3) Use disjunctive programming.

Searching for MILP constraint to prevent alternation of integer variable

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)

Calling a separation algorithm in Julia

I'm trying to solve a model using Julia-JuMP. The following is the outline of the model that I created. Here, z[i,j] is a binary variable and d[i,j] is the cost for which z[i,j]=1.
My constraint creates an infinite number of constraint and hence I need to use a separation algorithm to solve it.
First, I solve the model without any constraint, so the answer to all variables z[i,j] and d[i,j] are zero.
Then, I'm including the separation algorithm (which is given inside the if condition). Even though I'm including if z_value == 0, z_values are not passing to it.
Am I missing something in the format of this model?
m = Model(solver=GurobiSolver())
#variable(m, z[N,N], Bin)
#variable(m, d[N,N]>=0)
#objective(m, Min, sum{ d[i,j]*z[i,j], i in N, j in N} )
z_value = getvalue(z)
d_value = getvalue(d)
if z_value == 0
statement
elseif z_value == 1
statement
end
#constraint(m, sum{z[i,j], i in N, j in N}>=2)
solve(m)
println("Final solution: [ $(getvalue(z)), $(getvalue(d)) ]")
You're multiplying z by d which both are variables, hence your model is non-linear,
Are the costs d[i,j] constant or really a variable of the problem ?
If so you need to use a non-linear solver

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.