def test_inner_loop(): # Test TPI.inner_loop function. Provide inputs to function and # ensure that output returned matches what it has been before. input_tuple = utils.safe_read_pickle( os.path.join(CUR_PATH, 'test_io_data', 'tpi_inner_loop_inputs.pkl')) guesses, outer_loop_vars, params, j = input_tuple income_tax_params, tpi_params, initial_values, ind = params initial_values = initial_values tpi_params = tpi_params p = Specifications() (p.J, p.S, p.T, p.BW, p.beta, p.sigma, p.alpha, p.gamma, p.epsilon, Z, p.delta, p.ltilde, p.nu, p.g_y, p.g_n, tau_b, delta_tau, tau_payroll, tau_bq, p.rho, p.omega, N_tilde, lambdas, p.imm_rates, p.e, retire, p.mean_income_data, factor, h_wealth, p_wealth, m_wealth, p.b_ellipse, p.upsilon, p.chi_b, p.chi_n, theta, p.baseline) = tpi_params p.eta = p.omega.reshape(p.T + p.S, p.S, 1) * p.lambdas.reshape(1, p.J) p.Z = np.ones(p.T + p.S) * Z p.zeta_D = np.zeros(p.T + p.S) p.initial_foreign_debt_ratio = 0.0 p.initial_debt_ratio = 0.59 p.tau_bq = np.ones(p.T + p.S) * 0.0 p.tau_payroll = np.ones(p.T + p.S) * tau_payroll p.tau_b = np.ones(p.T + p.S) * tau_b p.delta_tau = np.ones(p.T + p.S) * delta_tau p.h_wealth = np.ones(p.T + p.S) * h_wealth p.p_wealth = np.ones(p.T + p.S) * p_wealth p.m_wealth = np.ones(p.T + p.S) * m_wealth p.retire = (np.ones(p.T + p.S) * retire).astype(int) p.tax_func_type = 'DEP' p.analytical_mtrs, etr_params, mtrx_params, mtry_params =\ income_tax_params p.etr_params = np.transpose(etr_params, (1, 0, 2))[:p.T, :, :] p.mtrx_params = np.transpose(mtrx_params, (1, 0, 2))[:p.T, :, :] p.mtry_params = np.transpose(mtry_params, (1, 0, 2))[:p.T, :, :] p.lambdas = lambdas.reshape(p.J, 1) p.num_workers = 1 (K0, b_sinit, b_splus1init, factor, initial_b, initial_n, p.omega_S_preTP, initial_debt, D0) = initial_values initial_values_in = (K0, b_sinit, b_splus1init, factor, initial_b, initial_n, D0) (r, K, BQ, TR) = outer_loop_vars wss = firm.get_w_from_r(r[-1], p, 'SS') w = np.ones(p.T + p.S) * wss w[:p.T] = firm.get_w_from_r(r[:p.T], p, 'TPI') outer_loop_vars_in = (r, w, r, BQ, TR, theta) guesses = (guesses[0], guesses[1]) test_tuple = TPI.inner_loop(guesses, outer_loop_vars_in, initial_values_in, j, ind, p) expected_tuple = utils.safe_read_pickle( os.path.join(CUR_PATH, 'test_io_data', 'tpi_inner_loop_outputs.pkl')) for i, v in enumerate(expected_tuple): assert (np.allclose(test_tuple[i], v))
def test_firstdoughnutring(): # Test TPI.firstdoughnutring function. Provide inputs to function and # ensure that output returned matches what it has been before. input_tuple = utils.safe_read_pickle( os.path.join(CUR_PATH, 'test_io_data', 'firstdoughnutring_inputs.pkl')) guesses, r, w, b, BQ, TR, j, params = input_tuple income_tax_params, tpi_params, initial_b = params tpi_params = tpi_params + [True] p = Specifications() (p.J, p.S, p.T, p.BW, p.beta, p.sigma, p.alpha, p.gamma, p.epsilon, Z, p.delta, p.ltilde, p.nu, p.g_y, p.g_n, tau_b, delta_tau, tau_payroll, tau_bq, p.rho, p.omega, N_tilde, lambdas, p.imm_rates, p.e, retire, p.mean_income_data, factor, h_wealth, p_wealth, m_wealth, p.b_ellipse, p.upsilon, p.chi_b, p.chi_n, theta, p.baseline) = tpi_params p.Z = np.ones(p.T + p.S) * Z p.zeta_D = np.zeros(p.T + p.S) p.initial_foreign_debt_ratio = 0.0 p.initial_debt_ratio = 0.59 p.tau_bq = np.ones(p.T + p.S) * 0.0 p.tau_payroll = np.ones(p.T + p.S) * tau_payroll p.tau_b = np.ones(p.T + p.S) * tau_b p.delta_tau = np.ones(p.T + p.S) * delta_tau p.h_wealth = np.ones(p.T + p.S) * h_wealth p.p_wealth = np.ones(p.T + p.S) * p_wealth p.m_wealth = np.ones(p.T + p.S) * m_wealth p.retire = (np.ones(p.T + p.S) * retire).astype(int) p.tax_func_type = 'DEP' p.analytical_mtrs, etr_params, mtrx_params, mtry_params =\ income_tax_params p.etr_params = np.transpose(etr_params, (1, 0, 2)) p.mtrx_params = np.transpose(mtrx_params, (1, 0, 2)) p.mtry_params = np.transpose(mtry_params, (1, 0, 2)) p.lambdas = lambdas.reshape(p.J, 1) p.num_workers = 1 bq = BQ / p.lambdas[j] tr = TR test_list = TPI.firstdoughnutring(guesses, r, w, bq, tr, theta, factor, j, initial_b, p) expected_list = utils.safe_read_pickle( os.path.join(CUR_PATH, 'test_io_data', 'firstdoughnutring_outputs.pkl')) assert (np.allclose(np.array(test_list), np.array(expected_list)))
def test_constant_demographics_TPI(): ''' This tests solves the model under the assumption of constant demographics, a balanced budget, and tax functions that do not vary over time. In this case, given how initial guesss for the time path are made, the time path should be solved for on the first iteration and the values all along the time path should equal their steady-state values. ''' output_base = "./OUTPUT" baseline_dir = "./OUTPUT" # Create output directory structure ss_dir = os.path.join(output_base, "SS") tpi_dir = os.path.join(output_base, "TPI") dirs = [ss_dir, tpi_dir] for _dir in dirs: try: print("making dir: ", _dir) os.makedirs(_dir) except OSError: pass spec = Specifications(run_micro=False, output_base=output_base, baseline_dir=baseline_dir, test=False, time_path=True, baseline=True, reform={}, guid='') user_params = {'constant_demographics': True, 'budget_balance': True, 'zero_taxes': True, 'maxiter': 2, 'eta': (spec.omega_SS.reshape(spec.S, 1) * spec.lambdas.reshape(1, spec.J))} spec.update_specifications(user_params) spec.get_tax_function_parameters(None, False) # Run SS ss_outputs = SS.run_SS(spec, None) # save SS results utils.mkdirs(os.path.join(baseline_dir, "SS")) ss_dir = os.path.join(baseline_dir, "SS/SS_vars.pkl") pickle.dump(ss_outputs, open(ss_dir, "wb")) # Run TPI tpi_output = TPI.run_TPI(spec, None) assert(np.allclose(tpi_output['bmat_splus1'][:spec.T, :, :], ss_outputs['bssmat_splus1']))
def test_twist_doughnut(): # Test TPI.twist_doughnut function. Provide inputs to function and # ensure that output returned matches what it has been before. input_tuple = utils.safe_read_pickle( os.path.join(CUR_PATH, 'test_io_data', 'twist_doughnut_inputs.pkl')) guesses, r, w, BQ, TR, j, s, t, params = input_tuple income_tax_params, tpi_params, initial_b = params tpi_params = tpi_params + [True] p = Specifications() (p.J, p.S, p.T, p.BW, p.beta, p.sigma, p.alpha, p.gamma, p.epsilon, Z, p.delta, p.ltilde, p.nu, p.g_y, p.g_n, tau_b, delta_tau, tau_payroll, tau_bq, p.rho, p.omega, N_tilde, lambdas, p.imm_rates, p.e, retire, p.mean_income_data, factor, h_wealth, p_wealth, m_wealth, p.b_ellipse, p.upsilon, p.chi_b, p.chi_n, theta, p.baseline) = tpi_params p.Z = np.ones(p.T + p.S) * Z p.tau_bq = np.ones(p.T + p.S) * 0.0 p.tau_c = np.ones((p.T + p.S, p.S, p.J)) * 0.0 p.tau_payroll = np.ones(p.T + p.S) * tau_payroll p.tau_b = np.ones(p.T + p.S) * tau_b p.delta_tau = np.ones(p.T + p.S) * delta_tau p.h_wealth = np.ones(p.T + p.S) * h_wealth p.p_wealth = np.ones(p.T + p.S) * p_wealth p.m_wealth = np.ones(p.T + p.S) * m_wealth p.retire = (np.ones(p.T + p.S) * retire).astype(int) p.tax_func_type = 'DEP' p.analytical_mtrs, etr_params, mtrx_params, mtry_params =\ income_tax_params p.lambdas = lambdas.reshape(p.J, 1) p.num_workers = 1 length = int(len(guesses) / 2) tau_c_to_use = np.diag(p.tau_c[:p.S, :, j], p.S - (s + 2)) bq = BQ[t:t + length] / p.lambdas[j] tr = TR[t:t + length] test_list = TPI.twist_doughnut(guesses, r, w, bq, tr, theta, factor, j, s, t, tau_c_to_use, etr_params, mtrx_params, mtry_params, initial_b, p) expected_list = utils.safe_read_pickle( os.path.join(CUR_PATH, 'test_io_data', 'twist_doughnut_outputs.pkl')) assert (np.allclose(np.array(test_list), np.array(expected_list)))
def test_run_TPI(): # Test TPI.run_TPI function. Provide inputs to function and # ensure that output returned matches what it has been before. input_tuple = utils.safe_read_pickle( os.path.join(CUR_PATH, 'test_io_data', 'run_TPI_inputs.pkl')) (income_tax_params, tpi_params, iterative_params, small_open_params, initial_values, SS_values, fiscal_params, biz_tax_params, output_dir, baseline_spending) = input_tuple tpi_params = tpi_params + [True] initial_values = initial_values + (0.0, ) p = Specifications() (J, S, T, BW, p.beta, p.sigma, p.alpha, p.gamma, p.epsilon, Z, p.delta, p.ltilde, p.nu, p.g_y, p.g_n, tau_b, delta_tau, tau_payroll, tau_bq, p.rho, p.omega, N_tilde, lambdas, p.imm_rates, p.e, retire, p.mean_income_data, factor, h_wealth, p_wealth, m_wealth, p.b_ellipse, p.upsilon, p.chi_b, p.chi_n, theta, p.baseline) = tpi_params new_param_values = { 'J': J, 'S': S, 'T': T, 'eta': (np.ones((S, J)) / (S * J)) } # update parameters instance with new values for test p.update_specifications(new_param_values, raise_errors=False) (J, S, T, BW, p.beta, p.sigma, p.alpha, p.gamma, p.epsilon, Z, p.delta, p.ltilde, p.nu, p.g_y, p.g_n, tau_b, delta_tau, tau_payroll, tau_bq, p.rho, p.omega, N_tilde, lambdas, p.imm_rates, p.e, retire, p.mean_income_data, factor, h_wealth, p_wealth, m_wealth, p.b_ellipse, p.upsilon, p.chi_b, p.chi_n, theta, p.baseline) = tpi_params p.omega_SS = p.omega[-1, :] p.eta = p.omega.reshape(T + S, S, 1) * lambdas.reshape(1, J) p.Z = np.ones(p.T + p.S) * Z p.zeta_D = np.zeros(p.T + p.S) p.initial_foreign_debt_ratio = 0.0 p.initial_debt_ratio = 0.59 p.tau_bq = np.ones(p.T + p.S) * 0.0 p.tau_payroll = np.ones(p.T + p.S) * tau_payroll p.tau_b = np.ones(p.T + p.S) * tau_b p.delta_tau = np.ones(p.T + p.S) * delta_tau p.h_wealth = np.ones(p.T + p.S) * h_wealth p.p_wealth = np.ones(p.T + p.S) * p_wealth p.m_wealth = np.ones(p.T + p.S) * m_wealth p.retire = (np.ones(p.T + p.S) * retire).astype(int) p.small_open, ss_firm_r, ss_hh_r = small_open_params p.ss_firm_r = np.ones(p.T + p.S) * ss_firm_r p.ss_hh_r = np.ones(p.T + p.S) * ss_hh_r p.maxiter, p.mindist_SS, p.mindist_TPI = iterative_params (p.budget_balance, alpha_T, alpha_G, p.tG1, p.tG2, p.rho_G, p.debt_ratio_ss) = fiscal_params p.alpha_T = np.concatenate((alpha_T, np.ones(40) * alpha_T[-1])) p.alpha_G = np.concatenate((alpha_G, np.ones(40) * alpha_G[-1])) (tau_b, delta_tau) = biz_tax_params p.tau_b = np.ones(p.T + p.S) * tau_b p.delta_tau = np.ones(p.T + p.S) * delta_tau p.analytical_mtrs, etr_params, mtrx_params, mtry_params =\ income_tax_params p.etr_params = np.transpose(etr_params, (1, 0, 2))[:p.T, :, :] p.mtrx_params = np.transpose(mtrx_params, (1, 0, 2))[:p.T, :, :] p.mtry_params = np.transpose(mtry_params, (1, 0, 2))[:p.T, :, :] p.lambdas = lambdas.reshape(p.J, 1) p.output = output_dir p.baseline_spending = baseline_spending p.num_workers = 1 (K0, b_sinit, b_splus1init, factor, initial_b, initial_n, p.omega_S_preTP, initial_debt, D0) = initial_values # Need to run SS first to get results ss_outputs = SS.run_SS(p, None) if p.baseline: utils.mkdirs(os.path.join(p.baseline_dir, "SS")) ss_dir = os.path.join(p.baseline_dir, "SS/SS_vars.pkl") pickle.dump(ss_outputs, open(ss_dir, "wb")) else: utils.mkdirs(os.path.join(p.output_base, "SS")) ss_dir = os.path.join(p.output_base, "SS/SS_vars.pkl") pickle.dump(ss_outputs, open(ss_dir, "wb")) test_dict = TPI.run_TPI(p, None) expected_dict = utils.safe_read_pickle( os.path.join(CUR_PATH, 'test_io_data', 'run_TPI_outputs.pkl')) # delete values key-value pairs that are not in both dicts del expected_dict['I_total'] del test_dict['etr_path'], test_dict['mtrx_path'], test_dict['mtry_path'] del test_dict['bmat_s'] test_dict['b_mat'] = test_dict.pop('bmat_splus1') test_dict['REVENUE'] = test_dict.pop('total_revenue') test_dict['T_H'] = test_dict.pop('TR') test_dict['IITpayroll_revenue'] = (test_dict['REVENUE'][:160] - test_dict['business_revenue']) del test_dict['T_P'], test_dict['T_BQ'], test_dict['T_W'] del test_dict['y_before_tax_mat'], test_dict['K_f'], test_dict['K_d'] del test_dict['D_d'], test_dict['D_f'] del test_dict['new_borrowing_f'], test_dict['debt_service_f'] del test_dict['resource_constraint_error'], test_dict['T_C'] del test_dict['r_gov'], test_dict['r_hh'], test_dict['tr_path'] for k, v in expected_dict.items(): try: assert (np.allclose(test_dict[k], v, rtol=1e-04, atol=1e-04)) except ValueError: assert (np.allclose(test_dict[k], v[:p.T, :, :], rtol=1e-04, atol=1e-04))
def runner(output_base, baseline_dir, test=False, time_path=True, baseline=True, reform={}, user_params={}, guid='', run_micro=True, data=None, client=None, num_workers=1): ''' This function runs the OG-India model, solving for the steady-state and (optionally) the time path equilibrium. Args: output_base (str): path to save output to baseline_dir (str): path where baseline model results are saved test (bool): whether to run model in test mode (which has a smaller state space and higher tolerances for solution) time_path (bool): whether to solve for the time path equlibrium baseline (bool): whether the model run is the baseline run reform (dict): Tax-Calculator policy dictionary user_params (dict): dictionary with updates to default parameters in OG-India guid (str): id for OG-India run run_micro (bool): whether to estimate tax functions from micro data or load saved parameters from pickle file data (str or Pandas DataFrame): path to or data to use in Tax-Calculator client (Dask client object): client num_workers (int): number of workers to use for parallelization with Dask Returns: None ''' tick = time.time() # Create output directory structure ss_dir = os.path.join(output_base, "SS") tpi_dir = os.path.join(output_base, "TPI") dirs = [ss_dir, tpi_dir] for _dir in dirs: try: print("making dir: ", _dir) os.makedirs(_dir) except OSError: pass print('In runner, baseline is ', baseline) # Get parameter class # Note - set run_micro false when initially load class # Update later with call to spec.get_tax_function_parameters() spec = Specifications(run_micro=False, output_base=output_base, baseline_dir=baseline_dir, test=test, time_path=time_path, baseline=baseline, reform=reform, guid=guid, data=data, client=client, num_workers=num_workers) spec.update_specifications(user_params) print('path for tax functions: ', spec.output_base) spec.get_tax_function_parameters(client, run_micro) ''' ------------------------------------------------------------------------ Run SS ------------------------------------------------------------------------ ''' ss_outputs = SS.run_SS(spec, client=client) ''' ------------------------------------------------------------------------ Pickle SS results ------------------------------------------------------------------------ ''' if baseline: utils.mkdirs(os.path.join(baseline_dir, "SS")) ss_dir = os.path.join(baseline_dir, "SS/SS_vars.pkl") pickle.dump(ss_outputs, open(ss_dir, "wb")) # Save pickle with parameter values for the run param_dir = os.path.join(baseline_dir, "model_params.pkl") pickle.dump(spec, open(param_dir, "wb")) else: utils.mkdirs(os.path.join(output_base, "SS")) ss_dir = os.path.join(output_base, "SS/SS_vars.pkl") pickle.dump(ss_outputs, open(ss_dir, "wb")) # Save pickle with parameter values for the run param_dir = os.path.join(output_base, "model_params.pkl") pickle.dump(spec, open(param_dir, "wb")) if time_path: ''' ------------------------------------------------------------------------ Run the TPI simulation ------------------------------------------------------------------------ ''' tpi_output = TPI.run_TPI(spec, client=client) ''' ------------------------------------------------------------------------ Pickle TPI results ------------------------------------------------------------------------ ''' tpi_dir = os.path.join(output_base, "TPI") utils.mkdirs(tpi_dir) tpi_vars = os.path.join(tpi_dir, "TPI_vars.pkl") pickle.dump(tpi_output, open(tpi_vars, "wb")) print("Time path iteration complete.") print("It took {0} seconds to get that part done.".format(time.time() - tick))