Capital accumulation problem
Consider the following capital accumulation problem, where a stochastic shock destroys are certain share of the production capital. The problem consists of the following variables:
- Production capital $K_1(t)$ before the shock (first stage), $K_2(t,s)$ after the shock at time $s$ (second stage).
- Investment in production capital in the first, $I_1(t)$, and second, $I_2(t,s)$, stage.
- Consumption $c_1(t)$ and $c_2(t,s)$ in the first and second stage. Consumption is thereby the residual of production minus the cost for investment in production capital (which is assumed to be quadratic)
\[\begin{aligned} c_1(t) &= K_1(t)^{0.5} - I_1(t)^2 \\ c_2(t,s) &= K_2(t,s)^{0.5} - I_2(t,s)^2 \end{aligned}\]
- The shock has an arrival rate of $\eta$ with the time horizon being scaled down to $T=1.0$. At the point of the shock, we assume a share $\gamma$ of production capital is being destroyed.
The social planer now maximizes the aggregated consumption over the whole time horizon. The whole problem writes as follows:
\[\begin{aligned} \max_{I_1(t),I_2(t,s)} &\int_0^T e^{\rho t}\cdot\left\{ Z_1(t)\cdot \Big[ K_1(t)^{0.5} - I_1(t)^2\Big] + Q(t) \right\} dt \\ s.t.\hspace{1cm} \dot{K_1}(t) &= I_1(t) - \delta K_1(t) &&,\qquad K_1(0) = K_1^0 \\ \dot{Z_1}(t) &= - \eta\cdot Z_1(t) &&,\qquad Z_1(0) = 1 \\ \dot{K_2}(t,s) &= I_2(t,s) - \delta K_2(t,s) &&,\qquad K_2(s,s) = (1-\gamma)\cdot K_1(s) \\ \dot{Z_2}(t,s) &= 0 &&,\qquad Z_2(s,s) = \eta\cdot Z_1(s) \\ Q(t) &= \int_0^t Z_2(t,s)\cdot \Big[ K_2(t,s)^{0.5} - I_2(t,s)^2\Big] ds \end{aligned}\]
Solution in Julia
To solve this problem with our Toolbox, we can use the main function TwoStageOptimisation
.
julia> Results = TwoStageOptimisation(UserParameters = MyPara,
ObjectiveIntegrand = U,
AggregationFunction = Q,
StateDynamic_1 = f1,
StateDynamic_2 = f2,
Shock = g,
SalvageFunction_1=S1,
SalvageFunction_2=S2)
But first we need to define the functions U, Q, f1, f2, g, S1
and S2
as well as the dictionary MyPara
.
Let us start with the dictionary.
MyPara
The dictionary MyPara
contains all relevant parameters of the model. We can initialize an empty dictionary by
julia> MyPara = Dict()
MyPara
contains information on
Model specific parameters
like $\rho$, $\eta$ and $\gamma$ in this example;
julia> MyPara["T"] = 1
julia> MyPara["rho"] = 0.05
julia> MyPara["delta"] = 0.1
julia> MyPara["eta"] = 0.5
julia> MyPara["gamma"] = 0.2
Model dimensions of controls and states
nCon
is the number of control variables in the first stage, nCon_dist
is the number of control variables in the second stage. nStat
and nStat_dist
are the dimensions of state variables before and after the shock.
julia> MyPara["nCon"] = 1
julia> MyPara["nCon_dist"] = 1
julia> MyPara["nStat"] = 2
julia> MyPara["nStat_dist"] = 2
Control boundaries and initial state values
julia> MyPara["ConMin"] = [0.0]
julia> MyPara["Con_distMin"] = [0.0]
julia> MyPara["InitStat"] = [0.1,1.0]
Algorithm specifying parameters
julia> MyPara["hstep"] = 0.05
julia> MyPara["InitLineStep"] = 1e-5
julia> MyPara["UpperLineStep"] = 1e-1
julia> MyPara["hLowBound"] = 0.01
julia> MyPara["PlotResultsIntermediateFrequency"] = 30
Information on the parameters base values, which are used if not specified differently, can be found in the section Parameters, Variables, Settings
Model functions
Now we need to specify all the functions used in the model. Any function, that is not defined is assumed to be the zero-function.
U(Con, Stat, t::Float64, Para::Dict)
covers the utility function in the first stage (without the aggregated part $Q(t)$ of the second stage). In our example this is
julia> U(Con, Stat, t::Float64, Para::Dict) = Stat[2]*(Stat[1]^0.5 - Con[1]^2)
Q(Con,Stat, t::Float64,s::Float64, Para::Dict)
contains the function which is integrated to obtain the second stage utiltiy.
julia> Q(Con,Stat, t::Float64,s::Float64, Para::Dict) = Stat[2]*(Stat[1]^0.5 - Con[1]^2)
f1(Con,Stat, t::Float64, Para::Dict)
andf2(Con,Stat, t::Float64, s::Float64, Para::Dict)
are the function of the right hand side of the state dynamics.
julia> f1(Con,Stat, t::Float64, Para::Dict) = [Con[1] - Para["delta"]*Stat[1],-Para["eta"]*Stat[2]]
julia> f2(Con,Stat, t::Float64, s::Float64, Para::Dict) = [Con[1] - Para["delta"]*Stat[1], 0]
g(Con,Stat,t::Float64, Para::Dict)
describes the transition function between the state variables in the two stages.
julia> g(Con,Stat,t::Float64, Para::Dict) = [(1-Para["gamma"])*Stat[1],Para["eta"]*Stat[2]]
S1(Stat, Para::Dict)
andS2(Stat_dist, Para::Dict)
are the salvage-function in the first and second stage. Since we have no salvage value in our toy-example, we could omit them as entries inTwoStageOptimisation
. However, we can also specifiy and enter them.
julia> S1(Stat, Para::Dict) = 0
julia> S2(Stat_dist, Para::Dict) = 0
Solve the model
Finally we can solve the model. But first, we specify, that we want to give the initial guess for the control profiles to the algorithm
julia> MyPara["LoadInits"] = true
Now we define the profiles. We can pick the dimensions across time how big we like, the controls get interpolated in the solution process. Here we decided for 100 points. We define the control profiles as entries in the Results
dictionary.
julia> Results = Dict()
julia> Results["Con"] = 4.0*ones(1,100,1)
julia> Results["Con_dist"] = 4.0*ones(100,100,1)
julia> Results = TwoStageOptimisation(Results = Results,UserParameters = MyPara,
ObjectiveIntegrand1 = U,
AggregationIntegrand2 = Q,
StateDynamic1 = f1,
StateDynamic2 = f2,
Shock12 = g,
SalvageFunction1=S1,
SalvageFunction2=S2)
Finally we can save the results in location of choice and also plot the final results. We have the option to save the plots, and they are automatically save
julia> SaveResults(Results,"CapitalAccumulation")
julia> PlotResults(Results,SavePlot = true)