AMPL: Subscript out of bound - ampl

Hello fellow optimizers!
I'm having some issues with the following constraint:
#The supply at node i equals what was present at the last time period + any new supply and subtracted by what has been extracted from the node.
subject to Constraint1 {i in I, t in T, c in C}:
l[i,t-1,c] + splus[i,t] - sum{j in J, v in V, a in A} x[i,j,v,t,c,a]= l[i,t,c];
which naturally causes this constraint to provide errors the first time it loops, as the t-1 is not defined (for me, l[i,0,c] is not defined. Where
var l{I,T,C} >= 0; # Supply at supply node I in time period T for company C.
param splus{I,T}; # Additional supply at i.
var x{N,N,V,T,C,A} integer >= 0; #Flow from some origin within N to a destination within N using vehicle V, in time T, for company C and product A.
and set T; (in the .mod) is a set defined as:
set T := 1 2 3 4 5 6 7; in the .dat file
I've tried to do:
subject to Constraint1 {i in I, t in T: t >= 2, c in C}:
all else same
which got me a syntax error. I've also tried to include "let l[1,0,1] := 0" for all possible combinations, which got me the error
error processing var l[...]:
no data for set I
I've also tried
subject to Constraint1 {i in I, t in T, p in TT: p>t, c in C}:
l[i,t,c] + splus[i,p] - sum{j in J, v in V, a in A} x[i,j,v,p,c,a]= l[i,p,c];
where
set TT := 2 3 4 5 6;
in the .dat file (and merely set TT; in the .mod) which also gave errors. Does someone have any idea of how to do this?

One way to fix this is to specify the condition t >= 2 at the end of the indexing expression:
subject to Constraint1 {i in I, t in T, c in C: t >= 2}:
...
See also Section A.3 Indexing expressions and subscripts for more details on syntax of indexing expressions.

Related

Indexing variables in sets in Xpress Mosel

I'm trying to solve a linear relaxation of a problem I've already solved with a Python library in order to see if it behaves in the same way in Xpress Mosel.
One of the index sets I'm using is not the typical c=1..n but a set of sets, meaning I've taken the 1..n set and have created all the combinations of subsets possible (for example the set 1..3 creates the set of sets {{1},{2},{3},{1,2},{2,3},{1,2,3}}).
In one of my constraints, one of the indexes must run inside each one of those subsets.
The respective code in Python is as follows (using the Gurobi library):
cluster=[1,2,3,4,5,6]
cluster1=[]
for L in range(1,len(cluster)+1):
for subset in itertools.combinations(cluster, L):
clusters1.append(list(subset))
ConstraintA=LinExpr()
ConstraintB=LinExpr()
for i in range(len(nodes)):
for j in range(len(nodes)):
if i<j and A[i][j]==1:
for l in range(len(clusters1)):
ConstraintA+=z[i,j]
for h in clusters1[l]:
restricao2B+=(x[i][h]-x[j][h])
model.addConstr(ConstraintA,GRB.GREATER_EQUAL,ConstraintB)
ConstraintA=LinExpr()
ConstraintB=LinExpr()
(In case the code above is confusing, which I suspect it to be)The constraint I'm trying to write is:
z(i,j)>= sum_{h in C1}(x(i,h)-x(j,h)) forall C1 in C
in which the C1 is each of those subsets.
Is there a way to do this in Mosel?
You could use some Mosel code along these lines (however, independently of the language that you are using, please be aware that the calculated 'set of all subsets' very quickly grows in size with an increasing number of elements in the original set C, so this constraint formulation will not scale up well):
declarations
C: set of integer
CS: set of set of integer
z,x: array(I:range,J:range) of mpvar
end-declarations
C:=1..6
CS:=union(i in C) {{i}}
forall(j in 1..C.size-1)
forall(s in CS | s.size=j, i in C | i > max(k in s) k ) CS+={s+{i}}
forall(s in CS,i in I, j in J) z(i,j) >= sum(h in s) (x(i,h)-x(j,h))
Giving this some more thought, the following version working with lists in place of sets is more efficient (that is, faster):
uses "mmsystem"
declarations
C: set of integer
L: list of integer
CS: list of list of integer
z,x: array(I:range,J:range) of mpvar
end-declarations
C:=1..6
L:=list(C)
qsort(SYS_UP, L) ! Making sure L is ordered
CS:=union(i in L) [[i]]
forall(j in 1..L.size-1)
forall(s in CS | s.size=j, i in L | i > s.last ) CS+=[s+[i]]
forall(s in CS,i in I, j in J) z(i,j) >= sum(h in s) (x(i,h)-x(j,h))

Define the function for distance matrix in ampl. Keep getting "i is not defined"

I'm trying to set up a ampl model which clusters given points in a 2-dimensional space according to the model of Saglam et al(2005). For testing purposes I want to generate randomly some datapoints and then calculate the euclidian distance matrix for them (since I need this one). I'm aware that I could only make the distance matrix without the data points but in a later step the data points will be given and then I need to calculate the distances between each the points.
Below you'll find the code I've written so far. While loading the model I keep getting the error message "i is not defined". Since i is a subscript that should run over x1 and x1 is a parameter which is defined over the set D and have one subscript, I cannot figure out why this code should be invalid. As far as I understand, I don't have to define variables if I use them only as subscripts?
reset;
# parameters to define clustered
param m; # numbers of data points
param n; # numbers of clusters
# sets
set D := 1..m; #points to be clustered
set L := 1..n; #clusters
# randomly generate datapoints
param x1 {D} = Uniform(1,m);
param x2 {D} = Uniform(1,m);
param d {D,D} = sqrt((x1[i]-x1[j])^2 + (x2[i]-x2[j])^2);
# variables
var x {D, L} binary;
var D_l {L} >=0;
var D_max >= 0;
#minimization funcion
minimize max_clus_dis: D_max;
# constraints
subject to C1 {i in D, j in D, l in L}: D_l[l] >= d[i,j] * (x[i,l] + x[j,l] - 1);
subject to C2 {i in D}: sum{l in L} x[i,l] = 1;
subject to C3 {l in L}: D_max >= D_l[l];
So far I tried to change the line form param x1 to
param x1 {i in D, j in D} = ...
as well as
param d {x1, x2} = ...
Alas, nothing of this helped. So, any help someone can offer is deeply appreciated. I searched the web but I found nothing useful for my task.
I found eventually what was missing. The line in which I calculated the parameter d should be
param d {i in D, j in D} = sqrt((x1[i]-x1[j])^2 + (x2[i]-x2[j])^2);
Retrospectively it's clear that the subscripts i and j should have been mentioned on the line, I don't know how I could miss that.

Minizinc "var set of int: x" instead of "set of int: x"

I have an array of set in the Golfers problem (in each week there should be formed groups, such that no two players play together more than once, and everybody plays exactly one time each week):
int: gr; %number of groups
set of int: G=1..gr;
int: sz; %size of groups
set of int: S=1..sz;
int: n=gr*sz; %number of players
set of int: P=1..n;
int: we; % number of weeks
set of int: W=1..we;
include "globals.mzn";
array[G,W] of var set of P: X; %X[g,w] is the set of people that form group g in week w
My constraints are as follow (I'm not sure if everything works correctly yet):
constraint forall (g in G, w in W) (card (X[g,w]) = sz); %Each group should have size sz
constraint forall (w in W, g,h in G where g > h) (disjoint(X[g,w], X[h,w])); % Nobody plays twice in one week
constraint forall (w,u in W where w > u) (forall (g,h in G) (card(X[g,w] intersect X[h,u]) <= 1 )); % Two players never meet more than once
constraint forall (w in 2..we) (w+sz-1 in X[1,w] /\ 1 in X[1,w]); %Symmetries breaking: week permutations
constraint forall (w in W, g in 1..gr-1) ( min(X[g,w]) < min(X[g+1,w]) ); %Symmetries breaking: group permutations
constraint forall (g in G, s in S) ( s+sz*(g-1) in X[g,1]);
solve satisfy;
output [ show(X[i,j]) ++ if j == we then "\n" else " " endif | i in 1..gr, j in 1..we ];
My problem lies in constraint number 5. I cannot use min on "var set of int: x", I should use it on "set of int: x". Unfortunately, I do not understand the difference between those two (from what I've read this may be connected to defining the size of each set, but I'm not sure).
Could someone explain the problem to me and propose a solution? I would be very very grateful. Thanks!
First of all: A var is a decision variable. The goal of all Minizinc programs are to decide the the value of all decision variables. You don't know what the values are and you are trying to find the values. Anything that is not a var is simply a known number. (disregarding the use of sets)
Doing min(X[g,w]) of a decision variable (var) is simply not implemented in Minizinc. The reason would be that using X[g,w] < X[g+1,w] without the min makes more sense. Why only constrain the lowest number in both sets insted of all numbers. I.e {1,3,5} < {1,4} insted of 1 < 1
(I hope MiniZinc has < on sets so I don't lie, I am not sure)
I have found out the solution - we should make an array of elements of the set to make the max function possible in this case.
constraint forall (w in 2..we) ( max([i | i in X[1,w-1]]) < max([i | i in X[1,w]])); %Symmetries breaking: week permutations
constraint forall (w in W, g in 1..gr-1) ( min([i | i in X[g,w]]) < min([i | i in X[g+1,w]]));% Symmetries breaking: group permutations (I have been trying to speed up the constraint above, but it does not work with var set of int..)

AMPL "Locking" a derived variable to a value

I want to investigate whether it is profitable to invest in an additional production facility, and hence I have to account for an capitilization in my objective function.
As such I am wondering if it is possible to, say, if y[t] = 1, then y[g] = 1
for g != t, g > t and where g,t is a subset of the time interval set T.
My first thought was to have:
subject to Constraint1:
y[t] = y[t-1] for all t in T
But that must surely render the solution of y to become the start value in y[0] which is something I obviously do not want.
For clarification. Assume that y[t] is a binary variable whose value is 1 if the investment is undertaken in time t, otherwise 0.
Hope anyone can shed some light into this!
Regards
The constraint y[t] = 1, then y[g] = 1 for g != t, g > t can be represented in AMPL as something like:
s.t. c{t in T: t != t0}: y[t + 1] >= y[t];
where t0 is the first element of set T. Note the use of >= instead of =. If y[t] is 1 for some t, it will drive y for all subsequent values of t to 1.

"Out of domain" error in MathProg (GLPK)

I am struggling with a seemingly simple model in MathProg. The model is as follows:
set W;
set V;
param b {W, V} binary;
param p;
var w {j in W} <= 0, >= 1;
minimize obj: 0;
subject to within_radius_of {i in V}:
sum {j in W} b[i,j] * w[j] >= 1;
subject to p_limit:
sum {j in W} w[j] <= p;
end;
When I run it, it gives me the error feasibility.glp:11: b[v1,w1] out of domain. I have no idea what is going wrong. Even more strange to me, if I change the relevant line to b[j,i] it keeps giving the exact same error (not b[w1,v1] as I expected).
I inspected the AMPL Diet Example carefully, and despite me seeing no difference in the relevant part of my model it still doesn't work. What is wrong?
Parameter b is declared as binary so it can only take values 0 or 1. You haven't provided a data file, but the error message suggests that the data for b is out of domain (not 0 or 1), for example:
data;
set W := w1;
set V := v1;
param b := w1 v1 0.5;
AMPL gives a more detailed error message in this case:
error processing param b['w1','v1']:
failed check: param b['w1','v1'] = 0.5
is not binary (0 or 1);
The reason why the order of indices doesn't matter in this case is that the data for b is checked completely before the model is actually instantiated. So it seems that w1 and v1 may be swapped in the data file.