2019-08-05 by Yinshan, list of changes made:
Merged generate_x_sequence
into one method
Added initializing steps to generate_sequence
method to eliminate the need of redefining instance for every plot
Removed unnecessary import
commands
Changed comment to docstring for the class SolowKappa
Changed $\alpha$ to $\alpha'$ in calculation of $\kappa$
Effect: slight change in $\kappa$ value for each time period (converge slower to the steady state), but no change in general convergence behavior
Modified unpacking commands for self variables, removed unused ones and added used ones
Factor accumulation:
(1) $ \frac{dL_t}{dt} = nL_t $
(2) $ \frac{dE_t}{dt} = gE_t $
(3) $ \frac{dK_t}{dt} = sY_t - δK_t $
Production function:
(4) $ Y_t = K_t^α(L_tE_t)^{(1-α)} $
Definition of capital-output ratio:
(5) $ κ_t = \frac{K_t}{Y_t} $
Solving for the rate of change of the capital-output ratio:
(6) $ Y_t = κ_t^{(α/(1-α))}(L_tE_t) $
(7) $ \frac{1}{K_t}\frac{dK_t}{dt} = \frac{s}{κ_t} - δ $
(8) $ \frac{1}{Y_t}\frac{dY_t}{dt} = α \left( \frac{1}{K_t}\frac{dK_t}{dt} \right) + (1-α)(n+g) $
(9) $ \frac{1}{κ_t}\frac{dκ_t}{dt} = \frac{1}{K_t}\frac{dK_t}{dt} - α \left( \frac{1}{K_t}\frac{dK_t}{dt} \right) - (1-α)(n+g) $
(10) $ \frac{1}{κ_t}\frac{dκ_t}{dt} = (1- α) \left( \frac{1}{K_t}\frac{dK_t}{dt} \right) - (1-α)(n+g) $
(11) $ \frac{1}{κ_t}\frac{dκ_t}{dt} = (1- α) \left( \frac{s}{κ_t} - δ \right) - (1-α)(n+g) $
(12) $ \frac{dκ_t}{dt} = (1- α) \left( s - (n+g+δ)κ_t \right) $
Integrating:
(13) $ κ_t = \frac{s}{n+g+δ} + e^{-(1-α)(n+g+δ)t} \left[ κ_0 - \frac{s}{n+g+δ} \right] $
Discretizing for a difference model:
(14) $ κ_{t+1} = κ_t + \left[ \frac{1 - e^{-(1-α)(n+g+δ)}}{n+g+δ} \right] \left( s - (n+g+δ)κ_t \right) $
(15) $ 1 - α' = (1 - α) [ 1 - \frac{(1-α)(n+g+δ)}{2} + \frac{(1-α)^2(n+g+δ)^2}{6} - ... ] $
(16) $ κ_{t+1} = κ_t + (1- α') \left( s - (n+g+δ)κ_t \right) $
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
class SolowKappa:
"""
Implements the Solow growth model calculation of the
capital-output ratio κ and other model variables
using the update rule:
κ_{t+1} = κ_t + (1- α) ( s - (n+g+δ)κ_t )
"""
def __init__(self, n=0.01, # population growth rate
s=0.20, # savings rate
δ=0.03, # depreciation rate
α=1/3, # share of labor
g=0.01, # productivity
κ=1.0, # current capital-labor ratio
E=1.0, # current efficiency of labor
L=1.0): # current labor force
self.n, self.s, self.δ, self.α, self.g = n, s, δ, α, g
self.κ, self.E, self.L = κ, E, L
self.Y = self.κ**(self.α/(1-self.α))*self.E*self.L
self.K = self.κ * self.Y
self.y = self.Y/self.L
self.α1 = 1-((1-np.exp((self.α-1)*(self.n+self.g+self.δ)))/(self.n+self.g+self.δ))
self.initdata = vars(self).copy()
def calc_next_period_kappa(self):
"Calculate the next period capital-output ratio."
# Unpack parameters (get rid of self to simplify notation)
n, s, δ, α1, g, κ= self.n, self.s, self.δ, self.α1, self.g, self.κ
# Apply the update rule
return (κ + (1 - α1)*( s - (n+g+δ)*κ ))
def calc_next_period_E(self):
"Calculate the next period efficiency of labor."
# Unpack parameters (get rid of self to simplify notation)
E, g = self.E, self.g
# Apply the update rule
return (E * np.exp(g))
def calc_next_period_L(self):
"Calculate the next period labor force."
# Unpack parameters (get rid of self to simplify notation)
n, L = self.n, self.L
# Apply the update rule
return (L*np.exp(n))
def update(self):
"Update the current state."
self.κ = self.calc_next_period_kappa()
self.E = self.calc_next_period_E()
self.L = self.calc_next_period_L()
self.Y = self.κ**(self.α/(1-self.α))*self.E*self.L
self.K = self.κ * self.Y
self.y = self.Y/self.L
def steady_state(self):
"Compute the steady state value of the capital-output ratio."
# Unpack parameters (get rid of self to simplify notation)
n, s, δ, g = self.n, self.s, self.δ, self.g
# Compute and return steady state
return (s /(n + g + δ))
def generate_sequence(self, t, var = 'κ', init = True):
"Generate and return time series of selected variable. Variable is κ by default. Start from t=0 by default."
path = []
# initialize data
if init == True:
for para in self.initdata:
setattr(self, para, self.initdata[para])
for i in range(t):
path.append(vars(self)[var])
self.update()
return path
T = 60
s1 = SolowKappa()
s2 = SolowKappa(κ=8.0)
fig, ax = plt.subplots(figsize=(9, 6))
# Plot the common steady-state value of the capital-output ratio
ax.plot([s1.steady_state()]*T, 'k-', label='steady state')
# Plot time series for each economy
for s in s1, s2:
lb = f'capital-output series from initial state κ = {s.κ}'
ax.plot(s.generate_sequence(T), 'o-', lw=2, alpha=0.5, label=lb)
ax.legend()
plt.show()
fig, ax = plt.subplots(figsize=(9, 6))
# Plot time series for each economy
for s in s1, s2:
lb = f'efficiency-of-labor series from initial state κ = {s.κ}'
ax.plot(s.generate_sequence(T, var='E'), 'o-', lw=2, alpha=0.5, label=lb)
ax.legend()
plt.show()
fig, ax = plt.subplots(figsize=(9, 6))
# Plot time series for each economy
for s in s1, s2:
lb = f'labor-force series from initial state κ = {s.κ}'
ax.plot(s.generate_sequence(T, var = 'L'), 'o-', lw=2, alpha=0.5, label=lb)
ax.legend()
plt.show()
fig, ax = plt.subplots(figsize=(9, 6))
# Plot time series for each economy
for s in s1, s2:
lb = f'capital-stock series from initial state κ = {s.κ}'
ax.plot(s.generate_sequence(T, var = 'K'), 'o-', lw=2, alpha=0.5, label=lb)
ax.legend()
plt.show()
fig, ax = plt.subplots(figsize=(9, 6))
# Plot time series for each economy
for s in s1, s2:
lb = f'output series from initial state κ = {s.κ}'
ax.plot(s.generate_sequence(T, var = 'Y'), 'o-', lw=2, alpha=0.5, label=lb)
ax.legend()
plt.show()
fig, ax = plt.subplots(figsize=(9, 6))
# Plot time series for each economy
for s in s1, s2:
lb = f'output-per-worker series from initial state κ = {s.κ}'
ax.plot(s.generate_sequence(T, var = 'y'), 'o-', lw=2, alpha=0.5, label=lb)
ax.legend()
plt.show()