GLPK - upper bound constraint does not work properly - linear-programming

I am using GLPK and I am struggling in understanding why an upper bound constraint is not respected.
I have something like this:
param n0;
param n1;
param n2;
param start_0{i in 0..n0};
param end_0{i in 0..n0};
param start_1{i in 0..n1};
param end_1{i in 0..n1};
param start_2{i in 0..n2};
param end_2{i in 0..n2};
var y0 {k in 0..n0} binary;
var y1 {k in 0..n1} binary;
var y2 {k in 0..n2} binary;
[...]
minimize obj: (sum{k in 0..n2}(end_2[k]*y2[k] + 600*y2[k]) - (sum{k in 0..n0} (start_0[k]*y0[k])));
[...]
s.t. c1: (sum{k in 0..n2} (end_2[k]*y2[k] ) - (sum{k in 0..n0} (start_0[k]*y0[k] ))) <= 7000;
s.t. c2_1: sum{k in 0..n0} y0[k] = 1 ;
s.t. c2_2: sum{k in 0..n1} y1[k] = 1 ;
s.t. c2_3: sum{k in 0..n2} y2[k] = 1 ;
[...]
solve;
[...]
printf (sum{k in 0..n2} (end_2[k]*y2[k] ) - (sum{k in 0..n0} (start_0[k]*y0[k] )));
The last printf gives me 7200. But the constraint c1 above should ensure that the difference is not greater than 7000.
The solver output is the following:
GLPK Integer Optimizer, v4.65
7 rows, 353 columns, 1332 non-zeros
353 integer variables, all of which are binary
Preprocessing...
6 rows, 353 columns, 1059 non-zeros
353 integer variables, all of which are binary
Scaling...
A: min|aij| = 1.000e+00 max|aij| = 1.625e+09 ratio = 1.625e+09
GM: min|aij| = 9.998e-01 max|aij| = 1.000e+00 ratio = 1.000e+00
EQ: min|aij| = 9.996e-01 max|aij| = 1.000e+00 ratio = 1.000e+00
2N: min|aij| = 7.561e-01 max|aij| = 1.000e+00 ratio = 1.323e+00
Constructing initial basis...
Size of triangular part is 6
Solving LP relaxation...
GLPK Simplex Optimizer, v4.65
6 rows, 353 columns, 1059 non-zeros
0: obj = -2.232000000e+05 inf = 1.329e-04 (2)
2: obj = 6.210000000e+04 inf = 0.000e+00 (0)
* 5: obj = 7.097321429e+03 inf = 0.000e+00 (0)
OPTIMAL LP SOLUTION FOUND
Integer optimization begins...
Long-step dual simplex will be used
+ 5: mip = not found yet >= -inf (1; 0)
+ 272: >>>>> 1.320000000e+04 >= 1.140000000e+04 13.6% (237; 2)
+ 304: mip = 1.320000000e+04 >= tree is empty 0.0% (0; 477)
INTEGER OPTIMAL SOLUTION FOUND
Time used: 0.0 secs
Memory used: 0.8 Mb (851464 bytes)
Display statement at line 22
[...]
Model has been successfully processed
What I am doing wrong?
Thanks a lot for your help,

Related

National competition in programming math problem

I encountered this problem practicing for an upcoming national competition. The problem goes as follows: You need to create a mixture of two ingredients being in relation to 1:1. You are given N different mixtures, each having its own weight Wi, and its relation in the mixture between the ingredients Mi, Ti (Each value, N, Wi, Mi, and Ti, will be less than 100). We need to find the biggest possible weight of the final mixture, keeping the relation to 1:1. We can take from each given mixture how much we want, we don't necessarily need to take the whole mixture, we can take some portion of it.
So with the given relation 1:1 in the final mixture, we know that we need to have an equal amount of weight from both ingredients possible. After that I need to know if I take K grams of some mixture, how much weight that is for ingredients A and B. So I came up with the following formula:
Let W be the weight in grams, and M and T be the relation between the ingredients respectively. If we want to take K (K <= W) grams we have the following:
Weight of ingredient A = M * (K / (M+T))
Weight of ingredient B = T * (K / (M+T))
#include <bits/stdc++.h>
using namespace std;
class state{
public:
int weight;
int A;
int B;
};
int n;
vector<state> arr;
double ans= 0;
void f(double weight_A, double weight_B, int idx){
if(weight_A == weight_B)
ans = max(ans, weight_A + weight_B);
if(idx >= n)
return;
int weight = arr[idx].weight, relA = arr[idx].A, relB = arr[idx].B;
for(int K = 0; K <= weight; K++){
f(weight_A + relA * (K * 1.0/(relA + relB)), weight_B + relB * (K * 1.0/(relA + relB)), idx+1);
}
}
int main(){
cin>>n;
for(int i = 0; i < n; i++){
state in;
cin>>in.weight>>in.A>>in.B;
arr.push_back(in);
}
f(0.0, 0.0, 0);
cout<<fixed<<setprecision(8);
cout<<ans<<endl;
}
The problem I encountered was that we don't necessarily need to take integer weights, some times to achieve the maximum possible weight of the final product we need to take decimal weights. Let's take a look at this example:
5
14 3 2
4 1 3
4 2 2
6 6 1
10 4 3
We have N = 5, and in each row are given 3 integers, Wi, Mi, and Ti. The weight of the ith mixture and its relation. My solution for this example gives 20.0000, and the correct solution for the above example is 20.85714286. Looking back my initial idea won't work because of the decimal numbers. I suppose there is some formula but I can't figure it out, can anyone help?
This is a Linear Programming problem, so you can solve it by constructing the problem in standard form, and then solve it with an optimization algorithm, like the simplex algorithm.
The objective is to maximize the quantity of medicine (from the original problem), that is the sum of quantities taken from each jar (I'll call the quantities x1, x2, ...).
The quantities are bounded to be lower than the weight Wi available in each jar.
The constraint is that the total amount of honey (first ingredient) is equal to the total amount of tahini (second ingredient). This would mean that:
sum(Mi/(Mi+Ti)*xi) = sum(Ti/(Mi+Ti)*xi)
You can take the second summation to the LHS and get:
sum((Mi-Ti)/(Mi+Ti)*xi) = 0
In order to get integer multipliers just multiply everything by the least common multiple of the denominators lcm(Mi+ti) and then divide by the gcd of the coefficients.
Using your example, the constraint would be:
(3-2)/(3+2) x1 + (1-3)/(1+3) x2 + (2-2)/(2+2) x3 + (6-1)/(6+1) x4 + (4-3)/(4+3) x5 = 0
that is
1/5 x1 -2/4 x2 + 0/4 x3 + 5/7 x4 + 1/7 x5 = 0
Multiply by the lcm(5,4,4,7,7)=140:
28 x1 -70 x2 + 0 x3 + 100 x4 + 20 x5 = 0
divide by 2:
14 x1 -35 x2 +0 x3 + 50 x4 + 10 x5 = 0
We are ready to solve the problem. Let's write it in CPLEX format:
maximize
quantity: x1 + x2 + x3 + x4 + x5
subject to
mix: 14 x1 -35 x2 +0 x3 + 50 x4 + 10 x5 = 0
bounds
x1 <= 14
x2 <= 4
x3 <= 4
x4 <= 6
x5 <= 10
end
Feed it to GLPK:
#include <stdio.h>
#include <stdlib.h>
#include <glpk.h>
int main(void)
{
glp_prob *P;
P = glp_create_prob();
glp_read_lp(P, NULL, "problem.cplex");
glp_adv_basis(P, 0);
glp_simplex(P, NULL);
glp_print_sol(P, "output.txt");
glp_delete_prob(P);
return 0;
}
And the output is:
Problem:
Rows: 1
Columns: 5
Non-zeros: 4
Status: OPTIMAL
Objective: quantity = 20.85714286 (MAXimum)
No. Row name St Activity Lower bound Upper bound Marginal
------ ------------ -- ------------- ------------- ------------- -------------
1 mix NS 0 0 = 0.0714286
No. Column name St Activity Lower bound Upper bound Marginal
------ ------------ -- ------------- ------------- ------------- -------------
1 x1 B 2.85714 0 14
2 x2 NU 4 0 4 3.5
3 x3 NU 4 0 4 1
4 x4 NL 0 0 6 -2.57143
5 x5 NU 10 0 10 0.285714
Karush-Kuhn-Tucker optimality conditions:
KKT.PE: max.abs.err = 0.00e+00 on row 0
max.rel.err = 0.00e+00 on row 0
High quality
KKT.PB: max.abs.err = 0.00e+00 on row 0
max.rel.err = 0.00e+00 on row 0
High quality
KKT.DE: max.abs.err = 0.00e+00 on column 0
max.rel.err = 0.00e+00 on column 0
High quality
KKT.DB: max.abs.err = 0.00e+00 on row 0
max.rel.err = 0.00e+00 on row 0
High quality
End of output
Of course given your input you should construct the problem in memory and feed it to the simplex algorithm without going through a file. Additionally, there's no need to get integer coefficients, it was just to allow a nicer problem formulation.

Optimize with indexing in linear programming

I have encountered several optimization problems that involve identifying one or more indices in a vector that maximizes or minimizes a cost. Is there a way to identify such indices in linear programming? I'm open to solutions in mathprog, CVXR, CVXPY, or any other API.
For example, identifying an index is needed for change point problems (find the index at which the function changes), putting distance constraints on the traveling salesman problem (visit city X before cumulative distance Y).
As a simple example, suppose we want to identify the location in a vector where the sum on either side is the most equal (their difference is smallest). In this example, the solution is index 5:
x = c(1, 3, 6, 4, 7, 9, 6, 2, 3)
Attempt 1
Using CVXR, I tried declaring split_index and using that as an index (e.g., x[1:split]):
library(CVXR)
split_index = Variable(1, integer = TRUE)
objective = Minimize(abs(sum(x[1:split_index]) - sum(x[(split_index+1):length(x)])))
result = solve(objective)
It errs 1:split_index with NA/NaN argument.
Attempt 2
Declare an explicit index-vector (indices) and do an elementwise logical test whether split_index <= indices. Then element-wise-multiply that binary vector with x to select one or the other side of the split:
indices = seq_along(x)
split_index = Variable(1, integer = TRUE)
is_first = split_index <= indices
objective = Minimize(abs(sum(x * is_first) - sum(x * !is_first)))
result = solve(objective)
It errs in x * is_first with non-numeric argument to binary operator. I suspect that this error arises because is_first is now an IneqConstraint object.
Symbols in red are decision variables and symbols in blue are constants.
R code:
> library(Rglpk)
> library(CVXR)
>
> x <- c(1, 3, 6, 4, 7, 9, 6, 2, 3)
> n <- length(x)
> delta <- Variable(n, boolean=T)
> y <- Variable(2)
> order <- list()
> for (i in 2:n) {
+ order[[as.character(i)]] <- delta[i-1] <= delta[i]
+ }
>
>
> problem <- Problem(Minimize(abs(y[1]-y[2])),
+ c(order,
+ y[1] == t(1-delta) %*% x,
+ y[2] == t(delta) %*%x))
> result <- solve(problem,solver = "GLPK", verbose=T)
GLPK Simplex Optimizer, v4.47
30 rows, 12 columns, 60 non-zeros
0: obj = 0.000000000e+000 infeas = 4.100e+001 (2)
* 7: obj = 0.000000000e+000 infeas = 0.000e+000 (0)
* 8: obj = 0.000000000e+000 infeas = 0.000e+000 (0)
OPTIMAL SOLUTION FOUND
GLPK Integer Optimizer, v4.47
30 rows, 12 columns, 60 non-zeros
9 integer variables, none of which are binary
Integer optimization begins...
+ 8: mip = not found yet >= -inf (1; 0)
+ 9: >>>>> 1.000000000e+000 >= 0.000000000e+000 100.0% (2; 0)
+ 9: mip = 1.000000000e+000 >= tree is empty 0.0% (0; 3)
INTEGER OPTIMAL SOLUTION FOUND
> result$getValue(delta)
[,1]
[1,] 0
[2,] 0
[3,] 0
[4,] 0
[5,] 0
[6,] 1
[7,] 1
[8,] 1
[9,] 1
> result$getValue(y)
[,1]
[1,] 21
[2,] 20
>
The absolute value is automatically linearized by CVXR.
At the end of the day, if you are selecting things by index, I think you need to work this with a set of corresponding binary selection variables. The fact that you are selecting "things in a row" as in your example problem is just something that needs to be handled with constraints on the binary variables.
To solve the problem you posed, I made a set of binary selection variables, call it s[i] where i = {0, 1, 2, ..., len(x)} and then constrained:
s[i] <= s[i-1] for i = {1, 2, ..., len(x)}
which enforces the "continuity" from the start up to the first non-selection and then thereafter.
My solution is in Python. LMK if you'd like me to post. The concept above, I think, is what you are asking about.

Python pyomo : Maximizing the sum of maximum in the objective function

This problem is an extension of an earlier question I aksed
Python pyomo : how and where to store sumproduct involving decision variables (1d array) and fixed data (matrix) (i have solved this piece).
Brief background : I am trying to solve an optimization problem where I need to select the best store from where an order can be fulfilled. For this illustration I have 2 orders (O1, O2) and 3 stores (str_1, str_2, str_3). While selecting the best store to fulfill an order, there are 4 factors : A, B, C and D. So for fulfilling order 1, each store will have 4 set of scores corresponding to each factor. Score will be between 0 and 1.
I need to determine the optimal weights for 4 factors (wtA, wtB, wtC, wtD - decision variables) such that sumproduct of weights and the score is maximum. (Weights should be between 0 and 100). For instance, say if we check if store 1 can service order 1, then sumproduct = wtA * score_O1_str_1_A + wtB * score_O1_str_1_B + wtC * score_O1_str_1_C + wtD * score_O1_str_1_D
I am holding the sumproduct in a dictionary now. The idea is to pick for each order the store with maximum score, and to maximize the sum of scores across all orders. E.g.
O1 -> str_1 = 88 ; O1 -> str_2 = 90 ; O1 -> str_3 = 86 ; O2 -> str_1 = 82 ; O2 -> str_2 = 92 ; O2 -> str_3 = 85 ;
Above are the weighted scores - sumproduct we get by multiplying weights (decision variables) and the scores (given to us). From above I would want to pick weights such that the sum of maximum score from fulfilling each order is maximized. So in this case O1 -> str_2 (90) and O2 -> str_2 (92). Sum of maximums = 90 + 92 = 182. I need to maximize this. I have written the code but doesn't seem to give me the right answer. Your help is much appreciated!
Please see the below code to see what I have done and where I am stuck:
from pyomo.environ import *
model = ConcreteModel(name="(weights)")
# scores for factors A, B, C and D for each order and store combination
order_str_scores = {
('O1', 'str_1') : [0.88, 0.85, 0.88, 0.93], # if order 1 is fulfilled from store 2 then these are the scores
('O1', 'str_2'): [0.93, 0.91, 0.95, 0.86],
('O1', 'str_3') : [0.83, 0.83, 0.87, 0.9],
('O2', 'str_1') : [0.85, 0.86, 0.84, 0.98],
('O2', 'str_2') : [0.87, 0.8, 0.85, 0.87],
('O2', 'str_3') : [0.91, 0.87, 0.95, 0.83],
}
model.orders = list(set([i[0] for i in order_str_scores.keys()]))
model.stores = list(set([i[1] for i in order_str_scores.keys()]))
# 4 factors (A, B, C & D) whose scores are mentioned in 'order_str_wts' dictionary
model.factors = ['A', 'B', 'C','D']
# below 4 decision variables (one for each factor) will hold the optimal number between 0 - 100
def dv_bounds(m, i):
return (0, 100)
model.x1 = Var(model.factors, within=NonNegativeReals, bounds=dv_bounds)
#Sum of these 4 decision variables should be equal to 100
def sum_wts(m):
return sum(m.x1[i] for i in model.factors) == 100
model.sum_wts = Constraint(rule=sum_wts)
# here I hold the sumproduct of scores and corresponding weights for each factor
D = {}
model.k = [('O1', 'str_1'), ('O1', 'str_2'), ('O1', 'str_3'), ('O2', 'str_1'), ('O2', 'str_2'), ('O2', 'str_3')]
for i in model.k:
D[i] = sum(model.x1[n] * order_str_scores[i][q] for n,q in zip(model.factors,range(4)))
# BELOW I GET STUCK. IDEA IS TO SELECT FOR EACH ORDER THE STORE WHICH HAS THE SUM OF WEIGHTED SCORES AND THE SUM OF SCORES ACROSS ORDERS SHOULD BE MAXIMUM
# create decision variable for each order, which will hold the maximum weighted score
model.x3 = Var(model.orders, within=NonNegativeReals, bounds=dv_bounds)
# add constraints
model.cons = ConstraintList()
for i in model.k:
model.cons.add(model.x3[i[0]] >= D[i])
model.obj = Objective(rule=obj_rule, sense=maximize)
opt = SolverFactory('glpk')
result_obj = opt.solve(model, tee=True)
model.display()
What solver does is - and it makes sense is to pick a value of model.x3['O1'] and model.x3['O2'] = 100. This is because the upper bound I have set is 100 for each and since it needs to maximize the sum it picks 100 for each.
However, what I want is model.x3['O1'] and model.x3['O2'] to pick the actual maximum value corresponding to the store from dictionary 'D' where I hold the sumproducts (weighted scores). And pick optimal weights such that the sum of the weighted scores - corresponding to the store with maximum weights is maximixed.
UPDATE : I was able to solve the problem, please look at the below complete code listing
from pyomo.environ import *
import itertools
model = ConcreteModel(name="(weights)")
# scores for factors 'A', 'B', 'C','D' for each order - store combination
order_str_scores = {
('O1', 'str_1') : [0.90, 0.90, 0.71, 0.93],
('O1', 'str_2'): [0.83, 0.91, 0.95, 0.86],
('O1', 'str_3') : [0.83, 0.83, 0.87, 0.9],
('O2', 'str_1') : [0.71, 0.56, 0.84, 0.55],
('O2', 'str_2') : [0.97, 0.9, 0.95, 0.87],
('O2', 'str_3') : [0.91, 0.87, 0.95, 0.83],
('O3', 'str_1') : [0.81, 0.86, 0.84, 0.85],
('O3', 'str_2') : [0.89, 0.84, 0.95, 0.87],
('O3', 'str_3') : [0.97, 0.87, 0.95, 0.86],
('O4', 'str_1') : [0.95, 0.96, 0.84, 0.85],
('O4', 'str_2') : [0.89, 0.74, 0.95, 0.87],
('O4', 'str_3') : [0.87, 0.77, 0.85, 0.83],
('O5', 'str_1') : [0.61, 0.86, 0.94, 0.85],
('O5', 'str_2') : [0.99, 0.84, 0.98, 0.97],
('O5', 'str_3') : [0.77, 0.87, 0.95, 0.83],
}
# bounds for each of the factors
factor_bounds = {
'A' : [80, 99],
'B' : [0, 20],
'C': [0, 20],
'D' : [0, 20],
}
# list of unique orders and stores. These will act as indices
model.orders = sorted(list(set([i[0] for i in order_str_scores.keys()])))
model.stores = sorted(list(set([i[1] for i in order_str_scores.keys()])))
# 4 factors 'availability', 'distance', 'storeCapacity','smoothing' whose scores are mentioned in 'order_str_wts' dictionary
model.factors = ['A', 'B', 'C','D']
# below 4 decision variables (one for each factor) will hold the optimal number between 0 - 100
def dv_bounds(m, i):
return (factor_bounds[i][0], factor_bounds[i][1])
model.x1 = Var(model.factors, within=NonNegativeReals, bounds=dv_bounds)
#Sum of these 4 decision variables should be equal to 100
def sum_wts(m):
return sum(m.x1[i] for i in model.factors) == 100
model.sum_wts = Constraint(rule=sum_wts)
# Hold the sumproduct of scores and corresponding weights for each factor
D = {}
model.k = list(itertools.product(model.orders, model.stores))
for i in model.k:
D[i] = sum(model.x1[n] * order_str_scores[i][q] for n,q in zip(model.factors,range(4)))
# DV : Binary auxiliary variable to help find the store with max weighted score
model.is_max = Var(model.orders, model.stores, within=Binary)
# DV : Variable to hold the maximum weighted score for each order
model.max_value = Var(model.orders, model.stores, within=NonNegativeReals)
# 1st helper constraint : or each order sum of binary DV variable == 1
def is_max_1(m, i):
return sum(m.is_max[i, j] for j in model.stores) == 1
model.is_max_1 = Constraint(model.orders, rule=is_max_1)
# 1st helper constraint to find the maximum weighted score and the corresponding store for each order
def is_max_const(m,i,j):
return m.max_value[i,j] <= 1000 * m.is_max[i,j]
model.is_max_const = Constraint(model.orders, model.stores, rule=is_max_const)
# 2nd helper constraint to find the maximum weighted score and the corresponding store for each order
def const_2(m,i,j,k):
return m.max_value[i, j] + (1000 * (1 - m.is_max[i, j])) >= D[i, k]
model.const_2 = Constraint(model.orders, model.stores, model.stores, rule=const_2)
# 3rd helper constraint to ensure that the selected max_value is greater than the D
def const_3(m,i,j):
return m.max_value[i,j] <= D[i, j]
model.const_3 = Constraint(model.orders, model.stores,rule=const_3)
# Define the objective function
def obj_rule(m):
return sum(m.max_value[i,j] for i in m.orders for j in m.stores)
model.obj = Objective(rule=obj_rule, sense=maximize)
opt = SolverFactory('glpk')
result_obj = opt.solve(model, tee=True)
model.display()

Linear index upper triangular matrix

If I have the upper triangular portion of a matrix, offset above the diagonal, stored as a linear array, how can the (i,j) indices of a matrix element be extracted from the linear index of the array?
For example, the linear array [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9 is storage for the matrix
0 a0 a1 a2 a3
0 0 a4 a5 a6
0 0 0 a7 a8
0 0 0 0 a9
0 0 0 0 0
And we want to know the (i,j) index in the array corresponding to an offset in the linear matrix, without recursion.
A suitable result, k2ij(int k, int n) -> (int, int) would satisfy, for example
k2ij(k=0, n=5) = (0, 1)
k2ij(k=1, n=5) = (0, 2)
k2ij(k=2, n=5) = (0, 3)
k2ij(k=3, n=5) = (0, 4)
k2ij(k=4, n=5) = (1, 2)
k2ij(k=5, n=5) = (1, 3)
[etc]
The equations going from linear index to (i,j) index are
i = n - 2 - floor(sqrt(-8*k + 4*n*(n-1)-7)/2.0 - 0.5)
j = k + i + 1 - n*(n-1)/2 + (n-i)*((n-i)-1)/2
The inverse operation, from (i,j) index to linear index is
k = (n*(n-1)/2) - (n-i)*((n-i)-1)/2 + j - i - 1
Verify in Python with:
from numpy import triu_indices, sqrt
n = 10
for k in range(n*(n-1)/2):
i = n - 2 - int(sqrt(-8*k + 4*n*(n-1)-7)/2.0 - 0.5)
j = k + i + 1 - n*(n-1)/2 + (n-i)*((n-i)-1)/2
assert np.triu_indices(n, k=1)[0][k] == i
assert np.triu_indices(n, k=1)[1][k] == j
for i in range(n):
for j in range(i+1, n):
k = (n*(n-1)/2) - (n-i)*((n-i)-1)/2 + j - i - 1
assert triu_indices(n, k=1)[0][k] == i
assert triu_indices(n, k=1)[1][k] == j
First, let's renumber a[k] in opposite order. We'll get:
0 a9 a8 a7 a6
0 0 a5 a4 a3
0 0 0 a2 a1
0 0 0 0 a0
0 0 0 0 0
Then k2ij(k, n) will become k2ij(n - k, n).
Now, the question is, how to calculate k2ij(k, n) in this new matrix. The sequence 0, 2, 5, 9 (indices of diagonal elements) corresponds to triangular numbers (after subtracting 1): a[n - i, n + 1 - i] = Ti - 1. Ti = i * (i + 1)/2, so if we know Ti, it's easy to solve this equation and get i (see formula in the linked wiki article, section "Triangular roots and tests for triangular numbers"). If k + 1 is not exactly a triangular number, the formula will still give you the useful result: after rounding it down, you'll get the highest value of i, for which Ti <= k, this value of i corresponds to the row index (counting from bottom), in which a[k] is located. To get the column (counting from right), you should simply calculate the value of Ti and subtract it: j = k + 1 - Ti. To be clear, these are not exacly i and j from your problem, you need to "flip" them.
I didn't write the exact formula, but I hope that you got the idea, and it will now be trivial to find it after performing some boring but simple calculations.
The following is an implimentation in matlab, which can be easily transferred to another language, like C++. Here, we suppose the matrix has size m*m, ind is the index in the linear array. The only thing different is that here, we count the lower triangular part of the matrix column by column, which is analogus to your case (counting the upper triangular part row by row).
function z= ind2lTra (ind, m)
rvLinear = (m*(m-1))/2-ind;
k = floor( (sqrt(1+8*rvLinear)-1)/2 );
j= rvLinear - k*(k+1)/2;
z=[m-j, m-(k+1)];
For the records, this is the same function, but with one-based indexing, and in Julia:
function iuppert(k::Integer,n::Integer)
i = n - 1 - floor(Int,sqrt(-8*k + 4*n*(n-1) + 1)/2 - 0.5)
j = k + i + ( (n-i+1)*(n-i) - n*(n-1) )÷2
return i, j
end
Here is a more efficient formulation for k:
k = (2 * n - 3 - i) * i / 2 + j - 1
In python 2:
def k2ij(k, n):
rows = 0
for t, cols in enumerate(xrange(n - 1, -1, -1)):
rows += cols
if k in xrange(rows):
return (t, n - (rows - k))
return None
In python, the most efficient way is:
array_size= 3
# make indices using k argument if you want above the diagonal
u, v = np.triu_indices(n=array_size,k=1)
# assuming linear indices above the diagonal i.e. 0 means (0,1) and not (0,0)
linear_indices = [0,1]
ijs = [(i,j) for (i,j) in zip(u[linear_indices], v[linear_indices])]
ijs
#[(0, 1), (0, 2)]

How can I write an if condition for my variable in GLPK?

Here is my full problem:
Information:
*Max. total investment: $125
*Pay-off is the sum of the units bought x pay-off/unit
*Cost per investment: Buy-in cost + cost/unit x number of units if you buy at least one unit
*The cost is sum of the costs per investment
Constraints:
*You may not invest in both 2 and 5.
*You may invest in 1 only if you invest at least one of 2 and 3.
*You must invest at least two of 3,4,5.
*You may not invest more than max number of units.
Problem: Maximize profit : pay-off - cost
xi: # of units i ∈ {1,2,3,4,5}
yi=1 if xi>0 else yi=0
cost = sum{i in I} buyInCost_i * yi + cost-unit_i*xi
pay-off = sum{i in I} (pay-off/unit)_i*xi
profit = pay-off - cost
Maximize profit
Subject to
y2+y5 <= 1
y1<= y2+y3
y3+y4+y5 >= 2
x1<=5, x2<=4, x3<=5, x4<=7, x5<=3
cost<=125
Here is my question:
For example I have this binary variable y
yi=1 if xi>0 else yi=0 and i ∈ {1,2,3,4,5}
I declared i as a data set
set I;
data;
set I := 1 2 3 4 5;
I don't know how to add if else condition to y variable in glpk. Can you please help me out?
My modelling :
set I;
/*if x[i]>0 y[i]=1 else y[i]=0 ?????*/
var y{i in I}, binary;
param a{i in I};
/* buy-in cost of investment i */
param b{i in I};
/* cost per unit of investment i */
param c{i in I};
/* pay-off per unit of investment i */
param d{i in I};
/* max number of units of investment i */
var x{i in I} >=0;
/* Number of units that is bought of investment i */
var po := sum{i in I} c[i]*x[i];
var cost := sum{i in I} a[i]*y[i] + b[i]*x[i];
maximize profit: po-cost;
s.t. c1: y[2]+y[5]<=1;
s.t. c2: y[1]<y[2]+y[3];
s.t. c3: y[3]+y[4]+y[5]>=2;
s.t. c4: x[1]<=5
x[2]<=4
x[3]<=5
x[4]<=7
x[5]<=3;
s.t. c5: cost <=125;
s.t. c6{i in I}: M * y[i] > x[i]; // if condition of y[i]
set I := 1 2 3 4 5;
param a :=
1 25
2 35
3 28
4 20
5 40;
param b :=
1 5
2 7
3 6
4 4
5 8;
param c :=
1 15
2 25
3 17
4 13
5 18;
param d :=
1 5
2 4
3 5
4 7
5 3;
param M := 10000;
I am getting this syntax error:
problem.mod:21: syntax error in variable statement
Context: ...I } ; param d { i in I } ; var x { i in I } >= 0 ; var po :=
MathProg model processing error
You can't directly do that (there is no way to write 'directly' an if constraint in a LP).
However, there are workarounds for this.
For example, you can write:
M * yi > xi
where M is a large constant (greater than any value of xi).
This way:
if xi > 0, then the constraint is equivalent to yi > 0, that is yi == 1 since yi is binary (if M is large enough).
if xi == 0, then the constraint is always verified, and yi will be equal to 0 since your objective is increasing with yi and you are minimizing.
in both case, the constraint is equivalent to the if test.