Skip to content

Commit 059e0f4

Browse files
mmckyHumphreyYang
andauthored
Fix SymPy OverflowError in solow.md by using Rational (#687)
* Fix SymPy OverflowError in solow.md by using Rational The SymPy solve() function was failing with 'mpz too large to convert to float' when using Python float values (0.3, 0.5, 2.0) in symbolic expressions with fractional exponents. Using sympy.Rational for exact arithmetic avoids the large intermediate mpz values that caused the overflow in factorint(). * minor updates --------- Co-authored-by: Humphrey Yang <u6474961@anu.edu.au>
1 parent c79d1da commit 059e0f4

File tree

1 file changed

+40
-36
lines changed

1 file changed

+40
-36
lines changed

lectures/solow.md

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ jupytext:
33
text_representation:
44
extension: .md
55
format_name: myst
6+
format_version: 0.13
7+
jupytext_version: 1.17.1
68
kernelspec:
7-
display_name: Python 3
8-
language: python
99
name: python3
10+
display_name: Python 3 (ipykernel)
11+
language: python
1012
---
1113

1214
(solow)=
@@ -117,16 +119,16 @@ The function $g$ from {eq}`solow` is then plotted, along with the 45-degree line
117119
Let's define the constants.
118120

119121
```{code-cell} ipython3
120-
A, s, alpha, delta = 2, 0.3, 0.3, 0.4
122+
A, s, α, δ = 2, 0.3, 0.3, 0.4
121123
x0 = 0.25
122124
xmin, xmax = 0, 3
123125
```
124126

125127
Now, we define the function $g$.
126128

127129
```{code-cell} ipython3
128-
def g(A, s, alpha, delta, k):
129-
return A * s * k**alpha + (1 - delta) * k
130+
def g(A, s, α, δ, k):
131+
return A * s * k**α + (1 - δ) * k
130132
```
131133

132134
Let's plot the 45-degree diagram of $g$.
@@ -139,7 +141,7 @@ def plot45(kstar=None):
139141
140142
ax.set_xlim(xmin, xmax)
141143
142-
g_values = g(A, s, alpha, delta, xgrid)
144+
g_values = g(A, s, α, δ, xgrid)
143145
144146
ymin, ymax = np.min(g_values), np.max(g_values)
145147
ax.set_ylim(ymin, ymax)
@@ -202,11 +204,10 @@ If initial capital is above this level, then the reverse is true.
202204
Let's plot the 45-degree diagram to show the $k^*$ in the plot.
203205

204206
```{code-cell} ipython3
205-
kstar = ((s * A) / delta)**(1/(1 - alpha))
207+
kstar = ((s * A) / δ)**(1/(1 - α))
206208
plot45(kstar)
207209
```
208210

209-
210211
From our graphical analysis, it appears that $(k_t)$ converges to $k^*$, regardless of initial capital
211212
$k_0$.
212213

@@ -221,7 +222,7 @@ At this parameterization, $k^* \approx 1.78$.
221222
Let's define the constants and three distinct initial conditions
222223

223224
```{code-cell} ipython3
224-
A, s, alpha, delta = 2, 0.3, 0.3, 0.4
225+
A, s, α, δ = 2, 0.3, 0.3, 0.4
225226
x0 = np.array([.25, 1.25, 3.25])
226227
227228
ts_length = 20
@@ -232,7 +233,7 @@ ymin, ymax = 0, 3.5
232233
```{code-cell} ipython3
233234
def simulate_ts(x0_values, ts_length):
234235
235-
k_star = (s * A / delta)**(1/(1-alpha))
236+
k_star = (s * A / δ)**(1/(1-α))
236237
fig, ax = plt.subplots(figsize=[11, 5])
237238
ax.set_xlim(xmin, xmax)
238239
ax.set_ylim(ymin, ymax)
@@ -243,7 +244,7 @@ def simulate_ts(x0_values, ts_length):
243244
for x_init in x0_values:
244245
ts[0] = x_init
245246
for t in range(1, ts_length):
246-
ts[t] = g(A, s, alpha, delta, ts[t-1])
247+
ts[t] = g(A, s, α, δ, ts[t-1])
247248
ax.plot(np.arange(ts_length), ts, '-o', ms=4, alpha=0.6,
248249
label=r'$k_0=%g$' %x_init)
249250
ax.plot(np.arange(ts_length), np.full(ts_length,k_star),
@@ -319,14 +320,14 @@ levels of capital combine to yield global stability.
319320
To see this in a figure, let's define the constants
320321

321322
```{code-cell} ipython3
322-
A, s, alpha, delta = 2, 0.3, 0.3, 0.4
323+
A, s, α, δ = 2, 0.3, 0.3, 0.4
323324
```
324325

325326
Next we define the function $g$ for growth in continuous time
326327

327328
```{code-cell} ipython3
328-
def g_con(A, s, alpha, delta, k):
329-
return A * s * k**alpha - delta * k
329+
def g_con(A, s, α, δ, k):
330+
return A * s * k**α - δ * k
330331
```
331332

332333
```{code-cell} ipython3
@@ -335,7 +336,7 @@ def plot_gcon(kstar=None):
335336
k_grid = np.linspace(0, 2.8, 10000)
336337
337338
fig, ax = plt.subplots(figsize=[11, 5])
338-
ax.plot(k_grid, g_con(A, s, alpha, delta, k_grid), label='$g(k)$')
339+
ax.plot(k_grid, g_con(A, s, α, δ, k_grid), label='$g(k)$')
339340
ax.plot(k_grid, 0 * k_grid, label="$k'=0$")
340341
341342
if kstar:
@@ -364,7 +365,7 @@ def plot_gcon(kstar=None):
364365
```
365366

366367
```{code-cell} ipython3
367-
kstar = ((s * A) / delta)**(1/(1 - alpha))
368+
kstar = ((s * A) / δ)**(1/(1 - α))
368369
plot_gcon(kstar)
369370
```
370371

@@ -450,14 +451,14 @@ $$
450451

451452
```{code-cell} ipython3
452453
A = 2.0
453-
alpha = 0.3
454-
delta = 0.5
454+
α = 0.3
455+
δ = 0.5
455456
```
456457

457458
```{code-cell} ipython3
458459
s_grid = np.linspace(0, 1, 1000)
459-
k_star = ((s_grid * A) / delta)**(1/(1 - alpha))
460-
c_star = (1 - s_grid) * A * k_star ** alpha
460+
k_star = ((s_grid * A) / δ)**(1/(1 - α))
461+
c_star = (1 - s_grid) * A * k_star ** α
461462
```
462463

463464
Let's find the value of $s$ that maximizes $c^*$ using [scipy.optimize.minimize_scalar](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize_scalar.html#scipy.optimize.minimize_scalar).
@@ -469,8 +470,8 @@ from scipy.optimize import minimize_scalar
469470

470471
```{code-cell} ipython3
471472
def calc_c_star(s):
472-
k = ((s * A) / delta)**(1/(1 - alpha))
473-
return - (1 - s) * A * k ** alpha
473+
k = ((s * A) / δ)**(1/(1 - α))
474+
return - (1 - s) * A * k ** α
474475
```
475476

476477
```{code-cell} ipython3
@@ -510,21 +511,26 @@ plt.show()
510511
One can also try to solve this mathematically by differentiating $c^*(s)$ and solve for $\frac{d}{ds}c^*(s)=0$ using [sympy](https://www.sympy.org/en/index.html).
511512

512513
```{code-cell} ipython3
513-
from sympy import solve, Symbol
514+
from sympy import solve, Symbol, Rational
514515
```
515516

516517
```{code-cell} ipython3
518+
# Use Rational for exact symbolic computation
519+
A = Rational(2)
520+
α = Rational(3, 10)
521+
δ = Rational(1, 2)
522+
517523
s_symbol = Symbol('s', real=True)
518-
k = ((s_symbol * A) / delta)**(1/(1 - alpha))
519-
c = (1 - s_symbol) * A * k ** alpha
524+
k = ((s_symbol * A) / δ)**(1/(1 - α))
525+
c = (1 - s_symbol) * A * k ** α
520526
```
521527

522528
Let's differentiate $c$ and solve using [sympy.solve](https://docs.sympy.org/latest/modules/solvers/solvers.html#sympy.solvers.solvers.solve)
523529

524530
```{code-cell} ipython3
525531
# Solve using sympy
526532
s_star = solve(c.diff())[0]
527-
print(f"s_star = {s_star}")
533+
print(f"s_star = {float(s_star)}")
528534
```
529535

530536
Incidentally, the rate of savings which maximizes steady state level of per capita consumption is called the [Golden Rule savings rate](https://en.wikipedia.org/wiki/Golden_Rule_savings_rate).
@@ -576,23 +582,23 @@ Let's define the constants for lognormal distribution and initial values used fo
576582

577583
```{code-cell} ipython3
578584
# Define the constants
579-
sig = 0.2
580-
mu = np.log(2) - sig**2 / 2
585+
σ = 0.2
586+
μ = np.log(2) - σ**2 / 2
581587
A = 2.0
582588
s = 0.6
583-
alpha = 0.3
584-
delta = 0.5
589+
α = 0.3
590+
δ = 0.5
585591
x0 = [.25, 3.25] # list of initial values used for simulation
586592
```
587593

588594
Let's define the function *k_next* to find the next value of $k$
589595

590596
```{code-cell} ipython3
591597
def lgnorm():
592-
return np.exp(mu + sig * np.random.randn())
598+
return np.exp(μ + σ * np.random.randn())
593599
594-
def k_next(s, alpha, delta, k):
595-
return lgnorm() * s * k**alpha + (1 - delta) * k
600+
def k_next(s, α, δ, k):
601+
return lgnorm() * s * k**α + (1 - δ) * k
596602
```
597603

598604
```{code-cell} ipython3
@@ -604,7 +610,7 @@ def ts_plot(x_values, ts_length):
604610
for x_init in x_values:
605611
ts[0] = x_init
606612
for t in range(1, ts_length):
607-
ts[t] = k_next(s, alpha, delta, ts[t-1])
613+
ts[t] = k_next(s, α, δ, ts[t-1])
608614
ax.plot(np.arange(ts_length), ts, '-o', ms=4,
609615
alpha=0.6, label=r'$k_0=%g$' %x_init)
610616
@@ -621,7 +627,5 @@ def ts_plot(x_values, ts_length):
621627
ts_plot(x0, 50)
622628
```
623629

624-
625-
626630
```{solution-end}
627631
```

0 commit comments

Comments
 (0)