$title A Successive Recalibration Algorithm for GE Models with Many Households
$ontext
This program constitutes explicit documentation of the solution
algorithm used to solve a general equilibrium model of the economic
effects of Russia's accession to the WTO based on Goskomstat's
consumer expenditure survey. That model has 55094 households. For
further details, see the working paper:
Poverty Effects of Russias WTO Accession: modeling real households
and endogenous productivity effects
Thomas Rutherford, University of Colorado
David Tarr, The World Bank
Oleksandr Shepotylo, University of Maryland
September, 2004
Contact: dtarr@worldbank.org
This is a small GAMS program which formulates a simple exchange model
with multiple households and shows how the model can be solved either
in "bottom-up" mode (with an explicit representation of the consumer
demands in the model) or through successive computation of a
"top-down" model.
The default configuration of this model has 1000 households. The
program output is the reporting parameter itrlog which should be
displayed as follows:
---- 459 PARAMETER itrlog Equilibrium price levels
bottomup iter0 iter1 iter2 iter3 iter4 iter5
i1 0.96239 0.95735 0.96309 0.96230 0.96241 0.96239 0.96239
i2 0.99602 0.99546 0.99607 0.99601 0.99602 0.99602 0.99602
i3 1.00449 1.00511 1.00439 1.00451 1.00449 1.00450 1.00449
i4 1.05347 1.05983 1.05275 1.05355 1.05346 1.05347 1.05347
i5 0.98992 0.98869 0.99005 0.98990 0.98992 0.98992 0.98992
i6 1.01483 1.01677 1.01456 1.01487 1.01483 1.01483 1.01483
i7 1.00364 1.00420 1.00353 1.00365 1.00363 1.00364 1.00364
i8 0.93811 0.93088 0.93903 0.93800 0.93813 0.93811 0.93812
i9 1.02511 1.02800 1.02476 1.02515 1.02510 1.02511 1.02511
i10 1.01202 1.01371 1.01176 1.01206 1.01201 1.01202 1.01202
CPU 0.36100 0.03000 0.04000 0.03000 0.03000 0.03000 0.02000
delta 0.25639 0.03186 0.00407 0.00052 0.00007 8.740106E-6
Rows labelled i1 to i10 report equilibrium prices from various models.
"bottomup" presents equilibrium prices for the integrated model in
which each of the households is explicitly modelled. The columns
labelled "iter0", "iter1", etc. report equilibrium prices returned for
successive steps in the approximation procedure. Notice that the
bottom up model agrees to five decimals the last three iterations of
the decomposition procedure.
The row labelled "CPU" reports elapsed time (calculated using the GAMS
internal function "system.timeexec") required to process each of the
models. (Notice that even with as few as 1000 households, the
decomposition procedure is much faster than the integrated bottom-up
model.)
The row labelled "delta" reports the computed deviation at each step
in the decomposition procedure. This deviation is the 1-norm of
changes in computed equilibrium prices from one iteration to the next.
The decomposition algorithm is terminated when delta falls below 1e-5
$offtext
* Define the dimensions of the model here:
$if not set nhh $set nhh 1000
set h Households /h1*h%nhh%/,
i Commodities /i1*i10/;
alias (i,j);
* Use randomly generated input data:
parameter c0(i,h) Reference consumption levels,
e0(i,h) Commodity endowments,
timestart Run time
sigma(h) Elasticities of substitution in demand;
c0(i,h) = uniform(0,1);
e0(i,h) = uniform(0,1);
sigma(h) = uniform(0.25, 2);
* Avoid the tedium of coding both Cobb-Douglas and CES
* demand functions:
sigma(h)$(abs(sigma(h)-1) < 0.01) = 0.99;
display c0, e0, sigma;
* Declare and solve a model with a fully disaggregate
* set of households:
$ontext
$model:bottomup
$commodities:
P(i)
$consumers:
HH(h)
$demand:HH(h) s:sigma(h)
e:P(i) q:e0(i,h)
d:P(i) q:c0(i,h)
$offtext
$sysinclude mpsgeset bottomup
equations mkt(i) Market clearance equation for p(i)
inc(h) Income balance equation;
parameter theta(i,h) Budget share,
hh0(h) Benchmark income level;
* Compute the benchmark budget shares:
theta(i,h) = c0(i,h)/sum(j,c0(j,h));
hh0(h) = sum(i, c0(i,h));
alias (i,i_);
$macro P_C(h) (sum(i_, theta(i_,h)*P(i_)**(1-sigma(h)))**(1/(1-sigma(h))))
mkt(i).. sum(h,e0(i,h)) =e= sum(h, c0(i,h)*(P_C(h)/P(i))**sigma(h) * HH(h)/(P_C(h)*hh0(h)));
inc(h).. HH(h) =e= sum(i, P(i)*e0(i,h));
model bottomup_mcp /mkt.P, inc.HH/;
* When an MPSGE model is formulated with high dimensionality, it is
* often necessary to manually increase the allocated workspace. Here
* I am allocating 50 megabytes to the workspace array, a value which
* is adequate for more than 10,000 households:
bottomup.workspace = 50;
* Solve the bottom-up model in a single shot:
* Normalize the price system by fixing one income level:
HH.FX("h1") = sum(i,e0(i,"h1"));
* Install a lower bound to avoid bad function calls:
P.LO(i) = 1e-5;
timestart = system.timeexec;
$if not set mpsge $set mpsge no
$ifthen.bottomup "%mpsge%"=="yes"
$include bottomup.gen
solve bottomup using mcp;
$else.bottomup
solve bottomup_mcp using mcp;
$endif.bottomup
parameter itrlog(*,*) Equilibrium price levels;
itrlog("CPU","bottomup") = system.timeexec - timestart;
itrlog(i,"bottomup") = P.L(i) * card(i) / sum(j, P.L(j));
* Next, solve the same model recursively using the
* successive recalibration algorithm:
* The top-down model is based on a single representative
* agent whose preferences are successively adjusted to
* locally portray the "community indifference curve" which
* describes the underlying household endowments and preferences:
parameter
pc(h) Household consumption price index,
u(h) Household utility index (relative to c0),
pref(i) Reference price
cref(i) Reference demand quantity;
* Initially calibrate the community indifference curve
* based on a price point at the center of the simplex:
u(h) = sum(i, e0(i,h))/sum(i,c0(i,h));
cref(i) = sum(h, c0(i,h) * u(h));
pref(i) = 1;
* Here is the top-down model. Note that the h set does
* not appear in this model:
$ontext
$model:topdown
$commodities:
P(i) ! Commodity prices
$consumers:
RA ! Reprsentative agent:
* Preferences are Cobb-Douglas:
$demand:RA s:1
e:P(i) q:(sum(h,e0(i,h)))
d:P(i) q:cref(i) p:pref(i)
$offtext
$sysinclude mpsgeset topdown
equations inc_topdown, mkt_topdown;
inc_topdown.. RA =e= sum((i,h), P(i)*e0(i,h));
$macro alpha(i) (cref(i)*pref(i)/sum(i_,cref(i_)*pref(i_)))
mkt_topdown(i).. sum(h, e0(i,h)) =e= alpha(i) * RA/P(i);
model topdown_mcp /inc_topdown.RA, mkt_topdown.P/;
* Fix aggregate income to normalize the price system:
RA.FX = sum(h, HH.L(h));
set iter Iterations in the projection algorithm /iter0*iter10/;
parameter delta Convergence metric /1/;
* Loop until we have drive the sum of absolute price changes
* to a small level:
loop(iter$(delta > 1e-5),
* Within each iteration we solve the top-down model. Note that
* each solution is very cheap because the model is small and the
* previous iteration's solution is already in place:
timestart = system.timeexec;
$ifthen.iter "%mpsge%"=="yes"
$include topdown.gen
solve topdown using mcp;
$else.iter
solve topdown_mcp using mcp;
$endif.iter
itrlog("CPU",iter) = system.timeexec - timestart;
* Record the current deviation:
delta = sum(i, abs(P.L(i)-pref(i)));
itrlog("delta",iter) = delta;
* Update the iteration log:
itrlog(i,iter) = P.L(i) * card(i) / sum(j, P.L(j));
* Recalibrate preferences of the representative agent based on
* demands of the individual households:
pc(h) = sum(i, theta(i,h) * P.L(i)**(1-sigma(h)))**(1/(1-sigma(h)));
* Utility index for household h (relative to c0):
u(h) = sum(i, e0(i,h)*P.L(i))/(pc(h)*sum(i,c0(i,h)));
* Reference consumption level for the representative agent:
cref(i) = sum(h, c0(i,h) * u(h) * (pc(h)/P.L(i))**sigma(h));
pref(i) = P.L(i);
);
option itrlog:5;
display itrlog;