def Euler_equation_solver(guesses, r, w, T_H, factor, j, params, chi_b, chi_n, tau_bq, rho, lambdas, weights, e): ''' Finds the euler error for certain b and n, one ability type at a time. Inputs: guesses = guesses for b and n (2Sx1 list) r = rental rate (scalar) w = wage rate (scalar) T_H = lump sum tax (scalar) factor = scaling factor to dollars (scalar) j = which ability group is being solved for (scalar) params = list of parameters (list) chi_b = chi^b_j (scalar) chi_n = chi^n_s (Sx1 array) tau_bq = bequest tax rate (scalar) rho = mortality rates (Sx1 array) lambdas = ability weights (scalar) weights = population weights (Sx1 array) e = ability levels (Sx1 array) Outputs: 2Sx1 list of euler errors ''' J, S, T, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire, mean_income_data, a_tax_income, b_tax_income, c_tax_income, d_tax_income, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = params b_guess = np.array(guesses[:S]) n_guess = np.array(guesses[S:]) b_s = np.array([0] + list(b_guess[:-1])) b_splus1 = b_guess b_splus2 = np.array(list(b_guess[1:]) + [0]) BQ = house.get_BQ(r, b_splus1, weights, lambdas[j], rho, g_n_ss) theta = tax.replacement_rate_vals(n_guess, w, factor, e[:,j], J, weights, lambdas[j]) error1 = house.euler_savings_func(w, r, e[:, j], n_guess, b_s, b_splus1, b_splus2, BQ, factor, T_H, chi_b[j], params, theta, tau_bq[j], rho, lambdas[j]) error2 = house.euler_labor_leisure_func(w, r, e[:, j], n_guess, b_s, b_splus1, BQ, factor, T_H, chi_n, params, theta, tau_bq[j], lambdas[j]) # Put in constraints for consumption and savings. According to the euler equations, they can be negative. When # Chi_b is large, they will be. This prevents that from happening. # I'm not sure if the constraints are needed for labor. But we might as well put them in for now. mask1 = n_guess < 0 mask2 = n_guess > ltilde mask3 = b_guess <= 0 error2[mask1] += 1e14 error2[mask2] += 1e14 error1[mask3] += 1e14 tax1 = tax.total_taxes(r, b_s, w, e[:, j], n_guess, BQ, lambdas[j], factor, T_H, None, 'SS', False, params, theta, tau_bq[j]) cons = house.get_cons(r, b_s, w, e[:, j], n_guess, BQ, lambdas[j], b_splus1, params, tax1) mask4 = cons < 0 error1[mask4] += 1e14 return list(error1.flatten()) + list(error2.flatten())
if get_baseline: initial_b = bssmat_splus1 initial_n = nssmat else: initial_b = bssmat_init initial_n = nssmat_init # Get an initial distribution of capital with the initial population distribution K0 = house.get_K(initial_b, omega_stationary[0].reshape(S, 1), lambdas, g_n_vector[0]) b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1])) b_splus1init = initial_b L0 = firm.get_L(e, initial_n, omega_stationary[0].reshape(S, 1), lambdas) Y0 = firm.get_Y(K0, L0, parameters) w0 = firm.get_w(Y0, L0, parameters) r0 = firm.get_r(Y0, K0, parameters) BQ0 = house.get_BQ(r0, initial_b, omega_stationary[0].reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0]) T_H_0 = tax.get_lump_sum(r0, b_sinit, w0, e, initial_n, BQ0, lambdas, factor_ss, omega_stationary[0].reshape(S, 1), 'SS', parameters, theta, tau_bq) tax0 = tax.total_taxes(r0, b_sinit, w0, e, initial_n, BQ0, lambdas, factor_ss, T_H_0, None, 'SS', False, parameters, theta, tau_bq) c0 = house.get_cons(r0, b_sinit, w0, e, initial_n, BQ0.reshape(1, J), lambdas.reshape(1, J), b_splus1init, parameters, tax0) ''' ------------------------------------------------------------------------ Solve for equilibrium transition path by TPI ------------------------------------------------------------------------ ''' def SS_TPI_firstdoughnutring(guesses, winit, rinit, BQinit, T_H_init, j): ''' Solves the first entries of the upper triangle of the twist doughnut. This is separate from the main TPI function because the the values of b and n are scalars,
bssmat = solutions[0:(S-1) * J].reshape(S-1, J) bq = solutions[(S-1)*J:S*J] bssmat_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat)) bssmat_splus1 = np.array(list(bssmat) + list(bq.reshape(1, J))) nssmat = solutions[S * J:2*S*J].reshape(S, J) wss, rss, factor_ss, T_Hss = solutions[2*S*J:] Kss = house.get_K(bssmat_splus1, omega_SS.reshape(S, 1), lambdas, g_n_ss) Lss = firm.get_L(e, nssmat, omega_SS.reshape(S, 1), lambdas) Yss = firm.get_Y(Kss, Lss, parameters) Iss = firm.get_I(Kss, Kss, delta, g_y, g_n_ss) theta = tax.replacement_rate_vals(nssmat, wss, factor_ss, e, J, omega_SS.reshape(S, 1), lambdas) BQss = house.get_BQ(rss, bssmat_splus1, omega_SS.reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_ss) b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat)) taxss = tax.total_taxes(rss, b_s, wss, e, nssmat, BQss, lambdas, factor_ss, T_Hss, None, 'SS', False, parameters, theta, tau_bq) cssmat = house.get_cons(rss, b_s, wss, e, nssmat, BQss.reshape(1, J), lambdas.reshape(1, J), bssmat_splus1, parameters, taxss) Css = house.get_C(cssmat, omega_SS.reshape(S, 1), lambdas) resource_constraint = Yss - (Css + Iss) print 'Resource Constraint Difference:', resource_constraint house.constraint_checker_SS(bssmat, nssmat, cssmat, parameters) b_s = np.array(list(np.zeros(J).reshape((1, J))) + list(bssmat)) b_splus1 = bssmat_splus1 b_splus2 = np.array(list(bssmat_splus1[1:]) + list(np.zeros(J).reshape((1, J))))
def SS_solver(b_guess_init, n_guess_init, wguess, rguess, T_Hguess, factorguess, chi_n, chi_b, params, iterative_params, tau_bq, rho, lambdas, weights, e): ''' Solves for the steady state distribution of capital, labor, as well as w, r, T_H and the scaling factor, using an iterative method similar to TPI. Inputs: b_guess_init = guesses for b (SxJ array) n_guess_init = guesses for n (SxJ array) wguess = guess for wage rate (scalar) rguess = guess for rental rate (scalar) T_Hguess = guess for lump sum tax (scalar) factorguess = guess for scaling factor to dollars (scalar) chi_n = chi^n_s (Sx1 array) chi_b = chi^b_j (Jx1 array) params = list of parameters (list) iterative_params = list of parameters that determine the convergence of the while loop (list) tau_bq = bequest tax rate (Jx1 array) rho = mortality rates (Sx1 array) lambdas = ability weights (Jx1 array) weights = population weights (Sx1 array) e = ability levels (SxJ array) Outputs: solutions = steady state values of b, n, w, r, factor, T_H ((2*S*J+4)x1 array) ''' J, S, T, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire, mean_income_data, a_tax_income, b_tax_income, c_tax_income, d_tax_income, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = params maxiter, mindist_SS = iterative_params # Rename the inputs w = wguess r = rguess T_H = T_Hguess factor = factorguess bssmat = b_guess_init nssmat = n_guess_init dist = 10 iteration = 0 dist_vec = np.zeros(maxiter) while (dist > mindist_SS) and (iteration < maxiter): # Solve for the steady state levels of b and n, given w, r, T_H and factor for j in xrange(J): # Solve the euler equations guesses = np.append(bssmat[:, j], nssmat[:, j]) solutions = opt.fsolve(Euler_equation_solver, guesses * .9, args=(r, w, T_H, factor, j, params, chi_b, chi_n, tau_bq, rho, lambdas, weights, e), xtol=1e-13) bssmat[:,j] = solutions[:S] nssmat[:,j] = solutions[S:] # print np.array(Euler_equation_solver(np.append(bssmat[:, j], nssmat[:, j]), r, w, T_H, factor, j, params, chi_b, chi_n, theta, tau_bq, rho, lambdas, e)).max() K = house.get_K(bssmat, weights.reshape(S, 1), lambdas.reshape(1, J), g_n_ss) L = firm.get_L(e, nssmat, weights.reshape(S, 1), lambdas.reshape(1, J)) Y = firm.get_Y(K, L, params) new_r = firm.get_r(Y, K, params) new_w = firm.get_w(Y, L, params) b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :])) average_income_model = ((new_r * b_s + new_w * e * nssmat) * weights.reshape(S, 1) * lambdas.reshape(1, J)).sum() new_factor = mean_income_data / average_income_model new_BQ = house.get_BQ(new_r, bssmat, weights.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss) theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, e, J, weights.reshape(S, 1), lambdas) new_T_H = tax.get_lump_sum(new_r, b_s, new_w, e, nssmat, new_BQ, lambdas.reshape(1, J), factor, weights.reshape(S, 1), 'SS', params, theta, tau_bq) r = misc_funcs.convex_combo(new_r, r, params) w = misc_funcs.convex_combo(new_w, w, params) factor = misc_funcs.convex_combo(new_factor, factor, params) T_H = misc_funcs.convex_combo(new_T_H, T_H, params) if T_H != 0: dist = np.array([misc_funcs.perc_dif_func(new_r, r)] + [misc_funcs.perc_dif_func(new_w, w)] + [misc_funcs.perc_dif_func(new_T_H, T_H)] + [misc_funcs.perc_dif_func(new_factor, factor)]).max() else: # If T_H is zero (if there are no taxes), a percent difference will throw NaN's, so we use an absoluate difference dist = np.array([misc_funcs.perc_dif_func(new_r, r)] + [misc_funcs.perc_dif_func(new_w, w)] + [abs(new_T_H - T_H)] + [misc_funcs.perc_dif_func(new_factor, factor)]).max() dist_vec[iteration] = dist # Similar to TPI: if the distance between iterations increases, then decrease the value of nu to prevent cycling if iteration > 10: if dist_vec[iteration] - dist_vec[iteration-1] > 0: nu /= 2.0 print 'New value of nu:', nu iteration += 1 print "Iteration: %02d" % iteration, " Distance: ", dist eul_errors = np.ones(J) b_mat = np.zeros((S, J)) n_mat = np.zeros((S, J)) # Given the final w, r, T_H and factor, solve for the SS b and n (if you don't do a final fsolve, there will be a slight mismatch, with high euler errors) for j in xrange(J): solutions1 = opt.fsolve(Euler_equation_solver, np.append(bssmat[:, j], nssmat[:, j])* .9, args=(r, w, T_H, factor, j, params, chi_b, chi_n, tau_bq, rho, lambdas, weights, e), xtol=1e-13) eul_errors[j] = np.array(Euler_equation_solver(solutions1, r, w, T_H, factor, j, params, chi_b, chi_n, tau_bq, rho, lambdas, weights, e)).max() b_mat[:, j] = solutions1[:S] n_mat[:, j] = solutions1[S:] print 'SS fsolve euler error:', eul_errors.max() solutions = np.append(b_mat.flatten(), n_mat.flatten()) other_vars = np.array([w, r, factor, T_H]) solutions = np.append(solutions, other_vars) return solutions
initial_b = bssmat_splus1 initial_n = nssmat else: initial_b = bssmat_init initial_n = nssmat_init # Get an initial distribution of capital with the initial population distribution K0 = house.get_K(initial_b, omega_stationary[0].reshape(S, 1), lambdas, g_n_vector[0]) b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1])) b_splus1init = initial_b L0 = firm.get_L(e, initial_n, omega_stationary[0].reshape(S, 1), lambdas) Y0 = firm.get_Y(K0, L0, parameters) w0 = firm.get_w(Y0, L0, parameters) r0 = firm.get_r(Y0, K0, parameters) BQ0 = house.get_BQ(r0, initial_b, omega_stationary[0].reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0]) T_H_0 = tax.get_lump_sum(r0, b_sinit, w0, e, initial_n, BQ0, lambdas, factor_ss, omega_stationary[0].reshape(S, 1), 'SS', parameters, theta, tau_bq) tax0 = tax.total_taxes(r0, b_sinit, w0, e, initial_n, BQ0, lambdas, factor_ss, T_H_0, None, 'SS', False, parameters, theta, tau_bq) c0 = house.get_cons(r0, b_sinit, w0, e, initial_n, BQ0.reshape(1, J), lambdas.reshape(1, J), b_splus1init, parameters, tax0) ''' ------------------------------------------------------------------------ Solve for equilibrium transition path by TPI ------------------------------------------------------------------------ ''' def SS_TPI_firstdoughnutring(guesses, winit, rinit, BQinit, T_H_init, j):