Skip to content

Commit cdef435

Browse files
committed
Replace brent_max with minimize_scalar.
1 parent 16413c8 commit cdef435

File tree

1 file changed

+74
-61
lines changed

1 file changed

+74
-61
lines changed

lectures/ak2.md

+74-61
Original file line numberDiff line numberDiff line change
@@ -551,34 +551,35 @@ class ClosedFormTrans:
551551
self.α, self.β = α, β
552552
553553
def simulate(self,
554-
T, # length of transitional path to simulate
555-
init_ss, # initial steady state
556-
τ_pol=None, # sequence of tax rates
557-
D_pol=None, # sequence of government debt levels
558-
G_pol=None): # sequence of government purchases
559-
554+
T, # length of transitional path to simulate
555+
init_ss, # initial steady state
556+
τ_pol=None, # sequence of tax rates
557+
D_pol=None, # sequence of government debt levels
558+
G_pol=None): # sequence of government purchases
559+
560560
α, β = self.α, self.β
561-
561+
562562
# unpack the steady state variables
563563
K_hat, Y_hat, Cy_hat, Co_hat = init_ss[:4]
564564
W_hat, r_hat = init_ss[4:6]
565565
τ_hat, D_hat, G_hat = init_ss[6:9]
566-
566+
567567
# initialize array containers
568568
# K, Y, Cy, Co
569569
quant_seq = np.empty((T+1, 4))
570-
570+
571571
# W, r
572572
price_seq = np.empty((T+1, 2))
573-
573+
574574
# τ, D, G
575575
policy_seq = np.empty((T+2, 3))
576-
576+
577577
# t=0, starting from steady state
578578
K0, Y0 = K_hat, Y_hat
579579
W0, r0 = W_hat, r_hat
580580
D0 = D_hat
581-
581+
δo = 0 # Define δo (set to 0 for this example, adjust as needed)
582+
582583
# fiscal policy
583584
if τ_pol is None:
584585
D1 = D_pol[1]
@@ -592,27 +593,27 @@ class ClosedFormTrans:
592593
D1 = D_pol[1]
593594
τ0 = τ_pol[0]
594595
G0 = τ0 * (Y0 + r0 * D0) + D1 - (1 + r0) * D0
595-
596+
596597
# optimal consumption plans
597598
Cy0, Co0 = K_to_C(K0, D0, τ0, r0, α, β)
598-
599+
599600
# t=0 economy
600601
quant_seq[0, :] = K0, Y0, Cy0, Co0
601602
price_seq[0, :] = W0, r0
602603
policy_seq[0, :] = τ0, D0, G0
603604
policy_seq[1, 1] = D1
604-
605+
605606
# starting from t=1 to T
606607
for t in range(1, T+1):
607-
608+
608609
# transition of K
609610
K_old, τ_old = quant_seq[t-1, 0], policy_seq[t-1, 0]
610611
D = policy_seq[t, 1]
611612
K = K_old ** α * (1 - τ_old) * (1 - α) * (1 - β) - D
612-
613+
613614
# output, capital return, wage
614615
Y, r, W = K_to_Y(K, α), K_to_r(K, α), K_to_W(K, α)
615-
616+
616617
# to satisfy the government budget constraint
617618
if τ_pol is None:
618619
D = D_pol[t]
@@ -629,22 +630,32 @@ class ClosedFormTrans:
629630
D_next = D_pol[t+1]
630631
τ = τ_pol[t]
631632
G = τ * (Y + r * D) + D_next - (1 + r) * D
632-
633+
633634
# optimal consumption plans
634-
Cy, Co = K_to_C(K, D, τ, r, α, β)
635-
635+
result = minimize_scalar(lambda Cy: -Cy_val(Cy, W, r_next, τ, τ_next, δy, δo_next, β),
636+
bounds=(1e-6, W*(1-τ)-δy-1e-6),
637+
method='bounded')
638+
639+
Cy_opt = result.x
640+
U_opt = -result.fun
641+
642+
Cy = Cy_opt
643+
Co = (1 + r * (1 - τ)) * (K + D) - δo
644+
636645
# store time t economy aggregates
637646
quant_seq[t, :] = K, Y, Cy, Co
638647
price_seq[t, :] = W, r
639648
policy_seq[t, 0] = τ
640649
policy_seq[t+1, 1] = D_next
641650
policy_seq[t, 2] = G
642-
651+
643652
self.quant_seq = quant_seq
644653
self.price_seq = price_seq
645654
self.policy_seq = policy_seq
646-
655+
647656
return quant_seq, price_seq, policy_seq
657+
658+
648659
649660
def plot(self):
650661
@@ -967,57 +978,57 @@ class AK2():
967978
self.α, self.β = α, β
968979
969980
def simulate(self,
970-
T, # length of transitional path to simulate
971-
init_ss, # initial steady state
972-
δy_seq, # sequence of lump sum tax for the young
973-
δo_seq, # sequence of lump sum tax for the old
974-
τ_pol=None, # sequence of tax rates
975-
D_pol=None, # sequence of government debt levels
976-
G_pol=None, # sequence of government purchases
977-
verbose=False,
978-
max_iter=500,
979-
tol=1e-5):
980-
981+
T, # length of transitional path to simulate
982+
init_ss, # initial steady state
983+
δy_seq, # sequence of lump sum tax for the young
984+
δo_seq, # sequence of lump sum tax for the old
985+
τ_pol=None, # sequence of tax rates
986+
D_pol=None, # sequence of government debt levels
987+
G_pol=None, # sequence of government purchases
988+
verbose=False,
989+
max_iter=500,
990+
tol=1e-5):
991+
981992
α, β = self.α, self.β
982-
993+
983994
# unpack the steady state variables
984995
K_hat, Y_hat, Cy_hat, Co_hat = init_ss[:4]
985996
W_hat, r_hat = init_ss[4:6]
986997
τ_hat, D_hat, G_hat = init_ss[6:9]
987-
998+
988999
# K, Y, Cy, Co
9891000
quant_seq = np.empty((T+2, 4))
990-
1001+
9911002
# W, r
9921003
price_seq = np.empty((T+2, 2))
993-
1004+
9941005
# τ, D, G
9951006
policy_seq = np.empty((T+2, 3))
9961007
policy_seq[:, 1] = D_pol
9971008
policy_seq[:, 2] = G_pol
998-
1009+
9991010
# initial guesses of prices
10001011
price_seq[:, 0] = np.ones(T+2) * W_hat
10011012
price_seq[:, 1] = np.ones(T+2) * r_hat
1002-
1013+
10031014
# initial guesses of policies
10041015
policy_seq[:, 0] = np.ones(T+2) * τ_hat
1005-
1016+
10061017
# t=0, starting from steady state
10071018
quant_seq[0, :2] = K_hat, Y_hat
1008-
1019+
10091020
if verbose:
10101021
# prepare to plot iterations until convergence
10111022
fig, axs = plt.subplots(1, 3, figsize=(14, 4))
1012-
1023+
10131024
# containers for checking convergence
10141025
price_seq_old = np.empty_like(price_seq)
10151026
policy_seq_old = np.empty_like(policy_seq)
1016-
1027+
10171028
# start iteration
10181029
i_iter = 0
10191030
while True:
1020-
1031+
10211032
if verbose:
10221033
# plot current prices at ith iteration
10231034
for i, name in enumerate(['W', 'r']):
@@ -1029,11 +1040,11 @@ class AK2():
10291040
axs[2].legend(bbox_to_anchor=(1.05, 1), loc='upper left')
10301041
axs[2].set_title('τ')
10311042
axs[2].set_xlabel('t')
1032-
1043+
10331044
# store old prices from last iteration
10341045
price_seq_old[:] = price_seq
10351046
policy_seq_old[:] = policy_seq
1036-
1047+
10371048
# start updating quantities and prices
10381049
for t in range(T+1):
10391050
K, Y = quant_seq[t, :2]
@@ -1043,40 +1054,41 @@ class AK2():
10431054
τ_next, D_next, G_next = policy_seq[t+1, :]
10441055
δy, δo = δy_seq[t], δo_seq[t]
10451056
δy_next, δo_next = δy_seq[t+1], δo_seq[t+1]
1046-
1057+
10471058
# consumption for the old
10481059
Co = (1 + r * (1 - τ)) * (K + D) - δo
1049-
1060+
10501061
# optimal consumption for the young
1051-
out = brent_max(Cy_val, 1e-6, W*(1-τ)-δy-1e-6,
1052-
args=(W, r_next, τ, τ_next,
1053-
δy, δo_next, β))
1054-
Cy = out[0]
1055-
1062+
result = minimize_scalar(lambda Cy: -Cy_val(Cy, W, r_next, τ, τ_next, δy, δo_next, β),
1063+
bounds=(1e-6, W*(1-τ)-δy-1e-6),
1064+
method='bounded')
1065+
1066+
Cy = result.x
1067+
10561068
quant_seq[t, 2:] = Cy, Co
10571069
τ_num = ((1 + r) * D + G - D_next - δy - δo)
10581070
τ_denom = (Y + r * D)
10591071
policy_seq[t, 0] = τ_num / τ_denom
1060-
1072+
10611073
# saving of the young
10621074
A_next = W * (1 - τ) - δy - Cy
1063-
1075+
10641076
# transition of K
10651077
K_next = A_next - D_next
10661078
Y_next = K_to_Y(K_next, α)
10671079
W_next, r_next = K_to_W(K_next, α), K_to_r(K_next, α)
1068-
1080+
10691081
quant_seq[t+1, :2] = K_next, Y_next
10701082
price_seq[t+1, :] = W_next, r_next
1071-
1083+
10721084
i_iter += 1
1073-
1085+
10741086
if (np.max(np.abs(price_seq_old - price_seq)) < tol) & \
10751087
(np.max(np.abs(policy_seq_old - policy_seq)) < tol):
10761088
if verbose:
10771089
print(f"Converge using {i_iter} iterations")
10781090
break
1079-
1091+
10801092
if i_iter > max_iter:
10811093
if verbose:
10821094
print(f"Fail to converge using {i_iter} iterations")
@@ -1085,9 +1097,10 @@ class AK2():
10851097
self.quant_seq = quant_seq
10861098
self.price_seq = price_seq
10871099
self.policy_seq = policy_seq
1088-
1100+
10891101
return quant_seq, price_seq, policy_seq
10901102
1103+
10911104
def plot(self):
10921105
10931106
quant_seq = self.quant_seq

0 commit comments

Comments
 (0)