GLPK/GMPL: Minimize objective function but keep it > 0 - constraints

I am trying to minimize an objective function that has three parameters: i, p, j like this:
param mlu{i in I, p in P, j in out[p]} := traffic[i,p]/capacity[j];
minimize MAXLU{i in I, p in P, j in out[p]}: mlu[i,p,j] * x[i,p,j];
but the objective function has to be greater than 0, otherwise it is defeating my purpose of minimization.
And I am trying to ensure this by adding a constraint on the objective function like this:
s.t. constraint1{i in I, p in P, j in out[p]} : MAXLU[i,p,j] != 0;
But I get the following error:
LP.mod:66: invalid reference to status, primal value, or dual value of objective MAXLU above solve statement
Context: i in I , p in P , j in out [ p ] } : MAXLU [ i , p , j ] !=
glp_mpl_generate: invalid call sequence
Error detected in file glpapi14.c at line 79
Aborted
Is it even possible to do this? Thank you for any help/suggestions!

You can refer to variables and parameters, but not objectives (MAXLU) in a constraint. A simple way to fix this is to replace MAXLU in constraint1 with the actual objective expression:
s.t. constraint1{i in I, p in P, j in out[p]} : mlu[i,p,j] * x[i,p,j] ...;
Moreover, you cannot define a constraint with expression != 0. You can have >= epsilon or <= epsilon instead where epsilon is a small number:
s.t. constraint1{i in I, p in P, j in out[p]} : mlu[i,p,j] * x[i,p,j] >= epsilon;

Related

Could not find the optimal solution after adding constraints

My code is as follows:
gekko = GEKKO(remote=True)
# create variable, each variable is a vector, each element
# of the vector is a binary
s = []
for i in range(N):
s.append(gekko.Array(gekko.Var, s_len[i], value=0, lb=0, ub=1, integer=True))
# some constants used in the objective/constraint function
c, d, r, m, L = create_c_d_r_m_L() # they are all numpy ndarry
# define the objective function
def objective():
obj = 0
for i in range(N):
obj += np.dot(s[i], c[i]) + np.dot(s[i], d[i])
for idx, (i, j) in enumerate(E):
obj += np.dot(np.dot(s[i], r[idx].reshape(s_len[i], s_len[j])),\
s[j]) # s[i] * r[i, j] * s[j]
return obj
# add constraints
# (a) each vector can only have and must have one 1
for i in range(N):
gekko.Equation(gekko.sum(s[i]) == 1)
# (b)
for t in range(N):
peak_mem = gekko.sum([np.dot(s[i], m[i]) for i in L[t]])
gekko.Equation(peak_mem < DEVICE_MEM)
# DEVICE_MEM is a predefined big int
# solve
gekko.Obj(objective())
gekko.solve(disp=True)
I found that when removing constraint (b), the solver can output the optimal solution for s. However, if we add (b) and set DEVICE_MEM to a very large number (which should not affect the solution), the s is not optimal anymore. I'm wondering if I am doing something wrong here because I tried both APOPT(solvertype=1) and IPOPT (solvertype=3) and they give the same nonoptimal results.
To give more context to the problem: this is an optimization over the graph. N represents the number of nodes in the graph. E is the set that contains all edges in the graph. c, d, m are three types of cost of a node. r is the cost of edges. Each node has multiple strategies (represented by the vector s[i]), and we need to select the best strategy for each node so that the overall cost is minimal.
Detailed constants:
# s_len: record the length of each vector
# (the # of strategies for each node,
# here we assume the length are all 10)
s_len = np.ones(N) * 10
# c, d, m are the costs of each node
# let's assume the c/d/m cost for i node is just i
c, d, m = [], [], []
for i in range(N):
c[i] = s_len[i] * [i]
d[i] = s_len[i] * [i]
m[i] = s_len[i] * [i]
# r is the edge cost, let's assume the cost for
# each edge is just i * j
r = []
for (i,j) in E: # E records all edges
cur_r = s_len[i] * s_len[j] * [i*j]
r.append(cur_r)
# L contains the node ids, we just randomly generate 10 integers here
L = []
for i in range(N):
cur_L = [randrange(N) for _ in range(10)]
L.append(cur_L)
I've been stuck on this for a while and any comments/answers are highly appreciated! Thanks!
Try reframing the inequality constraint:
for t in range(N):
peak_mem = gekko.sum([np.dot(s[i], m[i]) for i in L[t]])
gekko.Equation(peak_mem < DEVICE_MEM)
as a variable with an upper bound:
peak_mem = m.Array(m.Var,N,ub=DEVICE_MEM)
for t in range(N):
m.Equation(peak_mem[t]==\
gekko.sum([np.dot(s[i], m[i]) for i in L[t]])
The N inequality constraints peak_mem < DEVICE_MEM are converted to equality constraints with slack variables as s[i] = DEVICE_MEM - peak_mem with a simple inequality constraint on the slack s[i]>=0. If the inequality constraint far from the bound, then the slack variable can be very large. Formulating the equation as a variable may help.
I tried using the information in the question to pose a minimal problem that could reproduce the error and the potential solution. If you need more specific suggestions, please modify the code to be a complete and minimal example that reproduces the error. This helps with verifying the solution.

Ways to scroll an index that takes on different values at another index in CPLEX

I have a problem in CPLEX: I have two index i and j. For each j, i is different.
When I write the constraints, how can I make it clear that for j=1, the index i goes from 1 to 10 while for j=2 the index i goes from 1 to 3 and for j=3 i goes from 1 to 7?
For example:
int num_j=...; range J=1..num_j;
int num_i=...; range I=1..num_i;
forall (i in I) // where in I there must be the different values for each J
forall (j in J)
constraint 1: sum(m in M) y[i][j][m] == 1;
At array variable indexer size - 3 ways : union , tuple set, decision expression within Making Optimization Simple
I gave 3 ways do deal with that challenge.
With your data
int num_j=3;
range J=1..num_j;
int num_i[J]=[10,3,7];
range M=1..1;
range I=1..max(j in J) num_i[j];
dvar boolean y[I][J][M];
subject to
{
forall (j in J)
forall (i in 1..num_i[j]) // where in I there must be the different values for each J
sum(m in M) y[i][j][m] == 1;
}
works fine

solving matrices using Cramer's rule

So I searched the in internet looking for programs with Cramer's Rule and there were some few, but apparently these examples were for fixed matrices only like 2x2 or 4x4.
However, I am looking for a way to solve a NxN Matrix. So I started and reached the point of asking the user for the size of the matrix and asked the user to input the values of the matrix but then I don't know how to move on from here.
As in I guess my next step is to apply Cramer's rule and get the answers but I just don't know how.This is the step I'm missing. can anybody help me please?
First, you need to calculate the determinant of your equations system matrix - that is the matrix, that consists of the coefficients (from the left-hand side of the equations) - let it be D.
Then, to calculate the value of a certain variable, you need to take the matrix of your system (from the previous step), replace the coefficients of the corresponding column with constant terms (from the right-hand side), calculate the determinant of resulting matrix - let it be C, and divide C by D.
A bit more about the replacement from the previous step: say, your matrix if 3x3 (as in the image) - so, you have a system of equations, where every a coefficient is multiplied by x, every b - by y, and every c by z, and ds are the constant terms. So, to calculate y, you replace those coefficients that are multiplied by y - bs in this case, with ds.
You perform the second step for every variable and your system gets solved.
You can find an example in https://rosettacode.org/wiki/Cramer%27s_rule#C
Although the specific example deals with a 4X4 matrix the code is written to accommodate any size square matrix.
What you need is calculate the determinant. Cramer's rule is just for the determinant of a NxN matrix
if N is not big, you can use the Cramer's rule(see code below), which is quite straightforward. However, this method is not efficient; if your N is big, you need to resort to other methods, such as lu decomposition
Assuming your data is double, and result can be hold by double.
#include <malloc.h>
#include <stdio.h>
double det(double * matrix, int n) {
if( 1 >= n ) return matrix[ 0 ];
double *subMatrix = (double*)malloc(( n - 1 )*( n - 1 ) * sizeof(double));
double result = 0.0;
for( int i = 0; i < n; ++i ) {
for( int j = 0; j < n - 1; ++j ) {
for( int k = 0; k < i; ++k )
subMatrix[ j*( n - 1 ) + k ] = matrix[ ( j + 1 )*n + k ];
for( int k = i + 1; k < n; ++k )
subMatrix[ j*( n - 1 ) + ( k - 1 ) ] = matrix[ ( j + 1 )*n + k ];
}
if( i % 2 == 0 )
result += matrix[ 0 * n + i ] * det(subMatrix, n - 1);
else
result -= matrix[ 0 * n + i ] * det(subMatrix, n - 1);
}
free(subMatrix);
return result;
}
int main() {
double matrix[ ] = { 1,2,3,4,5,6,7,8,2,6,4,8,3,1,1,2 };
printf("%lf\n", det(matrix, 4));
return 0;
}

Setting an specific variable value in a non defined set value (AMPL)

Iā€™m having the following problem, which can be reduced from my code to:
set t:= 1..5; #Time periods
set e:= 1..2; #Inventory places
set p:= 1..3; #Products
var Iq{p,e,t} >= 0; #Inventory variable
#Moving variables:
# i for sums in t
# g for sums in e
# j for sums in p
subject to inventory_balance {j in p, i in t}:
sum{g in e} Iq[j,g,i] = sum{g in e} Iq[j,g,i-1] + sum{x in k} A[j,i,x] * Mt[i] - DS[i,j] ;
This is the inventory level, which is the sum of "g in e" of the inventory level at time i-1 plus other things. The problem is the "i-1" time period. The first iteration will be for time t=1 i.e because of the constraint it will become time t=0. I know that in that period (t=0) the amount of inventory is 0. So the thing is, how can I set the variable Iq[p,e,0] be 0 in a constraint?
Thanks in advance!
The easiest way to do it from where you are is:
set t := 0..5;
...
subject to starting_inventory_zero {j in p, k in e}: Iq{j,k,0} = 0;
and then tweak the indexing in inventory_balance to
{j in p, i in t: i > 0}
But if it were my code I'd do it with ordered sets:
set t := 0..5 ordered;
...
subject to starting_inventory_zero {j in p, k in e}: Iq{j,k,first(t)} = 0;
...
subject to inventory_balance {j in p, i in t: ord(i) > 1}:
sum{g in e} Iq[j,g,i] = sum{g in e} Iq[j,g,prev(i)] + sum{x in k} A[j,i,x] * Mt[i] - DS[i,j] ;
This does the same thing, but it generalises better. For instance, I could define my index set t as {JAN_2001, FEB_2001, ..., DEC_2016} and the code above would still work. (Unless I've made some typos, which is always possible!)

Writing a function with four arguments

I'm trying to solve this problem:
We define objects called (p.q) numbers. In R the (p,q) numbers are lists with four elements. The first element of the list is either the integer +1+1 or the integer āˆ’1āˆ’1. It gives the sign of the number. The second and third element are p and q, each a non-negative integer. And the fourth element is a vector of p+q+1 integers between zero and nine.
Write a function which takes the four arguments sign, p, q, and nums. Then check if the arguments satisfy all requirements for a (p,q) number. If not, stop with an error message. If yes, return the (p.q) number as a list with attribute pqNumber using the structure() function.
Here's my code so far. I'm not sure what's wrong or what I need to do.
`pqNumber <- function(sign, p, q, nums) {
nums <- c()
if (sign != 1 && sign != -1) stop ("sign must be 1 or -1")
if (round != p) stop ("p must be an integer")
if (round != q) stop ("q must be an integer")
if (p < 0) stop ("p cannot be negative")
if (q < 0) stop ("q cannot be negative")
if (length(nums) != p + q + 1) stop ("nums must be a vector of p+q+1 integers")
structure(list(sign = sign, p = p, q = q, nums = nums), class = "pqNumber")
}`

Resources