def run_time_path_iteration(Kss, Lss, Yss, BQss, theta, parameters, g_n_vector, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0, r0, BQ0, T_H_0, tax0, c0, initial_b, initial_n, factor_ss, tau_bq, chi_b, chi_n, get_baseline=False, output_dir="./OUTPUT", **kwargs): TPI_FIG_DIR = output_dir # Initialize Time paths domain = np.linspace(0, T, T) Kinit = (-1 / (domain + 1)) * (Kss - K0) + Kss Kinit[-1] = Kss Kinit = np.array(list(Kinit) + list(np.ones(S) * Kss)) Linit = np.ones(T + S) * Lss Yinit = firm.get_Y(Kinit, Linit, parameters) winit = firm.get_w(Yinit, Linit, parameters) rinit = firm.get_r(Yinit, Kinit, parameters) BQinit = np.zeros((T + S, J)) for j in xrange(J): BQinit[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S BQinit = np.array(BQinit) T_H_init = np.ones(T + S) * T_Hss # Make array of initial guesses domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J)) ending_b = bssmat_splus1 guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1)) guesses_b = np.append(guesses_b, ending_b_tail, axis=0) domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J)) guesses_n = domain3 * (nssmat - initial_n) + initial_n ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1)) guesses_n = np.append(guesses_n, ending_n_tail, axis=0) b_mat = np.zeros((T + S, S, J)) n_mat = np.zeros((T + S, S, J)) ind = np.arange(S) TPIiter = 0 TPIdist = 10 euler_errors = np.zeros((T, 2 * S, J)) TPIdist_vec = np.zeros(maxiter) while (TPIiter < maxiter) and (TPIdist >= mindist_TPI): Kpath_TPI = list(Kinit) + list(np.ones(10) * Kss) Lpath_TPI = list(Linit) + list(np.ones(10) * Lss) # Plot TPI for K for each iteration, so we can see if there is a # problem if PLOT_TPI is True: plt.figure() plt.axhline(y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--') plt.plot(np.arange(T + 10), Kpath_TPI[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$") plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K")) # Uncomment the following print statements to make sure all euler equations are converging. # If they don't, then you'll have negative consumption or consumption spikes. If they don't, # it is the initial guesses. You might need to scale them differently. It is rather delicate for the first # few periods and high ability groups. for j in xrange(J): b_mat[1, -1, j], n_mat[0, -1, j] = np.array( opt.fsolve(SS_TPI_firstdoughnutring, [guesses_b[1, -1, j], guesses_n[0, -1, j]], args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq), xtol=1e-13)) # if np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq)).max() > 1e-6: # print 'minidoughnut:', # np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, # j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, # factor_ss, j, parameters, theta, tau_bq)).max() for s in xrange(S - 2): # Upper triangle ind2 = np.arange(s + 2) b_guesses_to_use = np.diag(guesses_b[1:S + 1, :, j], S - (s + 2)) n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2)) solutions = opt.fsolve( Steady_state_TPI_solver, list(b_guesses_to_use) + list(n_guesses_to_use), args=(winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:len(solutions) / 2] b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec n_vec = solutions[len(solutions) / 2:] n_mat[ind2, S - (s + 2) + ind2, j] = n_vec # if abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n))).max() > 1e-6: # print 's-loop:', # abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, # BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, # theta, tau_bq, rho, lambdas, e, initial_b, chi_b, # chi_n))).max() for t in xrange(0, T): b_guesses_to_use = .75 * \ np.diag(guesses_b[t + 1:t + S + 1, :, j]) n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j]) solutions = opt.fsolve( Steady_state_TPI_solver, list(b_guesses_to_use) + list(n_guesses_to_use), args=(winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:S] b_mat[t + 1 + ind, ind, j] = b_vec n_vec = solutions[S:] n_mat[t + ind, ind, j] = n_vec inputs = list(solutions) euler_errors[t, :, j] = np.abs( Steady_state_TPI_solver(inputs, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n)) # if euler_errors.max() > 1e-6: # print 't-loop:', euler_errors.max() # Force the initial distribution of capital to be as given above. b_mat[0, :, :] = initial_b Kinit = household.get_K(b_mat[:T], omega_stationary[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI') Linit = firm.get_L(e.reshape(1, S, J), n_mat[:T], omega_stationary[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') Ynew = firm.get_Y(Kinit, Linit, parameters) wnew = firm.get_w(Ynew, Linit, parameters) rnew = firm.get_r(Ynew, Kinit, parameters) # the following needs a g_n term BQnew = household.get_BQ(rnew.reshape(T, 1), b_mat[:T], omega_stationary[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') bmat_s = np.zeros((T, S, J)) bmat_s[:, 1:, :] = b_mat[:T, :-1, :] T_H_new = np.array( list( tax.get_lump_sum( rnew.reshape(T, 1, 1), bmat_s, wnew.reshape(T, 1, 1), e.reshape(1, S, J), n_mat[:T], BQnew.reshape(T, 1, J), lambdas.reshape(1, 1, J), factor_ss, omega_stationary[:T]. reshape(T, S, 1), 'TPI', parameters, theta, tau_bq)) + [T_Hss] * S) winit[:T] = utils.convex_combo(wnew, winit[:T], parameters) rinit[:T] = utils.convex_combo(rnew, rinit[:T], parameters) BQinit[:T] = utils.convex_combo(BQnew, BQinit[:T], parameters) T_H_init[:T] = utils.convex_combo(T_H_new[:T], T_H_init[:T], parameters) guesses_b = utils.convex_combo(b_mat, guesses_b, parameters) guesses_n = utils.convex_combo(n_mat, guesses_n, parameters) if T_H_init.all() != 0: TPIdist = np.array( list(utils.perc_dif_func(rnew, rinit[:T])) + list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) + list(utils.perc_dif_func(wnew, winit[:T])) + list(utils.perc_dif_func(T_H_new, T_H_init))).max() else: TPIdist = np.array( list(utils.perc_dif_func(rnew, rinit[:T])) + list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) + list(utils.perc_dif_func(wnew, winit[:T])) + list(np.abs(T_H_new, T_H_init))).max() TPIdist_vec[TPIiter] = TPIdist # After T=10, if cycling occurs, drop the value of nu # wait til after T=10 or so, because sometimes there is a jump up # in the first couple iterations if TPIiter > 10: if TPIdist_vec[TPIiter] - TPIdist_vec[TPIiter - 1] > 0: nu /= 2 print 'New Value of nu:', nu TPIiter += 1 print '\tIteration:', TPIiter print '\t\tDistance:', TPIdist print 'Computing final solutions' # As in SS, you need the final distributions of b and n to match the final # w, r, BQ, etc. Otherwise the euler errors are large. You need one more # fsolve. for j in xrange(J): b_mat[1, -1, j], n_mat[0, -1, j] = np.array( opt.fsolve(SS_TPI_firstdoughnutring, [guesses_b[1, -1, j], guesses_n[0, -1, j]], args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq), xtol=1e-13)) for s in xrange(S - 2): # Upper triangle ind2 = np.arange(s + 2) b_guesses_to_use = np.diag(guesses_b[1:S + 1, :, j], S - (s + 2)) n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2)) solutions = opt.fsolve( Steady_state_TPI_solver, list(b_guesses_to_use) + list(n_guesses_to_use), args=(winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:len(solutions) / 2] b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec n_vec = solutions[len(solutions) / 2:] n_mat[ind2, S - (s + 2) + ind2, j] = n_vec for t in xrange(0, T): b_guesses_to_use = .75 * np.diag(guesses_b[t + 1:t + S + 1, :, j]) n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j]) solutions = opt.fsolve( Steady_state_TPI_solver, list(b_guesses_to_use) + list(n_guesses_to_use), args=(winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:S] b_mat[t + 1 + ind, ind, j] = b_vec n_vec = solutions[S:] n_mat[t + ind, ind, j] = n_vec inputs = list(solutions) euler_errors[t, :, j] = np.abs( Steady_state_TPI_solver(inputs, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n)) b_mat[0, :, :] = initial_b ''' ------------------------------------------------------------------------ Generate variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' Kpath_TPI = np.array(list(Kinit) + list(np.ones(10) * Kss)) Lpath_TPI = np.array(list(Linit) + list(np.ones(10) * Lss)) BQpath_TPI = np.array(list(BQinit) + list(np.ones((10, J)) * BQss)) b_s = np.zeros((T, S, J)) b_s[:, 1:, :] = b_mat[:T, :-1, :] b_splus1 = np.zeros((T, S, J)) b_splus1[:, :, :] = b_mat[1:T + 1, :, :] tax_path = tax.total_taxes(rinit[:T].reshape(T, 1, 1), b_s, winit[:T].reshape(T, 1, 1), e.reshape(1, S, J), n_mat[:T], BQinit[:T, :].reshape(T, 1, J), lambdas, factor_ss, T_H_init[:T].reshape(T, 1, 1), None, 'TPI', False, parameters, theta, tau_bq) c_path = household.get_cons(rinit[:T].reshape(T, 1, 1), b_s, winit[:T].reshape(T, 1, 1), e.reshape(1, S, J), n_mat[:T], BQinit[:T].reshape(T, 1, J), lambdas.reshape(1, 1, J), b_splus1, parameters, tax_path) Y_path = firm.get_Y(Kpath_TPI[:T], Lpath_TPI[:T], parameters) C_path = household.get_C(c_path, omega_stationary[:T].reshape(T, S, 1), lambdas, 'TPI') I_path = firm.get_I(Kpath_TPI[1:T + 1], Kpath_TPI[:T], delta, g_y, g_n_vector[:T]) print 'Resource Constraint Difference:', Y_path - C_path - I_path print 'Checking time path for violations of constaints.' for t in xrange(T): household.constraint_checker_TPI(b_mat[t], n_mat[t], c_path[t], t, parameters) eul_savings = euler_errors[:, :S, :].max(1).max(1) eul_laborleisure = euler_errors[:, S:, :].max(1).max(1) ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = { 'Kpath_TPI': Kpath_TPI, 'b_mat': b_mat, 'c_path': c_path, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure, 'Lpath_TPI': Lpath_TPI, 'BQpath_TPI': BQpath_TPI, 'n_mat': n_mat, 'rinit': rinit, 'Yinit': Yinit, 'T_H_init': T_H_init, 'tax_path': tax_path, 'winit': winit } if get_baseline: tpi_init_dir = os.path.join(output_dir, "TPIinit") utils.mkdirs(tpi_init_dir) tpi_init_vars = os.path.join(tpi_init_dir, "TPIinit_vars.pkl") pickle.dump(output, open(tpi_init_vars, "wb")) else: tpi_dir = os.path.join(output_dir, "TPI") utils.mkdirs(tpi_dir) tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl") pickle.dump(output, open(tpi_vars, "wb"))
def run_time_path_iteration(Kss, Lss, Yss, BQss, theta, income_tax_params, wealth_tax_params, ellipse_params, parameters, g_n_vector, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0, r0, BQ0, T_H_0, tax0, c0, initial_b, initial_n, factor_ss, tau_bq, chi_b, chi_n, output_dir="./OUTPUT", **kwargs): J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire, mean_income_data, \ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = parameters analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params TPI_FIG_DIR = output_dir # Initialize Time paths domain = np.linspace(0, T, T) Kinit = (-1 / (domain + 1)) * (Kss - K0) + Kss Kinit[-1] = Kss Kinit = np.array(list(Kinit) + list(np.ones(S) * Kss)) Linit = np.ones(T + S) * Lss Yinit = firm.get_Y(Kinit, Linit, parameters) winit = firm.get_w(Yinit, Linit, parameters) rinit = firm.get_r(Yinit, Kinit, parameters) BQinit = np.zeros((T + S, J)) for j in xrange(J): BQinit[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S BQinit = np.array(BQinit) if T_Hss < 1e-13 and T_Hss > 0.0 : T_Hss2 = 0.0 # sometimes SS is very small but not zero, even if taxes are zero, this get's rid of the approximation error, which affects the perc changes below else: T_Hss2 = T_Hss T_H_init = np.ones(T + S) * T_Hss2 # Make array of initial guesses domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J)) ending_b = bssmat_splus1 guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1)) guesses_b = np.append(guesses_b, ending_b_tail, axis=0) domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J)) guesses_n = domain3 * (nssmat - initial_n) + initial_n ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1)) guesses_n = np.append(guesses_n, ending_n_tail, axis=0) b_mat = np.zeros((T + S, S, J)) n_mat = np.zeros((T + S, S, J)) ind = np.arange(S) TPIiter = 0 TPIdist = 10 euler_errors = np.zeros((T, 2 * S, J)) TPIdist_vec = np.zeros(maxiter) while (TPIiter < maxiter) and (TPIdist >= mindist_TPI): Kpath_TPI = list(Kinit) + list(np.ones(10) * Kss) Lpath_TPI = list(Linit) + list(np.ones(10) * Lss) # Plot TPI for K for each iteration, so we can see if there is a # problem if PLOT_TPI is True: plt.figure() plt.axhline( y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--') plt.plot(np.arange( T + 10), Kpath_TPI[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$") plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K")) # Uncomment the following print statements to make sure all euler equations are converging. # If they don't, then you'll have negative consumption or consumption spikes. If they don't, # it is the initial guesses. You might need to scale them differently. It is rather delicate for the first # few periods and high ability groups. for j in xrange(J): b_mat[1, -1, j], n_mat[0, -1, j] = np.array(opt.fsolve(SS_TPI_firstdoughnutring, [guesses_b[1, -1, j], guesses_n[0, -1, j]], args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, income_tax_params, parameters, theta, tau_bq), xtol=1e-13)) # if np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq)).max() > 1e-6: # print 'minidoughnut:', # np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, # j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, # factor_ss, j, parameters, theta, tau_bq)).max() for s in xrange(S - 2): # Upper triangle ind2 = np.arange(s + 2) b_guesses_to_use = np.diag( guesses_b[1:S + 1, :, j], S - (s + 2)) n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2)) # initialize array of diagonal elements length_diag = (np.diag(np.transpose(etr_params[:S,:,0]),S-(s+2))).shape[0] etr_params_to_use = np.zeros((length_diag,etr_params.shape[2])) mtrx_params_to_use = np.zeros((length_diag,mtrx_params.shape[2])) mtry_params_to_use = np.zeros((length_diag,mtry_params.shape[2])) for i in range(etr_params.shape[2]): etr_params_to_use[:,i] = np.diag(np.transpose(etr_params[:S,:,i]),S-(s+2)) mtrx_params_to_use[:,i] = np.diag(np.transpose(mtrx_params[:S,:,i]),S-(s+2)) mtry_params_to_use[:,i] = np.diag(np.transpose(mtry_params[:S,:,i]),S-(s+2)) inc_tax_params_upper = (analytical_mtrs, etr_params_to_use, mtrx_params_to_use, mtry_params_to_use) solutions = opt.fsolve(Steady_state_TPI_solver, list( b_guesses_to_use) + list(n_guesses_to_use), args=( winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, inc_tax_params_upper, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:len(solutions) / 2] b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec n_vec = solutions[len(solutions) / 2:] n_mat[ind2, S - (s + 2) + ind2, j] = n_vec # if abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n))).max() > 1e-6: # print 's-loop:', # abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, # BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, # theta, tau_bq, rho, lambdas, e, initial_b, chi_b, # chi_n))).max() for t in xrange(0, T): b_guesses_to_use = .75 * \ np.diag(guesses_b[t + 1:t + S + 1, :, j]) n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j]) # initialize array of diagonal elements length_diag = (np.diag(np.transpose(etr_params[:,t:t+S,i]))).shape[0] etr_params_to_use = np.zeros((length_diag,etr_params.shape[2])) mtrx_params_to_use = np.zeros((length_diag,mtrx_params.shape[2])) mtry_params_to_use = np.zeros((length_diag,mtry_params.shape[2])) for i in range(etr_params.shape[2]): etr_params_to_use[:,i] = np.diag(np.transpose(etr_params[:,t:t+S,i])) mtrx_params_to_use[:,i] = np.diag(np.transpose(mtrx_params[:,t:t+S,i])) mtry_params_to_use[:,i] = np.diag(np.transpose(mtry_params[:,t:t+S,i])) inc_tax_params_TP = (analytical_mtrs, etr_params_to_use, mtrx_params_to_use, mtry_params_to_use) solutions = opt.fsolve(Steady_state_TPI_solver, list( b_guesses_to_use) + list(n_guesses_to_use), args=( winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, inc_tax_params_TP, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:S] b_mat[t + 1 + ind, ind, j] = b_vec n_vec = solutions[S:] n_mat[t + ind, ind, j] = n_vec inputs = list(solutions) euler_errors[t, :, j] = np.abs(Steady_state_TPI_solver( inputs, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, inc_tax_params_TP, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n)) # if euler_errors.max() > 1e-6: # print 't-loop:', euler_errors.max() # Force the initial distribution of capital to be as given above. b_mat[0, :, :] = initial_b Kinit = household.get_K(b_mat[:T], omega_stationary[:T].reshape( T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI') Linit = firm.get_L(e.reshape(1, S, J), n_mat[:T], omega_stationary[ :T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') Ynew = firm.get_Y(Kinit, Linit, parameters) wnew = firm.get_w(Ynew, Linit, parameters) rnew = firm.get_r(Ynew, Kinit, parameters) # the following needs a g_n term BQnew = household.get_BQ(rnew.reshape(T, 1), b_mat[:T], omega_stationary[:T].reshape( T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') bmat_s = np.zeros((T, S, J)) bmat_s[:, 1:, :] = b_mat[:T, :-1, :] # initialize array TH_tax_params = np.zeros((T,S,J,etr_params.shape[2])) for i in range(etr_params.shape[2]): TH_tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J)) T_H_new = np.array(list(tax.get_lump_sum(np.tile(rnew.reshape(T, 1, 1),(1,S,J)), bmat_s, np.tile(wnew.reshape( T, 1, 1),(1,S,J)), np.tile(e.reshape(1, S, J),(T,1,1)), n_mat[:T,:,:], BQnew.reshape(T, 1, J), lambdas.reshape( 1, 1, J), factor_ss, omega_stationary[:T].reshape(T, S, 1), 'TPI', TH_tax_params, parameters, theta, tau_bq)) + [T_Hss] * S) winit[:T] = utils.convex_combo(wnew, winit[:T], nu) rinit[:T] = utils.convex_combo(rnew, rinit[:T], nu) BQinit[:T] = utils.convex_combo(BQnew, BQinit[:T], nu) T_H_init[:T] = utils.convex_combo(T_H_new[:T], T_H_init[:T], nu) guesses_b = utils.convex_combo(b_mat, guesses_b, nu) guesses_n = utils.convex_combo(n_mat, guesses_n, nu) if T_H_init.all() != 0: TPIdist = np.array(list(utils.perc_dif_func(rnew, rinit[:T])) + list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) + list( utils.perc_dif_func(wnew, winit[:T])) + list(utils.perc_dif_func(T_H_new, T_H_init))).max() else: TPIdist = np.array(list(utils.perc_dif_func(rnew, rinit[:T])) + list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) + list( utils.perc_dif_func(wnew, winit[:T])) + list(np.abs(T_H_new, T_H_init))).max() TPIdist_vec[TPIiter] = TPIdist # After T=10, if cycling occurs, drop the value of nu # wait til after T=10 or so, because sometimes there is a jump up # in the first couple iterations # if TPIiter > 10: # if TPIdist_vec[TPIiter] - TPIdist_vec[TPIiter - 1] > 0: # nu /= 2 # print 'New Value of nu:', nu TPIiter += 1 print '\tIteration:', TPIiter print '\t\tDistance:', TPIdist return winit[:T], rinit[:T], T_H_init[:T], BQinit[:T], Yinit
def run_time_path_iteration(Kss, Lss, Yss, BQss, theta, parameters, g_n_vector, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0, r0, BQ0, T_H_0, tax0, c0, initial_b, initial_n, factor_ss, tau_bq, chi_b, chi_n, get_baseline=False, output_dir="./OUTPUT", **kwargs): TPI_FIG_DIR = output_dir # Initialize Time paths domain = np.linspace(0, T, T) Kinit = (-1 / (domain + 1)) * (Kss - K0) + Kss Kinit[-1] = Kss Kinit = np.array(list(Kinit) + list(np.ones(S) * Kss)) Linit = np.ones(T + S) * Lss Yinit = firm.get_Y(Kinit, Linit, parameters) winit = firm.get_w(Yinit, Linit, parameters) rinit = firm.get_r(Yinit, Kinit, parameters) BQinit = np.zeros((T + S, J)) for j in xrange(J): BQinit[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S BQinit = np.array(BQinit) T_H_init = np.ones(T + S) * T_Hss # Make array of initial guesses domain2 = np.tile(domain.reshape(T, 1, 1), (1, S, J)) ending_b = bssmat_splus1 guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b ending_b_tail = np.tile(ending_b.reshape(1, S, J), (S, 1, 1)) guesses_b = np.append(guesses_b, ending_b_tail, axis=0) domain3 = np.tile(np.linspace(0, 1, T).reshape(T, 1, 1), (1, S, J)) guesses_n = domain3 * (nssmat - initial_n) + initial_n ending_n_tail = np.tile(nssmat.reshape(1, S, J), (S, 1, 1)) guesses_n = np.append(guesses_n, ending_n_tail, axis=0) b_mat = np.zeros((T + S, S, J)) n_mat = np.zeros((T + S, S, J)) ind = np.arange(S) TPIiter = 0 TPIdist = 10 euler_errors = np.zeros((T, 2 * S, J)) TPIdist_vec = np.zeros(maxiter) while (TPIiter < maxiter) and (TPIdist >= mindist_TPI): Kpath_TPI = list(Kinit) + list(np.ones(10) * Kss) Lpath_TPI = list(Linit) + list(np.ones(10) * Lss) # Plot TPI for K for each iteration, so we can see if there is a # problem if PLOT_TPI is True: plt.figure() plt.axhline( y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--') plt.plot(np.arange( T + 10), Kpath_TPI[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$") plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K")) # Uncomment the following print statements to make sure all euler equations are converging. # If they don't, then you'll have negative consumption or consumption spikes. If they don't, # it is the initial guesses. You might need to scale them differently. It is rather delicate for the first # few periods and high ability groups. for j in xrange(J): b_mat[1, -1, j], n_mat[0, -1, j] = np.array(opt.fsolve(SS_TPI_firstdoughnutring, [guesses_b[1, -1, j], guesses_n[0, -1, j]], args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq), xtol=1e-13)) # if np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq)).max() > 1e-6: # print 'minidoughnut:', # np.array(SS_TPI_firstdoughnutring([b_mat[1, -1, j], n_mat[0, -1, # j]], winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, # factor_ss, j, parameters, theta, tau_bq)).max() for s in xrange(S - 2): # Upper triangle ind2 = np.arange(s + 2) b_guesses_to_use = np.diag( guesses_b[1:S + 1, :, j], S - (s + 2)) n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2)) solutions = opt.fsolve(Steady_state_TPI_solver, list( b_guesses_to_use) + list(n_guesses_to_use), args=( winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:len(solutions) / 2] b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec n_vec = solutions[len(solutions) / 2:] n_mat[ind2, S - (s + 2) + ind2, j] = n_vec # if abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n))).max() > 1e-6: # print 's-loop:', # abs(np.array(Steady_state_TPI_solver(solutions, winit, rinit, # BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, # theta, tau_bq, rho, lambdas, e, initial_b, chi_b, # chi_n))).max() for t in xrange(0, T): b_guesses_to_use = .75 * \ np.diag(guesses_b[t + 1:t + S + 1, :, j]) n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j]) solutions = opt.fsolve(Steady_state_TPI_solver, list( b_guesses_to_use) + list(n_guesses_to_use), args=( winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:S] b_mat[t + 1 + ind, ind, j] = b_vec n_vec = solutions[S:] n_mat[t + ind, ind, j] = n_vec inputs = list(solutions) euler_errors[t, :, j] = np.abs(Steady_state_TPI_solver( inputs, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n)) # if euler_errors.max() > 1e-6: # print 't-loop:', euler_errors.max() # Force the initial distribution of capital to be as given above. b_mat[0, :, :] = initial_b Kinit = household.get_K(b_mat[:T], omega_stationary[:T].reshape( T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI') Linit = firm.get_L(e.reshape(1, S, J), n_mat[:T], omega_stationary[ :T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') Ynew = firm.get_Y(Kinit, Linit, parameters) wnew = firm.get_w(Ynew, Linit, parameters) rnew = firm.get_r(Ynew, Kinit, parameters) # the following needs a g_n term BQnew = household.get_BQ(rnew.reshape(T, 1), b_mat[:T], omega_stationary[:T].reshape( T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI') bmat_s = np.zeros((T, S, J)) bmat_s[:, 1:, :] = b_mat[:T, :-1, :] T_H_new = np.array(list(tax.get_lump_sum(rnew.reshape(T, 1, 1), bmat_s, wnew.reshape( T, 1, 1), e.reshape(1, S, J), n_mat[:T], BQnew.reshape(T, 1, J), lambdas.reshape( 1, 1, J), factor_ss, omega_stationary[:T].reshape(T, S, 1), 'TPI', parameters, theta, tau_bq)) + [T_Hss] * S) winit[:T] = utils.convex_combo(wnew, winit[:T], parameters) rinit[:T] = utils.convex_combo(rnew, rinit[:T], parameters) BQinit[:T] = utils.convex_combo(BQnew, BQinit[:T], parameters) T_H_init[:T] = utils.convex_combo( T_H_new[:T], T_H_init[:T], parameters) guesses_b = utils.convex_combo(b_mat, guesses_b, parameters) guesses_n = utils.convex_combo(n_mat, guesses_n, parameters) if T_H_init.all() != 0: TPIdist = np.array(list(utils.perc_dif_func(rnew, rinit[:T])) + list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) + list( utils.perc_dif_func(wnew, winit[:T])) + list(utils.perc_dif_func(T_H_new, T_H_init))).max() else: TPIdist = np.array(list(utils.perc_dif_func(rnew, rinit[:T])) + list(utils.perc_dif_func(BQnew, BQinit[:T]).flatten()) + list( utils.perc_dif_func(wnew, winit[:T])) + list(np.abs(T_H_new, T_H_init))).max() TPIdist_vec[TPIiter] = TPIdist # After T=10, if cycling occurs, drop the value of nu # wait til after T=10 or so, because sometimes there is a jump up # in the first couple iterations if TPIiter > 10: if TPIdist_vec[TPIiter] - TPIdist_vec[TPIiter - 1] > 0: nu /= 2 print 'New Value of nu:', nu TPIiter += 1 print '\tIteration:', TPIiter print '\t\tDistance:', TPIdist print 'Computing final solutions' # As in SS, you need the final distributions of b and n to match the final # w, r, BQ, etc. Otherwise the euler errors are large. You need one more # fsolve. for j in xrange(J): b_mat[1, -1, j], n_mat[0, -1, j] = np.array(opt.fsolve(SS_TPI_firstdoughnutring, [guesses_b[1, -1, j], guesses_n[0, -1, j]], args=(winit[1], rinit[1], BQinit[1, j], T_H_init[1], initial_b, factor_ss, j, parameters, theta, tau_bq), xtol=1e-13)) for s in xrange(S - 2): # Upper triangle ind2 = np.arange(s + 2) b_guesses_to_use = np.diag(guesses_b[1:S + 1, :, j], S - (s + 2)) n_guesses_to_use = np.diag(guesses_n[:S, :, j], S - (s + 2)) solutions = opt.fsolve(Steady_state_TPI_solver, list( b_guesses_to_use) + list(n_guesses_to_use), args=( winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, s, 0, parameters, theta, tau_bq, rho, lambdas, e, initial_b, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:len(solutions) / 2] b_mat[1 + ind2, S - (s + 2) + ind2, j] = b_vec n_vec = solutions[len(solutions) / 2:] n_mat[ind2, S - (s + 2) + ind2, j] = n_vec for t in xrange(0, T): b_guesses_to_use = .75 * np.diag(guesses_b[t + 1:t + S + 1, :, j]) n_guesses_to_use = np.diag(guesses_n[t:t + S, :, j]) solutions = opt.fsolve(Steady_state_TPI_solver, list( b_guesses_to_use) + list(n_guesses_to_use), args=( winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n), xtol=1e-13) b_vec = solutions[:S] b_mat[t + 1 + ind, ind, j] = b_vec n_vec = solutions[S:] n_mat[t + ind, ind, j] = n_vec inputs = list(solutions) euler_errors[t, :, j] = np.abs(Steady_state_TPI_solver( inputs, winit, rinit, BQinit[:, j], T_H_init, factor_ss, j, None, t, parameters, theta, tau_bq, rho, lambdas, e, None, chi_b, chi_n)) b_mat[0, :, :] = initial_b ''' ------------------------------------------------------------------------ Generate variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' Kpath_TPI = np.array(list(Kinit) + list(np.ones(10) * Kss)) Lpath_TPI = np.array(list(Linit) + list(np.ones(10) * Lss)) BQpath_TPI = np.array(list(BQinit) + list(np.ones((10, J)) * BQss)) b_s = np.zeros((T, S, J)) b_s[:, 1:, :] = b_mat[:T, :-1, :] b_splus1 = np.zeros((T, S, J)) b_splus1[:, :, :] = b_mat[1:T + 1, :, :] tax_path = tax.total_taxes(rinit[:T].reshape(T, 1, 1), b_s, winit[:T].reshape(T, 1, 1), e.reshape( 1, S, J), n_mat[:T], BQinit[:T, :].reshape(T, 1, J), lambdas, factor_ss, T_H_init[:T].reshape(T, 1, 1), None, 'TPI', False, parameters, theta, tau_bq) c_path = household.get_cons(rinit[:T].reshape(T, 1, 1), b_s, winit[:T].reshape(T, 1, 1), e.reshape( 1, S, J), n_mat[:T], BQinit[:T].reshape(T, 1, J), lambdas.reshape(1, 1, J), b_splus1, parameters, tax_path) Y_path = firm.get_Y(Kpath_TPI[:T], Lpath_TPI[:T], parameters) C_path = household.get_C(c_path, omega_stationary[ :T].reshape(T, S, 1), lambdas, 'TPI') I_path = firm.get_I(Kpath_TPI[1:T + 1], Kpath_TPI[:T], delta, g_y, g_n_vector[:T]) print 'Resource Constraint Difference:', Y_path - C_path - I_path print'Checking time path for violations of constaints.' for t in xrange(T): household.constraint_checker_TPI( b_mat[t], n_mat[t], c_path[t], t, parameters) eul_savings = euler_errors[:, :S, :].max(1).max(1) eul_laborleisure = euler_errors[:, S:, :].max(1).max(1) ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = {'Kpath_TPI': Kpath_TPI, 'b_mat': b_mat, 'c_path': c_path, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure, 'Lpath_TPI': Lpath_TPI, 'BQpath_TPI': BQpath_TPI, 'n_mat': n_mat, 'rinit': rinit, 'Yinit': Yinit, 'T_H_init': T_H_init, 'tax_path': tax_path, 'winit': winit} if get_baseline: tpi_init_dir = os.path.join(output_dir, "TPIinit") utils.mkdirs(tpi_init_dir) tpi_init_vars = os.path.join(tpi_init_dir, "TPIinit_vars.pkl") pickle.dump(output, open(tpi_init_vars, "wb")) else: tpi_dir = os.path.join(output_dir, "TPI") utils.mkdirs(tpi_dir) tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl") pickle.dump(output, open(tpi_vars, "wb"))
def function_to_minimize(chi_params_scalars, chi_params_init, income_tax_parameters, ss_parameters, iterative_params, weights_SS, rho_vec, lambdas, tau_bq, e, output_dir): ''' Inputs: chi_params_scalars = guesses for multipliers for chi parameters ((S+J)x1 array) chi_params_init = chi parameters that will be multiplied ((S+J)x1 array) params = list of parameters (list) weights_SS = steady state population weights (Sx1 array) rho_vec = mortality rates (Sx1 array) lambdas = ability weights (Jx1 array) tau_bq = bequest tax rates (Jx1 array) e = ability levels (Jx1 array) Output: The sum of absolute percent deviations between the actual and simulated wealth moments ''' J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\ g_n_ss, tau_payroll, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_parameters analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_parameters chi_params_init *= chi_params_scalars # print 'Print Chi_b: ', chi_params_init[:J] # print 'Scaling vals:', chi_params_scalars[:J] ss_init_path = os.path.join(output_dir, "Saved_moments/SS_init_solutions.pkl") solutions_dict = pickle.load(open(ss_init_path, "rb")) solutions = solutions_dict['solutions'] b_guess = solutions[:(S * J)] n_guess = solutions[S * J:2 * S * J] wguess, rguess, factorguess, T_Hguess = solutions[(2 * S * J):] guesses = [wguess, rguess, T_Hguess, factorguess] args_ = (b_guess.reshape(S, J), n_guess.reshape(S, J), chi_params_init[J:], chi_params_init[:J], income_tax_parameters, ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e) [solutions, infodict, ier, message] = opt.fsolve(SS_fsolve, guesses, args=args_, xtol=mindist_SS, full_output=True) [wguess, rguess, T_Hguess, factorguess] = solutions fsolve_flag = True solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params_init[ J:], chi_params_init[:J], income_tax_parameters, ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e, fsolve_flag) b_new = solutions[:(S * J)] n_new = solutions[(S * J):(2 * S * J)] w_new, r_new, factor_new, T_H_new = solutions[(2 * S * J):] # Wealth Calibration Euler error5 = list(utils.check_wealth_calibration(b_new.reshape(S, J)[:-1, :], factor_new, ss_parameters, output_dir)) # labor calibration euler labor_path = os.path.join( output_dir, "Saved_moments/labor_data_moments.pkl") lab_data_dict = pickle.load(open(labor_path, "rb")) labor_sim = (n_new.reshape(S, J) * lambdas.reshape(1, J)).sum(axis=1) if DATASET == 'SMALL': lab_dist_data = lab_data_dict['labor_dist_data'][:S] else: lab_dist_data = lab_data_dict['labor_dist_data'] error6 = list(utils.perc_dif_func(labor_sim, lab_dist_data)) # combine eulers output = np.array(error5 + error6) # Constraints eul_error = np.ones(J) for j in xrange(J): eul_error[j] = np.abs(Euler_equation_solver(np.append(b_new.reshape(S, J)[:, j], n_new.reshape(S, J)[:, j]), r_new, w_new, T_H_new, factor_new, j, income_tax_parameters, ss_parameters, chi_params_init[:J], chi_params_init[J:], tau_bq, rho, lambdas, weights_SS, e)).max() fsolve_no_converg = eul_error.max() if np.isnan(fsolve_no_converg): fsolve_no_converg = 1e6 if fsolve_no_converg > 1e-4: # If the fsovle didn't converge (was NaN or above the tolerance), then tell the minimizer that this is a bad place to be # and don't save the solutions as initial guesses (since they might be # gibberish) output += 1e14 else: var_names = ['solutions'] dictionary = {} for key in var_names: dictionary[key] = locals()[key] ss_init_path = os.path.join( output_dir, "Saved_moments/SS_init_solutions.pkl") pickle.dump(dictionary, open(ss_init_path, "wb")) if (chi_params_init <= 0.0).any(): # In case the minimizer doesn't respect the bounds given output += 1e14 # Use generalized method of moments to fit the chi's weighting_mat = np.eye(2 * J + S) scaling_val = 100.0 value = np.dot(scaling_val * np.dot(output.reshape(1, 2 * J + S), weighting_mat), scaling_val * output.reshape(2 * J + S, 1)) print 'Value of criterion function: ', value.sum() # pickle output in case not converge global Nfeval, value_all, chi_params_all value_all[Nfeval] = value.sum() chi_params_all[:,Nfeval] = chi_params_init dict_GMM = dict([('values', value_all), ('chi_params', chi_params_all)]) ss_init_path = os.path.join(output_dir, "Saved_moments/SS_init_all.pkl") pickle.dump(dict_GMM, open(ss_init_path, "wb")) Nfeval += 1 return value.sum()
def SS_solver(b_guess_init, n_guess_init, wguess, rguess, T_Hguess, factorguess, chi_n, chi_b, tax_params, params, iterative_params, tau_bq, rho, lambdas, weights, e, fsolve_flag=False): ''' 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, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\ g_n_ss, tau_payroll, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = params analytical_mtrs, etr_params, mtrx_params, mtry_params = tax_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) if fsolve_flag == True: maxiter = 1 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 if j == 0: guesses = np.append(bssmat[:, j], nssmat[:, j]) else: guesses = np.append(bssmat[:, j-1], nssmat[:, j-1]) args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n, tau_bq, rho, lambdas, weights, e) [solutions, infodict, ier, message] = opt.fsolve(Euler_equation_solver, guesses * .9, args=args_, xtol=1e-13, full_output=True) print 'Max Euler errors: ', np.absolute(infodict['fvec']).max() 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 = household.get_K(bssmat, weights.reshape(S, 1), lambdas.reshape(1, J), g_n_ss, 'SS') L = firm.get_L(e, nssmat, weights.reshape(S, 1), lambdas.reshape(1, J), 'SS') 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 = household.get_BQ(new_r, bssmat, weights.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS') theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, e, J, weights.reshape(S, 1), lambdas) # lump_sum_tax_params = (a_etr_income, b_etr_income, c_etr_income, d_etr_income, # e_etr_income, f_etr_income, min_x_etr_income, max_x_etr_income, # min_y_etr_income, max_y_etr_income) 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', etr_params, params, theta, tau_bq) r = utils.convex_combo(new_r, r, nu) w = utils.convex_combo(new_w, w, nu) factor = utils.convex_combo(new_factor, factor, nu) T_H = utils.convex_combo(new_T_H, T_H, nu) if T_H != 0: dist = np.array([utils.perc_dif_func(new_r, r)] + [utils.perc_dif_func(new_w, w)] + [utils.perc_dif_func(new_T_H, T_H)] + [utils.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([utils.perc_dif_func(new_r, r)] + [utils.perc_dif_func(new_w, w)] + [abs(new_T_H - T_H)] + [utils.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): guesses = np.append(bssmat[:, j], nssmat[:, j]) args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n, tau_bq, rho, lambdas, weights, e) [solutions1, infodict, ier, message] = opt.fsolve(Euler_equation_solver, guesses * .9, args=args_, xtol=1e-13, full_output=True) eul_errors[j] = np.array(infodict['fvec']).max() print 'Max Euler errors: ', np.absolute(infodict['fvec']).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
def function_to_minimize(chi_params_scalars, chi_params_init, params, iterative_params, weights_SS, rho_vec, lambdas, tau_bq, e): ''' Inputs: chi_params_scalars = guesses for multipliers for chi parameters ((S+J)x1 array) chi_params_init = chi parameters that will be multiplied ((S+J)x1 array) params = list of parameters (list) weights_SS = steady state population weights (Sx1 array) rho_vec = mortality rates (Sx1 array) lambdas = ability weights (Jx1 array) tau_bq = bequest tax rates (Jx1 array) e = ability levels (Jx1 array) Output: The sum of absolute percent deviations between the actual and simulated wealth moments ''' 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 chi_params_init *= chi_params_scalars # print 'Print Chi_b: ', chi_params_init[:J] # print 'Scaling vals:', chi_params_scalars[:J] solutions_dict = pickle.load(open("OUTPUT/Saved_moments/SS_init_solutions.pkl", "rb")) solutions = solutions_dict['solutions'] b_guess = solutions[:S*J] n_guess = solutions[S*J:2*S*J] wguess, rguess, factorguess, T_Hguess = solutions[2*S*J:] solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params_init[J:], chi_params_init[:J], params, iterative_params, tau_bq, rho, lambdas, weights_SS, e) b_new = solutions[:S*J] n_new = solutions[S*J:2*S*J] w_new, r_new, factor_new, T_H_new = solutions[2*S*J:] # Wealth Calibration Euler error5 = list(utils.check_wealth_calibration(b_new.reshape(S, J)[:-1, :], factor_new, params)) # labor calibration euler lab_data_dict = pickle.load(open("OUTPUT/Saved_moments/labor_data_moments.pkl", "rb")) labor_sim = (n_new.reshape(S, J)*lambdas.reshape(1, J)).sum(axis=1) if DATASET == 'SMALL': lab_dist_data = lab_data_dict['labor_dist_data'][:S] else: lab_dist_data = lab_data_dict['labor_dist_data'] error6 = list(utils.perc_dif_func(labor_sim, lab_dist_data)) # combine eulers output = np.array(error5 + error6) # Constraints eul_error = np.ones(J) for j in xrange(J): eul_error[j] = np.abs(Euler_equation_solver(np.append(b_new.reshape(S, J)[:, j], n_new.reshape(S, J)[:, j]), r_new, w_new, T_H_new, factor_new, j, params, chi_params_init[:J], chi_params_init[J:], tau_bq, rho, lambdas, weights_SS, e)).max() fsolve_no_converg = eul_error.max() if np.isnan(fsolve_no_converg): fsolve_no_converg = 1e6 if fsolve_no_converg > 1e-4: # If the fsovle didn't converge (was NaN or above the tolerance), then tell the minimizer that this is a bad place to be # and don't save the solutions as initial guesses (since they might be gibberish) output += 1e14 else: var_names = ['solutions'] dictionary = {} for key in var_names: dictionary[key] = locals()[key] pickle.dump(dictionary, open("OUTPUT/Saved_moments/SS_init_solutions.pkl", "wb")) if (chi_params_init <= 0.0).any(): # In case the minimizer doesn't respect the bounds given output += 1e14 # Use generalized method of moments to fit the chi's weighting_mat = np.eye(2*J + S) scaling_val = 100.0 value = np.dot(scaling_val * np.dot(output.reshape(1, 2*J+S), weighting_mat), scaling_val * output.reshape(2*J+S, 1)) print 'Value of criterion function: ', value.sum() return value.sum()
def function_to_minimize(chi_params_scalars, chi_params_init, income_tax_parameters, ss_parameters, iterative_params, weights_SS, rho_vec, lambdas, tau_bq, e, output_dir): ''' Inputs: chi_params_scalars = guesses for multipliers for chi parameters ((S+J)x1 array) chi_params_init = chi parameters that will be multiplied ((S+J)x1 array) params = list of parameters (list) weights_SS = steady state population weights (Sx1 array) rho_vec = mortality rates (Sx1 array) lambdas = ability weights (Jx1 array) tau_bq = bequest tax rates (Jx1 array) e = ability levels (Jx1 array) Output: The sum of absolute percent deviations between the actual and simulated wealth moments ''' J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\ g_n_ss, tau_payroll, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_parameters analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_parameters chi_params_init *= chi_params_scalars # print 'Print Chi_b: ', chi_params_init[:J] # print 'Scaling vals:', chi_params_scalars[:J] ss_init_path = os.path.join(output_dir, "Saved_moments/SS_init_solutions.pkl") solutions_dict = pickle.load(open(ss_init_path, "rb")) solutions = solutions_dict['solutions'] b_guess = solutions[:(S * J)] n_guess = solutions[S * J:2 * S * J] wguess, rguess, factorguess, T_Hguess = solutions[(2 * S * J):] guesses = [wguess, rguess, T_Hguess, factorguess] args_ = (b_guess.reshape(S, J), n_guess.reshape(S, J), chi_params_init[J:], chi_params_init[:J], income_tax_parameters, ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e) [solutions, infodict, ier, message] = opt.fsolve(SS_fsolve, guesses, args=args_, xtol=mindist_SS, full_output=True) [wguess, rguess, T_Hguess, factorguess] = solutions fsolve_flag = True solutions = SS_solver(b_guess.reshape(S, J), n_guess.reshape(S, J), wguess, rguess, T_Hguess, factorguess, chi_params_init[J:], chi_params_init[:J], income_tax_parameters, ss_parameters, iterative_params, tau_bq, rho, lambdas, omega_SS, e, fsolve_flag) b_new = solutions[:(S * J)] n_new = solutions[(S * J):(2 * S * J)] w_new, r_new, factor_new, T_H_new = solutions[(2 * S * J):] # Wealth Calibration Euler error5 = list( utils.check_wealth_calibration( b_new.reshape(S, J)[:-1, :], factor_new, ss_parameters, output_dir)) # labor calibration euler labor_path = os.path.join(output_dir, "Saved_moments/labor_data_moments.pkl") lab_data_dict = pickle.load(open(labor_path, "rb")) labor_sim = (n_new.reshape(S, J) * lambdas.reshape(1, J)).sum(axis=1) if DATASET == 'SMALL': lab_dist_data = lab_data_dict['labor_dist_data'][:S] else: lab_dist_data = lab_data_dict['labor_dist_data'] error6 = list(utils.perc_dif_func(labor_sim, lab_dist_data)) # combine eulers output = np.array(error5 + error6) # Constraints eul_error = np.ones(J) for j in xrange(J): eul_error[j] = np.abs( Euler_equation_solver( np.append( b_new.reshape(S, J)[:, j], n_new.reshape(S, J)[:, j]), r_new, w_new, T_H_new, factor_new, j, income_tax_parameters, ss_parameters, chi_params_init[:J], chi_params_init[J:], tau_bq, rho, lambdas, weights_SS, e)).max() fsolve_no_converg = eul_error.max() if np.isnan(fsolve_no_converg): fsolve_no_converg = 1e6 if fsolve_no_converg > 1e-4: # If the fsovle didn't converge (was NaN or above the tolerance), then tell the minimizer that this is a bad place to be # and don't save the solutions as initial guesses (since they might be # gibberish) output += 1e14 else: var_names = ['solutions'] dictionary = {} for key in var_names: dictionary[key] = locals()[key] ss_init_path = os.path.join(output_dir, "Saved_moments/SS_init_solutions.pkl") pickle.dump(dictionary, open(ss_init_path, "wb")) if (chi_params_init <= 0.0).any(): # In case the minimizer doesn't respect the bounds given output += 1e14 # Use generalized method of moments to fit the chi's weighting_mat = np.eye(2 * J + S) scaling_val = 100.0 value = np.dot( scaling_val * np.dot(output.reshape(1, 2 * J + S), weighting_mat), scaling_val * output.reshape(2 * J + S, 1)) print 'Value of criterion function: ', value.sum() # pickle output in case not converge global Nfeval, value_all, chi_params_all value_all[Nfeval] = value.sum() chi_params_all[:, Nfeval] = chi_params_init dict_GMM = dict([('values', value_all), ('chi_params', chi_params_all)]) ss_init_path = os.path.join(output_dir, "Saved_moments/SS_init_all.pkl") pickle.dump(dict_GMM, open(ss_init_path, "wb")) Nfeval += 1 return value.sum()
def SS_solver(b_guess_init, n_guess_init, wguess, rguess, T_Hguess, factorguess, chi_n, chi_b, tax_params, params, iterative_params, tau_bq, rho, lambdas, weights, e, fsolve_flag=False): ''' 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, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\ g_n_ss, tau_payroll, retire, mean_income_data,\ h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = params analytical_mtrs, etr_params, mtrx_params, mtry_params = tax_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) if fsolve_flag == True: maxiter = 1 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 if j == 0: guesses = np.append(bssmat[:, j], nssmat[:, j]) else: guesses = np.append(bssmat[:, j - 1], nssmat[:, j - 1]) args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n, tau_bq, rho, lambdas, weights, e) [solutions, infodict, ier, message] = opt.fsolve(Euler_equation_solver, guesses * .9, args=args_, xtol=1e-13, full_output=True) print 'Max Euler errors: ', np.absolute(infodict['fvec']).max() 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 = household.get_K(bssmat, weights.reshape(S, 1), lambdas.reshape(1, J), g_n_ss, 'SS') L = firm.get_L(e, nssmat, weights.reshape(S, 1), lambdas.reshape(1, J), 'SS') 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 = household.get_BQ(new_r, bssmat, weights.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS') theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, e, J, weights.reshape(S, 1), lambdas) # lump_sum_tax_params = (a_etr_income, b_etr_income, c_etr_income, d_etr_income, # e_etr_income, f_etr_income, min_x_etr_income, max_x_etr_income, # min_y_etr_income, max_y_etr_income) 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', etr_params, params, theta, tau_bq) r = utils.convex_combo(new_r, r, nu) w = utils.convex_combo(new_w, w, nu) factor = utils.convex_combo(new_factor, factor, nu) T_H = utils.convex_combo(new_T_H, T_H, nu) if T_H != 0: dist = np.array([utils.perc_dif_func(new_r, r)] + [utils.perc_dif_func(new_w, w)] + [utils.perc_dif_func(new_T_H, T_H)] + [utils.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([utils.perc_dif_func(new_r, r)] + [utils.perc_dif_func(new_w, w)] + [abs(new_T_H - T_H)] + [utils.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): guesses = np.append(bssmat[:, j], nssmat[:, j]) args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n, tau_bq, rho, lambdas, weights, e) [solutions1, infodict, ier, message] = opt.fsolve(Euler_equation_solver, guesses * .9, args=args_, xtol=1e-13, full_output=True) eul_errors[j] = np.array(infodict['fvec']).max() print 'Max Euler errors: ', np.absolute(infodict['fvec']).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