* This research supported by the GAMS Applied General Equilibrium Research Fund. The software described here is designed for use with GAMS 2.50A, but it can be used with earlier GAMS systems. The authors remain responsible for any bugs which exist in this software. This software is not officially supported by GAMS Corporation.
** Please feel free to contact Collin at email@example.com with any comments/suggestions/bug reports.
The GAMS-F tool is intended to reduce complexity and improve transparency of GAMS programs without additional overhead. This tool allows the programmer to define "functions" in a GAMS program which can subsequently be substituted into parameter or equation definitions. Thus, a function may be defined in a GAMS file as
F(I) == A * K(I)**alpha * L(I)**(1-alpha)and the function can later be referenced in an equation as:
OUTPUT(I).. Y(I) =E= F(I);The preprocessor comments out the function definition and replaces the function reference as:
OUTPUT(I).. Y(I) =E= A * K(I)**alpha * L(I)**(1-alpha)This example is particularly simple. The function substitution system has some limited knowledge about GAMS syntax. For example, it knows that dummy sets referenced in a function declaration should be substituted to avoid collisions in the function reference. For example, the following would be valid:
F(I) == SUM(J, A(I,J) * Y(J)); EQ(J).. SUM(I, B(I,J) * F(I)) =E= C(J);In this case the preprocessor makes the replacement:
ALIAS(FCN000,J); EQ(J).. SUM(I, B(I,J) * (SUM(FCN000, A(I,FCN000) * Y(FCN000)))) =E= C(J);In addition to simplifying GAMS algebra, the GAMS function tool also provides some assistance for complementarity programmers.
A function may be used in place of an equation name in a mixed complementarity program model statement. For example, here is how the linear complementarity problem can be specified using the function syntax:
F(i) == q(i) + sum(j, M(i,j) * Z(j)); model lemke / F.Z /;We hope that the use of functions in MCP model definitions can clear up some of the confusion which has resulted from the initial use of oriented equations.
Command line syntax:
gams-f <input_file >output_fileThis command translates a GAMS input file with function definitions to a standard GAMS program in which function definitions are omitted and function references are replaced. The input file comes from standard input and output is written to standard output. Passing a command-line argument to GAMS-F will result in this message.
Syntax in GAMS:
$sysinclude gams-f [$exit]These statements invokes the preprocessor on the current file. The file appears as translated in the listing, but the source file itself is unaltered. The $exit statement is required for versions of GAMS prior to release 2.50a.
<func id>(args) == expression(args);where the argument list may include sets, parameters or variables. Here are a few examples:
(i) F(i) == SUM(j, alpha(i,j) * P(j)**(1-sigma))**(1/(1-sigma)); (ii) G(i,j) == PROD(t(k), a(i,j,k) * X(i,j)**alpha); (iii) H(i) == SMIN(j$(alpha(i) gt alpha(j)), a(i,j) * F(j));The preprocessor reads these function definitions and generates GAMS code which aliases any dummy sets and then makes the appropriate substitutions when the functions are referenced later in the code. Note that function definitions can reference previously defined functions.
NB: The preprocessor does not perform domain checking. Apart from counting dimensions in function references, all syntax checking is performed by the GAMS compiler on the translated code.
NB: GAMS-F uses set names FCN000, FCN001, etc. for sets and names EQN000, EQN001, etc. for MCP equations. Thus, GAMS identifiers of the form FCN??? or EQN??? are not permitted.
The preprocessor proceeds through the file in a linear fashion including any $include file which either
The output will indicate the line number of any actions taken, appending the file name of any $included file to the output.
Thus, the output for example 4 below would look like
GAMS-F Function Preprocessor Version 11/11/98 --------------------------------------------- Reading input file . . . Parsing input file . . .  Function object F compiled  Checking MODEL statement . . .  MCP conditions formulated for F . . . Writing output . . . GAMS-F terminating normally.If, for example, line 5 of the above example was
$include incfileand incfile.gms contained a function definition, this would be reflected in output as
 Examining file incfile.gms . . .  Including file incfile.gms . . .  Function object FCN1 compiled (INCFILE.GMS)
If you would like to examine the file produced by GAMS-F prior to GAMS compilation, you may use the syntax
gams-f.pl <input.gms >output.gmsin Unix or
gams-f <input.gms >output.gmsin Windows where input.gms is the name of your GAMS file and output.gms is the name of a file to which the GAMS-F output will be sent.
gams-f.gms GAMS sysinclude program file gams-f.pl Perl source code gams-f.exe Executable program for Windows (95/98/NT) (Windows only) perl.dll Perl dynamic link library called by gams-f (Windows only) cw3220mt.dll Perl dynamic link library called by gams-f (Windows only)If you are running a version of GAMS earlier than 2.50A, you need to edit the gams-f.gms file. Change the line which reads:
$hidden $stopAfter this change has been made, you need to invoke $sysinclude gams-f followed by an $exit statement.
Unix users should note that the gams-f.pl shebang assumes Perl is in /usr/local/bin.
$sysinclude gams-f $exit * Define the function F(X) F(X) == 2 * SIN(X/4); file kcon /con/; putclose kcon // "F when X is 3.14159: ", F(3.14159) //; putclose kcon // "F when X is 2*3.14159: ", F(2*3.14159) /;The output:
--- Starting compilation --- .GAMS-F.GMS(0) 143 Kb --- Running the GAMS function preprocessor ... GAMS-F Function Preprocessor 12/04/98 11:07 by Collin Starkweather and Thomas F. Rutherford ----------------------------------------------- Reading input file . . . Parsing input file . . .  Function object F compiled  Performing substitution of function F  Performing substitution of function F Writing output . . . GAMS-F terminating normally. --- ..GAMS-F.SCR(25) 147 Kb --- .GAMS-F.GMS(19) 147 Kb --- FUNCTION.GMS(2) 147 Kb --- Starting execution --- FUNCTION.GMS(21) 134 Kb F when X is 3.14159: 1.41 --- FUNCTION.GMS(30) 134 Kb F when X is 2*3.14159: 2.00 *** Status: Normal completion --- Erasing scratch filesExample 1: Functions Cannot Appear in Display Statements
$sysinclude gams-f $exit set i /1*10/; alias (i,j); parameter a(i,j) random matrix x(i) a vector function; a(i,j) = uniform(0,1); f(i) == sum(j, a(i,j)); * A function cannot be displayed -- you must * assign a parameter to do this: x(i) = f(i); display x;Example 2: Functions in PUT Statements are OK
$sysinclude gams-f $exit set i /1*10/; alias (i,j); parameter a(i,j) random matrix; a(i,j) = uniform(0,1); f(i) == sum(j, a(i,j)); * A function can be inserted into a PUT * statement: file kout /example2.out/; put kout; loop(i, put i.tl, f(i)/; );Example 3: Set Aliasing and Substitution
$sysinclude gams-f $exit set i /1*10/; alias (i,j); parameter a(i,j) random matrix; a(i,j) = uniform(0,1); f(i) == sum(j, a(i,j)); * GAMS-F substitutes dummy sets in the * definition so you don't need to worry * about which sets are used in the definition: parameter b(i,j) A second matrix; b(i,j) = a(i,j) + f(i); display b;Example 4: Using GAMS-F with MCP Models
$sysinclude gams-f $exit set i /1*3/; alias (i,j); parameter m(i,j) LCP data matrix q(i) LCP data vector; * Some random data (will this be a * P-matrix?) m(i,j) = uniform(0,1); q(i) = uniform(0,1); * Define the LCP function -- notice that we * can refer to z here even though it has not * yet been declared. Z must, however, be * declared prior to referencing f: f(i) == q(i) + sum(j, m(i,j) * z(j)); positive variable z(i) LCP unknonw; model lcp /f.z/; solve lcp using mcp;Example 5: A Perverse Example
$sysinclude gams-f $exit set i /1*10/; set j(i) /1*5/; parameter a(i,j); a(i,j) = 1; parameter b(i); * Notice that the j appear as a qualifier on * the sum over i is uncontrolled: x(j) == sum(i$j(i), a(i,j)); b(j) = x(j); display b;Example 6: An Example with Parameter Arguments
$sysinclude gams-f $exit set i goods /1*100/; alias (i,j); parameter pi Market prices t Tax rates tunif Uniform tax p0 Benchmark user price theta Benchmark value share; * Dummy data: pi(i) = uniform(0,2); t(i) = uniform(0,0.2); p0(i) = pi(i) * (1 + t(i)); theta(i) = p0(i) / sum(j, p0(j)); scalar sigma Elasticity of substitution /3/; * Define an expenditure function -- note that p is used as a * dummy argument here, even though it is in the GAMS symbol * table: e(pi,t) == sum(i, theta(i) * (pi(i)*(1+t(i))/p0(i))**(1-sigma))**(1/(1-sigma)); parameter expend functions at difference prices; expend("p0") = e(pi,t); tunif(i) = sum(j, t(j)) / card(j); expend("uniform") = e(pi,tunif); t(i) = 0; expend("notax") = e(pi,t); display expend;Example 7: A Larger Example
$title Simple 2 x 2 x 2 General Equilibrium Model (TWO3MCP,SEQ=131) * Invoke the function preprocessor. The $exit following this * call is required for versions of GAMS earlier than 2.50A. $sysinclude gams-f $exit * Reference: Shoven and Whalley: "Applied G.E. Models" * Journal of Economic Literature, XXII (1984) sets f factors /labor, capital/ s sectors /mfrs, nonmfrs/ h households /rich, poor/; alias (h,k), (s,ss), (f,ff); * * demand function parameters. * parameter sigmac(h) / rich 1.5 , poor 0.75/; table alpha(s,h) rich poor mfrs 0.5 0.3 nonmfrs 0.5 0.7; table e(f,h) rich poor labor 60 capital 25 * * production function parameters. * parameter phi(s) / mfrs 1.5, nonmfrs 2.0 /; table delta(f,s) mfrs nonmfrs labor 0.6 0.7 capital 0.4 0.3; parameter sigma(s) / mfrs 2.0, nonmfrs 0.5/; parameter tshr(h) share of tax revenue /rich 0.4, poor 0.6/, t(f,s) ad-valorem tax rates; t(f,s) = 0; positive variables w(f) factor price, p(s) commodity price, y(s) production level; pf(f,s) == w(f)*(1+t(f,s)); cost(s) == sum(f, delta(f,s)**sigma(s) * pf(f,s)**(1 - sigma(s)) )**(1/(1-sigma(s))) / phi(s); fd(f,s) == (delta(f,s) * cost(s) / pf(f,s))**sigma(s); fmkt(f) == sum(h, e(f,h)) - sum(s, fd(f,s) * y(s)); tax(s) == sum(f, t(f,s) * w(f) * y(s) * fd(f,s)); income(h) == sum(f, e(f,h) * w(f)) + tshr(h) * sum(s, tax(s)); d(s,h) == alpha(s,h) * income(h) * sum(ss, alpha(ss,h) * p(ss)**(sigmac(h)-1)) * p(s)**(-sigmac(h)); cmkt(s) == y(s) - sum(h, d(s,h)); profit(s) == cost(s) - p(s); model jel / fmkt.w, cmkt.p, profit.y/; * compute solution for this dimension problem: w.lo(f) = 0.0001; p.lo(s) = 0.0001; w.l(f) = 1; p.l(s) = 1; y.l(s) = 1; * Use labor as numeraire: w.fx("labor") = 1; * solve the reference case: solve jel using mcp; * apply tax in test problem: t("capital","mfrs") = 0.5; solve jel using mcp;