Gams Tips and Tricks

Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 10

GAMS Tips and Tricks

Below, a (random) list of useful tips and tricks for GAMS users is given. This list is oriented
at graduate students who start using GAMS but already know the general syntax. The list is
constructed largely as the result of concrete questions asked by GAMS users. Experienced
users will find many well-known modelling features, but may find some items they didnt
know yet.

In principle, almost everything can be found in the GAMS User Guide, which (among other
interesting documentation) can be found on http://www.gams.com/docs/document.htm. Some
new features are not in the official User guide yet; you can get these when you follow the very
useful advanced GAMS course by Bruce McCarl.

If you have any (good new) tips or tricks, or if you have found a bug / ambiguity in the
existing tips and tricks, send an email to [email protected].

1. Browse through the GAMS mailing list archive; it contains a lot of usefull tips and
tricks (including some of the hints below):
http://www.gams.de/3docs/gams_archives/external.html gives a summary of the main
topics and the full archive can be browsed at
http://www.listserv.gmd.de/archives/gams-l.html

{Contributed by Rob Dellink}

2. GAMS comes with a library of 160 models; take a look at these models when building
your own model (the library can be found on the hard disk in the MODLIB
subdirectory and on the GAMS homepage).

{Contributed by Rob Dellink}

3. First solve a model using zero iterations to check whether the benchmark (i.e. the base
data you provide) is replicated by the model. This is to make sure that there are no
errors in the calibration of the model.

<modelname>.iterlim = 0;

solve <modelname> using <solver> maximising <optimand>;

<modelname>.iterlim = 2000;

{Contributed by Rob Dellink}


4. Use the abort statement if the model specification is incorrect, that is, if you end up
with a solution that does not satisfy some condition you know that has to be satisfied;
for example, if the benchmark does not replicate, you can use:

ABORT$(<modelname>.OBJVAL GT 1E-6) "DATA CALIBRATION ERROR! LARGEST


ERROR: ", <modelname>.OBJVAL;

Or in case you know (by Walras law) that the level of C2 has to equal the level of X2:

ABORT$((C2.L-X2.L)**2 gt 1E-20) "Walras law not obeyed!";

{Contributed by Rob Dellink}

5. Always check whether your model has been normally completed and found an optimal
solution:

DISPLAY <modelname>.MODELSTAT, <modelname>.SOLVESTAT;

Both should equal 1 if the model is linear; solvestat should equal 2 for non-linear
models. You can use an abort statement if one or both is incorrect:

ABORT$(<modelname>.MODELSTAT <> 1) "Model not normally completed",


<modelname.MODELSTAT;

ABORT$(<modelname>.SOLVESTAT <> 2) "No local optimum found",


<modelname.SOLVESTAT;

{Contributed by Rob Dellink}

6. Provide starting values! If you have some clue about good values for your variables,
give that information to the GAMS model. It will avoid the often-found zero-
solution, that an optimum is found where all variables equal zero. Moreover, it will
help in avoiding infeasibilities.
You could compare specifying a model without starting values as asking a person what
"bank" means without telling them what language it is. Where should that person start
looking? "Bank" can mean many different things across different languagesTo
provide starting values, give the name of the variable, add ".L" and then specify the
indices of theat variable (remember that ".L" should come before the indices!):

VARIABLE X(J);

X.L(J) = 1;

X.L("1") = 2;

< insert model declaration etcetera here >

{Contributed by Rob Dellink}


7. If you want to comment out several lines, use the $ontext and $offtext commands.
Make a habit of starting your GAMS files withsomething like the following:

$TITLE The name of my model, version xx

$ontext

version: xx

date: dd-mm-yy

author of this version: initials

based on: previous version x

characteristics:

new in this version: compared to version x

problem1: none?!

note1: feature y still has to be included

note2: feature z may need to be modified

$offtext

{Contributed by Rob Dellink}

8. You can limit the output listing file by including the following statements:

$offsymxref

{This stops the print of a complete cros-reference list of symbols }

$offlisting

{This stops the echo print of the input file}

option limcol = 0;

{This stops the print of the column listing}

option limrow = 0;

{This stops the print of the equation listing}

{Contributed by Rob Dellink}


9. If you fix the level of a variable (variable.fx = ), dont forget to free it again:

variable.lo = -inf;

variable.up = inf;

{Contributed by Rob Dellink}

10. When you are debugging your model, try shortening the execution time by
using $exit to exclude the last part of your code: $exit will stop the GAMS
execution, command after this line (perhaps including elaborate sensititivty analysis)
will not be executed.

{Contributed by Rob Dellink}

11. If you have infeasibilities, there are (at least) three things you can do to aleviate
your problems:
1. Remove all unneccesary upper and lower bounds and fixed variables from your
code;
2. Provide better starting values;
3. Change equalities into inequalities (it is always a good thing to use inequalities in
stead of equalities).

{Contributed by Judit Szonyi and Rob Dellink}

12. Learn to use vector notation instead of scalars; it makes larger models much
more campact:

SETS J Sectors /1,2/;

VARIABLES Y(J) Production;

Instead of:

VARIABLES Y1 Producer 1

Y2 Producer 2;

For two sectors, this does not make much difference. But imagine writing out 60
sectors or more. It is much easier to use the vector notation from the start, when your
model is still small, than to have to rewrite it when you enlarge the model.

{Contributed by Rob Dellink}


13. You can use some identifiers of sets in put statements:set element label:
<setname>.tl (useful in loops)set element associated text: <setname>.te(index)

set associated text: <setname>.ts

Example:

file out /"results.out"/; put out;

set i associated text of set /i1 first element, i2 second element,


i3/;

put i.ts /;

loop(i, put i.tl, i.te(i) /);

The resulting file results.out will look like:

associated text of set

i1 first element

i2 second element

i3 I3

{Contributed by Rob Dellink}

14. To get a good insight of the impacts of a parameter value on the model results
(i.e. a sensitivity analysis), build a loop of solves for different parameter values; for
example:

SET RANGE /iter0*iter10/;

SCALARS

COUNT

LOWEST /0.1/

HIGHEST /0.9/;

PARAMETER XVALUE(RANGE) Parameter subject to sensitivity analysis

RESULTS(RANGE) Model results;

< insert model declaration etcetera here >

LOOP(RANGE,

COUNT = (ORD(RANGE)-1)/(CARD(RANGE)-1);
XVALUE(RANGE) = (1-COUNT)*LOWEST + COUNT*HIGHEST;

SOLVE <modelname> USING <solver> MAXIMISING <optimand>;

RESULTS(RANGE) = ;

);

DISPLAY RESULTS;

{Contributed by Rob Dellink}

15. How to get information on your screen in run-time? If you run several
simulations within the same GAMS model (for instance, you do a loop of solves), you
can

display "%system.filesys%/";

file screen /'con'/;

LOOP(t,

< include commands here >

putclose screen 'The current value of index t is ',t.tl/;

);

Note: this may not work properly on a Unix or Windows NT platform.

If you use the GAMS-IDE, make sure that the DOS window is visible (select File /
Options / Execute and choose Normal for the DOS window).

{Contributed by Rob Dellink}

16. If you want to get graphs of model results right after the model solve, take a
look at the GNUPLOT utility which is available on the Internet (you can access it
from the GAMS homepage); youll have to install this free utility separately.

{Contributed by Rob Dellink}

17. Many users know the $include command to include pieces of GAMS code,
but if you want to pass a parameter to the file that is to be included, use the
$batinclude command.

$BATINCLUDE FILES.INC "versionX"


and FILES.INC may look like:

$CALL 'MD %1'

FILE results /"%1\results.out"/;

SET Version /%1/;

When running the program, "%1" will be automatically substituted by "versionX". In


this example, a subdirectory versionx will be made and output directed to the file
results will be written to the file results.out in this subdirectory; finally, a set with
only one element "versionx" is declared.

{Contributed by Rob Dellink}

18. If you have a model that costs a lot of time to calculate, then think about using
the save and restart feature. This is especially handy if you have solved your model
and are thinking about ways to organise the output. You caan run your model, save the
work files from this run and restart from these workfiles for output handling. For
example, if you have a GAMS-file (say, part1.gms) in which the data is read, the
variables and equations are specified and your model is solved, then save the workfiles
as, say, model1. Then, write the output handling code in a separate file (say,
part2.gms), using the restart option. If you want to change anything in part2.gms,
you do not have to solve the model again, you can just include the workfiles. This can
save a lot of time (especially for larger models) and you can play around with how you
want your output organised at little cost. Note that this save and restart feature can also
be handy in other circumstances, like saving after solving a base scenario and then
solving several scenarios using the restarted base. The code in the example above
looks like this:

GAMS part1 s=model1

GAMS part2 r=model1

{Contributed by Rob Dellink}

19. In GAMS version 2.50 on newer, you can direct output to an Excel file via the
XLimport, XLexport and XLdump routines; see
http://nash.colorado.edu/tomruth/xllink/xllink.htm for more details. Alternatively, you
could use put statements to make output file 'manually' (see the GAMS user guide for
more details).

{contributed by Erik Schmieman and Rob Dellink}

20. When using multidimensional datasets with a restricted number of allowed


elements, you can use dynamic sets or set mapping to limit the set elements. The
following example gives a full GAMS program that shows the dynamic sets and
mapping.

$title A simple illustration of using dynamic sets


$ontext
This small example illustrates how one can limit the number of
elements
that are used in parameters by using either dynamic sets or set
mapping.
In this case, both procedures give the same results.
The example also show how the dynamic sets can be used.
$offtext
sets
x /x1*x3/
y /y1*y4/
xx(x)
yy(y)
xy(x,y);
parameter
a(x,y) the basis from which you retrieve the non-zero elements;
*Suppose you know the values of a
a(x,y) = 1;
a('x1',y) = 0;
a('x2','y2') = 0;
a('x2','y3') = 0;
a('x2','y4') = 0;
a('x3','y2') = 0;
*Determine the dynamic sets
xx(x) = yes$(sum(y, a(x,y)) ne 0);
yy(y) = yes$(sum(x, a(x,y)) ne 0);
xy(x,y) = yes$(a(x,y) ne 0);
* The same set with only non-zero elements could be retrieved through
mapping
set yx(x,y) /x2.y1, x3.(y1,y3*y4)/;
display x,y,a,xx,yy,xy,yx;
parameter
b(x,y) the whole set with values regardless of zeros in a
c(x,y) parameter b corrected for non-existent x
d(x,y) parameter b corrected for non-existent y
e(x,y) parameter b corrected for non-existent x and y
f(x,y) parameter b for only existent elements based on dynamic set xy
g(x,y) parameter b for only existent elements based on mapped set yx
h(*,*) parameter b using the dynamic set xy
sumx(y) parameter h summed over x;
b(x,y) = 1;
c(xx,y) = 1;
d(x,yy) = 1;
e(xx,yy) = 1;
f(x,y)$xy(x,y) = 1;
g(x,y)$yx(x,y) = 1;
h(xy) = 1;
sumx(y) = sum(x, h(x,y));
display b,c,d,e,f,g,h,sumx;

{Contributed by Rob Dellink and Erik Schmieman}


21. If you want to have an equation where you divide the righthand side by another
variable, you may encounter division by zero errors. Suppose you have the
equation

vv1(x,y).. v1(x,y) =e= a(x,y);

vv2(x,y)$(a(x,y) ne 0).. v2(x,y) =e= rhs/v1(x,y);

Note that the second equation can only be made conditional upon the parameter a, not
on variable v1.

In this straighforward case, you can solve the error as follows:

vv1(x,y).. v1(x,y) =e= a(x,y);

vv2(x,y)$(a(x,y) ne 0).. v2(x,y)*v1(x,y) =e= rhs;

{Contributed by Rob Dellink}

22. If you want to build multisectoral Computable General Equilibrium models,


think about using the MPSGE subsystem to GAMS. See the GAMS homepage, the
homepage of MPSGE-guru Tom Rutherford, or contact Rob Dellink.

{Contributed by Rob Dellink}

23. When doing mathematical programming where there is a chance of obtaining a


non-
unique solution, it makes sense to do "near-optimal solution space" analysis.
Basically what you do is after finding the solution, rerunning the model with a
lower bound on the initial objective variable of e.g. 99%, 97.5%, or 95% of the
optimal value and using a variety of choice variables as new objectives, both
minimising and maximising their values. This provides you with a set of
solutions that are very close to the optimal value.

The lower bound on the initial objective variable (in case of a minimisation
problem this is obviously an upper bound) should depend on the level of
variability you find in the "near-optimal solution space".

Let me refer to two articles:


Makowski, D., E.M.T. Hendrix, M.K. Van Ittersum and W.A.H. Rossing (2000)
Ecological Modelling 131:65-77.
and
Chapter 7 in my book: Kruseman, G. (2000) bio-economic modelling for
agricultural intensification. Mansholt Studies 20, Wageningen: Mansholt
Institute with Bakhuys publishers.

"near-optimal solution space" analysis is fairly simple to do in GAMS and it


gives you a lot of information about the stability of the model and the
variability of choice variables.

See GAMS example

{Contributed by Gideon Kruseman}

24. One user of the GAMS reader misspecified the capital equation in a neo-
classical growth model as follows.

He used K(t) =E= ((K0$ord(t)=1) + K(t-1)*(1-delta) + I(t);


instead of K(t) =E= (K0$(ord(t)=1) + K(t-1)*(1-delta) + I(t);

Can you find the difference between the two? The impact is enormous. I was surprised
that the top specification did not give an error message.
The lesson to be learnt: always be careful with those brackets. I love them because
they force you to think very precisely about what you want to model.

{Contributed by Rob Dellink}

25. When you model equations that contain lags or leads, e.g. EQ1(t).. A(t+1)
=E= A(t)+B(t);, and you don't restrict this equation, you will calculate A(t+1) also
for the last period t. Since this next period A is not within the model horizon, you are
not interested in it and hence the calculation is unnecesary. You can save computing
time if you restrict the function not to calculate the after-horizon period:
EQ1(t)$(ord(t) le card(t)-1).. A(t+1) =E= A(t)+B(t);

Use the constraint both on the definition and declaration of the equation!

This is especially relevant if the model is large and the equation is relatively difficult (e.g. a
lot of summing and multiplication).

{Contributed by Muhammad Al-Salamah}

You might also like