Page 1 of 1

A scalar drives the length of a set

Posted: Tue May 26, 2020 11:21 am
by aileen
I need my set to be able to change depending on the value of a scalar, e.g:

Code: Select all

scalar dim /10/; set myset /1*dim/;

Re: A scalar drives the length of a set

Posted: Tue May 26, 2020 11:26 am
by aileen
Before going into the details please note that set elements are not numbers - even if you choose labels that look like numbers. In fact, our recommendation is to avoid using set elements that look like numbers since it can cause confusion in different circumstances. If you write

Code: Select all

set t /t1 * t5/;
set i /i1 * i5/;
you won't get the two confused. If you write

Code: Select all

set i /5 * 9/;
set j /3 * 8/;
you'll be surprised to find that the order of elements in set j is 5, 6, 7, 8, 3, 4. That's because the ordering comes from the collection of all unique set elements in a GAMS program - and the order is defined by when they appear. The only advantage of labels that look like numbers is that you can use the .val suffix.

But now back to the original question. In general GAMS prefers to do this the other way around:

Code: Select all

set myset /i1*i10/;
scalar dim;
dim = card(myset);
In the GAMS philosophy sets drive the model. Creating sets based on data (e.g. scalars) requires the use of dynamic sets, which are a little bit more difficult to use than static sets. Moreover, you need to have an estimate of how big your scalar will maximal ever be. Here is a fragment that illustrates how you can use dynamic sets:

Code: Select all

set univ the universe /i1*i1000/;
scalar dim /6/;
set myset(univ);

myset(univ)$(ord(univ) <= dim) = yes;

display myset; 

* declare equations, variables and parameters over the universe set
* but use them over myset
parameter p(univ);
p(myset) = 1;
You can also pass compile time information through the command line: gams x.gms –dim=5 with x.gms.

Code: Select all

$if not set dim $set dim 5

set myset / i1*i%dim%/
In addition, if the value of the scalar is known at compile time (e.g. due to a data statement) you can use $eval to build a corresponding set:

Code: Select all

scalar dim /10/; 
$eval DIM dim
set myset /i1*i%DIM%/;