Simple Arithmetic Constraint on List ECLiPSe clp - list

I want to do a simple constraint over all values of a list,
I want each index of each row of an array to have the following (ic) constraint:
500 #= 2^X1 + 2^X2 + 2^X3 + ... + 2^X9
I try to do the code below. Array is a 9x9 matrix and for every row I want the above constraint to be satisfied. However, this does not seem to work, the program does not find any possible values that satisfy the constraint.
model(Array) :-
Array :: 1..9,
(for(I,1,9), param(Array)
do
X1 is Array[I,1],
X2 is Array(I,2],
X3 is Array[I,3],
X4 is Array[I,4],
X5 is Array[I,5],
X6 is Array[I,6],
X7 is Array[I,7],
X8 is Array[I,8],
X9 is Array[I,9],
500 #= 2^X1 + 2^X2 + 2^X3 + 2^X4 + 2^X5 + 2x^X6 + 2^X7 + 2^X8 + 2^X9
),
term_variables(Array,L),
labeling(L),
printBoard(Array).

This seems to be a bug in the implementation of integer constraints involving exponentiation expressions. Since your variables are all integral anyway, you can replace the #= with $= and it will work (the # constraints are supposed to impose integrality on the variables, while the $ constraints don't do this).
By the way, you could shorten your code this way:
...,
( foreacharg(Row,Array) do
( foreacharg(X,Row), foreach(2^X,Powers) do true ),
500 $= sum(Powers)
),
...

Related

lp_solve return uniform solution

Can lp_solve return a unifrom solution? (Is there a flag or something that will force this kinf of behavior?)
Say that I have this:
max: x + y + z + w;
x + y + z + w <= 100;
Results in:
Actual values of the variables:
x 100
y 0
z 0
w 0
However, I would like to have something like:
Actual values of the variables:
x 25
y 25
z 25
w 25
This is an oversimplyfied example, but the idea is that if the variables have the same factor in the objective function, then the result should idealy be more uniform and not everything for one, and the other what is left.
Is this possible to do? (I've tested other libs and some of them seem to do this by default like the solver on Excel or Gekko for Python).
EDIT:
For instance, Gekko has already this behavior without me especifing anything...
from gekko import GEKKO
m = GEKKO()
x1,x2,x3,x4 = [m.Var() for i in range(4)]
#upper bounds
x1.upper = 100
x2.upper = 100
x3.upper = 100
x4.upper = 100
# Constrain
m.Equation(x1 + x2 + x3 + x4 <= 100)
# Objective
m.Maximize(x1 + x2 + x3 + x4)
m.solve(disp=False)
print(x1.value, x2.value, x3.value, x4.value)
>> [24.999999909] [24.999999909] [24.999999909] [24.999999909]
You would need to explicitly model this (as another objective). A solver does nothing automatically: it just finds a solution that obeys the constraints and optimizes the objective function.
Also, note that many linear solvers will produce so-called basic solutions (corner points). So "all variables in the middle" does not come naturally at all.
The example in Gekko ended on [25,25,25,25] because of how the solver took a step towards the solution from an initial guess of [0,0,0,0] (default in Gekko). The problem is under-specified so there are an infinite number of feasible solutions. Changing the guess values gives a different solution.
from gekko import GEKKO
m = GEKKO()
x1,x2,x3,x4 = m.Array(m.Var,4,lb=0,ub=100)
x1.value=50 # change initial guess
m.Equation(x1 + x2 + x3 + x4 <= 100)
m.Maximize(x1 + x2 + x3 + x4)
m.solve(disp=False)
print(x1.value, x2.value, x3.value, x4.value)
Solution with guess values [50,0,0,0]
[3.1593723566] [32.280209196] [32.280209196] [32.280209196]
Here is one method with equality constraints m.Equations([x1==x2,x1==x3,x1==x4]) to modify the problem to guarantee a unique solution that can be used by any linear programming solver.
from gekko import GEKKO
m = GEKKO()
x1,x2,x3,x4 = m.Array(m.Var,4,lb=0,ub=100)
x1.value=50 # change initial guess
m.Equation(x1 + x2 + x3 + x4 <= 100)
m.Maximize(x1 + x2 + x3 + x4)
m.Equations([x1==x2,x1==x3,x1==x4])
m.solve(disp=False)
print(x1.value, x2.value, x3.value, x4.value)
This gives a solution:
[25.000000002] [25.000000002] [25.000000002] [25.000000002]
QP Solution
Switching to a QP solver allows a slight penalty for deviations but doesn't consume a degree of freedom.
from gekko import GEKKO
m = GEKKO()
x1,x2,x3,x4 = m.Array(m.Var,4,lb=0,ub=100)
x1.value=50 # change initial guess
m.Equation(x1 + x2 + x3 + x4 <= 100)
m.Maximize(x1 + x2 + x3 + x4)
penalty = 1e-5
m.Minimize(penalty*(x1-x2)**2)
m.Minimize(penalty*(x1-x3)**2)
m.Minimize(penalty*(x1-x4)**2)
m.solve(disp=False)
print(x1.value, x2.value, x3.value, x4.value)
Solution with QP penalty
[24.999998377] [25.000000544] [25.000000544] [25.000000544]

Adding constrain to check if there exist a combination of pairs such that it statisfy a ratio?

Lets say I have a set of items in a set x0, ..., x14 each consisting its own values v0, ..., v14
I am trying to at most 8 items such that I get the maximum value.
I am able to get the following maximization problem
max v0*x0 + ... + v14*x14
s.t.
x0 + ... + x14 <= 8
0 <= x0 <= 1
.
.
0 <= x14 <= 1
However, I need to add another constrains, that is for the items chosen, I should be able to pair them such that their ratio is less than 2.
i.e. lets say that the item chosen is x0, x1, x3, x4, x8, x9, x10, x11 with the maximum value they would also have a configuration of pairing such that,
(v0 * x0)/(v1 * x1) <= 2,
(v3 * x3)/(v9 * x9) <= 2,
(v4 * x4)/(v11 * x11)<= 2,
(v8 * x8)/(v10 * x10)<= 2,
Any idea on how to formulate the above set of constrains?
So you can precompute the valid pairs, and their value (the sum of the 2 elements)
So there are at most 14 * 13 / 2 potential ordered pairs, much less valid ones.
You need to select 4 pairs subject to the constraint that once a pair is selected, any pairs involving the same elements cannot be selected. This is a simple at most one constraints on 14 subsets of pairs.
for all item in items:
sum(bool_pair for all bool_pair involving item) <= 1
You can use CP-SAT or the linear solver wrapper to solve this.

Coefficients Reduction in Linear Programming lead to incoherent results

I'm a little bit confused about a result that I got after a coefficients reduction on a constraint of a linear programming problem.
The problem is:
maximize z = x1 + x2 + x3 + x4 + x5 + x6
subject to: 6*x1 + 3*x2 - 5*x3 + 2*x4 + 7*x5 - 4*x6 <= 15
where:
1<=x1<=2 continuos
1<=x2<=2 continuos
1<=x3<=2 continuos
1<=x4<=2 continuos
1<=x5<=2 continuos
1<=x6<=2 continuos
After the coefficients reduction the contraints will be:
subject to: 3*x1 + 3*x2 - 3*x3 + 2*x4 + 3*x5 - 3*x6 <= 8
as stated in the Applied Integer Programming book (Der-San Chen - Robert G.Batson - Yu Dang) at page 96 (there is a little error at page 97. The x1 coefficient is 3 not 1).
After that I've tried to submit the problem to ampl with and without the coefficients reduction. But I got two different results:
[without coefficients reduction]
CPLEX 12.6.1.0: optimal integer solution; objective 11.57142857
display x;
x1 2
x2 2
x3 2
x4 2
x5 1.57
x6 2
[with coefficients reduction]
CPLEX 12.6.1.0: optimal integer solution; objective 11.33333333
display x;
x1 2
x2 2
x3 2
x4 2
x5 1.33
x6 2
why? can the solution be considered correct anyway even if the result for x5 is a little different?
I've used three different solver (minos, gurobi, cplex) but they output the same results on the problem.
If you are referring to the technique in 4.4.3, then it's clear what's the problem here.
Suppose we are given a constraint of the form
a1*y1+ a2*y2 + ... + ai*yi < b
where yi = 0 or 1
You are not allowed to use this technique, as your coefficients are continuous ( in [1,2]) and not binary as needed here!

Can a modulo operation be expressed as a constraint in CPLEX?

I have a situation where I want to associate a fixed cost in my optimization function if a summation is even. That is, if
(x1 + x2 + x3)%2 = 0
Is there a way this can be modeled in CPLEX? All the variables are binary, so really, I just want to express x1 + x2 + x3 = 0 OR x1 + x2 + x3 = 2
Yes, you can do this by introducing a new binary variable. (Note that we are modifying the underlying formulation, not tinkering with CPLEX per se for the modulo.)
Your constraints are
x1 + x2 + x3 = 0 OR 2
Let's introduce a new binary variable Y and rewrite the constraint.
Combined Constraint: x1 + x2 + x3 = 0(1-Y) + 2Y
This works because if Y is 0, one of the choices gets selected, and if Y=1 the other choice gets selected.
When simplified:
x1+x2+x3-2Y = 0
x_i, Y binary
Addendum
In your specific case, the constraint got simplified because one of the rhs terms was 0. Instead, more generally, if you had b1 or b2 as the two rhs choices,
the constraint would become
x1 + x2 + x3 = b1(Y) + b2(1-Y).
If you had inequalities in your constraint (<=), you'd use the Big-M trick, and then introduce a new binary variable, thereby making the model choose one of the constraints.
Hope that helps.

Do loop with 2 variables changing in each step of loop

I'm working on Fortran 90. I need to calculate a recursion like xn = 6*(xn-1) + 7*(xn-2) where (xn-1) is the n-1 step and (xn-2) is the n-2 step. So if we set x1 = 2 and x0 = 1 we get x2 = 6*x1 + 7*x0 and so on for each n.
So I wrote
x0 = 1.
x1 = 2.
do i = 1,20
xn = 6.*x1 + 7.*x0
x1 = xn
x0 = x1
end do
but this code is replacing x0 and x1 for xn and I need to replace x1 for xn and x0 for x1 in each step. I'd tryed many things but I failed. Any idea how to do that?
Though the answer has already been added to this question, let me answer a more general question which is encountered more frequently. Consider the problem where the very next value in the iteration depends on n previous values. In the present case n = 2. The general strategy to solve this problem is to construct another 1-d array of size n and save all the initial values x(1),x(2),..,x(n) in this array. Then in each iteration we use these values to calculate the next value x(n+1) and update the array with x(1) by x(2), x(2) by x(3),...,x(n) by x(n+1) and again use these values to calculate the next value of x and so on. A particular example where such strategy must necessarily be used is the integration of time-delayed systems.
#parthian-shot has given the correct answer in the comment. But that leaves the question marked as unanswered, so I am repeating it here:
You are assigning the value of xn to x1, and then the value of x1 (which is now the same as xn) to x0. You just need to flip it around:
do i = 1,20
xn = 6.*x1 + 7.*x0
x0 = x1
x1 = xn
end do