$title Public Infrastructure, Services and Distortionary Taxation $ontext Ghosh and Roy (2002) present a planning model incorporating both public capital (a stock) and public services (a flow) in addition to private capital and labor. In their planning framework with an omniscient social planner, nothing distinguishes public and private goods, as the planner is fully informed and optimizes on all margins. In this GAMS program I demonstrate that their portrayal of the problem may fall far short of reality. When public goods are non-excludible, there are serious constraints related to financing. Incentives effects of taxation may have a first order impact on the growth effects of accumulation. A concrete numerical example illustrates this point. Here is the model. References: Optimal Growth with Public Capital and Public Services Sugata Ghosh and Udayan Roy Economics of Planning 35: 271-292, 2002. $offtext set t Time (years) /0*100/, tf(t) First year tl(t) Last year; parameters alpha Stock share of public goods /0.3/ beta Private capital value share /0.4/ rho Intertemporal discount rate /0.03/ delta Capital depreciation rate /0.05/ k0 Base year private capital /1/ kg0 Base year public capital /1/ tax(t) Output tax in second best setting df(t) Discount factor to year t; tf(t) = yes$(ord(t)=1); tl(t) = yes$(ord(t)=card(t)); df(t) = exp(-rho*(ord(t)-1)); variables U Intertemporal utility TAU Public output share C(t) Consumption, G(t) Public services, Y(t) Output, I(t) Private Investment, IG(t) Public investment, K(t) Private capital stock, KG(t) Public capital stock, KT Terminal private capital stock, KGT Terminal public capital stock; positive variables I,IG; equations welfare, output, provision, private, public, production, termk, termkg; welfare.. U =E= - (sum(t, df(t) * log(C(t))) - sum(t, tax(t)*Y(t))); output(t).. (1-TAU) * Y(t) =e= C(t) + I(t); provision(t).. TAU*Y(t) =e= G(t) + IG(t); private(t).. k0$tf(t) + K(t-1) * (1 - delta) + I(t-1) =E= K(t); public(t).. kg0$tf(t) + KG(t-1) * (1 - delta) + IG(t-1) =E= KG(t); termk.. sum(tl, K(tl) * (1 - delta) + I(tl)) =E= KT; termkg.. sum(tl, KG(tl) * (1 - delta) + IG(tl)) =E= KGT; production(t).. (KG(t)**alpha * G(t)**(1-alpha))**(1-beta) * K(t)**beta =E= Y(t); TAU.LO = 0; TAU.UP = 1; C.L(t) = 1; G.L(t) = 1; KG.L(t) = 1; K.L(t) = 1; C.LO(t) = 0.00001; G.LO(t) = 0.00001; KG.LO(t) = 0.001; K.LO(t) = 0.001; * Begin with a naive assumption: KT.FX = 10; KGT.FX = 10; * We first evaluate the first-best: tax(t) = 0; MODEL growth /all/; SOLVE growth USING nlp MINIMIZING u; * Scale equations and variables to improve robustness: growth.scaleopt = 1; output.scale(t) = C.L(t) + I.L(t); provision.scale(t) = G.L(t) + IG.L(t); private.scale(t) = K.L(t); public.scale(t) = KG.L(t); termk.scale = KT.L; termkg.scale = KGT.L; production.scale(t) = Y.L(t); U.SCALE = max(1,U.L); TAU.SCALE = max(1,TAU.L); C.SCALE(t) = max(1,C.L(t)); G.SCALE(t) = max(1,G.L(t)); Y.SCALE(t) = max(1,Y.L(t)); I.SCALE(t) = max(1,I.L(t)); IG.SCALE(t) = max(1,IG.L(t)); K.SCALE(t) = max(1,K.L(t)); KG.SCALE(t) = max(1,KG.L(t)); SOLVE growth USING nlp MINIMIZING u; * we are not memory-constrained with this model, so we can * keep GAMS in core to minimize the time cost of loading and unloading * the program: option solvelink=2; parameter itlog Iteration log of terminal targets; set itradj Iterative adjustments of terminal capital /it0*it20/; loop(itradj, itlog(itradj,"K") = KT.L; itlog(itradj,"KG") = KGT.L; * Impose a constant growth rate over private and public capital * in the last half of the planning period: loop(tl(t), KT.FX = K.L(t-50) * (Y.L(t-40)/Y.L(t-50))**5; KGT.FX = KG.L(t-50) * (Y.L(t-40)/Y.L(t-50))**5; ); SOLVE growth USING nlp MINIMIZING u; ); display itlog; PARAMETER gamma Growth rates of primal variables; gamma(t+1,"Y") = 100 * (Y.L(t+1)/Y.L(t)-1); gamma(t+1,"C") = 100 * (C.L(t+1)/C.L(t)-1); gamma(t+1,"G") = 100 * (G.L(t+1)/G.L(t)-1); gamma(t+1,"K") = 100 * (K.L(t+1)/K.L(t)-1); gamma(t+1,"KG") = 100 * (KG.L(t+1)/KG.L(t)-1); $setglobal domain itradj $libinclude plot itlog set tlbl(t) Labels for graphical output /0,20,40,60,80,100/; $setglobal domain t $setglobal labels tlbl $libinclude plot gamma scalar taxlvl Homotopy parameter used to move the economy to a second best solution /0/; VARIABLES P(t) Private output price PG(t) Public output price MC(t) Marginal cost of production PK(t) Private capital price PKG(t) Public capital price PKT Salvage value of private capital PKGT Salvage value of public capital; POSITIVE VARIABLES PK,PKG; EQUATIONS OPTC, OPTTAU, OPTY, OPTG, OPTK, OPTKG, OPTI, OPTIG, OPTKT, OPTKGT; * Write down first-order conditions for the first-best model: OPTC(t).. P(t)*C(t) =E= df(t); OPTTAU.. sum(t, P(t)*Y(t)) =E= sum(t,PG(t)*Y(t)); OPTY(t).. MC(t) =E= (1-TAU) * P(t) + TAU * PG(t) * (1-taxlvl); OPTG(t).. PG(t) * G(t) =E= MC(t) * Y(t) * (1-alpha)*(1-beta); OPTI(t).. P(t) =E= PK(t+1) + PKT$tl(t); OPTIG(t).. PG(t) =E= PKG(t+1) + PKGT$tl(t); OPTK(t).. PK(t)*K(t) =E= (1-delta)*(PK(t+1) + PKT$tl(t)) * K(t) + beta * MC(t) * Y(t); OPTKG(t).. PKG(t)*KG(t) =e= (1-delta)*(PKG(t+1) + PKGT$tl(t)) * KG(t) + (1-beta)*alpha * MC(t) * Y(t); OPTKT.. KT =E= sum(tl(t), K(t-30) * (Y.L(t-20)/Y.L(t-30))**3); OPTKGT.. KGT =E= sum(tl(t), KG(t-30) * (Y(t-20)/Y(t-30))**3); model PUBLICMCP / OPTC.C, OUTPUT.P, PROVISION.PG, PRIVATE.PK, PUBLIC.PKG, TERMK.PKT, TERMKG.PKGT, PRODUCTION.MC, OPTTAU.TAU, OPTY.Y, OPTG.G, OPTK.K, OPTKG.KG, OPTI.I, OPTIG.IG, OPTKT.KT, OPTKGT.KGT /; P.L(t) = OUTPUT.M(t); MC.L(t) = PRODUCTION.M(t); PG.L(t) = PROVISION.M(t); PK.L(t) = PRIVATE.M(t); PKG.L(t) = PUBLIC.M(t); PKT.L = TERMK.M; PKGT.L = TERMKG.M; * Scale this model as well: PUBLICMCP.SCALEOPT = 1; P.SCALE(t) = P.L(t); MC.SCALE(t) = MC.L(t); PG.SCALE(t) = PG.L(t); PK.SCALE(t) = PK.L(t); PKG.SCALE(t) = PKG.L(t); PKT.SCALE = PKT.L; PKGT.SCALE = PKGT.L; OPTC.SCALE(t) = P.L(t)*C.L(t); OPTTAU.SCALE = sum(t, P.L(t)*Y.L(t)); OPTY.SCALE(t) = MC.L(t); OPTG.SCALE(t) = PG.L(t) * G.L(t); OPTI.SCALE(t) = P.L(t); OPTIG.SCALE(t) = PG.L(t); OPTK.SCALE(t) = PK.L(t)*K.L(t); OPTKG.SCALE(t) = PKG.L(t)*KG.L(t); OPTKT.SCALE = KT.L; OPTKGT.SCALE = KGT.L; * Our first solution simply replicates the NLP solution. It will not * be a precise solution because the terminal capital stocks are not * precisely targeted: PUBLICMCP.ITERLIM = 0; solve PUBLICMCP using MCP; * Compute a precisely targetted solution using the MCP formulation * in which non-skew symmetric systems are easily represented and solved: KT.UP = INF; KT.LO = 0; KGT.UP = INF; KGT.LO = 0; PUBLICMCP.ITERLIM = 1000000; solve PUBLICMCP using MCP; * OK, we now move to a second-best setting. First declare parameters * to be used for presenting results: PARAMETER utility Intertemporal welfare, gammac Growth rate in consumption gammay Growth rate in aggregate output gammag Growth rate in public services gammak Growth rate of private capital gammakg Growth rate of public capital invshare Investment share of public output; * Declare a set over tax rates to be applied in the second-best model. * The first-best tax rate is 55.1%, and we explore tax rates in the * second-best model ranging from 45% to 60%: set taulvl Tax rate in the second best /45*60/; alias (t,tt); * Save the first-best values for comparison: utility(taulvl,"FirstBest") = prod(t, C.L(t)**(df(t)/sum(tt,df(tt)))); gammac(t,"FirstBest") = 100 * (C.L(t+1)/C.L(t)-1); gammag(t,"FirstBest") = 100 * (G.L(t+1)/G.L(t)-1); gammay(t,"FirstBest") = 100 * (Y.L(t+1)/Y.L(t)-1); gammak(t,"FirstBest") = 100 * (K.L(t+1)/K.L(t)-1); gammakg(t,"FirstBest") = 100 * (KG.L(t+1)/KG.L(t)-1); invshare(t,"FirstBest")$(G.L(t)+IG.L(t)) = IG.L(t)/(G.L(t)+IG.L(t)); * The second-best model is difficult to solve from a poor starting * point. For this reason, it is helpful to solve a sequence of models * in which the tax rate on public provision is gradually increased from * 0 to 100%: set taxrates /0,10,20,30,40,50,60,70,80,90,100/; loop(taxrates, TAU.FX = TAU.L; taxlvl = 0.1 * (ord(taxrates)-1); solve PUBLICMCP using MCP; *$libinclude plot gamma ); display taxlvl; * Define which tax rates to plot, and define a tuple to relabel the * graphs: SET TAUPLOT(TAULVL) /45,50,55,60/; alias (uu,*); loop(taulvl, TAU.FX = 0.44 + 0.01 * ORD(taulvl); solve PUBLICMCP using MCP; utility(taulvl,"secondbest") = prod(t, C.L(t)**(df(t)/sum(tt,df(tt)))); * Save growth rates and public investment shares for selected tax rates: if (tauplot(taulvl), gammac(t,taulvl) = 100 * (C.L(t+1)/C.L(t)-1); gammag(t,taulvl) = 100 * (G.L(t+1)/G.L(t)-1); gammay(t,taulvl) = 100 * (Y.L(t+1)/Y.L(t)-1); gammak(t,taulvl) = 100 * (K.L(t+1)/K.L(t)-1); gammakg(t,taulvl) = 100 * (KG.L(t+1)/KG.L(t)-1); invshare(t,taulvl)$(G.L(t)+IG.L(t)) = IG.L(t)/(G.L(t)+IG.L(t)); ); ); set tplot(t) /0*50/; $setglobal domain tplot $setglobal gp_opt0 'set key outside width 3' $setglobal gp_opt1 "set xlabel 'year'" * Generate reports: $libinclude plot invshare $libinclude plot gammac $libinclude plot gammag $libinclude plot gammay $libinclude plot gammak $libinclude plot gammakg $setglobal domain taulvl $setglobal labels taulvl $setglobal gp_opt0 'set yrange[0:1]' $setglobal gp_opt1 "set xlabel 'tax rate'" $libinclude plot utility