25. The Solow-Swan Growth Model#

In this lecture we review a famous model due to Robert Solow (1925–2023) and Trevor Swan (1918–1989).

The model is used to study growth over the long run.

Although the model is simple, it contains some interesting lessons.

We will use the following imports.

import matplotlib.pyplot as plt
import numpy as np

25.1. The model#

In a Solow–Swan economy, agents save a fixed fraction of their current incomes.

Savings sustain or increase the stock of capital.

Capital is combined with labor to produce output, which in turn is paid out to workers and owners of capital.

To keep things simple, we ignore population and productivity growth.

For each integer t0t \geq 0, output YtY_t in period tt is given by Yt=F(Kt,Lt)Y_t = F(K_t, L_t), where KtK_t is capital, LtL_t is labor and FF is an aggregate production function.

The function FF is assumed to be nonnegative and homogeneous of degree one, meaning that

F(λK,λL)=λF(K,L)for all λ0 F(\lambda K, \lambda L) = \lambda F(K, L) \quad \text{for all } \lambda \geq 0

Production functions with this property include

  • the Cobb-Douglas function F(K,L)=AKαL1αF(K, L) = A K^{\alpha} L^{1-\alpha} with 0α10 \leq \alpha \leq 1.

  • the CES function F(K,L)={aKρ+bLρ}1/ρF(K, L) = \left\{ a K^\rho + b L^\rho \right\}^{1/\rho} with a,b,ρ>0a, b, \rho > 0.

Here, α\alpha is the output elasticity of capital and ρ\rho is a parameter that determines the elasticity of substitution between capital and labor.

We assume a closed economy, so aggregate domestic investment equals aggregate domestic saving.

The saving rate is a constant ss satisfying 0s10 \leq s \leq 1, so that aggregate investment and saving both equal sYts Y_t.

Capital depreciates: without replenishing through investment, one unit of capital today becomes 1δ1-\delta units tomorrow.

Thus,

Kt+1=sF(Kt,Lt)+(1δ)Kt K_{t+1} = s F(K_t, L_t) + (1 - \delta) K_t

Without population growth, LtL_t equals some constant LL.

Setting kt:=Kt/Lk_t := K_t / L and using homogeneity of degree one now yields

kt+1=sF(Kt,L)L+(1δ)KtL=sF(Kt,L)L+(1δ)kt=sF(kt,1)+(1δ)kt k_{t+1} = s \frac{F(K_t, L)}{L} + (1 - \delta) \frac{K_t}{L} = s \frac{F(K_t, L)}{L} + (1 - \delta) k_t = s F(k_t, 1) + (1 - \delta) k_t

With f(k):=F(k,1)f(k) := F(k, 1), the final expression for capital dynamics is

(25.1)#kt+1=g(kt) where g(k):=sf(k)+(1δ)k k_{t+1} = g(k_t) \text{ where } g(k) := s f(k) + (1 - \delta) k

Our aim is to learn about the evolution of ktk_t over time, given an exogenous initial capital stock k0k_0.

25.2. A graphical perspective#

To understand the dynamics of the sequence (kt)t0(k_t)_{t \geq 0} we use a 45-degree diagram.

To do so, we first need to specify the functional form for ff and assign values to the parameters.

We choose the Cobb–Douglas specification f(k)=Akαf(k) = A k^\alpha and set A=2.0A=2.0, α=0.3\alpha=0.3, s=0.3s=0.3 and δ=0.4\delta=0.4.

The function gg from (25.1) is then plotted, along with the 45-degree line.

Let’s define the constants.

A, s, alpha, delta = 2, 0.3, 0.3, 0.4
x0 = 0.25
xmin, xmax = 0, 3

Now, we define the function gg.

def g(A, s, alpha, delta, k):
    return A * s * k**alpha + (1 - delta) * k

Let’s plot the 45-degree diagram of gg.

def plot45(kstar=None):
    xgrid = np.linspace(xmin, xmax, 12000)

    fig, ax = plt.subplots()

    ax.set_xlim(xmin, xmax)

    g_values = g(A, s, alpha, delta, xgrid)

    ymin, ymax = np.min(g_values), np.max(g_values)
    ax.set_ylim(ymin, ymax)

    lb = r'$g(k) = sAk^{\alpha} + (1 - \delta)k$'
    ax.plot(xgrid, g_values,  lw=2, alpha=0.6, label=lb)
    ax.plot(xgrid, xgrid, 'k-', lw=1, alpha=0.7, label=r'$45^{\circ}$')

    if kstar:
        fps = (kstar,)

        ax.plot(fps, fps, 'go', ms=10, alpha=0.6)

        ax.annotate(r'$k^* = (sA / \delta)^{(1/(1-\alpha))}$',
                 xy=(kstar, kstar),
                 xycoords='data',
                 xytext=(-40, -60),
                 textcoords='offset points',
                 fontsize=14,
                 arrowprops=dict(arrowstyle="->"))

    ax.legend(loc='upper left', frameon=False, fontsize=12)

    ax.set_xticks((0, 1, 2, 3))
    ax.set_yticks((0, 1, 2, 3))

    ax.set_xlabel('$k_t$', fontsize=12)
    ax.set_ylabel('$k_{t+1}$', fontsize=12)

    plt.show()
plot45()
_images/eb2a0ba00ca8d7a87326646dfcc72fd65d591f85b30fd9993efc3e91ac1e034b.png

Suppose, at some ktk_t, the value g(kt)g(k_t) lies strictly above the 45-degree line.

Then we have kt+1=g(kt)>ktk_{t+1} = g(k_t) > k_t and capital per worker rises.

If g(kt)<ktg(k_t) < k_t then capital per worker falls.

If g(kt)=ktg(k_t) = k_t, then we are at a steady state and ktk_t remains constant.

(A steady state of the model is a fixed point of the mapping gg.)

From the shape of the function gg in the figure, we see that there is a unique steady state in (0,)(0, \infty).

It solves k=sAkα+(1δ)kk = s Ak^{\alpha} + (1-\delta)k and hence is given by

(25.2)#k:=(sAδ)1/(1α) k^* := \left( \frac{s A}{\delta} \right)^{1/(1 - \alpha)}

If initial capital is below kk^*, then capital increases over time.

If initial capital is above this level, then the reverse is true.

Let’s plot the 45-degree diagram to show the kk^* in the plot.

kstar = ((s * A) / delta)**(1/(1 - alpha))
plot45(kstar)
_images/fc30c38bacfd4aa9f3343cbf24614d332f18cc531cca19de891e9ba0d220de54.png

From our graphical analysis, it appears that (kt)(k_t) converges to kk^*, regardless of initial capital k0k_0.

This is a form of global stability.

The next figure shows three time paths for capital, from three distinct initial conditions, under the parameterization listed above.

At this parameterization, k1.78k^* \approx 1.78.

Let’s define the constants and three distinct initial conditions

A, s, alpha, delta = 2, 0.3, 0.3, 0.4
x0 = np.array([.25, 1.25, 3.25])

ts_length = 20
xmin, xmax = 0, ts_length
ymin, ymax = 0, 3.5
def simulate_ts(x0_values, ts_length):

    k_star = (s * A / delta)**(1/(1-alpha))
    fig, ax = plt.subplots(figsize=[11, 5])
    ax.set_xlim(xmin, xmax)
    ax.set_ylim(ymin, ymax)

    ts = np.zeros(ts_length)

    # simulate and plot time series
    for x_init in x0_values:
        ts[0] = x_init
        for t in range(1, ts_length):
            ts[t] = g(A, s, alpha, delta, ts[t-1])
        ax.plot(np.arange(ts_length), ts, '-o', ms=4, alpha=0.6,
                label=r'$k_0=%g$' %x_init)
    ax.plot(np.arange(ts_length), np.full(ts_length,k_star),
            alpha=0.6, color='red', label=r'$k^*$')
    ax.legend(fontsize=10)

    ax.set_xlabel(r'$t$', fontsize=14)
    ax.set_ylabel(r'$k_t$', fontsize=14)

    plt.show()
simulate_ts(x0, ts_length)
_images/cbc9f4786772249302319ae8e7a37935cad9515e3ec072122ccfb57cb38dadfe.png

As expected, the time paths in the figure all converge to kk^*.

25.3. Growth in continuous time#

In this section, we investigate a continuous time version of the Solow–Swan growth model.

We will see how the smoothing provided by continuous time can simplify our analysis.

Recall that the discrete time dynamics for capital are given by kt+1=sf(kt)+(1δ)ktk_{t+1} = s f(k_t) + (1 - \delta) k_t.

A simple rearrangement gives the rate of change per unit of time:

Δkt=sf(kt)δktwhereΔkt:=kt+1kt \Delta k_t = s f(k_t) - \delta k_t \quad \text{where} \quad \Delta k_t := k_{t+1} - k_t

Taking the time step to zero gives the continuous time limit

(25.3)#kt=sf(kt)δktwithkt:=ddtkt k'_t = s f(k_t) - \delta k_t \qquad \text{with} \qquad k'_t := \frac{d}{dt} k_t

Our aim is to learn about the evolution of ktk_t over time, given an initial stock k0k_0.

A steady state for (25.3) is a value kk^* at which capital is unchanging, meaning kt=0k'_t = 0 or, equivalently, sf(k)=δks f(k^*) = \delta k^*.

We assume f(k)=Akαf(k) = Ak^\alpha, so kk^* solves sAkα=δks A k^\alpha = \delta k.

The solution is the same as the discrete time case—see (25.2).

The dynamics are represented in the next figure, maintaining the parameterization we used above.

Writing kt=g(kt)k'_t = g(k_t) with g(k)=sAkαδkg(k) = s Ak^\alpha - \delta k, values of kk with g(k)>0g(k) > 0 imply kt>0k'_t > 0, so capital is increasing.

When g(k)<0g(k) < 0, the opposite occurs. Once again, high marginal returns to savings at low levels of capital combined with low rates of return at high levels of capital combine to yield global stability.

To see this in a figure, let’s define the constants

A, s, alpha, delta = 2, 0.3, 0.3, 0.4

Next we define the function gg for growth in continuous time

def g_con(A, s, alpha, delta, k):
    return A * s * k**alpha - delta * k
def plot_gcon(kstar=None):

    k_grid = np.linspace(0, 2.8, 10000)

    fig, ax = plt.subplots(figsize=[11, 5])
    ax.plot(k_grid, g_con(A, s, alpha, delta, k_grid), label='$g(k)$')
    ax.plot(k_grid, 0 * k_grid, label="$k'=0$")

    if kstar:
        fps = (kstar,)

        ax.plot(fps, 0, 'go', ms=10, alpha=0.6)


        ax.annotate(r'$k^* = (sA / \delta)^{(1/(1-\alpha))}$',
                 xy=(kstar, 0),
                 xycoords='data',
                 xytext=(0, 60),
                 textcoords='offset points',
                 fontsize=12,
                 arrowprops=dict(arrowstyle="->"))

    ax.legend(loc='lower left', fontsize=12)

    ax.set_xlabel("$k$",fontsize=10)
    ax.set_ylabel("$k'$", fontsize=10)

    ax.set_xticks((0, 1, 2, 3))
    ax.set_yticks((-0.3, 0, 0.3))

    plt.show()
kstar = ((s * A) / delta)**(1/(1 - alpha))
plot_gcon(kstar)
_images/53d167007c17b9383b6f28b82560e13a18f37b38c767901492506b6912171ba3.png

This shows global stability heuristically for a fixed parameterization, but how would we show the same thing formally for a continuum of plausible parameters?

In the discrete time case, a neat expression for ktk_t is hard to obtain.

In continuous time the process is easier: we can obtain a relatively simple expression for ktk_t that specifies the entire path.

The first step is to set xt:=kt1αx_t := k_t^{1-\alpha}, so that xt=(1α)ktαktx'_t = (1-\alpha) k_t^{-\alpha} k'_t.

Substituting into kt=sAktαδktk'_t = sAk_t^\alpha - \delta k_t leads to the linear differential equation

(25.4)#xt=(1α)(sAδxt) x'_t = (1-\alpha) (sA - \delta x_t)

This equation, which is a linear ordinary differential equation, has the solution

xt=(k01αsAδ)eδ(1α)t+sAδ x_t = \left( k_0^{1-\alpha} - \frac{sA}{\delta} \right) \mathrm{e}^{-\delta (1-\alpha) t} + \frac{sA}{\delta}

(You can confirm that this function xtx_t satisfies (25.4) by differentiating it with respect to tt.)

Converting back to ktk_t yields

(25.5)#kt=[(k01αsAδ)eδ(1α)t+sAδ]1/(1α) k_t = \left[ \left( k_0^{1-\alpha} - \frac{sA}{\delta} \right) \mathrm{e}^{-\delta (1-\alpha) t} + \frac{sA}{\delta} \right]^{1/(1-\alpha)}

Since δ>0\delta > 0 and α(0,1)\alpha \in (0, 1), we see immediately that ktkk_t \to k^* as tt \to \infty independent of k0k_0.

Thus, global stability holds.

25.4. Exercises#

Exercise 25.1

Plot per capita consumption cc at the steady state, as a function of the savings rate ss, where 0s10 \leq s \leq 1.

Use the Cobb–Douglas specification f(k)=Akαf(k) = A k^\alpha.

Set A=2.0,α=0.3,A=2.0, \alpha=0.3, and δ=0.5\delta=0.5

Also, find the approximate value of ss that maximizes the c(s)c^*(s) and show it in the plot.

Exercise 25.2

Stochastic Productivity

To bring the Solow–Swan model closer to data, we need to think about handling random fluctuations in aggregate quantities.

Among other things, this will eliminate the unrealistic prediction that per-capita output yt=Aktαy_t = A k^\alpha_t converges to a constant y:=A(k)αy^* := A (k^*)^\alpha.

We shift to discrete time for the following discussion.

One approach is to replace constant productivity with some stochastic sequence (At)t1(A_t)_{t \geq 1}.

Dynamics are now

(25.6)#kt+1=sAt+1f(kt)+(1δ)kt k_{t+1} = s A_{t+1} f(k_t) + (1 - \delta) k_t

We suppose ff is Cobb–Douglas and (At)(A_t) is IID and lognormal.

Now the long run convergence obtained in the deterministic case breaks down, since the system is hit with new shocks at each point in time.

Consider A=2.0,s=0.6,α=0.3,A=2.0, s=0.6, \alpha=0.3, and δ=0.5\delta=0.5

Generate and plot the time series ktk_t.