3030 β = 0.95
3131end
3232
33- println (" Solving model..." )
34- solve! (RBC)
3533
36- # Get steady states
37- println (" Computing steady states..." )
38- SS_non_stochastic = get_steady_state (RBC, stochastic = false )
39- SS_stochastic = get_steady_state (RBC, stochastic = true )
40-
41- println (" Non-stochastic steady state:" )
42- println (SS_non_stochastic)
43- println (" \n Stochastic steady state:" )
44- println (SS_stochastic)
45-
46- # Get auxiliary indices for the steady state input
47- aux_idx = RBC. solution. perturbation. auxiliary_indices
48- SS_for_func = SS_non_stochastic[aux_idx. dyn_ss_idx]
49-
50- # Number of variables and shocks
51- n_vars = length (RBC. var)
52- n_shocks = length (RBC. exo)
53- n_dyn_eqs = length (RBC. dyn_equations)
54- n_calib_eqs = length (RBC. calibration_equations)
55- n_total_eqs = n_dyn_eqs + n_calib_eqs
56-
57- println (" \n Model dimensions:" )
58- println (" Variables: " , n_vars)
59- println (" Shocks: " , n_shocks)
60- println (" Dynamic equations: " , n_dyn_eqs)
61- println (" Calibration equations: " , n_calib_eqs)
62- println (" Total equations: " , n_total_eqs)
63-
64- # Generate Sobol sequence for shocks
65- n_draws = 100
66- println (" \n Generating " , n_draws, " Sobol draws for shocks..." )
67-
68- # Generate Sobol sequence in [0,1]
69- shock_draws_uniform = QuasiMonteCarlo. sample (n_draws, n_shocks, SobolSample ())
34+ include (" ./models/Gali_2015_chapter_3_nonlinear.jl" )
7035
71- # Convert to normal distribution using inverse error function
72- normal_draws = @. sqrt (2 ) * erfinv (2 * shock_draws_uniform - 1 )
36+ m = Gali_2015_chapter_3_nonlinear
7337
74- # Standardize to zero mean and unit variance
75- normal_draws .- = mean (normal_draws, dims = 2 )
76- normal_draws ./= Statistics . std (normal_draws, dims = 2 )
38+ # Get steady states
39+ SS_non_stochastic = get_steady_state (m, stochastic = false , derivatives = false ) |> collect
40+ SS_stochastic = get_steady_state (m, stochastic = true , derivatives = false ) |> collect
7741
78- println (" Shock draws shape: " , size (normal_draws))
79- println (" Shock draws mean: " , mean (normal_draws, dims= 2 ))
80- println (" Shock draws std: " , Statistics. std (normal_draws, dims= 2 ))
8142
8243# Calibration parameters
83- calib_params = zeros (length (RBC . calibration_equations_parameters))
44+ calib_params = zeros (length (m . calibration_equations_parameters))
8445
8546# Define residual function that returns per-equation average residuals
8647# This is compatible with NonlinearSolve.jl
48+ # function residual_function(vars_flat, p)
8749function residual_function! (residual_avg, vars_flat, p)
88- shock_draws, model, SS_for_func , calib_params = p
50+ shock_draws, model, SS_non_stochastic , calib_params = p
8951
9052 n_draws = size (shock_draws, 2 )
91- n_vars = length (model. var)
53+ # n_vars = length(model.var)
9254
9355 # Unpack variables: [past; present; future]
94- past = vars_flat[1 : n_vars]
95- present = vars_flat[n_vars+ 1 : 2 * n_vars]
96- future = vars_flat[2 * n_vars+ 1 : 3 * n_vars]
56+ past = vars_flat# [1:n_vars]
57+ present = vars_flat# [n_vars+1:2*n_vars]
58+ future = vars_flat# [2*n_vars+1:3*n_vars]
9759
9860 n_eqs = length (model. dyn_equations) + length (model. calibration_equations)
99- residual_temp = zeros (n_eqs)
61+ residual_temp = zeros (eltype (vars_flat), n_eqs)
10062
10163 # Initialize average residuals to zero
10264 fill! (residual_avg, 0.0 )
65+ # residual_avg = zeros(eltype(vars_flat), n_eqs)
10366
10467 # Sum residuals across all shock draws
10568 for i in 1 : n_draws
10669 shocks = shock_draws[:, i]
10770
10871 # Evaluate dynamic equations
10972 get_dynamic_residuals (residual_temp, model. parameter_values, calib_params,
110- past, present, future, SS_for_func , shocks, model)
111-
73+ past, present, future, SS_non_stochastic , shocks, model)
74+
11275 # Accumulate residuals
113- residual_avg .+ = residual_temp
76+ residual_avg .+ = abs .( residual_temp)
11477 end
11578
11679 # Average over draws
@@ -119,75 +82,81 @@ function residual_function!(residual_avg, vars_flat, p)
11982 return nothing
12083end
12184
122- # Initial guess: use stochastic steady state for all time periods
123- println (" \n Setting up nonlinear problem..." )
124- initial_vars = vcat (SS_stochastic, SS_stochastic, SS_stochastic)
85+
86+ # Number of variables and shocks
87+ n_shocks = length (m. exo)
88+
89+ # Generate Sobol sequence for shocks
90+ n_draws = 1000
91+
92+ # Generate Sobol sequence in [0,1]
93+ shock_draws_uniform = QuasiMonteCarlo. sample (n_draws, n_shocks, SobolSample ())
94+
95+ # Convert to normal distribution using inverse error function
96+ normal_draws = @. sqrt (2 ) * erfinv (2 * shock_draws_uniform - 1 )
97+
98+ # Standardize to zero mean and unit variance
99+ normal_draws .- = mean (normal_draws, dims= 2 )
100+ normal_draws ./= Statistics. std (normal_draws, dims= 2 )
125101
126102# Package parameters for the residual function
127- params = (normal_draws, RBC, SS_for_func, calib_params)
103+ params = (normal_draws, m, SS_non_stochastic, calib_params)
104+
105+ # Initial guess: use stochastic steady state for all time periods
106+ initial_vars = copy (SS_stochastic)
128107
129108# Test initial residuals
130- residual_test = zeros (n_total_eqs )
109+ residual_test = zeros (length (m . dyn_equations) + length (m . calibration_equations) )
131110residual_function! (residual_test, initial_vars, params)
132- println (" Initial residual norm: " , norm ( residual_test))
111+ println (" Initial residual norm: " , sum (abs2, residual_test))
133112println (" Initial max|residual|: " , maximum (abs .(residual_test)))
134113
135114# Set up nonlinear problem
136- println (" \n Solving nonlinear system..." )
137- println (" This may take a moment..." )
138-
139115prob = NonlinearProblem (residual_function!, initial_vars, params)
140116
141117# Solve using Newton-Raphson with automatic differentiation
142- sol = solve (prob, NewtonRaphson (; autodiff = AutoFiniteDiff ()))
118+ solLM = solve (prob, LevenbergMarquardt (), show_trace = Val (true ))
119+ solTR = solve (prob, TrustRegion (), show_trace = Val (true ))
120+ # sol = solve(prob, show_trace = Val(true))
121+
122+ sum (abs, solTR. u - SS_stochastic)
123+ sum (abs, solLM. u - SS_stochastic)
124+
125+ sum (abs2, solLM. resid)
126+ sum (abs2, solTR. resid)
127+
128+ residual_function! (residual_test, solLM. u, params)
129+ sum (abs2, residual_test)
130+
143131
144132println (" \n Solution complete!" )
145133println (" Solution return code: " , sol. retcode)
146- println (" Final residual norm: " , norm ( sol. resid))
134+ println (" Final residual norm: " , sum (abs2, sol. resid))
147135println (" Final max|residual|: " , maximum (abs .(sol. resid)))
148136
149137# Extract solved variables
150- solved_past = sol. u[1 : n_vars]
151- solved_present = sol. u[n_vars+ 1 : 2 * n_vars]
152- solved_future = sol. u[2 * n_vars+ 1 : 3 * n_vars]
153-
154- println (" \n Solved variables:" )
155- println (" Past: " , solved_past)
156- println (" Present: " , solved_present)
157- println (" Future: " , solved_future)
138+ println (" \n Solved variables:" , sol. u)
158139
159140println (" \n Comparison with steady states:" )
160- for (i, var) in enumerate (RBC . var)
141+ for (i, var) in enumerate (m . var)
161142 println (" " , var, " :" )
162143 println (" Non-stochastic SS: " , SS_non_stochastic[i])
163144 println (" Stochastic SS: " , SS_stochastic[i])
164- println (" Solved (past): " , solved_past[i])
165- println (" Solved (present): " , solved_present[i])
166- println (" Solved (future): " , solved_future[i])
145+ println (" Solved: " , sol. u[i])
167146end
168147
148+ n_eqs = length (m. dyn_equations) + length (m. calibration_equations)
149+
169150# Evaluate residuals at the solution for a few shock draws
170151println (" \n Per-draw residuals at solution for first 5 shock draws:" )
171- residual = zeros (n_total_eqs )
152+ residual = zeros (n_eqs )
172153for i in 1 : min (5 , n_draws)
173154 shocks = normal_draws[:, i]
174- get_dynamic_residuals (residual, RBC . parameter_values, calib_params,
175- solved_past, solved_present, solved_future, SS_for_func , shocks, RBC )
155+ get_dynamic_residuals (residual, m . parameter_values, calib_params,
156+ sol . u, sol . u, sol . u, SS_non_stochastic , shocks, m )
176157 println (" Draw " , i, " : max|residual| = " , maximum (abs .(residual)),
177158 " , mean|residual| = " , sum (abs .(residual))/ length (residual))
178159end
179160
180- println (" \n Script completed successfully!" )
181-
182- # Evaluate residuals at the optimal point for a few shock draws
183- println (" \n Residuals at optimal point for first 5 shock draws:" )
184- residual = zeros (n_total_eqs)
185- for i in 1 : min (5 , n_draws)
186- shocks = shock_draws[:, i]
187- get_dynamic_residuals (residual, RBC. parameter_values, calib_params,
188- opt_past, opt_present, opt_future, SS_for_func, shocks, RBC)
189- println (" Draw " , i, " : max|residual| = " , maximum (abs .(residual)),
190- " , mean|residual| = " , sum (abs .(residual))/ length (residual))
191- end
192161
193- println ( " \n Script completed successfully! " )
162+ m . dyn_equations_func
0 commit comments