$title Steps in Debugging the MCP version of an MPSGE Model

$ontext

> Dear Tom,
>  
> I wonder if you can help me? As an educational exercise, I am
> attempting to rewrite the algebraic form of the Markusen/Rutherford
> model M1-2S in vector syntax. My attempt is attached. As you will see
> from the list file, my code replicates the benchmark. But implementing
> the tax counterfactual leads to infeasibilities in the factor market
> and income balance equations. I think the problem is in the way that I
> have implemented tax in the algebra; but neither removing the tax nor
> implementing a non-tax counterfactual (i.e. increasing the labour
> endowment) seem to help.
>  
> I hope you can tell me where I have gone wrong, but I would appreciate
> any assistance.

Back in graduate school days I shared an apartment for a couple of
years with a physicist who specialized in quantum mechanics.  His name
was Tad. He reminded me of the character Bernie who was in the early
Doonesbury comic strips.  Tad would do his quantum mechanics homework
problems in blue ballpoint pen on discarded lineprinter paper from the
computer center, the large perforated sheets which were 11"x17".  He
would furiously fill pages with closely written lines of equations.
Every so often he would groan, having discovered an error, and he
would then get out his red ballpoint pen and proceed to find and
correct his mistake.  I was always intrigued by Tad's powers of
concentration.

In contrast, I was completely intolerant of debugging math
assignments.  When I did my humble linear algebra homework sets, I
would work on one clean sheet of paper at a time.  When I found a bug,
the paper would go in the trash and I would start over again.  In
short, my idea of debugging is to start over again.

I tell you this so you won't feel bad when I tell you that I won't go
through your algebra to find your errors.  When it comes to CES
functions, I have generally found that I do this differently than is
suggested in textbooks.  My approach is based on the "calibrated share
form", as described in this paper:

http://www.gamsworld.org/mpsge/debreu/ces.pdf

Rather than try to figure out what you were trying to do in this
model, I've instead fixed your model using my approach to debugging
which is to throw out the code which doesn't work and bring in
equations that do.  The basic steps I follow when developing an
algebraic version of an MPSGE model are:

1. Implement the MPSGE model, first replicating the benchmark and then
computing one or more representative counterfactual solutions.

2. Write the equations of the corresponding GAMS/MCP model.

3. Verify that the GAMS/MCP model replicates the benchmark.

4. Verify that the GAMS/MCP model replicates the counterfactuals.

At no point prior to verifying the GAMS/MCP model do I every run the
algebraic model with a positive iteration limit.  The .iterlim=0
option is essential here because it permits me to locate precisely
which equations are in error.

It is quite common in this process to set up an algebraic model which
satisfies the benchmark equilibrium but fails to replicate a
counterfactual.  It is for this reason that it is advisable to explore
several counterfactual simulations to be sure that you have a
handshake with the MPSGE model.

With your model I have therefore:

1. Inserted the MPSGE code and replicated the benchmark equilibrium.

2. Introduced an iteration limit of zero for the algebraic model.

3. Verified that your MCP model replicates the benchmark.

4. Computed a counterfactual simulation with the MPSGE model.

5. Initiated the MCP model from the MPSGE solution to verify that the
MCP equations are not satisfied.

At this point in the debugging process, I replace one MCP equation at
a time.  I know which equations are violated based on the solution
listing.  I usually begin with the zero profit equations and then do
the income balance and market clearance conditions.

The bad news is that the following equations in your model are
invalid:
        PROFIT(I)       Zero profit condition 
        CMKT(I)         Commodity market clearance
        FMKT(F)         Factor market clearance
        I_CONS          Income = factor earnings plus taxes

The good news is that you have written two of the model equations correctly:

        PRF_W           Zero profit for aggregate consumption
        MKT_W           Market clearance for aggregate consumption

I'm not going to go through your equations.  While they probably would
be more familiar to me than Tad's quantum mechanics homework, without
strong incentives I'm just unable to work through conventional
approaches to CES functions: it's just too confusing.

$offtext 

*       Read in SAM

TABLE BENCH(*,*)  Benchmark financial flows (e.g. an input-output table)

                X       Y        W           CONS
        X     120     -20     -100    
        Y     -20     120     -100    
        W                      200           -200
        L     -40     -60                     100
        K     -60     -40                     100;

*       Declare the underlying sets:

SET     I       Produced goods          /X, Y/,
        F       Factors of production   /L, K/;

*       Use I and J to both index goods:

ALIAS (I,J), (F,FF);

PARAMETER       Y0(I)           Benchmark sectoral output,
                FD0(F,I)        Benchmark factor demands,
                VA0(i)          Benchmark value added
                II0(j,i)        Benchmark intermediate inputs
                ti0(i)          Benchmark total intermediate inputs
                C0(I)           Benchmark consumption demand, 
                E0(F)           Factor endowments, 
                T(I)            Sectoral ad-valorem tax rate, 
                H0              Benchmark total consumption;

*       Extract data from the original format into model-specific arrays:

Y0(I)         = BENCH(I,I);          
FD0(F,I)      = -BENCH(F,I);
va0(i)        = sum(f,fd0(f,i)) ;
ii0(j,i)      = -bench(j,i) ;
ii0(i,i)      = 0 ;
ti0(i)        = sum(j,ii0(j,i)) ;
C0(I)         = -BENCH(I,"W");       
H0            = SUM(I, C0(I));
E0(F)         = BENCH(F,"CONS");     
T(I)          = 0;

DISPLAY Y0, FD0, ii0, C0, E0, T;

parameter  sigma(i)  Substition elasticity between intermediates and VA /x 0.5, y 0.75/;

$ONTEXT
$MODEL: M22

$SECTORS:
        Y(i)    ! Activity level for sector Y
        W       ! Activity level for sector W (Hicksian welfare index)

$COMMODITIES:
        PC(i)   ! Price index for commodity 
        PF(f)   ! Price index for primary factor 
        PW      ! Price index for welfare (expenditure function)

$CONSUMERS:
        CONS    ! Income level for consumer CONS

$PROD:Y(i) s:sigma(i)  va:1
        O:PC(i) Q:y0(i)
        I:PC(j) Q:ii0(j,i)      
        I:PF(F) Q:fd0(f,i)      A:CONS  T:t(i)  va:

$PROD:W s:1
        O:PW   Q:200
        I:PC(i) Q:C0(i)

$DEMAND:CONS
        D:PW    Q:200
        E:PF(f) Q:e0(f)

$OFFTEXT
$SYSINCLUDE mpsgeset M22

PW.FX = 1;
$INCLUDE M22.GEN
SOLVE M22 USING MCP;

parameter       alpha(f,i)      Factor input benchmark value share
                beta(j,i)       Good input share of total intermediates
                gamma(i)        Intermediate share of total inputs
                delta(i)        Consumption value share
                sigma(i)        Substition elasticity between intermediates and VA
                theta(i)        Substition elasticity between intermediate inputs
;

alpha(f,i) = fd0(f,i) / sum(ff, fd0(ff,i));
beta(j,i) = ii0(j,i)/ti0(i) ;
gamma(i) = sum(j, ii0(j,i))/y0(i) ;
delta(i) = c0(i) / h0;
sigma('x') = 0.5 ; sigma('y') = 0.75 ;
theta(i) = 0.9 ;
display alpha, beta, delta, gamma, sigma, theta;


* Retain initial values of model variables
* (Really only so I can reset changes made for counterfactuals 
*  back to benchmark levels afterwards)

parameter
yy(i)           sectoral output
fd(f,i)         factor demands
c(i)            consumption demand
e(f)            factor endowments
h               total consumption
;
                
yy(i) = Y0(I) ;
fd(f,i) = FD0(F,I) ;
c(i) = C0(I) ;
h = h0 ;
e(f) = E0(F) ;


*       Present the algebraic syntax.  No variable declarations are 
*       needed because we use the same variables which appear in the
*       MPSGE model:

EQUATIONS
        PROFIT(I)       Zero profit condition 
        CMKT(I)         Commodity market clearance
        FMKT(F)         Factor market clearance
        PRF_W           Zero profit for aggregate consumption
        MKT_W           Market clearance for aggregate consumption
        I_CONS          Income = factor earnings plus taxes
;

PROFIT(I)..     y0(i)*( gamma(i) * ( (sum(j,beta(j,i)*pc(j)**(1-theta(i))))**(1/(1-theta(i))) )**(1-sigma(i)) +
                (1-gamma(i)) * (prod(f,pf(f)**alpha(f,i)))**(1-sigma(i)) )**(1/(1-sigma(i))) 
                =e= y0(i)*pc(i) ;

PRF_W..         h0*prod(j, pc(j)**delta(j)) =e= h0*pw ;

CMKT(I)..       y0(i)*y(i) =e= c0(i)*w*prod(j,pc(i)**delta(i))/pc(i) + sum(j, ii0(i,j)*y(j)*(pc(j)/pc(i))**sigma(j)) ;

MKT_W..         H0 * W =E= CONS / PW;

FMKT(F)..       e(f) =e= sum( i, fd0(f,i)*y(i)* (pc(i)/((1+t(i))*prod(ff,pf(f)**alpha(f,i))))**sigma(i) 
                        * prod(ff,pf(f)**alpha(f,i)) /pf(f) ) ;

I_CONS..        cons =E= sum(f,e(F)) 
                        + sum( i, t(i)*va0(i)*y(i)*prod(f,pf(f)**alpha(f,i))*( pc(i)/ ((1+t(i))
                        *prod(f,pf(f)**alpha(f,i))) )**sigma(i) ) ;


MODEL ALGEBRAIC /PROFIT.Y, PRF_W.W, CMKT.PC, FMKT.PF, MKT_W.PW, I_CONS.CONS/;

*--------------------------------------------------------------------------------------------

*       Replicate benchmark (use initial values from the MPSGE model which
*       are already loaded) 

algebraic.iterlim = 0;
SOLVE ALGEBRAIC USING MCP;

*--------------------------------------------------------------------------------------------
*       Abort if the benchmark is inconsistent:

abort$(algebraic.objval > 1e-5) "Benchmark is inconsistent.";

*--------------------------------------------------------------------------------------------
*       Compute a counterfactual equilibrium for the MPSGE model:

t('x') = 0.5 ;
$INCLUDE M22.GEN
SOLVE M22 USING MCP;

*--------------------------------------------------------------------------------------------
*       Use the MPSGE solution to diagnose which equations in the 
*       algebraic model are mis-specified:

ALGEBRAIC.iterlim = 0;
SOLVE ALGEBRAIC USING MCP;

*--------------------------------------------------------------------------------------------
$ontext

First, look only at the zero profit conditions.  We see that there are problems
with the Y sectors, but not with the W sector:

---- VAR Y  Activity level for sector Y

         LOWER          LEVEL          UPPER         MARGINAL

X          .             0.8619        +INF          -39.9559      
Y          .             1.1091        +INF             .          

                           LOWER          LEVEL          UPPER         MARGINAL

---- VAR W                   .             0.9838        +INF             .          


Rewrite this set of equations using the calibrated share form:

$offtext


EQUATIONS       PRF_Y(i)        Zero profit (based on calibrated share form);

PRF_Y(i)..      
        ( gamma(i)    * sum(j, beta(j,i) * PC(j)**(1-sigma(i))) +
         (1-gamma(i)) * prod(f, (PF(f)*(1+t(i)))**alpha(f,i))**(1-sigma(i))
        )**(1/(1-sigma(i)))
                =e= PC(i);

MODEL altalg1 /PRF_Y.Y, PRF_W.W, CMKT.PC, FMKT.PF, MKT_W.PW, I_CONS.CONS/;

*       Now we replace the original profit equation by this new one to see
*       if it fixes the Y profit conditions: 

altalg1.iterlim = 0;
SOLVE altalg1 USING MCP;

*--------------------------------------------------------------------------------------------
$ontext

Next I look at the market clearance conditions which are violated at the
equilibrium point:

---- VAR PF  Price index for primary factor

         LOWER          LEVEL          UPPER         MARGINAL

L          .             0.8412        +INF           -1.0899      
K          .             0.7871        +INF            1.7956      

Once again, use the calibrated share form of the demand functions:

$offtext

EQUATION        MKT_PF(f)       Market clearance condition for factors;

MKT_PF(f)..     e0(f) =E= sum(i, Y(i) * fd0(f,i) * 
                                  prod(ff, PF(ff)**alpha(ff,i))/PF(f)
                                * (PC(i)/prod(ff, (PF(ff)*(1+t(i)))**alpha(ff,i)))**sigma(i));

MODEL altalg2 /PRF_Y.Y, PRF_W.W, CMKT.PC, MKT_PF.PF, MKT_W.PW, I_CONS.CONS/;

ALTALG2.ITERLIM = 0;
SOLVE ALTALG2 USING MCP;

*--------------------------------------------------------------------------------------------
$ontext

Next, I note that the income equation is out of balance:

---- VAR CONS                .           196.7655        +INF          -37.1748      

Income is based on factor holdings and tax revenues.  Use the demand
functions derived above to write down the tax revenue:

$offtext

EQUATION        INCOME  Income clearance condition;

INCOME..        CONS =E= sum(f, PF(f) * e0(f)) +
                         sum((i,f), Y(i) * fd0(f,i) * PF(f) * t(i) * 
                                  prod(ff, PF(ff)**alpha(ff,i))/PF(f)
                                * (PC(i)/prod(ff, (PF(ff)*(1+t(i)))**alpha(ff,i)))**sigma(i));

MODEL altalg3 /PRF_Y.Y, PRF_W.W, CMKT.PC, MKT_PF.PF, MKT_W.PW, INCOME.CONS/;

ALTALG3.ITERLIM = 0;
SOLVE ALTALG3 USING MCP;

*--------------------------------------------------------------------------------------------
$ontext

Finally, I note that (alas) the commodity market conditions also have a bug:

---- VAR PC  Price index for commodity

         LOWER          LEVEL          UPPER         MARGINAL

X          .             1.1512        +INF          -12.9190      
Y          .             0.8687        +INF           14.8719      

Okay, we do some more algebra:

$offtext

EQUATION        MKT_PC(i)       Market clearance condition;

MKT_PC(i)..     y0(i) * Y(i) =e= sum(j, ii0(i,j) * Y(j) * (PC(j)/PC(i))**sigma(j))
                                + c0(i) * W * PW/PC(i);

MODEL altalg4 /PRF_Y.Y, PRF_W.W, MKT_PC.PC, MKT_PF.PF, MKT_W.PW, INCOME.CONS/;

ALTALG4.ITERLIM = 0;
SOLVE ALTALG4 USING MCP;

*       Voila!  We have a model which satifies one necessary condition
*       for consistency.  If the model were more complex, we'd
*       probably want to check about a dozen more cases.

*       It makes you wonder why you need to have the model in an
*       algebraic format in the first place!