Wednesday, May 17, 2017

Small GAMS trick: $eval

In GAMS we typically first declare sets and and then deduce things like the number of elements in a set:

set i/i1*i20/;
scalar
n;
n =
card
(i);

Often the question comes up: Can I do it the other way around? First declare the scalar n and then create set if that size?  We can use a funny trick for that, using a variant of the $set construct:

scalar n /20/;
$eval n n
set i /i1 * i%n%/
;

In general I prefer to write this as:

$set n 20
scalar n /%n%/
;
set i /i1 * i%n%/
;

(a little bit less of a “surprise factor” is probably good).

Notes:

  • The assignment n = card(i) is done at execution time. All other operations are at compile time. In some more advanced cases this can be an important distinction.
  • The construct $eval n n is like a $set. It will evaluate the right most n and the result is used to populate the preprocessor identifier (the left most n).
  • To make sure a preprocessor identifier holds a numeric value, you can use scalar N /%id%/.  GAMS will complain if the macro contains a string that does not correspond to a number.