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

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.

Related

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!

Sum of product: can we vectorize the following in C++? (using Eigen or other libraries)

UPDATE: the (sparse) three-dimensional matrix v in my question below is symmetric: v(i1,i2,i3) = v(j1,j2,j3) where (j1,j2,j3) is any of the 6 permutations of (i1,i2,i3), i.e.
v(i1,i2,i3) = v(i1,i3,i2) = v(i2,i3,i1) = v(i2,i1,i3) = v(i3,i1,i2) = v(i3,i2,i1).
Moreover, v(i1,i2,i3) != 0 only when i1 != i2 && i1 != i3 && i2 != i3.
E.g. v(i,i,j) = 0, v(i, k, k) = 0, v(k, j, k) = 0, etc...
I thought that with this additional information, I could already get a significant speed-up by doing the following:
Remark: v contains duplicate values (a triplet (i,j,k) has 6 permutations, and the values of v for these 6 are the same).
So I defined a more compact matrix uthat contains only non-duplicates of v. The indices of u are (i1,i2,i3) where i1 < i2 < i3. The length of u is equal to the length of v divided by 6.
I computed the sum by iterating over the new value vector and the new index vectors.
With this, I only got a little speed-up. I realized that instead of iterating N times doing a multiplication each time, I iterated N/6 times doing 6 multiplications each time, and that's pretty much the same as before :(
Hope somebody could come up with a better solution.
--- (Original question) ---
In my program I have an expensive operation that is repeated every iteration.
I have three n-dimensional vectors x1, x2 and x3 that are supposed to change every iteration.
I have four N-dimensional vectors I1, I2, I3 and v that are pre-defined and will not change, where:
I1, I2 and I3 contain the indices of respectively x1, x2 and x3 (the elements in I_i are between 0 and n-1)
v is a vector of values.
For example:
We can see v as a (reshaped) sparse three-dimensional matrix, each index k of v corresponds to a triplet (i1,i2,i3) of indices of x1, x2, x3.
I want to compute at each iteration three n-dimensional vectors y1, y2 and y3 defined by:
y1[i1] = sum_{i2,i3} v(i1,i2,i3)*x2(i2)*x3(i3)
y2[i2] = sum_{i1,i3} v(i1,i2,i3)*x1(i1)*x3(i3)
y3[i3] = sum_{i1,i2} v(i1,i2,i3)*x1(i1)*x2(i2)
More precisely what the program does is:
Repeat:
Compute y1 then update x1 = f(y1)
Compute y2 then update x2 = f(y2)
Compute y3 then update x3 = f(y3)
where f is some external function.
I would like to know if there is a C++ library that helps me to do so as fast as possible. Using for loops is just too slow.
Thank you very much for your help!
Update: Looks like it's not easy to get a better solution than the straight-forward for loops. If the vector of indices I1 above is ordered in non-decreasing order, can we compute y1 faster?
For example: I1 = [0 0 0 0 1 1 2 2 2 3 3 3 ... n n].
The simple answer is no, at least, not trivially. Your access pattern (e.g. x2(i2)*x3(i3)) does not (at least at compile time) access contiguous memory, but rather has a layer of indirection. Due to this, SIMD instructions are pretty useless, as they work on chunks of memory. What you may want to consider doing is creating a copy of xM sorted according to iM, removing the layer of indirection. This should reduce the number of cache misses in that xM(iM) generates and since it's accessed N times, that may reduce some of the wall time (assuming N is large).
If maximal accuracy is not critical, you may want to consider using a FFT method instead of the convolution (at least, that's how I understood your question. Feel free to correct me if I'm wrong).
Assuming you are doing a convolution and the vectors (a and b, same size as in your question) are large, the result (c) can be calculated naïvely as
// O(n^2)
for(int i = 0; i < c.size(); i++)
c(i) = a(i) * b.array();
Using the convolution theorem, you could take the Fourier transform of both a and b and perform an element wise multiplication and then take the inverse Fourier transform of the result to get c (will probably differ a little):
// O(n log(n)); note A, B, and C are vectors of complex floating point numbers
fft.fwd(a, A);
fft.fwd(b, B);
C = A.array() * B.array();
fft.inv(C, c);

Simple Arithmetic Constraint on List ECLiPSe clp

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)
),
...

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