GLPK MathProg - conditional constraint - linear-programming

I have the following MILP problem, relevant part of code:
param n, integer, >= 0;
set jobs := 1..n;
param P{i in jobs, j in jobs}, binary;
var s{i in jobs}, integer, >=0;
var e{i in jobs}, integer, >=0;
var Cmax, integer, >=0;
minimize total: Cmax;
s.t. crit_3{i in jobs,j in jobs}: s[i] >= e[j];
I want the criterion crit_3 to represent the following equation:
Basically, I want the constraints to only activate for a given combination of i and j when the matrix P[i,j] = 1. How can I achieve this?

Something like s.t. crit_3{i in jobs,j in jobs: P[i,j]=1}: s[i] >= e[j]; should do the job.

Related

Linearization of non-linear program or other solver

I have a linear program that represent a time series of actions (the variables are ordered). The objective function is MIN. For every variable I have the constraint
Xi <= max_value.
I want the constraint to represent the real world more precisely, so I need to change that constrain as follow:
if sum(X1,...,Xi-1) > some_value then Xi <= max_value_1, else Xi <= max_value_2.
Is there a way to make it linear?
If not, is there a ready made solver (like ortools) for this?
Thanks
Provided your variable are integral, or can be scaled up to be integral, you can use CP-SAT for this.
This is explained in the section of the documentation.
if sum(X1,...,Xi-1) > some_value then Xi <= max_value_1, else Xi <= max_value_2.
y(i) = sum(X(1),...,X(i-1))
y(i) <= (1-δ(i))*some_value + δ(i)*M
y(i) >= δ(i)*(some_value+0.00001) - (1-δ(i))*M
X(i) <= max_value_1*δ(i) + max_value_2*(1-δ(i))
δ(i) ∈ {0,1}
Here M is a large enough constant, and y is an extra continuous variable.

Modeling a binary constraint in AMPL - CPLEX

i have the following constraints
i tried to model it in AMPL using the following code:
var y {1..njobs} binary;
subject to overlap
{i in 1..njobs, j in i+1..njobs: i<>j}:
xi[i] + si[i] <= xi[j]+m*y[i];
subject to order
{i in 1..njobs, j in i+1..njobs: i<j}:
y[i] + y[j] = 1;
i'm new to this topic and seem to miss something in the code above. any suggestions?
According to the constraints, y has two indices, i and j, but your code only gives it a single index.
Should be something like:
var y {1..njobs,1..njobs} binary;
subject to overlap
{i in 1..njobs, j in i+1..njobs: i<>j}:
xi[i] + si[i] <= xi[j]+m*y[i,j];
subject to order
{i in 1..njobs, j in i+1..njobs: i<j}:
y[i,j] + y[j,i] = 1;
Currently the behaviour for when i = j is undefined. You may want to either add a constraint that defines the behaviour in that case, or exclude it from the index space when you declare y, e.g.:
var y {i in 1..njobs,j in 1..njobs: i <> j} binary;

Gurobi constraints and objective function

I am very new to Gurobi. I am trying to solve the following ILP
minimize \sum_i c_i y_i + \sum_i \sum_j D_{ij} x_{ij}
Here D is stored as a 2D numpy array.
My constraints are as follows
x_{ij} <= y_i
y_i + \sum_j x_{ij} = 1
Here's the image of the algebra :
My code so far is as follows,
from gurobipy import *
def gurobi(D,c):
n = D.shape[0]
m = Model()
X = m.addVars(n,n,vtype=GRB.BINARY)
y = m.addVars(n,vtype=GRB.BINARY)
m.update()
for j in range(D.shape[0]):
for i in range(D.shape[0]):
m.addConstr(X[i,j] <= y[i])
I am not sure about, how to implement the second constraint and specify the objective function, as objective terms includes a numpy array. Any help ?
Unfortunately I don't have GUROBI because it's really expensive...
but, according to this tutorial the second constraint should be implemented like this :
for i in range(n):
m.addConstr(y[i] + quicksum(X[i,j] for j in range(n), i) == 1)
while the objective function can be defined as :
m.setObjective(quicksum(c[i]*y[i] for i in range(n)) + quicksum(quicksum(D[i,j] * x[i,j]) for i in range(n) for j in range(n)), GRB.MINIMIZE)
N.B: I'm assuming D is a matrix n x n
This is a very simple case. You can write the first constraint this way. It is a good habit to name your constraints.
m.addConstrs((x[i,j] <= y[j] for i in range(D.shape[0]) for j in range(D.shape[0])), name='something')
If you want to add the second constraint, you can write it like this
m.addConstrs((y[i] + x.sum(i, '*') <= 1 for i in range(n)), name='something')
you could write the second equations ass well using quicksum as suggested by digEmAll.
The advantage of using quicksum is that you can add if condition so that you don't um over all values of j. Here is how you could do it
m.addConstrs((y[i] + quicksum(x[i, j] for j in range(n)) <= 1 for i in range(n)), name='something')
if you only needed some values of j to sum over then you could:
m.addConstrs((y[i] + quicksum(x[i, j] for j in range(n) if j condition) <= 1 for i in range(n)), name='something')
I hope this helps

Map upper triangular matrix on vector skipping the diagonal

I have a problem that could be boiled down to finding a way of mapping a triangular matrix to a vector skipping the diagonal.
Basically I need to translate this C++ code using the Gecode libraries
// implied constraints
for (int k=0, i=0; i<n-1; i++)
for (int j=i+1; j<n; j++, k++)
rel(*this, d[k], IRT_GQ, (j-i)*(j-i+1)/2);
Into this MiniZinc (functional) code
constraint
forall ( i in 1..m-1 , j in i+1..m )
( (differences[?]) >= (floor(int2float(( j-i )*( j-i+1 )) / int2float(2)) ));
And I need to figure out the index in differences[?].
MiniZinc is a functional/mathematical language with no proper for loops.
So I have to map those indexes i and j that are touching all and only the cells of an upper triangular matrix, skipping its diagonal, to a k that numbers those cells from 0 to whatever.
If this was a regular triangular matrix (it's not), a solution like this would do
index = x + (y+1)*y/2
The matrix I'm handling is a square n*n matrix with indexes going from 0 to n-1, but it would be nice to provide a more general solution for an n*m matrix.
Here's the full Minizinc code
% modified version of the file found at https://github.com/MiniZinc/minizinc-benchmarks/blob/master/golomb/golomb.mzn
include "alldifferent.mzn";
int: m;
int: n = m*m;
array[1..m] of var 0..n: mark;
array[int] of var 0..n: differences = [mark[j] - mark[i] | i in 1..m, j in i+1..m];
constraint mark[1] = 0;
constraint forall ( i in 1..m-1 ) ( mark[i] < mark[i+1] );
% this version of the constraint works
constraint forall ( i in 1..m-1 , j in i+1..m )
( (mark[j] - mark[i]) >= (floor(int2float(( j-i )*( j-i+1 )) / int2float(2))) );
%this version does not
%constraint forall ( i in 1..m-1, j in i+1..m )
% ( (differences[(i-1) + ((j-2)*(j-1)) div 2]) >= (floor(int2float(( j-i )*( j-i+1 )) / int2float(2))) );
constraint alldifferent(differences);
constraint differences[1] < differences[(m*(m-1)) div 2];
solve :: int_search(mark, input_order, indomain, complete) minimize mark[m];
output ["golomb ", show(mark), "\n"];
Thanks.
Be careful. The formula you found from that link, index = x + (y+1)*y/2, includes the diagonal entries, and is for a lower triangular matrix, which I gather is not what you want. The exact formula you are looking for is actually index = x + ((y-1)y)/2
(see: https://math.stackexchange.com/questions/646117/how-to-find-a-function-mapping-matrix-indices).
Again, watch out, this formula I gave you assumes your indices: x,y, are zero-based. Your MiniZinc code is using indices i,j that start from 1 (1 <= i <= m), 1 <= j <= m)). For indices that start from 1, the formula is T(i,j) = i + ((j-2)(j-1))/2. So your code should look like:
constraint
forall ( i in 1..m-1 , j in i+1..m )
((distances[(i + ((j-2)*(j-1)) div 2]) >= ...
Note that (j-2)(j-1) will always be a multiple of 2, so we can just use integer division with divisor 2 (no need to worry about converting to/from floats).
The above assumes you are using a square m*m matrix.
To generalise to a M*N rectangular matrix, one formula could be:
where 0 <= i < M, 0<= j < N [If you again, need your indices to start from 1, replace i with i-1 and j with j-1 in the above formula]. This touches all of cells of an upper triangular matrix as well as the 'extra block on the side' of the square that occurs when N > M. That is, it touches all cells (i,j) such that i < j for 0 <= i < M, 0 <= j < N.
Full code:
% original: https://github.com/MiniZinc/minizinc-benchmarks/blob/master/golomb/golomb.mzn
include "alldifferent.mzn";
int: m;
int: n = m*m;
array[1..m] of var 0..n: mark;
array[1..(m*(m-1)) div 2] of var 0..n: differences;
constraint mark[1] = 0;
constraint forall ( i in 1..m-1 ) ( mark[i] < mark[i+1] );
constraint alldifferent(differences);
constraint forall (i,j in 1..m where j > i)
(differences[i + ((j-1)*(j-2)) div 2] = mark[j] - mark[i]);
constraint forall (i,j in 1..m where j > i)
(differences[i + ((j-1)*(j-2)) div 2] >= (floor(int2float(( j-i )*( j-i+1 )) / int2float(2))));
constraint differences[1] < differences[(m*(m-1)) div 2];
solve :: int_search(mark, input_order, indomain, complete)
minimize mark[m];
output ["golomb ", show(mark), "\n"];
Lower triangular version (take previous code and swap i and j where necessary):
% original: https://github.com/MiniZinc/minizinc-benchmarks/blob/master/golomb/golomb.mzn
include "alldifferent.mzn";
int: m;
int: n = m*m;
array[1..m] of var 0..n: mark;
array[1..(m*(m-1)) div 2] of var 0..n: differences;
constraint mark[1] = 0;
constraint forall ( i in 1..m-1 ) ( mark[i] < mark[i+1] );
constraint alldifferent(differences);
constraint forall (i,j in 1..m where i > j)
(differences[j + ((i-1)*(i-2)) div 2] = mark[i] - mark[j]);
constraint forall (i,j in 1..m where i > j)
(differences[j + ((i-1)*(i-2)) div 2] >= (floor(int2float(( i-j )*( i-j+1 )) / int2float(2))));
constraint differences[1] < differences[(m*(m-1)) div 2];
solve :: int_search(mark, input_order, indomain, complete)
minimize mark[m];
output ["golomb ", show(mark), "\n"];

The formula of computing the Mel-filterbank coefficient

I am working with MFCC in a project about Speech Recognition. According to the document in this website http://practicalcryptography.com/miscellaneous/machine-learning/guide-mel-frequency-cepstral-coefficients-mfccs/, the formula of computing the Mel-filterbank is as follows:
`H (k, m) = 0 if ( k < f[m-1] )
= (k - f(m-1)) / (f[m] - f[m-1]) if ( f[m-1] <= k <= f[m] )
= (f[m+1] - k) / (f[m+1] - f[m]) if ( f[m] <= k <= f[m+1] )
= 0 if ( k > f[m+1] )`
I think something was wrong here. What is "k"? This website isn't the only one. I have search many document and it's still remained. Besides, if m == 1 , f[0] isn't computed, so the condition ( k < f[m-1] ) is wrong, isn't it? Can anybody help me?
You're defining a function H which takes formal arguments k and m. That's how k is defined. f[0] is perfectly well defined.
Basically, the formula describes this form ___/\___ with the peak at k=f[m].