* This web page documents a computational tool which has been developed within the project "Indicators and Quantitative Tools for Improving the Impact Assessment Process for Sustainability" (I.Q. Tools), 6th Framework Programme of the European Commission, Contract SSP1-CT-2003-502078, Thematic Priority 8: Policy Oriented Research.
GAMS is a modeling language designed for use by specialized analysts in a wide range of disciplines. GAMS was invented by an Austrian physicist, Alex Meeraus, for use by economists at the World Bank during the 1970s. The fundamental strngth of GAMS lies in the ease with which mathematically-defined models can be formulated and solved. GAMS itself does not provide model solutions; these tasks are delegated to a large number of subsystems, specialized algorithms for particular classes of mathematical programs. GAMS provides an intermediate set of services by translating an analyst's description of a mathematical model into a format understood by an appropriate solver.
GAMS has been designed primarily to meet the needs of the modeller rather than the needs of the modeller's client. A client for a mathematical model typically has data, a conceptual framework and a set of policy-related questions. The client contracts the modeller to formulate and analyze a model (or several models) which address the policy questions in which he is interested. The deliverables for a modeling contract typically include an operational GAMS program and a written report summarizing the mathematical details of the model and the model results. Results are typically in the form of tables or figures which compare model outcomes for alternative policies and a common set of assumptions. It would also be common practice to deliver a sensitivity analysis of model results for a particular policy, under a range of alternative parameter assumptions. For simplicity, we can name these "policy" and "sensitivity" analyses.
A model-based analysis often involves iterations between the client and the modeller in which the specific set of policy instruments and underlying parameter assumptions are defined and evaluated.
In Figure 1 the client suggests a set of policy inputs, t, which may be evaluated with the model. He also may suggest a set of assumptions for behavioral parameters, ξ, such as elasticities of substitution or long-run growth rates. The modeller takes these suggestions, revises her GAMS program accordingly, and then generates a set of tables and figures, T(t,ξ) and F(t,ξ).
It has been my experiece that clients are often disappointed with the amount of specialized knowledge required to assess a model. A written report provides only a glimpse into what has been learned in the total modelling exercise. If the modeller has good writing skills but poor programming skills, the client may very easily be mislead about the true nature of what can be learned on the basis of the calculations. On the other hand, if the modeller is a good programmer but a poor writer, the client may have a very informative model but at the same time have no idea of the policy implications of the results.
GAMS QS --p1="epsilon / 5, 10, 20/" --p2="eta /5,10,20/" --p3="etaL /5,10,20/" del output\*.lst del output\*.gdx call output\RUNGAMS.BATQS.GMS produces the batch file RUNGAMS.BAT which executes GAMS solutions for all combintations of three input parameters, representing a total of 27 different scenarios. This file appears as follows:
@echo off if not exist output\nul mkdir output\ title Solving case 1 out of 27 echo set q_inputs/"5"."5"."5"/; >output\1.gms echo $set epsilon "5" >>output\1.gms echo $set eta "5" >>output\1.gms echo $set etaL "5" >>output\1.gms echo $include model >>output\1.gms gams output\1.gms gdx=output\1 o=output\1.lst ...The ECHO command is used to generate scenario files in which input values are assigned and a set is declared which "labels" the resulting GDX file with the input assumptions. For example, program 1.gms appears as:
set q_inputs/"5"."5"."5"/; $set epsilon "5" $set eta "5" $set etaL "5" $include model
$if not set epsilon $set epsilon 10 $if not set eta $set eta 10 $if not set etaL $set etaL 10Through the use of environment variables, inputs may be either numeric or text. Furthermore, a model may have many such inputs, corresponding to the many dimensions in which sensitivity anlysis may be conducted. In any given study of a model, only a selected set of inputs may be varied.
Environment variables are treated a string substitutions in GAMS programs. Hence, if the inputs shown in this example may be referenced in the GAMS program as follows:
* Environment variables can appear in declarations: parameter etaL Elasticity of transformation for land /%etaL%/; * Environment variables can be used in assignments: eta("tex") = %eta%; epsilon("tex") = %epsilon%;
copy pivotreporttemplate.xls output\pivotreport.xls gams qr --item=hev --domain="" o=output\hev.lst xlsfile=output\pivotreport gams qr --item=quant --domain="s,item" o=output\quant.lst xlsfile=output\pivotreport gams qr --item=qpct --domain="s,item" o=output\qpct.lst xlsfile=output\pivotreport gams qr --item=gprice --domain="s,item" o=output\gprice.lst xlsfile=output\pivotreport gams qr --item=fprice --domain="factor,item" o=output\fprice.lst xlsfile=output\pivotreport
When you use QR.GMS to transfer data to Excel, it is formatted as a flat list with the expectation that these data will be used in Pivot Table and Pivot Chart reports.
Here is the PivotTable which is linked to the fprice parameter:
A Pivot Chart provides an interactive framework for formatting graphs which compare results across different scenarios. Here is the PivotChart which is produced by parameter hev:
A concise introduction is provided here. (More links are provided here.)
Many books have been written to introduce these Excel programming tools. One example is the O'Reilly book Excel 2003: The Missing Manual by Matthew MacDonald. Chapter 20 describes PivotTables and PivotCharts. (Numerous features of PivotTables are only accessible via the programmatic interface (VBA), hence books such as Writing Excel Macros by Steven Roman (O'Reilly) may also be useful.)
$title QTool Solution Program (QS.GMS) $if not set model $set model model $if not set outdir $set outdir output\ $call 'if not exist %outdir%\nul mkdir %outdir%' $if not set p1 $abort "Input parameter P1 must be defined as an environment variable." SETS $if set p1 p1 %p1% $if set p2 p2 %p2% $if set p3 p3 %p3% $if set p4 p4 %p4% $if set p5 p5 %p5% $if set p6 p6 %p6% ; file kbat /%outdir%\rungams.bat/; kbat.lw=0; kbat.nd=0; kbat.nw=0; kbat.tw=0; put kbat,'@echo off'/'if not exist %outdir%\nul mkdir %outdir%'/; file kinc /%outdir%\qr.inc/; scalar id /0/, nrun; * Branch to the appropriate loop depending on the number of items: $if not defined p2 $goto 1 $if not defined p3 $goto 2 $if not defined p4 $goto 3 $if not defined p5 $goto 4 $if not defined p6 $goto 5 $goto 6 $label 1 $if defined p3 $abort 'Did not expect p3 to be defined if p2 is not defined.' $if defined p4 $abort 'Did not expect p4 to be defined if p2 is not defined.' $if defined p5 $abort 'Did not expect p5 to be defined if p2 is not defined.' $if defined p6 $abort 'Did not expect p6 to be defined if p2 is not defined.' nrun = card(p1); loop(p1, id = id + 1; put 'title Solving case ',id,' out of ',nrun/; put 'echo set q_inputs/"',p1.tl,'"/; >%outdir%\',id,'.gms'/; put 'echo $set ',p1.ts,' "',p1.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $include %model% >>%outdir%\',id,'.gms'/; put 'gams %outdir%\',id,'.gms gdx=%outdir%\',id,' o=%outdir%\',id,'.lst'/; ); putclose; putclose kinc, '$setglobal inputs ',p1.ts/; $exit $label 2 $if defined p4 $abort 'Did not expect p4 to be defined if p3 is not defined.' $if defined p5 $abort 'Did not expect p5 to be defined if p3 is not defined.' $if defined p6 $abort 'Did not expect p6 to be defined if p3 is not defined.' nrun = card(p1)*card(p2); loop((p1,p2), id = id + 1; put 'title Solving case ',id,' out of ',nrun/; put 'echo set q_inputs/"',p1.tl,'"."',p2.tl,'"/; >%outdir%\',id,'.gms'/; put 'echo $set ',p1.ts,' "',p1.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $set ',p2.ts,' "',p2.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $include %model% >>%outdir%\',id,'.gms'/; put 'gams %outdir%\',id,'.gms gdx=%outdir%\',id,' o=%outdir%\',id,'.lst'/; ); putclose; putclose kinc, '$setglobal inputs ',p1.ts,',',p2.ts/; $exit $label 3 $if defined p5 $abort 'Did not expect p5 to be defined if p4 is not defined.' $if defined p6 $abort 'Did not expect p6 to be defined if p4 is not defined.' nrun = card(p1)*card(p2)*card(p3); loop((p1,p2,p3), id = id + 1; put 'title Solving case ',id,' out of ',nrun/; put 'echo set q_inputs/"',p1.tl,'"."',p2.tl,'"."',p3.tl,'"/; >%outdir%\',id,'.gms'/; put 'echo $set ',p1.ts,' "',p1.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $set ',p2.ts,' "',p2.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $set ',p3.ts,' "',p3.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $include %model% >>%outdir%\',id,'.gms'/; put 'gams %outdir%\',id,'.gms gdx=%outdir%\',id,' o=%outdir%\',id,'.lst'/; ); putclose; putclose kinc, '$setglobal inputs ',p1.ts,',',p2.ts,',',p3.ts/; $exit $label 4 $if defined p6 $abort 'Did not expect p6 to be defined if p5 is not defined.' nrun = card(p1)*card(p2)*card(p3)*card(p4); loop((p1,p2,p3,p4), id = id + 1; put 'title Solving case ',id,' out of ',nrun/; put 'echo set q_inputs/"',p1.tl,'"."',p2.tl,'"."',p3.tl,'"."',p4.tl,'"/; >%outdir%\',id,'.gms'/; put 'echo $set ',p1.ts,' "',p1.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $set ',p2.ts,' "',p2.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $set ',p3.ts,' "',p3.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $set ',p4.ts,' "',p4.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $include %model% >>%outdir%\',id,'.gms'/; put 'gams %outdir%\',id,'.gms gdx=%outdir%\',id,' o=%outdir%\',id,'.lst'/; ); putclose; putclose kinc, '$setglobal inputs ',p1.ts,',',p2.ts,',',p3.ts,',',p4.ts/; $exit $label 5 nrun = card(p1)*card(p2)*card(p3)*card(p4)*card(p5); loop((p1,p2,p3,p4,p5), id = id + 1; put 'title Solving case ',id,' out of ',nrun/; put 'echo set q_inputs/"',p1.tl,'"."',p2.tl,'"."',p3.tl,'"."',p4.tl,'"."',p5.tl,'"/; >%outdir%\',id,'.gms'/; put 'echo $set ',p1.ts,' "',p1.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $set ',p2.ts,' "',p2.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $set ',p3.ts,' "',p3.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $set ',p4.ts,' "',p4.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $set ',p5.ts,' "',p5.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $include %model% >>%outdir%\',id,'.gms'/; put 'gams %outdir%\',id,'.gms gdx=%outdir%\',id,' o=%outdir%\',id,'.lst'/; ); putclose; putclose kinc, '$setglobal inputs ',p1.ts,',',p2.ts,',',p3.ts,',',p4.ts,',',p5.ts/; $exit $label 6 nrun = card(p1)*card(p2)*card(p3)*card(p4)*card(p5)*card(p6); loop((p1,p2,p3,p4,p5,p6), id = id + 1; put 'title Solving case ',id,' out of ',nrun/; put 'echo set q_inputs/"',p1.tl,'"."',p2.tl,'"."',p3.tl,'"."',p4.tl,'"."',p5.tl,'"."',p6.tl,'"/; >%outdir%\',id,'.gms'/; put 'echo $set ',p1.ts,' "',p1.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $set ',p2.ts,' "',p2.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $set ',p3.ts,' "',p3.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $set ',p4.ts,' "',p4.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $set ',p5.ts,' "',p5.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $set ',p6.ts,' "',p6.tl,'" >>%outdir%\',id,'.gms'/; put 'echo $include %model% >>%outdir%\',id,'.gms'/; put 'gams %outdir%\',id,'.gms gdx=%outdir%\',id,' o=%outdir%\',id,'.lst'/; ); putclose; putclose kinc, '$setglobal inputs ',p1.ts,',',p2.ts,',',p3.ts,',',p4.ts,',',p5.ts,',',p6.ts/; $exit
$title QTool Report Program (QR.GMS) $if not set item $abort 'Expected to have an item defined.' $if not set domain $abort 'Expected to have the domain defined.' $if not set outdir $set outdir output $if not set xlsfile $set xlsfile %outdir%\pivotreport $call 'gdxmerge %outdir%\*.gdx id=%item%,q_inputs'; set q_r(*) Runs; $gdxin merged.gdx $load q_r=Merged_set_1 $if exist "%outdir%\qr.inc" $include "%outdir%\qr.inc" alias (*,%inputs%); $if "%domain%"=="" $goto nodomain $label domain alias (*,%domain%); set header /%inputs%,%domain%,value/; parameter pt_item(*,%domain%) Item to be pivoted; set inputs(*,%inputs%) Correspondence of runs to input assignments; $load pt_item=%item% inputs=q_inputs display pt_item; parameter p_item; loop(q_r, loop(inputs(q_r,%inputs%), p_item(%inputs%,%domain%) = pt_item(q_r,%domain%); )); execute_unload '%outdir%\pivotdata.gdx',p_item=%item%,header; $goto gdxxrw $label nodomain set header /%inputs%,value/; parameter pt_items(*) Item to be pivoted; set inputs(*,%inputs%) Correspondence of runs to input assignments; $load pt_items=%item% inputs=q_inputs display pt_items; parameter p_items; loop(q_r, loop(inputs(q_r,%inputs%), p_items(%inputs%) = pt_items(q_r); )); execute_unload '%outdir%\pivotdata.gdx',p_items=%item%,header; $label gdxxrw $onecho >%outdir%\gdxxrw.rsp set=header rng="%item%!a1" values=nodata cdim=1 rdim=0 par=%item% rng="%item%!a2" cdim=0 $offecho execute 'gdxxrw i="%outdir%\pivotdata.gdx" o="%xlsfile%.xls" @%outdir%\gdxxrw.rsp'; execute 'del %outdir%\pivotdata.gdx';