2011年6月13日星期一

GAMS tips and tricks




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 didn’t 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 Rob.Dellink@wur.nl.

  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}

  1. 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}

  1. 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}

  1. 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}

  1. 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}

  1. 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 languages…To 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}

  1. 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}

  1. 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}

  1. If you fix the level of a variable (variable.fx = …), don’t forget to free it again:
variable.lo = -inf;
variable.up = inf;
{Contributed by Rob Dellink}

  1. 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}

  1. 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}

  1. 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}

  1. 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}

  1. 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}

  1. 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}

  1. 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); you’ll have to install this free utility separately.
{Contributed by Rob Dellink}

  1. 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}

  1. 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}

  1. 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}

  1. 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}

  1. 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}

  1. 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}

  1. 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. 
{Contributed by Gideon Kruseman}

  1. 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}

  1. 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}









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 didn't 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 Rob.Dellink@wur.nl.
________________________________________
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 languages¡­To 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 = ¡­), don't 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); you'll 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}