def test_D_G_path(baseline_spending, Y, TR, Revenue, Gbaseline, budget_balance, expected_tuple): p = Specifications() new_param_values = { 'T': 320, 'S': 80, 'debt_ratio_ss': 1.2, 'tG1': 20, 'tG2': 256, 'alpha_T': [0.09], 'alpha_G': [0.05], 'rho_G': 0.1, 'g_y_annual': 0.03, 'baseline_spending': baseline_spending, 'budget_balance': budget_balance } p.update_specifications(new_param_values, raise_errors=False) r_gov = np.ones(p.T + p.S) * 0.03 p.g_n = np.ones(p.T + p.S) * 0.02 D0_baseline = 0.59 Gbaseline[0] = 0.05 dg_fixed_values = (Y, Revenue, TR, Gbaseline, D0_baseline) test_tuple = fiscal.D_G_path(r_gov, dg_fixed_values, p) for i, v in enumerate(test_tuple): assert np.allclose(v[:p.T], expected_tuple[i][:p.T])
def test_D_G_path(baseline_spending, Y, T_H, REVENUE, Gbaseline, D_expected, G_expected): p = Specifications() new_param_values = { 'T': 320, 'S': 80, 'debt_ratio_ss': 1.2, 'tG1': 20, 'tG2': 256, 'alpha_T': [0.09], 'alpha_G': [0.05], 'rho_G': 0.1, 'g_y_annual': 0.03, 'budget_balance': False, 'baseline_spending': baseline_spending } p.update_specifications(new_param_values, raise_errors=False) r_gov = np.ones(p.T + p.S) * 0.03 p.g_n = np.ones(p.T + p.S) * 0.02 D0 = 0.59 G0 = 0.05 dg_fixed_values = (Y, REVENUE, T_H, D0, G0) test_D, test_G = fiscal.D_G_path(r_gov, dg_fixed_values, Gbaseline, p) assert np.allclose(test_D, D_expected) assert np.allclose(test_G, G_expected)
def run_TPI(p, client=None): ''' Solve for transition path equilibrium of OG-USA. Args: p (OG-USA Specifications object): model parameters client (Dask client object): client Returns: output (dictionary): dictionary with transition path solution results ''' # unpack tuples of parameters initial_values, ss_vars, theta, baseline_values = get_initial_SS_values(p) (B0, b_sinit, b_splus1init, factor, initial_b, initial_n) =\ initial_values (TRbaseline, Gbaseline, D0_baseline) = baseline_values print('Government spending breakpoints are tG1: ', p.tG1, '; and tG2:', p.tG2) # Initialize guesses at time paths # Make array of initial guesses for labor supply and savings guesses_b = utils.get_initial_path(initial_b, ss_vars['bssmat_splus1'], p, 'ratio') guesses_n = utils.get_initial_path(initial_n, ss_vars['nssmat'], p, 'ratio') b_mat = guesses_b n_mat = guesses_n ind = np.arange(p.S) # Get path for aggregate savings and labor supply` L_init = np.ones((p.T + p.S, )) * ss_vars['Lss'] B_init = np.ones((p.T + p.S, )) * ss_vars['Bss'] L_init[:p.T] = aggr.get_L(n_mat[:p.T], p, 'TPI') B_init[1:p.T] = aggr.get_B(b_mat[:p.T], p, 'TPI', False)[:p.T - 1] B_init[0] = B0 K_init = B_init * ss_vars['Kss'] / ss_vars['Bss'] K = K_init K_d = K_init * ss_vars['K_d_ss'] / ss_vars['Kss'] K_f = K_init * ss_vars['K_f_ss'] / ss_vars['Kss'] L = L_init B = B_init Y = np.zeros_like(K) Y[:p.T] = firm.get_Y(K[:p.T], L[:p.T], p, 'TPI') Y[p.T:] = ss_vars['Yss'] r = np.zeros_like(Y) r[:p.T] = firm.get_r(Y[:p.T], K[:p.T], p, 'TPI') r[p.T:] = ss_vars['rss'] # For case where economy is small open econ r[p.zeta_K == 1] = p.world_int_rate[p.zeta_K == 1] # Compute other interest rates r_gov = fiscal.get_r_gov(r, p) r_hh = aggr.get_r_hh(r, r_gov, K, ss_vars['Dss']) # compute w w = np.zeros_like(r) w[:p.T] = firm.get_w_from_r(r[:p.T], p, 'TPI') w[p.T:] = ss_vars['wss'] # initial guesses at fiscal vars if p.budget_balance: if np.abs(ss_vars['TR_ss']) < 1e-13: TR_ss2 = 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 pct changes below else: TR_ss2 = ss_vars['TR_ss'] TR = np.ones(p.T + p.S) * TR_ss2 total_tax_revenue = TR - ss_vars['agg_pension_outlays'] G = np.zeros(p.T + p.S) D = np.zeros(p.T + p.S) D_d = np.zeros(p.T + p.S) D_f = np.zeros(p.T + p.S) else: if p.baseline_spending: TR = TRbaseline G = Gbaseline G[p.T:] = ss_vars['Gss'] else: TR = p.alpha_T * Y G = np.ones(p.T + p.S) * ss_vars['Gss'] D = np.ones(p.T + p.S) * ss_vars['Dss'] D_d = D * ss_vars['D_d_ss'] / ss_vars['Dss'] D_f = D * ss_vars['D_f_ss'] / ss_vars['Dss'] total_tax_revenue = np.ones(p.T + p.S) * ss_vars['total_tax_revenue'] # Initialize bequests BQ0 = aggr.get_BQ(r_hh[0], initial_b, None, p, 'SS', True) if not p.use_zeta: BQ = np.zeros((p.T + p.S, p.J)) for j in range(p.J): BQ[:, j] = (list(np.linspace(BQ0[j], ss_vars['BQss'][j], p.T)) + [ss_vars['BQss'][j]] * p.S) BQ = np.array(BQ) else: BQ = (list(np.linspace(BQ0, ss_vars['BQss'], p.T)) + [ss_vars['BQss']] * p.S) BQ = np.array(BQ) TPIiter = 0 TPIdist = 10 euler_errors = np.zeros((p.T, 2 * p.S, p.J)) TPIdist_vec = np.zeros(p.maxiter) # TPI loop while (TPIiter < p.maxiter) and (TPIdist >= p.mindist_TPI): r_gov[:p.T] = fiscal.get_r_gov(r[:p.T], p) if not p.budget_balance: K[:p.T] = firm.get_K_from_Y(Y[:p.T], r[:p.T], p, 'TPI') r_hh[:p.T] = aggr.get_r_hh(r[:p.T], r_gov[:p.T], K[:p.T], D[:p.T]) outer_loop_vars = (r, w, r_hh, BQ, TR, theta) euler_errors = np.zeros((p.T, 2 * p.S, p.J)) lazy_values = [] for j in range(p.J): guesses = (guesses_b[:, :, j], guesses_n[:, :, j]) lazy_values.append( delayed(inner_loop)(guesses, outer_loop_vars, initial_values, j, ind, p)) if client: futures = client.compute(lazy_values, num_workers=p.num_workers) results = client.gather(futures) else: results = results = compute(*lazy_values, scheduler=dask.multiprocessing.get, num_workers=p.num_workers) for j, result in enumerate(results): euler_errors[:, :, j], b_mat[:, :, j], n_mat[:, :, j] = result bmat_s = np.zeros((p.T, p.S, p.J)) bmat_s[0, 1:, :] = initial_b[:-1, :] bmat_s[1:, 1:, :] = b_mat[:p.T - 1, :-1, :] bmat_splus1 = np.zeros((p.T, p.S, p.J)) bmat_splus1[:, :, :] = b_mat[:p.T, :, :] etr_params_4D = np.tile( p.etr_params.reshape(p.T, p.S, 1, p.etr_params.shape[2]), (1, 1, p.J, 1)) bqmat = household.get_bq(BQ, None, p, 'TPI') trmat = household.get_tr(TR, None, p, 'TPI') tax_mat = tax.net_taxes(r_hh[:p.T], w[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat[:p.T, :, :], factor, trmat[:p.T, :, :], theta, 0, None, False, 'TPI', p.e, etr_params_4D, p) r_hh_path = utils.to_timepath_shape(r_hh) wpath = utils.to_timepath_shape(w) c_mat = household.get_cons(r_hh_path[:p.T, :, :], wpath[:p.T, :, :], bmat_s, bmat_splus1, n_mat[:p.T, :, :], bqmat[:p.T, :, :], tax_mat, p.e, p.tau_c[:p.T, :, :], p) y_before_tax_mat = household.get_y(r_hh_path[:p.T, :, :], wpath[:p.T, :, :], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], p) (total_tax_rev, iit_payroll_tax_revenue, agg_pension_outlays, bequest_tax_revenue, wealth_tax_revenue, cons_tax_revenue, business_tax_revenue, payroll_tax_revenue, iit_revenue) = aggr.revenue(r_hh[:p.T], w[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat[:p.T, :, :], c_mat[:p.T, :, :], Y[:p.T], L[:p.T], K[:p.T], factor, theta, etr_params_4D, p, 'TPI') total_tax_revenue[:p.T] = total_tax_rev dg_fixed_values = (Y, total_tax_revenue, agg_pension_outlays, TR, Gbaseline, D0_baseline) (Dnew, G[:p.T], D_d[:p.T], D_f[:p.T], new_borrowing, debt_service, new_borrowing_f) =\ fiscal.D_G_path(r_gov, dg_fixed_values, p) L[:p.T] = aggr.get_L(n_mat[:p.T], p, 'TPI') B[1:p.T] = aggr.get_B(bmat_splus1[:p.T], p, 'TPI', False)[:p.T - 1] K_demand_open = firm.get_K(L[:p.T], p.world_int_rate[:p.T], p, 'TPI') K[:p.T], K_d[:p.T], K_f[:p.T] = aggr.get_K_splits( B[:p.T], K_demand_open, D_d[:p.T], p.zeta_K[:p.T]) Ynew = firm.get_Y(K[:p.T], L[:p.T], p, 'TPI') rnew = r.copy() rnew[:p.T] = firm.get_r(Ynew[:p.T], K[:p.T], p, 'TPI') # For case where economy is small open econ r[p.zeta_K == 1] = p.world_int_rate[p.zeta_K == 1] r_gov_new = fiscal.get_r_gov(rnew, p) r_hh_new = aggr.get_r_hh(rnew[:p.T], r_gov_new[:p.T], K[:p.T], Dnew[:p.T]) # compute w wnew = firm.get_w_from_r(rnew[:p.T], p, 'TPI') b_mat_shift = np.append(np.reshape(initial_b, (1, p.S, p.J)), b_mat[:p.T - 1, :, :], axis=0) BQnew = aggr.get_BQ(r_hh_new[:p.T], b_mat_shift, None, p, 'TPI', False) bqmat_new = household.get_bq(BQnew, None, p, 'TPI') (total_tax_rev, iit_payroll_tax_revenue, agg_pension_outlays, bequest_tax_revenue, wealth_tax_revenue, cons_tax_revenue, business_tax_revenue, payroll_tax_revenue, iit_revenue) = aggr.revenue(r_hh_new[:p.T], wnew[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat_new[:p.T, :, :], c_mat[:p.T, :, :], Ynew[:p.T], L[:p.T], K[:p.T], factor, theta, etr_params_4D, p, 'TPI') total_tax_revenue[:p.T] = total_tax_rev TR_new = fiscal.get_TR(Ynew[:p.T], TR[:p.T], G[:p.T], total_tax_revenue[:p.T], agg_pension_outlays[:p.T], p, 'TPI') # update vars for next iteration w[:p.T] = wnew[:p.T] r[:p.T] = utils.convex_combo(rnew[:p.T], r[:p.T], p.nu) BQ[:p.T] = utils.convex_combo(BQnew[:p.T], BQ[:p.T], p.nu) D[:p.T] = Dnew[:p.T] Y[:p.T] = utils.convex_combo(Ynew[:p.T], Y[:p.T], p.nu) if not p.baseline_spending: TR[:p.T] = utils.convex_combo(TR_new[:p.T], TR[:p.T], p.nu) guesses_b = utils.convex_combo(b_mat, guesses_b, p.nu) guesses_n = utils.convex_combo(n_mat, guesses_n, p.nu) print('r diff: ', (rnew[:p.T] - r[:p.T]).max(), (rnew[:p.T] - r[:p.T]).min()) print('BQ diff: ', (BQnew[:p.T] - BQ[:p.T]).max(), (BQnew[:p.T] - BQ[:p.T]).min()) print('TR diff: ', (TR_new[:p.T] - TR[:p.T]).max(), (TR_new[:p.T] - TR[:p.T]).min()) print('Y diff: ', (Ynew[:p.T] - Y[:p.T]).max(), (Ynew[:p.T] - Y[:p.T]).min()) if not p.baseline_spending: if TR.all() != 0: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list( utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(TR_new[:p.T], TR[:p.T]))).max() else: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list( utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(np.abs(TR[:p.T]))).max() else: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list(utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(Ynew[:p.T], Y[:p.T]))).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('Iteration:', TPIiter) print('\tDistance:', TPIdist) # Compute effective and marginal tax rates for all agents mtrx_params_4D = np.tile( p.mtrx_params.reshape(p.T, p.S, 1, p.mtrx_params.shape[2]), (1, 1, p.J, 1)) mtry_params_4D = np.tile( p.mtry_params.reshape(p.T, p.S, 1, p.mtry_params.shape[2]), (1, 1, p.J, 1)) e_3D = np.tile(p.e.reshape(1, p.S, p.J), (p.T, 1, 1)) mtry_path = tax.MTR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, True, e_3D, etr_params_4D, mtry_params_4D, p) mtrx_path = tax.MTR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, False, e_3D, etr_params_4D, mtrx_params_4D, p) etr_path = tax.ETR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, e_3D, etr_params_4D, p) C = aggr.get_C(c_mat, p, 'TPI') # Note that implicity in this computation is that immigrants' # wealth is all in the form of private capital I_d = aggr.get_I(bmat_splus1[:p.T], K_d[1:p.T + 1], K_d[:p.T], p, 'TPI') I = aggr.get_I(bmat_splus1[:p.T], K[1:p.T + 1], K[:p.T], p, 'TPI') # solve resource constraint # foreign debt service costs debt_service_f = fiscal.get_debt_service_f(r_hh, D_f) RC_error = aggr.resource_constraint(Y[:p.T - 1], C[:p.T - 1], G[:p.T - 1], I_d[:p.T - 1], K_f[:p.T - 1], new_borrowing_f[:p.T - 1], debt_service_f[:p.T - 1], r_hh[:p.T - 1], p) # Compute total investment (not just domestic) I_total = aggr.get_I(None, K[1:p.T + 1], K[:p.T], p, 'total_tpi') # Compute resource constraint error rce_max = np.amax(np.abs(RC_error)) print('Max absolute value resource constraint error:', rce_max) print('Checking time path for violations of constraints.') for t in range(p.T): household.constraint_checker_TPI(b_mat[t], n_mat[t], c_mat[t], t, p.ltilde) eul_savings = euler_errors[:, :p.S, :].max(1).max(1) eul_laborleisure = euler_errors[:, p.S:, :].max(1).max(1) print('Max Euler error, savings: ', eul_savings) print('Max Euler error labor supply: ', eul_laborleisure) ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = { 'Y': Y[:p.T], 'B': B, 'K': K, 'K_f': K_f, 'K_d': K_d, 'L': L, 'C': C, 'I': I, 'I_total': I_total, 'I_d': I_d, 'BQ': BQ, 'total_tax_revenue': total_tax_revenue, 'business_tax_revenue': business_tax_revenue, 'iit_payroll_tax_revenue': iit_payroll_tax_revenue, 'iit_revenue': iit_revenue, 'payroll_tax_revenue': payroll_tax_revenue, 'TR': TR, 'agg_pension_outlays': agg_pension_outlays, 'bequest_tax_revenue': bequest_tax_revenue, 'wealth_tax_revenue': wealth_tax_revenue, 'cons_tax_revenue': cons_tax_revenue, 'G': G, 'D': D, 'D_f': D_f, 'D_d': D_d, 'r': r, 'r_gov': r_gov, 'r_hh': r_hh, 'w': w, 'bmat_splus1': bmat_splus1, 'bmat_s': bmat_s[:p.T, :, :], 'n_mat': n_mat[:p.T, :, :], 'c_path': c_mat, 'bq_path': bqmat, 'tr_path': trmat, 'y_before_tax_mat': y_before_tax_mat, 'tax_path': tax_mat, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure, 'resource_constraint_error': RC_error, 'new_borrowing_f': new_borrowing_f, 'debt_service_f': debt_service_f, 'etr_path': etr_path, 'mtrx_path': mtrx_path, 'mtry_path': mtry_path } tpi_dir = os.path.join(p.output_base, "TPI") utils.mkdirs(tpi_dir) tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl") with open(tpi_vars, "wb") as f: pickle.dump(output, f) if np.any(G) < 0: print('Government spending is negative along transition path' + ' to satisfy budget') if (((TPIiter >= p.maxiter) or (np.absolute(TPIdist) > p.mindist_TPI)) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found' + ' (TPIdist)') if ((np.any(np.absolute(RC_error) >= p.mindist_TPI * 10)) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found ' + '(RC_error)') if ((np.any(np.absolute(eul_savings) >= p.mindist_TPI) or (np.any(np.absolute(eul_laborleisure) > p.mindist_TPI))) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found ' + '(eulers)') return output
def run_TPI(p, client=None): # unpack tuples of parameters initial_values, SS_values, baseline_values = get_initial_SS_values(p) (B0, b_sinit, b_splus1init, factor, initial_b, initial_n, D0) = initial_values (Kss, Bss, Lss, rss, wss, BQss, T_Hss, total_revenue_ss, bssmat_splus1, nssmat, Yss, Gss, theta) = SS_values (T_Hbaseline, Gbaseline) = baseline_values print('Government spending breakpoints are tG1: ', p.tG1, '; and tG2:', p.tG2) # Initialize guesses at time paths # Make array of initial guesses for labor supply and savings domain = np.linspace(0, p.T, p.T) domain2 = np.tile(domain.reshape(p.T, 1, 1), (1, p.S, p.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, p.S, p.J), (p.S, 1, 1)) guesses_b = np.append(guesses_b, ending_b_tail, axis=0) domain3 = np.tile(np.linspace(0, 1, p.T).reshape(p.T, 1, 1), (1, p.S, p.J)) guesses_n = domain3 * (nssmat - initial_n) + initial_n ending_n_tail = np.tile(nssmat.reshape(1, p.S, p.J), (p.S, 1, 1)) guesses_n = np.append(guesses_n, ending_n_tail, axis=0) b_mat = guesses_b # np.zeros((p.T + p.S, p.S, p.J)) n_mat = guesses_n # np.zeros((p.T + p.S, p.S, p.J)) ind = np.arange(p.S) L_init = np.ones((p.T + p.S, )) * Lss B_init = np.ones((p.T + p.S, )) * Bss L_init[:p.T] = aggr.get_L(n_mat[:p.T], p, 'TPI') B_init[1:p.T] = aggr.get_K(b_mat[:p.T], p, 'TPI', False)[:p.T - 1] B_init[0] = B0 if not p.small_open: if p.budget_balance: K_init = B_init else: K_init = B_init * Kss / Bss else: K_init = firm.get_K(L_init, p.firm_r, p, 'TPI') K = K_init L = L_init B = B_init Y = np.zeros_like(K) Y[:p.T] = firm.get_Y(K[:p.T], L[:p.T], p, 'TPI') Y[p.T:] = Yss r = np.zeros_like(Y) if not p.small_open: r[:p.T] = firm.get_r(Y[:p.T], K[:p.T], p, 'TPI') r[p.T:] = rss else: r = p.firm_r # compute w w = np.zeros_like(r) w[:p.T] = firm.get_w_from_r(r[:p.T], p, 'TPI') w[p.T:] = wss r_gov = fiscal.get_r_gov(r, p) if p.budget_balance: r_hh = r else: r_hh = aggr.get_r_hh(r, r_gov, K, p.debt_ratio_ss * Y) if p.small_open: r_hh = p.hh_r BQ0 = aggr.get_BQ(r[0], initial_b, None, p, 'SS', True) if not p.use_zeta: BQ = np.zeros((p.T + p.S, p.J)) for j in range(p.J): BQ[:, j] = (list(np.linspace(BQ0[j], BQss[j], p.T)) + [BQss[j]] * p.S) BQ = np.array(BQ) else: BQ = (list(np.linspace(BQ0, BQss, p.T)) + [BQss] * p.S) BQ = np.array(BQ) if p.budget_balance: if np.abs(T_Hss) < 1e-13: 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 = np.ones(p.T + p.S) * T_Hss2 total_revenue = T_H G = np.zeros(p.T + p.S) elif not p.baseline_spending: T_H = p.alpha_T * Y elif p.baseline_spending: T_H = T_Hbaseline T_H_new = p.T_H # Need to set T_H_new for later reference G = Gbaseline G_0 = Gbaseline[0] # Initialize some starting value if p.budget_balance: D = 0.0 * Y else: D = p.debt_ratio_ss * Y TPIiter = 0 TPIdist = 10 euler_errors = np.zeros((p.T, 2 * p.S, p.J)) TPIdist_vec = np.zeros(p.maxiter) print('analytical mtrs in tpi = ', p.analytical_mtrs) print('tax function type in tpi = ', p.tax_func_type) # TPI loop while (TPIiter < p.maxiter) and (TPIdist >= p.mindist_TPI): r_gov[:p.T] = fiscal.get_r_gov(r[:p.T], p) if p.budget_balance: r_hh[:p.T] = r[:p.T] else: K[:p.T] = firm.get_K_from_Y(Y[:p.T], r[:p.T], p, 'TPI') r_hh[:p.T] = aggr.get_r_hh(r[:p.T], r_gov[:p.T], K[:p.T], D[:p.T]) if p.small_open: r_hh[:p.T] = p.hh_r[:p.T] outer_loop_vars = (r, w, r_hh, BQ, T_H, theta) euler_errors = np.zeros((p.T, 2 * p.S, p.J)) lazy_values = [] for j in range(p.J): guesses = (guesses_b[:, :, j], guesses_n[:, :, j]) lazy_values.append( delayed(inner_loop)(guesses, outer_loop_vars, initial_values, j, ind, p)) results = compute(*lazy_values, scheduler=dask.multiprocessing.get, num_workers=p.num_workers) for j, result in enumerate(results): euler_errors[:, :, j], b_mat[:, :, j], n_mat[:, :, j] = result bmat_s = np.zeros((p.T, p.S, p.J)) bmat_s[0, 1:, :] = initial_b[:-1, :] bmat_s[1:, 1:, :] = b_mat[:p.T - 1, :-1, :] bmat_splus1 = np.zeros((p.T, p.S, p.J)) bmat_splus1[:, :, :] = b_mat[:p.T, :, :] L[:p.T] = aggr.get_L(n_mat[:p.T], p, 'TPI') B[1:p.T] = aggr.get_K(bmat_splus1[:p.T], p, 'TPI', False)[:p.T - 1] if np.any(B) < 0: print('B has negative elements. B[0:9]:', B[0:9]) print('B[T-2:T]:', B[p.T - 2, p.T]) etr_params_4D = np.tile( p.etr_params.reshape(p.T, p.S, 1, p.etr_params.shape[2]), (1, 1, p.J, 1)) bqmat = household.get_bq(BQ, None, p, 'TPI') tax_mat = tax.total_taxes(r_hh[:p.T], w[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat[:p.T, :, :], factor, T_H[:p.T], theta, 0, None, False, 'TPI', p.e, etr_params_4D, p) r_hh_path = utils.to_timepath_shape(r_hh, p) wpath = utils.to_timepath_shape(w, p) c_mat = household.get_cons(r_hh_path[:p.T, :, :], wpath[:p.T, :, :], bmat_s, bmat_splus1, n_mat[:p.T, :, :], bqmat[:p.T, :, :], tax_mat, p.e, p.tau_c[:p.T, :, :], p) if not p.small_open: if p.budget_balance: K[:p.T] = B[:p.T] else: if not p.baseline_spending: Y = T_H / p.alpha_T # maybe unecessary (total_rev, T_Ipath, T_Ppath, T_BQpath, T_Wpath, T_Cpath, business_revenue) = aggr.revenue( r_hh[:p.T], w[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat[:p.T, :, :], c_mat[:p.T, :, :], Y[:p.T], L[:p.T], K[:p.T], factor, theta, etr_params_4D, p, 'TPI') total_revenue = np.array( list(total_rev) + [total_revenue_ss] * p.S) # set intial debt value if p.baseline: D_0 = p.initial_debt_ratio * Y[0] else: D_0 = D0 if not p.baseline_spending: G_0 = p.alpha_G[0] * Y[0] dg_fixed_values = (Y, total_revenue, T_H, D_0, G_0) Dnew, G = fiscal.D_G_path(r_gov, dg_fixed_values, Gbaseline, p) K[:p.T] = B[:p.T] - Dnew[:p.T] if np.any(K < 0): print('K has negative elements. Setting them ' + 'positive to prevent NAN.') K[:p.T] = np.fmax(K[:p.T], 0.05 * B[:p.T]) else: K[:p.T] = firm.get_K(L[:p.T], p.firm_r[:p.T], p, 'TPI') Ynew = firm.get_Y(K[:p.T], L[:p.T], p, 'TPI') if not p.small_open: rnew = firm.get_r(Ynew[:p.T], K[:p.T], p, 'TPI') else: rnew = r.copy() r_gov_new = fiscal.get_r_gov(rnew, p) if p.budget_balance: r_hh_new = rnew[:p.T] else: r_hh_new = aggr.get_r_hh(rnew, r_gov_new, K[:p.T], Dnew[:p.T]) if p.small_open: r_hh_new = p.hh_r[:p.T] # compute w wnew = firm.get_w_from_r(rnew[:p.T], p, 'TPI') b_mat_shift = np.append(np.reshape(initial_b, (1, p.S, p.J)), b_mat[:p.T - 1, :, :], axis=0) BQnew = aggr.get_BQ(r_hh_new[:p.T], b_mat_shift, None, p, 'TPI', False) bqmat_new = household.get_bq(BQnew, None, p, 'TPI') (total_rev, T_Ipath, T_Ppath, T_BQpath, T_Wpath, T_Cpath, business_revenue) = aggr.revenue( r_hh_new[:p.T], wnew[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat_new[:p.T, :, :], c_mat[:p.T, :, :], Ynew[:p.T], L[:p.T], K[:p.T], factor, theta, etr_params_4D, p, 'TPI') total_revenue = np.array(list(total_rev) + [total_revenue_ss] * p.S) if p.budget_balance: T_H_new = total_revenue elif not p.baseline_spending: T_H_new = p.alpha_T[:p.T] * Ynew[:p.T] # If baseline_spending==True, no need to update T_H, it's fixed if p.small_open and not p.budget_balance: # Loop through years to calculate debt and gov't spending. # This is done earlier when small_open=False. if p.baseline: D_0 = p.initial_debt_ratio * Y[0] else: D_0 = D0 if not p.baseline_spending: G_0 = p.alpha_G[0] * Ynew[0] dg_fixed_values = (Ynew, total_revenue, T_H, D_0, G_0) Dnew, G = fiscal.D_G_path(r_gov_new, dg_fixed_values, Gbaseline, p) if p.budget_balance: Dnew = D w[:p.T] = wnew[:p.T] r[:p.T] = utils.convex_combo(rnew[:p.T], r[:p.T], p.nu) BQ[:p.T] = utils.convex_combo(BQnew[:p.T], BQ[:p.T], p.nu) D = Dnew Y[:p.T] = utils.convex_combo(Ynew[:p.T], Y[:p.T], p.nu) if not p.baseline_spending: T_H[:p.T] = utils.convex_combo(T_H_new[:p.T], T_H[:p.T], p.nu) guesses_b = utils.convex_combo(b_mat, guesses_b, p.nu) guesses_n = utils.convex_combo(n_mat, guesses_n, p.nu) print('r diff: ', (rnew[:p.T] - r[:p.T]).max(), (rnew[:p.T] - r[:p.T]).min()) print('BQ diff: ', (BQnew[:p.T] - BQ[:p.T]).max(), (BQnew[:p.T] - BQ[:p.T]).min()) print('T_H diff: ', (T_H_new[:p.T] - T_H[:p.T]).max(), (T_H_new[:p.T] - T_H[:p.T]).min()) print('Y diff: ', (Ynew[:p.T] - Y[:p.T]).max(), (Ynew[:p.T] - Y[:p.T]).min()) if not p.baseline_spending: if T_H.all() != 0: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list( utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(wnew[:p.T], w[:p.T])) + list(utils.pct_diff_func(T_H_new[:p.T], T_H[:p.T]))).max() else: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list( utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(wnew[:p.T], w[:p.T])) + list(np.abs(T_H[:p.T]))).max() else: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list(utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(wnew[:p.T], w[:p.T])) + list(utils.pct_diff_func(Ynew[:p.T], Y[:p.T]))).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('Iteration:', TPIiter) print('\tDistance:', TPIdist) # Compute effective and marginal tax rates for all agents mtrx_params_4D = np.tile( p.mtrx_params.reshape(p.T, p.S, 1, p.mtrx_params.shape[2]), (1, 1, p.J, 1)) mtry_params_4D = np.tile( p.mtry_params.reshape(p.T, p.S, 1, p.mtry_params.shape[2]), (1, 1, p.J, 1)) e_3D = np.tile(p.e.reshape(1, p.S, p.J), (p.T, 1, 1)) mtry_path = tax.MTR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, True, e_3D, etr_params_4D, mtry_params_4D, p) mtrx_path = tax.MTR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, False, e_3D, etr_params_4D, mtrx_params_4D, p) etr_path = tax.ETR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, e_3D, etr_params_4D, p) C = aggr.get_C(c_mat, p, 'TPI') if not p.small_open: I = aggr.get_I(bmat_splus1[:p.T], K[1:p.T + 1], K[:p.T], p, 'TPI') rc_error = Y[:p.T] - C[:p.T] - I[:p.T] - G[:p.T] else: I = ((1 + np.squeeze(np.hstack( (p.g_n[1:p.T], p.g_n_ss)))) * np.exp(p.g_y) * K[1:p.T + 1] - (1.0 - p.delta) * K[:p.T]) BI = aggr.get_I(bmat_splus1[:p.T], B[1:p.T + 1], B[:p.T], p, 'TPI') new_borrowing = (D[1:p.T] * (1 + p.g_n[1:p.T]) * np.exp(p.g_y) - D[:p.T - 1]) rc_error = (Y[:p.T - 1] + new_borrowing - (C[:p.T - 1] + BI[:p.T - 1] + G[:p.T - 1]) + (p.hh_r[:p.T - 1] * B[:p.T - 1] - (p.delta + p.firm_r[:p.T - 1]) * K[:p.T - 1] - p.hh_r[:p.T - 1] * D[:p.T - 1])) # Compute total investment (not just domestic) I_total = ((1 + p.g_n[:p.T]) * np.exp(p.g_y) * K[1:p.T + 1] - (1.0 - p.delta) * K[:p.T]) rce_max = np.amax(np.abs(rc_error)) print('Max absolute value resource constraint error:', rce_max) print('Checking time path for violations of constraints.') for t in range(p.T): household.constraint_checker_TPI(b_mat[t], n_mat[t], c_mat[t], t, p.ltilde) eul_savings = euler_errors[:, :p.S, :].max(1).max(1) eul_laborleisure = euler_errors[:, p.S:, :].max(1).max(1) print('Max Euler error, savings: ', eul_savings) print('Max Euler error labor supply: ', eul_laborleisure) ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = { 'Y': Y[:p.T], 'B': B, 'K': K, 'L': L, 'C': C, 'I': I, 'I_total': I_total, 'BQ': BQ, 'total_revenue': total_revenue, 'business_revenue': business_revenue, 'IITpayroll_revenue': T_Ipath, 'T_H': T_H, 'T_P': T_Ppath, 'T_BQ': T_BQpath, 'T_W': T_Wpath, 'T_C': T_Cpath, 'G': G, 'D': D, 'r': r, 'r_gov': r_gov, 'r_hh': r_hh, 'w': w, 'bmat_splus1': bmat_splus1, 'bmat_s': bmat_s[:p.T, :, :], 'n_mat': n_mat[:p.T, :, :], 'c_path': c_mat, 'bq_path': bqmat, 'tax_path': tax_mat, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure, 'resource_constraint_error': rc_error, 'etr_path': etr_path, 'mtrx_path': mtrx_path, 'mtry_path': mtry_path } tpi_dir = os.path.join(p.output_base, "TPI") utils.mkdirs(tpi_dir) tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl") pickle.dump(output, open(tpi_vars, "wb")) if np.any(G) < 0: print('Government spending is negative along transition path' + ' to satisfy budget') if (((TPIiter >= p.maxiter) or (np.absolute(TPIdist) > p.mindist_TPI)) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found' + ' (TPIdist)') if ((np.any(np.absolute(rc_error) >= p.mindist_TPI * 10)) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found ' + '(rc_error)') if ((np.any(np.absolute(eul_savings) >= p.mindist_TPI) or (np.any(np.absolute(eul_laborleisure) > p.mindist_TPI))) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found ' + '(eulers)') return output
def run_TPI(p, client=None): # unpack tuples of parameters initial_values, ss_vars, theta, baseline_values = get_initial_SS_values(p) (B0, b_sinit, b_splus1init, factor, initial_b, initial_n, D0) = initial_values (T_Hbaseline, Gbaseline) = baseline_values print('Government spending breakpoints are tG1: ', p.tG1, '; and tG2:', p.tG2) # Initialize guesses at time paths # Make array of initial guesses for labor supply and savings domain = np.linspace(0, p.T, p.T) domain2 = np.tile(domain.reshape(p.T, 1, 1), (1, p.S, p.J)) ending_b = ss_vars['bssmat_splus1'] guesses_b = (-1 / (domain2 + 1)) * (ending_b - initial_b) + ending_b ending_b_tail = np.tile(ending_b.reshape(1, p.S, p.J), (p.S, 1, 1)) guesses_b = np.append(guesses_b, ending_b_tail, axis=0) domain3 = np.tile(np.linspace(0, 1, p.T).reshape(p.T, 1, 1), (1, p.S, p.J)) guesses_n = domain3 * (ss_vars['nssmat'] - initial_n) + initial_n ending_n_tail = np.tile(ss_vars['nssmat'].reshape(1, p.S, p.J), (p.S, 1, 1)) guesses_n = np.append(guesses_n, ending_n_tail, axis=0) b_mat = guesses_b n_mat = guesses_n ind = np.arange(p.S) L_init = np.ones((p.T + p.S, )) * ss_vars['Lss'] B_init = np.ones((p.T + p.S, )) * ss_vars['Bss'] L_init[:p.T] = aggr.get_L(n_mat[:p.T], p, 'TPI') B_init[1:p.T] = aggr.get_K(b_mat[:p.T], p, 'TPI', False)[:p.T - 1] B_init[0] = B0 if not p.small_open: if p.budget_balance: K_init = B_init else: K_init = B_init * ss_vars['Kss'] / ss_vars['Bss'] else: K_init = firm.get_K(L_init, p.firm_r, p, 'TPI') K = K_init K_d = K_init * ss_vars['K_d_ss'] / ss_vars['Kss'] K_f = K_init * ss_vars['K_f_ss'] / ss_vars['Kss'] L = L_init B = B_init Y = np.zeros_like(K) Y[:p.T] = firm.get_Y(K[:p.T], L[:p.T], p, 'TPI') Y[p.T:] = ss_vars['Yss'] r = np.zeros_like(Y) if not p.small_open: r[:p.T] = firm.get_r(Y[:p.T], K[:p.T], p, 'TPI') r[p.T:] = ss_vars['rss'] else: r = p.firm_r # compute w w = np.zeros_like(r) w[:p.T] = firm.get_w_from_r(r[:p.T], p, 'TPI') w[p.T:] = ss_vars['wss'] r_gov = fiscal.get_r_gov(r, p) if p.budget_balance: r_hh = r else: r_hh = aggr.get_r_hh(r, r_gov, K, ss_vars['Dss']) if p.small_open: r_hh = p.hh_r BQ0 = aggr.get_BQ(r[0], initial_b, None, p, 'SS', True) if not p.use_zeta: BQ = np.zeros((p.T + p.S, p.J)) for j in range(p.J): BQ[:, j] = (list(np.linspace(BQ0[j], ss_vars['BQss'][j], p.T)) + [ss_vars['BQss'][j]] * p.S) BQ = np.array(BQ) else: BQ = (list(np.linspace(BQ0, ss_vars['BQss'], p.T)) + [ss_vars['BQss']] * p.S) BQ = np.array(BQ) if p.budget_balance: if np.abs(ss_vars['T_Hss']) < 1e-13: 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 = ss_vars['T_Hss'] T_H = np.ones(p.T + p.S) * T_Hss2 total_revenue = T_H G = np.zeros(p.T + p.S) elif not p.baseline_spending: T_H = p.alpha_T * Y G = np.ones(p.T + p.S) * ss_vars['Gss'] elif p.baseline_spending: T_H = T_Hbaseline T_H_new = p.T_H # Need to set T_H_new for later reference G = Gbaseline G_0 = Gbaseline[0] # Initialize some starting values if p.budget_balance: D = np.zeros(p.T + p.S) else: D = np.ones(p.T + p.S) * ss_vars['Dss'] if ss_vars['Dss'] == 0: D_d = np.zeros(p.T + p.S) D_f = np.zeros(p.T + p.S) else: D_d = D * ss_vars['D_d_ss'] / ss_vars['Dss'] D_f = D * ss_vars['D_f_ss'] / ss_vars['Dss'] total_revenue = np.ones(p.T + p.S) * ss_vars['total_revenue_ss'] TPIiter = 0 TPIdist = 10 euler_errors = np.zeros((p.T, 2 * p.S, p.J)) TPIdist_vec = np.zeros(p.maxiter) # TPI loop while (TPIiter < p.maxiter) and (TPIdist >= p.mindist_TPI): r_gov[:p.T] = fiscal.get_r_gov(r[:p.T], p) if p.budget_balance: r_hh[:p.T] = r[:p.T] else: K[:p.T] = firm.get_K_from_Y(Y[:p.T], r[:p.T], p, 'TPI') r_hh[:p.T] = aggr.get_r_hh(r[:p.T], r_gov[:p.T], K[:p.T], D[:p.T]) if p.small_open: r_hh[:p.T] = p.hh_r[:p.T] outer_loop_vars = (r, w, r_hh, BQ, T_H, theta) euler_errors = np.zeros((p.T, 2 * p.S, p.J)) lazy_values = [] for j in range(p.J): guesses = (guesses_b[:, :, j], guesses_n[:, :, j]) lazy_values.append( delayed(inner_loop)(guesses, outer_loop_vars, initial_values, j, ind, p)) results = compute(*lazy_values, scheduler=dask.multiprocessing.get, num_workers=p.num_workers) for j, result in enumerate(results): euler_errors[:, :, j], b_mat[:, :, j], n_mat[:, :, j] = result bmat_s = np.zeros((p.T, p.S, p.J)) bmat_s[0, 1:, :] = initial_b[:-1, :] bmat_s[1:, 1:, :] = b_mat[:p.T - 1, :-1, :] bmat_splus1 = np.zeros((p.T, p.S, p.J)) bmat_splus1[:, :, :] = b_mat[:p.T, :, :] etr_params_4D = np.tile( p.etr_params.reshape(p.T, p.S, 1, p.etr_params.shape[2]), (1, 1, p.J, 1)) bqmat = household.get_bq(BQ, None, p, 'TPI') tax_mat = tax.total_taxes(r_hh[:p.T], w[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat[:p.T, :, :], factor, T_H[:p.T], theta, 0, None, False, 'TPI', p.e, etr_params_4D, p) r_hh_path = utils.to_timepath_shape(r_hh, p) wpath = utils.to_timepath_shape(w, p) c_mat = household.get_cons(r_hh_path[:p.T, :, :], wpath[:p.T, :, :], bmat_s, bmat_splus1, n_mat[:p.T, :, :], bqmat[:p.T, :, :], tax_mat, p.e, p.tau_c[:p.T, :, :], p) y_before_tax_mat = (r_hh_path[:p.T, :, :] * bmat_s[:p.T, :, :] + wpath[:p.T, :, :] * p.e * n_mat[:p.T, :, :]) if not p.baseline_spending and not p.budget_balance: Y[:p.T] = T_H[:p.T] / p.alpha_T[:p.T] # maybe unecessary (total_rev, T_Ipath, T_Ppath, T_BQpath, T_Wpath, T_Cpath, business_revenue) = aggr.revenue( r_hh[:p.T], w[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat[:p.T, :, :], c_mat[:p.T, :, :], Y[:p.T], L[:p.T], K[:p.T], factor, theta, etr_params_4D, p, 'TPI') total_revenue[:p.T] = total_rev # set intial debt value if p.baseline: D0 = p.initial_debt_ratio * Y[0] if not p.baseline_spending: G_0 = p.alpha_G[0] * Y[0] dg_fixed_values = (Y, total_revenue, T_H, D0, G_0) Dnew, G[:p.T] = fiscal.D_G_path(r_gov, dg_fixed_values, Gbaseline, p) # Fix initial amount of foreign debt holding D_f[0] = p.initial_foreign_debt_ratio * Dnew[0] for t in range(1, p.T): D_f[t + 1] = (D_f[t] / (np.exp(p.g_y) * (1 + p.g_n[t + 1])) + p.zeta_D[t] * (Dnew[t + 1] - (Dnew[t] / (np.exp(p.g_y) * (1 + p.g_n[t + 1]))))) D_d[:p.T] = Dnew[:p.T] - D_f[:p.T] else: # if budget balance Dnew = np.zeros(p.T + 1) G[:p.T] = np.zeros(p.T) D_f[:p.T] = np.zeros(p.T) D_d[:p.T] = np.zeros(p.T) L[:p.T] = aggr.get_L(n_mat[:p.T], p, 'TPI') B[1:p.T] = aggr.get_K(bmat_splus1[:p.T], p, 'TPI', False)[:p.T - 1] K_demand_open = firm.get_K(L[:p.T], p.firm_r[:p.T], p, 'TPI') K_d[:p.T] = B[:p.T] - D_d[:p.T] if np.any(K_d < 0): print('K_d has negative elements. Setting them ' + 'positive to prevent NAN.') K_d[:p.T] = np.fmax(K_d[:p.T], 0.05 * B[:p.T]) K_f[:p.T] = p.zeta_K[:p.T] * (K_demand_open - B[:p.T] + D_d[:p.T]) K = K_f + K_d if np.any(B) < 0: print('B has negative elements. B[0:9]:', B[0:9]) print('B[T-2:T]:', B[p.T - 2, p.T]) if p.small_open: K[:p.T] = K_demand_open Ynew = firm.get_Y(K[:p.T], L[:p.T], p, 'TPI') rnew = r.copy() if not p.small_open: rnew[:p.T] = firm.get_r(Ynew[:p.T], K[:p.T], p, 'TPI') else: rnew[:p.T] = r[:p.T].copy() r_gov_new = fiscal.get_r_gov(rnew, p) if p.budget_balance: r_hh_new = rnew[:p.T] else: r_hh_new = aggr.get_r_hh(rnew[:p.T], r_gov_new[:p.T], K[:p.T], Dnew[:p.T]) if p.small_open: r_hh_new = p.hh_r[:p.T] # compute w wnew = firm.get_w_from_r(rnew[:p.T], p, 'TPI') b_mat_shift = np.append(np.reshape(initial_b, (1, p.S, p.J)), b_mat[:p.T - 1, :, :], axis=0) BQnew = aggr.get_BQ(r_hh_new[:p.T], b_mat_shift, None, p, 'TPI', False) bqmat_new = household.get_bq(BQnew, None, p, 'TPI') (total_rev, T_Ipath, T_Ppath, T_BQpath, T_Wpath, T_Cpath, business_revenue) = aggr.revenue( r_hh_new[:p.T], wnew[:p.T], bmat_s, n_mat[:p.T, :, :], bqmat_new[:p.T, :, :], c_mat[:p.T, :, :], Ynew[:p.T], L[:p.T], K[:p.T], factor, theta, etr_params_4D, p, 'TPI') total_revenue[:p.T] = total_rev if p.budget_balance: T_H_new = total_revenue elif not p.baseline_spending: T_H_new = p.alpha_T[:p.T] * Ynew[:p.T] # If baseline_spending==True, no need to update T_H, it's fixed # update vars for next iteration w[:p.T] = wnew[:p.T] r[:p.T] = utils.convex_combo(rnew[:p.T], r[:p.T], p.nu) BQ[:p.T] = utils.convex_combo(BQnew[:p.T], BQ[:p.T], p.nu) D[:p.T] = Dnew[:p.T] Y[:p.T] = utils.convex_combo(Ynew[:p.T], Y[:p.T], p.nu) if not p.baseline_spending: T_H[:p.T] = utils.convex_combo(T_H_new[:p.T], T_H[:p.T], p.nu) guesses_b = utils.convex_combo(b_mat, guesses_b, p.nu) guesses_n = utils.convex_combo(n_mat, guesses_n, p.nu) print('r diff: ', (rnew[:p.T] - r[:p.T]).max(), (rnew[:p.T] - r[:p.T]).min()) print('BQ diff: ', (BQnew[:p.T] - BQ[:p.T]).max(), (BQnew[:p.T] - BQ[:p.T]).min()) print('T_H diff: ', (T_H_new[:p.T] - T_H[:p.T]).max(), (T_H_new[:p.T] - T_H[:p.T]).min()) print('Y diff: ', (Ynew[:p.T] - Y[:p.T]).max(), (Ynew[:p.T] - Y[:p.T]).min()) if not p.baseline_spending: if T_H.all() != 0: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list( utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(T_H_new[:p.T], T_H[:p.T]))).max() else: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list( utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(np.abs(T_H[:p.T]))).max() else: TPIdist = np.array( list(utils.pct_diff_func(rnew[:p.T], r[:p.T])) + list(utils.pct_diff_func(BQnew[:p.T], BQ[:p.T]).flatten()) + list(utils.pct_diff_func(Ynew[:p.T], Y[:p.T]))).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('Iteration:', TPIiter) print('\tDistance:', TPIdist) # Compute effective and marginal tax rates for all agents mtrx_params_4D = np.tile( p.mtrx_params.reshape(p.T, p.S, 1, p.mtrx_params.shape[2]), (1, 1, p.J, 1)) mtry_params_4D = np.tile( p.mtry_params.reshape(p.T, p.S, 1, p.mtry_params.shape[2]), (1, 1, p.J, 1)) e_3D = np.tile(p.e.reshape(1, p.S, p.J), (p.T, 1, 1)) mtry_path = tax.MTR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, True, e_3D, etr_params_4D, mtry_params_4D, p) mtrx_path = tax.MTR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, False, e_3D, etr_params_4D, mtrx_params_4D, p) etr_path = tax.ETR_income(r_hh_path[:p.T], wpath[:p.T], bmat_s[:p.T, :, :], n_mat[:p.T, :, :], factor, e_3D, etr_params_4D, p) C = aggr.get_C(c_mat, p, 'TPI') # Note that implicity in this computation is that immigrants' # wealth is all in the form of private capital I_d = aggr.get_I(bmat_splus1[:p.T], K_d[1:p.T + 1], K_d[:p.T], p, 'TPI') I = aggr.get_I(bmat_splus1[:p.T], K[1:p.T + 1], K[:p.T], p, 'TPI') # solve resource constraint # net foreign borrowing new_borrowing_f = (D_f[1:p.T + 1] * np.exp(p.g_y) * (1 + p.g_n[1:p.T + 1]) - D_f[:p.T]) debt_service_f = D_f * r_hh RC_error = aggr.resource_constraint(Y[:p.T - 1], C[:p.T - 1], G[:p.T - 1], I_d[:p.T - 1], K_f[:p.T - 1], new_borrowing_f[:p.T - 1], debt_service_f[:p.T - 1], r_hh[:p.T - 1], p) # Compute total investment (not just domestic) I_total = ((1 + p.g_n[:p.T]) * np.exp(p.g_y) * K[1:p.T + 1] - (1.0 - p.delta) * K[:p.T]) rce_max = np.amax(np.abs(RC_error)) print('Max absolute value resource constraint error:', rce_max) print('Checking time path for violations of constraints.') for t in range(p.T): household.constraint_checker_TPI(b_mat[t], n_mat[t], c_mat[t], t, p.ltilde) eul_savings = euler_errors[:, :p.S, :].max(1).max(1) eul_laborleisure = euler_errors[:, p.S:, :].max(1).max(1) print('Max Euler error, savings: ', eul_savings) print('Max Euler error labor supply: ', eul_laborleisure) ''' ------------------------------------------------------------------------ Save variables/values so they can be used in other modules ------------------------------------------------------------------------ ''' output = { 'Y': Y[:p.T], 'B': B, 'K': K, 'K_f': K_f, 'K_d': K_d, 'L': L, 'C': C, 'I': I, 'I_total': I_total, 'I_d': I_d, 'BQ': BQ, 'total_revenue': total_revenue, 'business_revenue': business_revenue, 'IITpayroll_revenue': T_Ipath, 'T_H': T_H, 'T_P': T_Ppath, 'T_BQ': T_BQpath, 'T_W': T_Wpath, 'T_C': T_Cpath, 'G': G, 'D': D, 'D_f': D_f, 'D_d': D_d, 'r': r, 'r_gov': r_gov, 'r_hh': r_hh, 'w': w, 'bmat_splus1': bmat_splus1, 'bmat_s': bmat_s[:p.T, :, :], 'n_mat': n_mat[:p.T, :, :], 'c_path': c_mat, 'bq_path': bqmat, 'y_before_tax_mat': y_before_tax_mat, 'tax_path': tax_mat, 'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure, 'resource_constraint_error': RC_error, 'new_borrowing_f': new_borrowing_f, 'debt_service_f': debt_service_f, 'etr_path': etr_path, 'mtrx_path': mtrx_path, 'mtry_path': mtry_path } tpi_dir = os.path.join(p.output_base, "TPI") utils.mkdirs(tpi_dir) tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl") pickle.dump(output, open(tpi_vars, "wb")) if np.any(G) < 0: print('Government spending is negative along transition path' + ' to satisfy budget') if (((TPIiter >= p.maxiter) or (np.absolute(TPIdist) > p.mindist_TPI)) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found' + ' (TPIdist)') if ((np.any(np.absolute(RC_error) >= p.mindist_TPI * 10)) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found ' + '(RC_error)') if ((np.any(np.absolute(eul_savings) >= p.mindist_TPI) or (np.any(np.absolute(eul_laborleisure) > p.mindist_TPI))) and ENFORCE_SOLUTION_CHECKS): raise RuntimeError('Transition path equlibrium not found ' + '(eulers)') return output