Example #1
0
def create_tpi_params(a_tax_income,
                      b_tax_income,
                      c_tax_income,
                      d_tax_income,
                      b_ellipse,
                      upsilon,
                      J,
                      S,
                      T,
                      beta,
                      sigma,
                      alpha,
                      Z,
                      delta,
                      ltilde,
                      nu,
                      g_y,
                      tau_payroll,
                      retire,
                      mean_income_data,
                      get_baseline=True,
                      input_dir="./OUTPUT",
                      **kwargs):

    if get_baseline:
        ss_init = os.path.join(input_dir, "SSinit/ss_init_vars.pkl")
        variables = pickle.load(open(ss_init, "rb"))
        for key in variables:
            globals()[key] = variables[key]
    else:
        params_path = os.path.join(input_dir,
                                   "Saved_moments/params_changed.pkl")
        variables = pickle.load(open(params_path, "rb"))
        for key in variables:
            globals()[key] = variables[key]
        var_path = os.path.join(input_dir, "SS/ss_vars.pkl")
        variables = pickle.load(open(var_path, "rb"))
        for key in variables:
            globals()[key] = variables[key]
        init_tpi_vars = os.path.join(input_dir, "SSinit/ss_init_tpi_vars.pkl")
        variables = pickle.load(open(init_tpi_vars, "rb"))
        for key in variables:
            globals()[key] = variables[key]
    '''
    ------------------------------------------------------------------------
    Set other parameters and initial values
    ------------------------------------------------------------------------
    '''

    # Make a vector of all one dimensional parameters, to be used in the
    # following functions
    income_tax_params = [
        a_tax_income, b_tax_income, c_tax_income, d_tax_income
    ]
    wealth_tax_params = [h_wealth, p_wealth, m_wealth]
    ellipse_params = [b_ellipse, upsilon]
    parameters = [
        J, S, T, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss,
        tau_payroll, retire, mean_income_data
    ] + income_tax_params + wealth_tax_params + ellipse_params

    N_tilde = omega.sum(1)
    omega_stationary = omega / N_tilde.reshape(T + S, 1)

    if get_baseline:
        initial_b = bssmat_splus1
        initial_n = nssmat
    else:
        initial_b = bssmat_init
        initial_n = nssmat_init
    # Get an initial distribution of capital with the initial population
    # distribution
    K0 = household.get_K(initial_b, omega_stationary[0].reshape(S, 1), lambdas,
                         g_n_vector[0], 'SS')
    b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1]))
    b_splus1init = initial_b
    L0 = firm.get_L(e, initial_n, omega_stationary[0].reshape(S, 1), lambdas,
                    'SS')
    Y0 = firm.get_Y(K0, L0, parameters)
    w0 = firm.get_w(Y0, L0, parameters)
    r0 = firm.get_r(Y0, K0, parameters)
    BQ0 = household.get_BQ(r0, initial_b, omega_stationary[0].reshape(S, 1),
                           lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS')
    T_H_0 = tax.get_lump_sum(r0, b_sinit, w0, e, initial_n, BQ0, lambdas,
                             factor_ss, omega_stationary[0].reshape(S, 1),
                             'SS', parameters, theta, tau_bq)
    tax0 = tax.total_taxes(r0, b_sinit, w0, e, initial_n, BQ0, lambdas,
                           factor_ss, T_H_0, None, 'SS', False, parameters,
                           theta, tau_bq)
    c0 = household.get_cons(r0, b_sinit, w0, e, initial_n, BQ0.reshape(1, J),
                            lambdas.reshape(1, J), b_splus1init, parameters,
                            tax0)

    return (income_tax_params, wealth_tax_params, ellipse_params, parameters,
            N_tilde, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0, w0,
            r0, BQ0, T_H_0, tax0, c0, initial_b, initial_n)
Example #2
0
def create_tpi_params(**sim_params):
    '''
    ------------------------------------------------------------------------
    Set factor and initial capital stock to SS from baseline
    ------------------------------------------------------------------------
    '''
    baseline_ss = os.path.join(sim_params['baseline_dir'], "SS/SS_vars.pkl")
    ss_baseline_vars = pickle.load(open(baseline_ss, "rb"))
    factor = ss_baseline_vars['factor_ss']
    #initial_b = ss_baseline_vars['bssmat_s'] + ss_baseline_vars['BQss']/lambdas
    initial_b = ss_baseline_vars['bssmat_splus1']
    initial_n = ss_baseline_vars['nssmat']

    SS_values = (ss_baseline_vars['Kss'], ss_baseline_vars['Lss'],
                 ss_baseline_vars['rss'], ss_baseline_vars['wss'],
                 ss_baseline_vars['BQss'], ss_baseline_vars['T_Hss'],
                 ss_baseline_vars['bssmat_splus1'], ss_baseline_vars['nssmat'])

    # Make a vector of all one dimensional parameters, to be used in the
    # following functions
    wealth_tax_params = [
        sim_params['h_wealth'], sim_params['p_wealth'], sim_params['m_wealth']
    ]
    ellipse_params = [sim_params['b_ellipse'], sim_params['upsilon']]
    chi_params = [sim_params['chi_b_guess'], sim_params['chi_n_guess']]

    N_tilde = sim_params['omega'].sum(
        1
    )  #this should just be one in each year given how we've constructed omega
    sim_params['omega'] = sim_params['omega'] / N_tilde.reshape(
        sim_params['T'] + sim_params['S'], 1)

    tpi_params = [sim_params['J'], sim_params['S'], sim_params['T'], sim_params['BW'],
                  sim_params['beta'], sim_params['sigma'], sim_params['alpha'],
                  sim_params['Z'], sim_params['delta'], sim_params['ltilde'],
                  sim_params['nu'], sim_params['g_y'], sim_params['g_n_vector'],
                  sim_params['tau_payroll'], sim_params['tau_bq'], sim_params['rho'], sim_params['omega'], N_tilde,
                  sim_params['lambdas'], sim_params['e'], sim_params['retire'], sim_params['mean_income_data'], factor] + \
                  wealth_tax_params + ellipse_params + chi_params
    iterative_params = [
        sim_params['maxiter'], sim_params['mindist_SS'],
        sim_params['mindist_TPI']
    ]


    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, e, retire, mean_income_data,\
                  factor, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n = tpi_params

    ## Assumption for tax functions is that policy in last year of BW is
    # extended permanently
    etr_params_TP = np.zeros((S, T + S, sim_params['etr_params'].shape[2]))
    etr_params_TP[:, :BW, :] = sim_params['etr_params']
    etr_params_TP[:, BW:, :] = np.reshape(
        sim_params['etr_params'][:, BW - 1, :],
        (S, 1, sim_params['etr_params'].shape[2]))

    mtrx_params_TP = np.zeros((S, T + S, sim_params['mtrx_params'].shape[2]))
    mtrx_params_TP[:, :BW, :] = sim_params['mtrx_params']
    mtrx_params_TP[:, BW:, :] = np.reshape(
        sim_params['mtrx_params'][:, BW - 1, :],
        (S, 1, sim_params['mtrx_params'].shape[2]))

    mtry_params_TP = np.zeros((S, T + S, sim_params['mtry_params'].shape[2]))
    mtry_params_TP[:, :BW, :] = sim_params['mtry_params']
    mtry_params_TP[:, BW:, :] = np.reshape(
        sim_params['mtry_params'][:, BW - 1, :],
        (S, 1, sim_params['mtry_params'].shape[2]))

    income_tax_params = (sim_params['analytical_mtrs'], etr_params_TP,
                         mtrx_params_TP, mtry_params_TP)
    '''
    ------------------------------------------------------------------------
    Set other parameters and initial values
    ------------------------------------------------------------------------
    '''
    # Get an initial distribution of capital with the initial population
    # distribution
    K0_params = (omega[0].reshape(S, 1), lambdas, g_n_vector[0], 'SS')
    K0 = household.get_K(initial_b, K0_params)

    b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1]))
    b_splus1init = initial_b
    L0_params = (e, omega[0].reshape(S, 1), lambdas, 'SS')
    L0 = firm.get_L(initial_n, L0_params)
    Y0_params = (alpha, Z)
    Y0 = firm.get_Y(K0, L0, Y0_params)
    w0 = firm.get_w(Y0, L0, alpha)
    r0_params = (alpha, delta)
    r0 = firm.get_r(Y0, K0, r0_params)

    BQ0_params = (omega[0].reshape(S, 1), lambdas, rho.reshape(S, 1),
                  g_n_vector[0], 'SS')
    BQ0 = household.get_BQ(r0, initial_b, BQ0_params)

    theta_params = (e, J, omega[0].reshape(S, 1), lambdas)
    theta = tax.replacement_rate_vals(initial_n, w0, factor, theta_params)

    T_H_params = (e, lambdas, omega[0].reshape(S, 1), 'SS',
                  etr_params_TP[:, 0, :], theta, tau_bq, tau_payroll, h_wealth,
                  p_wealth, m_wealth, retire, T, S, J)
    T_H_0 = tax.get_lump_sum(r0, w0, b_sinit, initial_n, BQ0, factor,
                             T_H_params)

    etr_params_3D = np.tile(
        np.reshape(etr_params_TP[:, 0, :], (S, 1, etr_params_TP.shape[2])),
        (1, J, 1))
    tax0_params = (e, lambdas, 'SS', retire, etr_params_3D, h_wealth, p_wealth,
                   m_wealth, tau_payroll, theta, tau_bq, J, S)
    tax0 = tax.total_taxes(r0, w0, b_sinit, initial_n, BQ0, factor, T_H_0,
                           None, False, tax0_params)

    c0_params = (e, lambdas.reshape(1, J), g_y)
    c0 = household.get_cons(r0, w0, b_sinit, b_splus1init, initial_n,
                            BQ0.reshape(1, J), tax0, c0_params)

    initial_values = (K0, b_sinit, b_splus1init, L0, Y0, w0, r0, BQ0, T_H_0,
                      factor, tax0, c0, initial_b, initial_n)

    return (income_tax_params, tpi_params, iterative_params, initial_values,
            SS_values)
Example #3
0
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"))
Example #4
0
def create_tpi_params(a_tax_income, b_tax_income, c_tax_income,
                      d_tax_income,
                      b_ellipse, upsilon, J, S, T, beta, sigma, alpha, Z,
                      delta, ltilde, nu, g_y, tau_payroll, retire,
                      mean_income_data, get_baseline=True, input_dir="./OUTPUT", **kwargs):

    if get_baseline:
        ss_init = os.path.join(input_dir, "SSinit/ss_init_vars.pkl")
        variables = pickle.load(open(ss_init, "rb"))
        for key in variables:
            globals()[key] = variables[key]
    else:
        params_path = os.path.join(
            input_dir, "Saved_moments/params_changed.pkl")
        variables = pickle.load(open(params_path, "rb"))
        for key in variables:
            globals()[key] = variables[key]
        var_path = os.path.join(input_dir, "SS/ss_vars.pkl")
        variables = pickle.load(open(var_path, "rb"))
        for key in variables:
            globals()[key] = variables[key]
        init_tpi_vars = os.path.join(input_dir, "SSinit/ss_init_tpi_vars.pkl")
        variables = pickle.load(open(init_tpi_vars, "rb"))
        for key in variables:
            globals()[key] = variables[key]

    '''
    ------------------------------------------------------------------------
    Set other parameters and initial values
    ------------------------------------------------------------------------
    '''

    # Make a vector of all one dimensional parameters, to be used in the
    # following functions
    income_tax_params = [a_tax_income,
                         b_tax_income, c_tax_income, d_tax_income]
    wealth_tax_params = [h_wealth, p_wealth, m_wealth]
    ellipse_params = [b_ellipse, upsilon]
    parameters = [J, S, T, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire,
                  mean_income_data] + income_tax_params + wealth_tax_params + ellipse_params

    N_tilde = omega.sum(1)
    omega_stationary = omega / N_tilde.reshape(T + S, 1)

    if get_baseline:
        initial_b = bssmat_splus1
        initial_n = nssmat
    else:
        initial_b = bssmat_init
        initial_n = nssmat_init
    # Get an initial distribution of capital with the initial population
    # distribution
    K0 = household.get_K(initial_b, omega_stationary[
                         0].reshape(S, 1), lambdas, g_n_vector[0], 'SS')
    b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1]))
    b_splus1init = initial_b
    L0 = firm.get_L(e, initial_n, omega_stationary[
                    0].reshape(S, 1), lambdas, 'SS')
    Y0 = firm.get_Y(K0, L0, parameters)
    w0 = firm.get_w(Y0, L0, parameters)
    r0 = firm.get_r(Y0, K0, parameters)
    BQ0 = household.get_BQ(r0, initial_b, omega_stationary[0].reshape(
        S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS')
    T_H_0 = tax.get_lump_sum(r0, b_sinit, w0, e, initial_n, BQ0, lambdas, factor_ss, omega_stationary[
                             0].reshape(S, 1), 'SS', parameters, theta, tau_bq)
    tax0 = tax.total_taxes(r0, b_sinit, w0, e, initial_n, BQ0, lambdas,
                           factor_ss, T_H_0, None, 'SS', False, parameters, theta, tau_bq)
    c0 = household.get_cons(r0, b_sinit, w0, e, initial_n, BQ0.reshape(
        1, J), lambdas.reshape(1, J), b_splus1init, parameters, tax0)

    return (income_tax_params, wealth_tax_params, ellipse_params, parameters,
            N_tilde, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0,
            w0, r0, BQ0, T_H_0, tax0, c0, initial_b, initial_n)
Example #5
0
def run_TPI(income_tax_params,
            tpi_params,
            iterative_params,
            initial_values,
            SS_values,
            output_dir="./OUTPUT"):

    # unpack tuples of parameters
    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    maxiter, mindist_SS, mindist_TPI = iterative_params
    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, e, retire, mean_income_data,\
                  factor, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n = tpi_params
    K0, b_sinit, b_splus1init, L0, Y0,\
            w0, r0, BQ0, T_H_0, factor, tax0, c0, initial_b, initial_n = initial_values
    Kss, Lss, rss, wss, BQss, T_Hss, bssmat_splus1, nssmat = SS_values

    TPI_FIG_DIR = output_dir
    # Initialize guesses at time paths
    domain = np.linspace(0, T, T)
    K_init = (-1 / (domain + 1)) * (Kss - K0) + Kss
    K_init[-1] = Kss
    K_init = np.array(list(K_init) + list(np.ones(S) * Kss))
    L_init = np.ones(T + S) * Lss

    K = K_init
    L = L_init
    Y_params = (alpha, Z)
    Y = firm.get_Y(K, L, Y_params)
    w = firm.get_w(Y, L, alpha)
    r_params = (alpha, delta)
    r = firm.get_r(Y, K, r_params)
    BQ = np.zeros((T + S, J))
    for j in xrange(J):
        BQ[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S
    BQ = np.array(BQ)
    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 = np.ones(T + S) * T_Hss2

    # Make array of initial guesses for labor supply and savings
    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
    PLOT_TPI = False

    euler_errors = np.zeros((T, 2 * S, J))
    TPIdist_vec = np.zeros(maxiter)

    while (TPIiter < maxiter) and (TPIdist >= mindist_TPI):
        # Plot TPI for K for each iteration, so we can see if there is a
        # problem
        if PLOT_TPI is True:
            K_plot = list(K) + list(np.ones(10) * Kss)
            L_plot = list(L) + list(np.ones(10) * Lss)
            plt.figure()
            plt.axhline(y=Kss,
                        color='black',
                        linewidth=2,
                        label=r"Steady State $\hat{K}$",
                        ls='--')
            plt.plot(np.arange(T + 10),
                     Kpath_plot[: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.

        # theta_params = (e[-1, j], 1, omega[0].reshape(S, 1), lambdas[j])
        # theta = tax.replacement_rate_vals(n, w, factor, theta_params)
        theta = np.zeros((J, ))

        guesses = (guesses_b, guesses_n)
        outer_loop_vars = (r, w, K, BQ, T_H)
        inner_loop_params = (income_tax_params, tpi_params, initial_values,
                             theta, ind)

        # Solve HH problem in inner loop
        euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars,
                                                inner_loop_params)

        # 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
        K_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J),
                    g_n_vector[:T], 'TPI')
        K[:T] = household.get_K(b_mat[:T], K_params)
        L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1),
                    lambdas.reshape(1, 1, J), 'TPI')
        L[:T] = firm.get_L(n_mat[:T], L_params)

        Y_params = (alpha, Z)
        Ynew = firm.get_Y(K[:T], L[:T], Y_params)
        wnew = firm.get_w(Ynew[:T], L[:T], alpha)
        r_params = (alpha, delta)
        rnew = firm.get_r(Ynew[:T], K[:T], r_params)

        BQ_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J),
                     rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI')
        BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat[:T, :, :],
                                 BQ_params)
        bmat_s = np.zeros((T, S, J))
        bmat_s[:, 1:, :] = b_mat[:T, :-1, :]
        bmat_splus1 = np.zeros((T, S, J))
        bmat_splus1[:, :, :] = b_mat[1:T + 1, :, :]

        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_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)),
                      lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1),
                      'TPI', TH_tax_params, theta, tau_bq, tau_payroll,
                      h_wealth, p_wealth, m_wealth, retire, T, S, J)
        T_H_new = np.array(
            list(
                tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1), (
                    1, S, J)), np.tile(wnew[:T].reshape(T, 1, 1), (
                        1, S, J)), bmat_s, n_mat[:T, :, :], BQnew[:T].reshape(
                            T, 1, J), factor, T_H_params)) + [T_Hss] * S)

        w[:T] = utils.convex_combo(wnew[:T], w[:T], nu)
        r[:T] = utils.convex_combo(rnew[:T], r[:T], nu)
        BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu)
        T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[: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.all() != 0:
            TPIdist = np.array(
                list(utils.pct_diff_func(rnew[:T], r[:T])) +
                list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) +
                list(utils.pct_diff_func(wnew[:T], w[:T])) +
                list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max()
        else:
            TPIdist = np.array(
                list(utils.pct_diff_func(rnew[:T], r[:T])) +
                list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) +
                list(utils.pct_diff_func(wnew[:T], w[:T])) +
                list(np.abs(T_H_new[:T], T_H[: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 '\tIteration:', TPIiter
        print '\t\tDistance:', TPIdist

    if ((TPIiter >= maxiter) or
        (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS:
        raise RuntimeError("Transition path equlibrium not found")

    Y[:T] = Ynew

    # Solve HH problem in inner loop
    guesses = (guesses_b, guesses_n)
    outer_loop_vars = (r, w, K, BQ, T_H)
    inner_loop_params = (income_tax_params, tpi_params, initial_values, theta,
                         ind)
    euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars,
                                            inner_loop_params)
    b_mat[0, :, :] = initial_b

    K_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J),
                g_n_vector[:T], 'TPI')
    K[:T] = household.get_K(
        b_mat[:T],
        K_params)  # this is what old code does, but it's strange - why use
    # b_mat -- what is going on with initial period, etc.

    etr_params_path = np.zeros((T, S, J, etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        etr_params_path[:, :, :, i] = np.tile(
            np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)),
            (1, 1, J))
    tax_path_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), lambdas, 'TPI',
                       retire, etr_params_path, h_wealth, p_wealth, m_wealth,
                       tau_payroll, theta, tau_bq, J, S)
    tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1), (1, S, J)),
                               np.tile(w[:T].reshape(T, 1, 1),
                                       (1, S, J)), bmat_s, n_mat[:T, :, :],
                               BQ[:T, :].reshape(T, 1, J), factor,
                               T_H[:T].reshape(T, 1, 1), None, False,
                               tax_path_params)

    cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y)
    c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1),
                                bmat_s, bmat_splus1, n_mat[:T, :, :],
                                BQ[:T].reshape(T, 1, J), tax_path, cons_params)
    C_params = (omega[:T].reshape(T, S, 1), lambdas, 'TPI')
    C = household.get_C(c_path, C_params)
    I_params = (delta, g_y, g_n_vector[:T])
    I = firm.get_I(K[1:T + 1], K[:T], I_params)
    print 'Resource Constraint Difference:', Y[:T] - C[:T] - I[:T]

    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,
                                         ltilde)

    eul_savings = euler_errors[:, :S, :].max(1).max(1)
    eul_laborleisure = euler_errors[:, S:, :].max(1).max(1)

    print 'Max Euler error, savings: ', eul_savings
    print 'Max Euler error labor supply: ', eul_laborleisure

    if ((np.any(np.absolute(eul_savings) >= mindist_TPI) or
         (np.any(np.absolute(eul_laborleisure) > mindist_TPI)))
            and ENFORCE_SOLUTION_CHECKS):
        raise RuntimeError("Transition path equlibrium not found")
    '''
    ------------------------------------------------------------------------
    Save variables/values so they can be used in other modules
    ------------------------------------------------------------------------
    '''

    output = {
        'Y': Y,
        'K': K,
        'L': L,
        'C': C,
        'I': I,
        'BQ': BQ,
        'T_H': T_H,
        'r': r,
        'w': w,
        'b_mat': b_mat,
        'n_mat': n_mat,
        'c_path': c_path,
        'tax_path': tax_path,
        'eul_savings': eul_savings,
        'eul_laborleisure': eul_laborleisure
    }

    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"))

    macro_output = {
        'Y': Y,
        'K': K,
        'L': L,
        'C': C,
        'I': I,
        'BQ': BQ,
        'T_H': T_H,
        'r': r,
        'w': w,
        'tax_path': tax_path
    }

    # Non-stationary output
    # macro_ns_output = {'K_ns_path': K_ns_path, 'C_ns_path': C_ns_path, 'I_ns_path': I_ns_path,
    #           'L_ns_path': L_ns_path, 'BQ_ns_path': BQ_ns_path,
    #           'rinit': rinit, 'Y_ns_path': Y_ns_path, 'T_H_ns_path': T_H_ns_path,
    #           'w_ns_path': w_ns_path}

    return output, macro_output
Example #6
0
def create_tpi_params(**sim_params):

    '''
    ------------------------------------------------------------------------
    Set factor and initial capital stock to SS from baseline
    ------------------------------------------------------------------------
    '''
    baseline_ss = os.path.join(sim_params['baseline_dir'], "SS/SS_vars.pkl")
    ss_baseline_vars = pickle.load(open(baseline_ss, "rb"))
    factor = ss_baseline_vars['factor_ss']
    initial_b = ss_baseline_vars['bssmat_splus1']
    if sim_params['baseline']:
        T_H_baseline = np.zeros(sim_params['T'] + sim_params['S'])
    else:
        baseline_tpi = os.path.join(sim_params['baseline_dir'], "TPI/TPI_vars.pkl")
        tpi_baseline_vars = pickle.load(open(baseline_tpi, "rb"))
        T_H_baseline = tpi_baseline_vars['T_H']

    if sim_params['baseline']==True:
        SS_values = (ss_baseline_vars['Kss'],ss_baseline_vars['Lss'], ss_baseline_vars['rss'],
                 ss_baseline_vars['wss'], ss_baseline_vars['BQss'], ss_baseline_vars['T_Hss'], ss_baseline_vars['Gss'],
                 ss_baseline_vars['bssmat_splus1'], ss_baseline_vars['nssmat'])
        wss = ss_baseline_vars['wss']
        nssmat = ss_baseline_vars['nssmat']
    elif sim_params['baseline']==False:
        reform_ss = os.path.join(sim_params['input_dir'], "SS/SS_vars.pkl")
        print('Directory for SS values for TPI = ', reform_ss)
        ss_reform_vars = pickle.load(open(reform_ss, "rb"))
        SS_values = (ss_reform_vars['Kss'],ss_reform_vars['Lss'], ss_reform_vars['rss'],
                 ss_reform_vars['wss'], ss_reform_vars['BQss'], ss_reform_vars['T_Hss'], ss_reform_vars['Gss'],
                 ss_reform_vars['bssmat_splus1'], ss_reform_vars['nssmat'])
        wss = ss_reform_vars['wss']
        nssmat = ss_reform_vars['nssmat']

    initial_n = nssmat  # set initial_n to SS value under policy regime running


    # Make a vector of all one dimensional parameters, to be used in the
    # following functions
    wealth_tax_params = [sim_params['h_wealth'], sim_params['p_wealth'], sim_params['m_wealth']]
    ellipse_params = [sim_params['b_ellipse'], sim_params['upsilon']]
    chi_params = [sim_params['chi_b_guess'], sim_params['chi_n_guess']]

    N_tilde = sim_params['omega'].sum(1) #this should just be one in each year given how we've constructed omega
    sim_params['omega'] = sim_params['omega'] / N_tilde.reshape(sim_params['T'] + sim_params['S'], 1)

    theta_params = (sim_params['e'], sim_params['S'], sim_params['retire'])
    theta = tax.replacement_rate_vals(nssmat, wss, factor, theta_params)

    tpi_params = [sim_params['J'], sim_params['S'], sim_params['T'], sim_params['BW'],
                  sim_params['beta'], sim_params['sigma'], sim_params['alpha'],
                  sim_params['Z'], sim_params['delta'], sim_params['ltilde'],
                  sim_params['nu'], sim_params['g_y'], sim_params['g_n_vector'],
                  sim_params['tau_payroll'], sim_params['tau_bq'], sim_params['rho'], sim_params['omega'], N_tilde,
                  sim_params['lambdas'], sim_params['imm_rates'], sim_params['e'],
                  sim_params['retire'], sim_params['mean_income_data'], factor, T_H_baseline] + \
                  wealth_tax_params + ellipse_params + chi_params + [theta]
    iterative_params = [sim_params['maxiter'], sim_params['mindist_SS'], sim_params['mindist_TPI']]

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, imm_rates, e, retire, mean_income_data,\
                  factor, T_H_baseline, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n, theta = tpi_params

    ## Assumption for tax functions is that policy in last year of BW is
    # extended permanently
    etr_params_TP = np.zeros((S,T+S,sim_params['etr_params'].shape[2]))
    etr_params_TP[:,:BW,:] = sim_params['etr_params']
    etr_params_TP[:,BW:,:] = np.reshape(sim_params['etr_params'][:,BW-1,:],(S,1,sim_params['etr_params'].shape[2]))

    mtrx_params_TP = np.zeros((S,T+S,sim_params['mtrx_params'].shape[2]))
    mtrx_params_TP[:,:BW,:] = sim_params['mtrx_params']
    mtrx_params_TP[:,BW:,:] = np.reshape(sim_params['mtrx_params'][:,BW-1,:],(S,1,sim_params['mtrx_params'].shape[2]))

    mtry_params_TP = np.zeros((S,T+S,sim_params['mtry_params'].shape[2]))
    mtry_params_TP[:,:BW,:] = sim_params['mtry_params']
    mtry_params_TP[:,BW:,:] = np.reshape(sim_params['mtry_params'][:,BW-1,:],(S,1,sim_params['mtry_params'].shape[2]))

    income_tax_params = (sim_params['analytical_mtrs'], etr_params_TP, mtrx_params_TP, mtry_params_TP)

    '''
    ------------------------------------------------------------------------
    Set other parameters and initial values
    ------------------------------------------------------------------------
    '''
    # Get an initial distribution of capital with the initial population
    # distribution

    b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1]))
    b_splus1init = initial_b


    omega_S_preTP = sim_params['omega_S_preTP']
    K0_params = (omega_S_preTP.reshape(S, 1), lambdas, imm_rates[0].reshape(S,1), g_n_vector[0], 'SS')
    K0 = household.get_K(initial_b, K0_params)


    initial_values = (K0, b_sinit, b_splus1init, factor, initial_b, initial_n, omega_S_preTP)

    return (income_tax_params, tpi_params, iterative_params, initial_values, SS_values)
Example #7
0
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"))
Example #8
0
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
Example #9
0
def create_tpi_params(analytical_mtrs, etr_params, mtrx_params, mtry_params,
                      b_ellipse, upsilon, J, S, T, BW, beta, sigma, alpha, Z,
                      delta, ltilde, nu, g_y, tau_payroll, retire,
                      mean_income_data, run_params,
                      input_dir="./OUTPUT", baseline_dir="./OUTPUT", **kwargs):

    globals().update(run_params)

    ss_init = os.path.join(input_dir, "SSinit/ss_init_vars.pkl")
    variables = pickle.load(open(ss_init, "rb"))
    for key in variables:
        globals()[key] = variables[key]

    '''
    ------------------------------------------------------------------------
    Set factor and initial capital stock to SS from baseline
    ------------------------------------------------------------------------
    '''
    baseline_ss = os.path.join(baseline_dir, "SSinit/ss_init_vars.pkl")
    ss_baseline_vars = pickle.load(open(baseline_ss, "rb"))
    factor = ss_baseline_vars['factor_ss']
    #initial_b = ss_baseline_vars['bssmat_s'] + ss_baseline_vars['BQss']/lambdas
    initial_b= ss_baseline_vars['bssmat_splus1'] 


    '''
    ------------------------------------------------------------------------
    Set other parameters and initial values
    ------------------------------------------------------------------------
    '''

    # Make a vector of all one dimensional parameters, to be used in the
    # following functions
    # Put income tax parameters in a tuple 
    # Assumption here is that tax parameters of last year of budget
    # window continue forever and so will be SS values
    etr_params_TP = np.zeros((S,T+S,etr_params.shape[2]))
    etr_params_TP[:,:BW,:] = etr_params
    etr_params_TP[:,BW:,:] = np.reshape(etr_params[:,BW-1,:],(S,1,etr_params.shape[2]))

    mtrx_params_TP = np.zeros((S,T+S,mtrx_params.shape[2]))
    mtrx_params_TP[:,:BW,:] = mtrx_params
    mtrx_params_TP[:,BW:,:] = np.reshape(mtrx_params[:,BW-1,:],(S,1,mtrx_params.shape[2]))

    mtry_params_TP = np.zeros((S,T+S,mtry_params.shape[2]))
    mtry_params_TP[:,:BW,:] = mtry_params
    mtry_params_TP[:,BW:,:] = np.reshape(mtry_params[:,BW-1,:],(S,1,mtry_params.shape[2]))

    income_tax_params = (analytical_mtrs, etr_params_TP, mtrx_params_TP, mtry_params_TP)


    wealth_tax_params = [h_wealth, p_wealth, m_wealth]
    ellipse_params = [b_ellipse, upsilon]
    parameters = [J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y, g_n_ss, tau_payroll, retire,
                  mean_income_data]  + wealth_tax_params + ellipse_params

    N_tilde = omega.sum(1)
    omega_stationary = omega / N_tilde.reshape(T + S, 1)

    initial_n = nssmat

    # Get an initial distribution of capital with the initial population
    # distribution
    K0 = household.get_K(initial_b, omega_stationary[
                         0].reshape(S, 1), lambdas, g_n_vector[0], 'SS')


    b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1]))
    b_splus1init = initial_b
    L0 = firm.get_L(e, initial_n, omega_stationary[
                    0].reshape(S, 1), lambdas, 'SS')
    Y0 = firm.get_Y(K0, L0, parameters)
    w0 = firm.get_w(Y0, L0, parameters)
    r0 = firm.get_r(Y0, K0, parameters)
    BQ0 = household.get_BQ(r0, initial_b, omega_stationary[0].reshape(
        S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS')

    T_H_0 = tax.get_lump_sum(r0, b_sinit, w0, e, initial_n, BQ0, lambdas, factor_ss, omega_stationary[
                             0].reshape(S, 1), 'SS', etr_params_TP[:,0,:], parameters, theta, tau_bq)

    tax0_params = (J, S, retire, np.tile(np.reshape(etr_params_TP[:,0,:],(S,1,etr_params_TP.shape[2])),(1,J,1)), 
                    h_wealth, p_wealth, m_wealth, tau_payroll)
    tax0 = tax.total_taxes(r0, b_sinit, w0, e, initial_n, BQ0, lambdas,
                           factor_ss, T_H_0, None, 'SS', False, tax0_params, theta, tau_bq)
    c0 = household.get_cons(r0, b_sinit, w0, e, initial_n, BQ0.reshape(
        1, J), lambdas.reshape(1, J), b_splus1init, parameters, tax0)

    return (income_tax_params, wealth_tax_params, ellipse_params, parameters,
            N_tilde, omega_stationary, K0, b_sinit, b_splus1init, L0, Y0,
            w0, r0, BQ0, T_H_0, factor, tax0, c0, initial_b, initial_n)
Example #10
0
def create_tpi_params(**sim_params):
    '''
    ------------------------------------------------------------------------
    Set factor and initial capital stock to SS from baseline
    ------------------------------------------------------------------------
    '''
    baseline_ss = os.path.join(sim_params['baseline_dir'], "SS/SS_vars.pkl")
    ss_baseline_vars = pickle.load(open(baseline_ss, "rb"))
    factor = ss_baseline_vars['factor_ss']
    initial_b = ss_baseline_vars['bssmat_splus1']
    if sim_params['baseline']:
        T_H_baseline = np.zeros(sim_params['T'] + sim_params['S'])
    else:
        baseline_tpi = os.path.join(sim_params['baseline_dir'],
                                    "TPI/TPI_vars.pkl")
        tpi_baseline_vars = pickle.load(open(baseline_tpi, "rb"))
        T_H_baseline = tpi_baseline_vars['T_H']

    if sim_params['baseline'] == True:
        SS_values = (ss_baseline_vars['Kss'], ss_baseline_vars['Lss'],
                     ss_baseline_vars['rss'], ss_baseline_vars['wss'],
                     ss_baseline_vars['BQss'], ss_baseline_vars['T_Hss'],
                     ss_baseline_vars['Gss'],
                     ss_baseline_vars['bssmat_splus1'],
                     ss_baseline_vars['nssmat'])
        wss = ss_baseline_vars['wss']
        nssmat = ss_baseline_vars['nssmat']
    elif sim_params['baseline'] == False:
        reform_ss = os.path.join(sim_params['input_dir'], "SS/SS_vars.pkl")
        print('Directory for SS values for TPI = ', reform_ss)
        ss_reform_vars = pickle.load(open(reform_ss, "rb"))
        SS_values = (ss_reform_vars['Kss'], ss_reform_vars['Lss'],
                     ss_reform_vars['rss'], ss_reform_vars['wss'],
                     ss_reform_vars['BQss'], ss_reform_vars['T_Hss'],
                     ss_reform_vars['Gss'], ss_reform_vars['bssmat_splus1'],
                     ss_reform_vars['nssmat'])
        wss = ss_reform_vars['wss']
        nssmat = ss_reform_vars['nssmat']

    initial_n = nssmat  # set initial_n to SS value under policy regime running

    # Make a vector of all one dimensional parameters, to be used in the
    # following functions
    wealth_tax_params = [
        sim_params['h_wealth'], sim_params['p_wealth'], sim_params['m_wealth']
    ]
    ellipse_params = [sim_params['b_ellipse'], sim_params['upsilon']]
    chi_params = [sim_params['chi_b_guess'], sim_params['chi_n_guess']]

    N_tilde = sim_params['omega'].sum(
        1
    )  #this should just be one in each year given how we've constructed omega
    sim_params['omega'] = sim_params['omega'] / N_tilde.reshape(
        sim_params['T'] + sim_params['S'], 1)

    theta_params = (sim_params['e'], sim_params['S'], sim_params['retire'])
    theta = tax.replacement_rate_vals(nssmat, wss, factor, theta_params)

    tpi_params = [sim_params['J'], sim_params['S'], sim_params['T'], sim_params['BW'],
                  sim_params['beta'], sim_params['sigma'], sim_params['alpha'],
                  sim_params['Z'], sim_params['delta'], sim_params['ltilde'],
                  sim_params['nu'], sim_params['g_y'], sim_params['g_n_vector'],
                  sim_params['tau_payroll'], sim_params['tau_bq'], sim_params['rho'], sim_params['omega'], N_tilde,
                  sim_params['lambdas'], sim_params['imm_rates'], sim_params['e'],
                  sim_params['retire'], sim_params['mean_income_data'], factor, T_H_baseline] + \
                  wealth_tax_params + ellipse_params + chi_params + [theta]
    iterative_params = [
        sim_params['maxiter'], sim_params['mindist_SS'],
        sim_params['mindist_TPI']
    ]

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, imm_rates, e, retire, mean_income_data,\
                  factor, T_H_baseline, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n, theta = tpi_params

    ## Assumption for tax functions is that policy in last year of BW is
    # extended permanently
    etr_params_TP = np.zeros((S, T + S, sim_params['etr_params'].shape[2]))
    etr_params_TP[:, :BW, :] = sim_params['etr_params']
    etr_params_TP[:, BW:, :] = np.reshape(
        sim_params['etr_params'][:, BW - 1, :],
        (S, 1, sim_params['etr_params'].shape[2]))

    mtrx_params_TP = np.zeros((S, T + S, sim_params['mtrx_params'].shape[2]))
    mtrx_params_TP[:, :BW, :] = sim_params['mtrx_params']
    mtrx_params_TP[:, BW:, :] = np.reshape(
        sim_params['mtrx_params'][:, BW - 1, :],
        (S, 1, sim_params['mtrx_params'].shape[2]))

    mtry_params_TP = np.zeros((S, T + S, sim_params['mtry_params'].shape[2]))
    mtry_params_TP[:, :BW, :] = sim_params['mtry_params']
    mtry_params_TP[:, BW:, :] = np.reshape(
        sim_params['mtry_params'][:, BW - 1, :],
        (S, 1, sim_params['mtry_params'].shape[2]))

    income_tax_params = (sim_params['analytical_mtrs'], etr_params_TP,
                         mtrx_params_TP, mtry_params_TP)
    '''
    ------------------------------------------------------------------------
    Set other parameters and initial values
    ------------------------------------------------------------------------
    '''
    # Get an initial distribution of capital with the initial population
    # distribution

    b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1]))
    b_splus1init = initial_b

    omega_S_preTP = sim_params['omega_S_preTP']
    K0_params = (omega_S_preTP.reshape(S, 1), lambdas,
                 imm_rates[0].reshape(S, 1), g_n_vector[0], 'SS')
    K0 = household.get_K(initial_b, K0_params)

    initial_values = (K0, b_sinit, b_splus1init, factor, initial_b, initial_n,
                      omega_S_preTP)

    return (income_tax_params, tpi_params, iterative_params, initial_values,
            SS_values)
Example #11
0
def TPI_fsolve(guesses, 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

    # create full time paths with guesses and SS values
    rinit = np.zeros(T+S)
    winit = np.zeros(T+S)
    T_H_init = np.zeros(T+S)
    BQinit = np.zeros((T+S,J))
    rinit[:T] = guesses[0:T].reshape(T)
    winit[:T] = guesses[T:2*T].reshape(T)
    rinit[T:] = rss
    winit[T:] = wss
    T_H_init[:T] = guesses[2*T:3*T].reshape(T)
    BQinit[:T,:] = guesses[3*T:].reshape(T,J)
    T_H_init[T:] = T_Hss
    BQinit[T:,:] = BQss

    

    # Make array of initial guesses for distribution of 
    # savings and labor supply
    domain = np.linspace(0, T, T)
    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)

    euler_errors = np.zeros((T, 2 * S, J))

    # Solve hh problem over time path:
    # 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')

    # Plotting of Kpath and Lpath to check convergence
    # make vectors of Kpath and Lpath to plot
    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
    TPI_FIG_DIR = output_dir
    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"))


    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)

    error1 = rinit[:T]-rnew[:T] 
    error2 = winit[:T]-wnew[:T] 
    error3 = T_H_init[:T]-T_H_new[:T]
    error4 = BQinit[:T] - BQnew[:T]

    # Check and punish constraing violations
    mask1 = rinit[:T] <= 0
    mask2 = winit[:T] <= 0
    mask3 = np.isnan(rinit[:T])
    mask4 = np.isnan(winit[:T])
    error1[mask1] = 1e14
    error2[mask2] = 1e14
    error1[mask3] = 1e14
    error2[mask4] = 1e14
    mask5 = T_H_init[:T] < 0
    mask6 = np.isnan(T_H_init[:T])
    mask7 = BQinit[:T] < 0
    mask8 = np.isnan(BQinit[:T])
    error3[mask5] = 1e14
    error3[mask6] = 1e14
    error4[mask7] = 1e14
    error4[mask8] = 1e14

    errors = np.array(list(error1) +list(error2) + list(error3) + list(error4.flatten()))

    print '\t\tDistance:', np.absolute(errors).max()

    return errors 
Example #12
0
def run_TPI(income_tax_params,
            tpi_params,
            iterative_params,
            initial_values,
            SS_values,
            fix_transfers=False,
            output_dir="./OUTPUT"):

    # unpack tuples of parameters
    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    maxiter, mindist_SS, mindist_TPI = iterative_params
    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, imm_rates, e, retire, mean_income_data,\
                  factor, T_H_baseline, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n, theta = tpi_params
    K0, b_sinit, b_splus1init, factor, initial_b, initial_n, omega_S_preTP = initial_values
    Kss, Lss, rss, wss, BQss, T_Hss, Gss, bssmat_splus1, nssmat = SS_values

    TPI_FIG_DIR = output_dir
    # Initialize guesses at time paths
    domain = np.linspace(0, T, T)
    r = np.ones(T + S) * rss
    BQ = np.zeros((T + S, J))
    BQ0_params = (omega_S_preTP.reshape(S, 1), lambdas, rho.reshape(S, 1),
                  g_n_vector[0], 'SS')
    BQ0 = household.get_BQ(r[0], initial_b, BQ0_params)
    for j in xrange(J):
        BQ[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S
    BQ = np.array(BQ)
    # print "BQ values = ", BQ[0, :], BQ[100, :], BQ[-1, :], BQss
    # print "K0 vs Kss = ", K0-Kss

    if fix_transfers:
        T_H = T_H_baseline
    else:
        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(T + S) * T_Hss2 * (r / rss)
    G = np.ones(T + S) * Gss
    # # print "T_H values = ", T_H[0], T_H[100], T_H[-1], T_Hss
    # # print "omega diffs = ", (omega_S_preTP-omega[-1]).max(), (omega[10]-omega[-1]).max()
    #
    # Make array of initial guesses for labor supply and savings
    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)
    # print 'diff btwn start and end b: ', (guesses_b[0]-guesses_b[-1]).max()
    #
    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)
    # # print 'diff btwn start and end n: ', (guesses_n[0]-guesses_n[-1]).max()
    #
    # # find economic aggregates
    K = np.zeros(T + S)
    L = np.zeros(T + S)
    K[0] = K0
    K_params = (omega[:T - 1].reshape(T - 1, S, 1), lambdas.reshape(1, 1, J),
                imm_rates[:T - 1].reshape(T - 1, S, 1), g_n_vector[1:T], 'TPI')
    K[1:T] = household.get_K(guesses_b[:T - 1], K_params)
    K[T:] = Kss
    L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1),
                lambdas.reshape(1, 1, J), 'TPI')
    L[:T] = firm.get_L(guesses_n[:T], L_params)
    L[T:] = Lss
    Y_params = (alpha, Z)
    Y = firm.get_Y(K, L, Y_params)
    r_params = (alpha, delta)
    r[:T] = firm.get_r(Y[:T], K[:T], r_params)

    # uncomment lines below if want to use starting values from prior run
    r = TPI_START_VALUES['r']
    K = TPI_START_VALUES['K']
    L = TPI_START_VALUES['L']
    Y = TPI_START_VALUES['Y']
    T_H = TPI_START_VALUES['T_H']
    BQ = TPI_START_VALUES['BQ']
    G = TPI_START_VALUES['G']

    guesses_b = TPI_START_VALUES['b_mat']
    guesses_n = TPI_START_VALUES['n_mat']

    TPIiter = 0
    TPIdist = 10
    PLOT_TPI = False

    euler_errors = np.zeros((T, 2 * S, J))
    TPIdist_vec = np.zeros(maxiter)

    # print 'analytical mtrs in tpi = ', analytical_mtrs

    while (TPIiter < maxiter) and (TPIdist >= mindist_TPI):
        # Plot TPI for K for each iteration, so we can see if there is a
        # problem
        if PLOT_TPI is True:
            K_plot = list(K) + list(np.ones(10) * Kss)
            L_plot = list(L) + list(np.ones(10) * Lss)
            plt.figure()
            plt.axhline(y=Kss,
                        color='black',
                        linewidth=2,
                        label=r"Steady State $\hat{K}$",
                        ls='--')
            plt.plot(np.arange(T + 10),
                     Kpath_plot[:T + 10],
                     'b',
                     linewidth=2,
                     label=r"TPI time path $\hat{K}_t$")
            plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K"))

        guesses = (guesses_b, guesses_n)
        w_params = (Z, alpha, delta)
        w = firm.get_w_from_r(r, w_params)
        # print 'r and rss diff = ', r-rss
        # print 'w and wss diff = ', w-wss
        # print 'BQ and BQss diff = ', BQ-BQss
        # print 'T_H and T_Hss diff = ', T_H - T_Hss
        # print 'guess b and bss = ', (bssmat_splus1 - guesses_b).max()
        # print 'guess n and nss = ', (nssmat - guesses_n).max()
        outer_loop_vars = (r, w, BQ, T_H)
        inner_loop_params = (income_tax_params, tpi_params, initial_values,
                             ind)

        # Solve HH problem in inner loop
        euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars,
                                                inner_loop_params)

        # print 'guess b and bss = ', (b_mat - guesses_b).max()
        # print 'guess n and nss over time = ', (n_mat - guesses_n).max(axis=2).max(axis=1)
        # print 'guess n and nss over age = ', (n_mat - guesses_n).max(axis=0).max(axis=1)
        # print 'guess n and nss over ability = ', (n_mat - guesses_n).max(axis=0).max(axis=0)
        # quit()

        print 'Max Euler error: ', (np.abs(euler_errors)).max()

        bmat_s = np.zeros((T, S, J))
        bmat_s[0, 1:, :] = initial_b[:-1, :]
        bmat_s[1:, 1:, :] = b_mat[:T - 1, :-1, :]
        bmat_splus1 = np.zeros((T, S, J))
        bmat_splus1[:, :, :] = b_mat[:T, :, :]

        K[0] = K0
        K_params = (omega[:T - 1].reshape(T - 1, S,
                                          1), lambdas.reshape(1, 1, J),
                    imm_rates[:T - 1].reshape(T - 1, S,
                                              1), g_n_vector[1:T], 'TPI')
        K[1:T] = household.get_K(bmat_splus1[:T - 1], K_params)
        L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1),
                    lambdas.reshape(1, 1, J), 'TPI')
        L[:T] = firm.get_L(n_mat[:T], L_params)
        # print 'K diffs = ', K-K0
        # print 'L diffs = ', L-L[0]

        Y_params = (alpha, Z)
        Ynew = firm.get_Y(K[:T], L[:T], Y_params)
        r_params = (alpha, delta)
        rnew = firm.get_r(Ynew[:T], K[:T], r_params)
        wnew = firm.get_w_from_r(rnew, w_params)

        omega_shift = np.append(omega_S_preTP.reshape(1, S),
                                omega[:T - 1, :],
                                axis=0)
        BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J),
                     rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI')
        # b_mat_shift = np.append(np.reshape(initial_b, (1, S, J)),
        #                         b_mat[:T-1, :, :], axis=0)
        b_mat_shift = bmat_splus1[:T, :, :]
        # print 'b diffs = ', (bmat_splus1[100, :, :] - initial_b).max(), (bmat_splus1[0, :, :] - initial_b).max(), (bmat_splus1[1, :, :] - initial_b).max()
        # print 'r diffs = ', rnew[1]-r[1], rnew[100]-r[100], rnew[-1]-r[-1]
        BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift,
                                 BQ_params)
        BQss2 = np.empty(J)
        for j in range(J):
            BQss_params = (omega[1, :], lambdas[j], rho, g_n_vector[1], 'SS')
            BQss2[j] = household.get_BQ(rnew[1], bmat_splus1[1, :, j],
                                        BQss_params)
        # print 'BQ test = ', BQss2-BQss, BQss-BQnew[1], BQss-BQnew[100], BQss-BQnew[-1]

        total_tax_params = np.zeros((T, S, J, etr_params.shape[2]))
        for i in range(etr_params.shape[2]):
            total_tax_params[:, :, :, i] = np.tile(
                np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)),
                (1, 1, J))

        tax_receipt_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)),
                              lambdas.reshape(1, 1,
                                              J), omega[:T].reshape(T, S,
                                                                    1), 'TPI',
                              total_tax_params, theta, tau_bq, tau_payroll,
                              h_wealth, p_wealth, m_wealth, retire, T, S, J)
        net_tax_receipts = np.array(
            list(
                tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1), (
                    1, S, J)), np.tile(wnew[:T].reshape(T, 1, 1), (
                        1, S, J)), bmat_s, n_mat[:T, :, :], BQnew[:T].reshape(
                            T, 1, J), factor, tax_receipt_params)) +
            [T_Hss] * S)

        r[:T] = utils.convex_combo(rnew[:T], r[:T], nu)
        BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu)
        if fix_transfers:
            T_H_new = T_H
            G[:T] = net_tax_receipts[:T] - T_H[:T]
        else:
            T_H_new = net_tax_receipts
            T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[:T], nu)
            G[:T] = 0.0

        etr_params_path = np.zeros((T, S, J, etr_params.shape[2]))
        for i in range(etr_params.shape[2]):
            etr_params_path[:, :, :, i] = np.tile(
                np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)),
                (1, 1, J))
        tax_path_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), lambdas,
                           'TPI', retire, etr_params_path, h_wealth, p_wealth,
                           m_wealth, tau_payroll, theta, tau_bq, J, S)
        b_to_use = np.zeros((T, S, J))
        b_to_use[0, 1:, :] = initial_b[:-1, :]
        b_to_use[1:, 1:, :] = b_mat[:T - 1, :-1, :]
        tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1), (1, S, J)),
                                   np.tile(w[:T].reshape(T, 1, 1),
                                           (1, S, J)), b_to_use,
                                   n_mat[:T, :, :], BQ[:T, :].reshape(T, 1, J),
                                   factor, T_H[:T].reshape(T, 1, 1), None,
                                   False, tax_path_params)

        y_path = (np.tile(r[:T].reshape(T, 1, 1),
                          (1, S, J)) * b_to_use[:T, :, :] +
                  np.tile(w[:T].reshape(T, 1, 1),
                          (1, S, J)) * np.tile(e.reshape(1, S, J),
                                               (T, 1, 1)) * n_mat[:T, :, :])
        cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y)
        c_path = household.get_cons(r[:T].reshape(T, 1,
                                                  1), w[:T].reshape(T, 1, 1),
                                    b_to_use[:T, :, :], b_mat[:T, :, :],
                                    n_mat[:T, :, :], BQ[:T].reshape(T, 1, J),
                                    tax_path, cons_params)

        guesses_b = utils.convex_combo(b_mat, guesses_b, nu)
        guesses_n = utils.convex_combo(n_mat, guesses_n, nu)
        if T_H.all() != 0:
            TPIdist = np.array(
                list(utils.pct_diff_func(rnew[:T], r[:T])) +
                list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) +
                list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max()
            print 'r dist = ', np.array(
                list(utils.pct_diff_func(rnew[:T], r[:T]))).max()
            print 'BQ dist = ', np.array(
                list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten())).max()
            print 'T_H dist = ', np.array(
                list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max()
            print 'T_H path = ', T_H[:20]
            # print 'r old = ', r[:T]
            # print 'r new = ', rnew[:T]
            # print 'K old = ', K[:T]
            # print 'L old = ', L[:T]
            # print 'income = ', y_path[:, :, -1]
            # print 'taxes = ', tax_path[:, :, -1]
            # print 'labor supply = ', n_mat[:, :, -1]
            # print 'max and min labor = ', n_mat.max(), n_mat.min()
            # print 'max and min labor = ', np.argmax(n_mat), np.argmin(n_mat)
            # print 'max and min labor, j = 7 = ', n_mat[:,:,-1].max(), n_mat[:,:,-1].min()
            # print 'max and min labor, j = 6 = ', n_mat[:,:,-2].max(), n_mat[:,:,-2].min()
            # print 'max and min labor, j = 5 = ', n_mat[:,:,4].max(), n_mat[:,:,4].min()
            # print 'max and min labor, j = 4 = ', n_mat[:,:,3].max(), n_mat[:,:,3].min()
            # print 'max and min labor, j = 3 = ', n_mat[:,:,2].max(), n_mat[:,:,2].min()
            # print 'max and min labor, j = 2 = ', n_mat[:,:,1].max(), n_mat[:,:,1].min()
            # print 'max and min labor, j = 1 = ', n_mat[:,:,0].max(), n_mat[:,:,0].min()
            # print 'max and min labor, S = 80 = ', n_mat[:,-1,-1].max(), n_mat[:,-1,-1].min()
            # print "number  > 1 = ", (n_mat > 1).sum()
            # print "number  < 0, = ", (n_mat < 0).sum()
            # print "number  > 1, j=7 = ", (n_mat[:T,:,-1] > 1).sum()
            # print "number  < 0, j=7 = ", (n_mat[:T,:,-1] < 0).sum()
            # print "number  > 1, s=80, j=7 = ", (n_mat[:T,-1,-1] > 1).sum()
            # print "number  < 0, s=80, j=7 = ", (n_mat[:T,-1,-1] < 0).sum()
            # print "number  > 1, j= 7, age 80= ", (n_mat[:T,-1,-1] > 1).sum()
            # print "number  < 0, j = 7, age 80= ", (n_mat[:T,-1,-1] < 0).sum()
            # print "number  > 1, j= 7, age 80, period 0 to 10= ", (n_mat[:30,-1,-1] > 1).sum()
            # print "number  < 0, j = 7, age 80, period 0 to 10= ", (n_mat[:30,-1,-1] < 0).sum()
            # print "number  > 1, j= 7, age 70-79, period 0 to 10= ", (n_mat[:30,70:80,-1] > 1).sum()
            # print "number  < 0, j = 7, age 70-79, period 0 to 10= ", (n_mat[:30,70:80   ,-1] < 0).sum()
            # diag_dict = {'n_mat': n_mat, 'b_mat': b_mat, 'y_path': y_path, 'c_path': c_path}
            # pickle.dump(diag_dict, open('tpi_iter1.pkl', 'wb'))

        else:
            TPIdist = np.array(
                list(utils.pct_diff_func(rnew[:T], r[:T])) +
                list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) +
                list(np.abs(T_H_new[:T] - T_H[: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 '\tIteration:', TPIiter
        print '\t\tDistance:', TPIdist

    Y[:T] = Ynew

    # Solve HH problem in inner loop
    guesses = (guesses_b, guesses_n)
    outer_loop_vars = (r, w, BQ, T_H)
    inner_loop_params = (income_tax_params, tpi_params, initial_values, ind)
    euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars,
                                            inner_loop_params)

    bmat_s = np.zeros((T, S, J))
    bmat_s[0, 1:, :] = initial_b[:-1, :]
    bmat_s[1:, 1:, :] = b_mat[:T - 1, :-1, :]
    bmat_splus1 = np.zeros((T, S, J))
    bmat_splus1[:, :, :] = b_mat[:T, :, :]

    K[0] = K0
    K_params = (omega[:T - 1].reshape(T - 1, S, 1), lambdas.reshape(1, 1, J),
                imm_rates[:T - 1].reshape(T - 1, S, 1), g_n_vector[1:T], 'TPI')
    K[1:T] = household.get_K(bmat_splus1[:T - 1], K_params)
    L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1),
                lambdas.reshape(1, 1, J), 'TPI')
    L[:T] = firm.get_L(n_mat[:T], L_params)

    Y_params = (alpha, Z)
    Ynew = firm.get_Y(K[:T], L[:T], Y_params)
    r_params = (alpha, delta)
    rnew = firm.get_r(Ynew[:T], K[:T], r_params)
    wnew = firm.get_w_from_r(rnew, w_params)

    omega_shift = np.append(omega_S_preTP.reshape(1, S),
                            omega[:T - 1, :],
                            axis=0)
    BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J),
                 rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI')
    b_mat_shift = np.append(np.reshape(initial_b, (1, S, J)),
                            b_mat[:T - 1, :, :],
                            axis=0)
    BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift, BQ_params)

    total_tax_params = np.zeros((T, S, J, etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        total_tax_params[:, :, :, i] = np.tile(
            np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)),
            (1, 1, J))

    tax_receipt_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)),
                          lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1),
                          'TPI', total_tax_params, theta, tau_bq, tau_payroll,
                          h_wealth, p_wealth, m_wealth, retire, T, S, J)
    net_tax_receipts = np.array(
        list(
            tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1), (
                1, S, J)), np.tile(wnew[:T].reshape(T, 1, 1), (
                    1, S, J)), bmat_s, n_mat[:T, :, :], BQnew[:T].reshape(
                        T, 1, J), factor, tax_receipt_params)) + [T_Hss] * S)

    if fix_transfers:
        G[:T] = net_tax_receipts[:T] - T_H[:T]
    else:
        T_H[:T] = net_tax_receipts[:T]
        G[:T] = 0.0

    etr_params_path = np.zeros((T, S, J, etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        etr_params_path[:, :, :, i] = np.tile(
            np.reshape(np.transpose(etr_params[:, :T, i]), (T, S, 1)),
            (1, 1, J))
    tax_path_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), lambdas, 'TPI',
                       retire, etr_params_path, h_wealth, p_wealth, m_wealth,
                       tau_payroll, theta, tau_bq, J, S)
    tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1), (1, S, J)),
                               np.tile(w[:T].reshape(T, 1, 1),
                                       (1, S, J)), bmat_s, n_mat[:T, :, :],
                               BQ[:T, :].reshape(T, 1, J), factor,
                               T_H[:T].reshape(T, 1, 1), None, False,
                               tax_path_params)

    cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y)
    c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1),
                                bmat_s, bmat_splus1, n_mat[:T, :, :],
                                BQ[:T].reshape(T, 1, J), tax_path, cons_params)
    C_params = (omega[:T].reshape(T, S, 1), lambdas, 'TPI')
    C = household.get_C(c_path, C_params)
    I_params = (delta, g_y, omega[:T].reshape(T, S, 1), lambdas,
                imm_rates[:T].reshape(T, S, 1), g_n_vector[1:T + 1], 'TPI')
    I = firm.get_I(bmat_splus1[:T], K[1:T + 1], K[:T], I_params)
    rc_error = Y[:T] - C[:T] - I[:T] - G[:T]
    print 'Resource Constraint Difference:', rc_error

    # compute utility
    u_params = (sigma, np.tile(chi_n.reshape(1, S, 1),
                               (T, 1, J)), b_ellipse, ltilde, upsilon,
                np.tile(rho.reshape(1, S, 1),
                        (T, 1, J)), np.tile(chi_b.reshape(1, 1, J), (T, S, 1)))
    utility_path = household.get_u(c_path[:T, :, :], n_mat[:T, :, :],
                                   bmat_splus1[:T, :, :], u_params)

    # compute before and after-tax income
    y_path = (np.tile(r[:T].reshape(T, 1, 1), (1, S, J)) * bmat_s[:T, :, :] +
              np.tile(w[:T].reshape(T, 1, 1),
                      (1, S, J)) * np.tile(e.reshape(1, S, J),
                                           (T, 1, 1)) * n_mat[:T, :, :])
    inctax_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), etr_params_path)
    y_aftertax_path = (y_path - tax.tau_income(
        np.tile(r[:T].reshape(T, 1, 1),
                (1, S, J)), np.tile(w[:T].reshape(T, 1, 1), (1, S, J)),
        bmat_s[:T, :, :], n_mat[:T, :, :], factor, inctax_params))

    # compute after-tax wealth
    wtax_params = (h_wealth, p_wealth, m_wealth)
    b_aftertax_path = bmat_s[:T, :, :] - tax.tau_wealth(
        bmat_s[:T, :, :], wtax_params)

    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,
                                         ltilde)

    eul_savings = euler_errors[:, :S, :].max(1).max(1)
    eul_laborleisure = euler_errors[:, 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,
        'K': K,
        'L': L,
        'C': C,
        'I': I,
        'BQ': BQ,
        'G': G,
        'T_H': T_H,
        'r': r,
        'w': w,
        'b_mat': b_mat,
        'n_mat': n_mat,
        'c_path': c_path,
        'tax_path': tax_path,
        'bmat_s': bmat_s,
        'utility_path': utility_path,
        'b_aftertax_path': b_aftertax_path,
        'y_aftertax_path': y_aftertax_path,
        'y_path': y_path,
        'eul_savings': eul_savings,
        'eul_laborleisure': eul_laborleisure
    }

    macro_output = {
        'Y': Y,
        'K': K,
        'L': L,
        'C': C,
        'I': I,
        'BQ': BQ,
        'G': G,
        'T_H': T_H,
        'r': r,
        'w': w,
        'tax_path': tax_path
    }

    # if ((TPIiter >= maxiter) or (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS :
    #     raise RuntimeError("Transition path equlibrium not found")
    #
    # if ((np.any(np.absolute(rc_error) >= 1e-6))
    #     and ENFORCE_SOLUTION_CHECKS):
    #     raise RuntimeError("Transition path equlibrium not found")
    #
    # if ((np.any(np.absolute(eul_savings) >= mindist_TPI) or
    #     (np.any(np.absolute(eul_laborleisure) > mindist_TPI)))
    #     and ENFORCE_SOLUTION_CHECKS):
    #     raise RuntimeError("Transition path equlibrium not found")

    return output, macro_output
Example #13
0
def create_tpi_params(**sim_params):

    '''
    ------------------------------------------------------------------------
    Set factor and initial capital stock to SS from baseline
    ------------------------------------------------------------------------
    '''
    baseline_ss = os.path.join(sim_params['baseline_dir'], "SS/SS_vars.pkl")
    ss_baseline_vars = pickle.load(open(baseline_ss, "rb"))
    factor = ss_baseline_vars['factor_ss']
    initial_b = ss_baseline_vars['bssmat_splus1']
    initial_n = ss_baseline_vars['nssmat']
    if sim_params['baseline_spending']==True:
        baseline_tpi = os.path.join(sim_params['baseline_dir'], "TPI/TPI_vars.pkl")
        tpi_baseline_vars = pickle.load(open(baseline_tpi, "rb"))
        T_Hbaseline = tpi_baseline_vars['T_H']
        Gbaseline   = tpi_baseline_vars['G']

    theta_params = (sim_params['e'], sim_params['S'], sim_params['retire'])
    if sim_params['baseline']==True:
        SS_values = (ss_baseline_vars['Kss'], ss_baseline_vars['Bss'], ss_baseline_vars['Lss'], ss_baseline_vars['rss'],
                 ss_baseline_vars['wss'], ss_baseline_vars['BQss'], ss_baseline_vars['T_Hss'], ss_baseline_vars['revenue_ss'],
                 ss_baseline_vars['bssmat_splus1'], ss_baseline_vars['nssmat'], ss_baseline_vars['Yss'], ss_baseline_vars['Gss'])
        theta = tax.replacement_rate_vals(ss_baseline_vars['nssmat'], ss_baseline_vars['wss'], factor, theta_params)
    elif sim_params['baseline']==False:
        reform_ss = os.path.join(sim_params['input_dir'], "SS/SS_vars.pkl")
        ss_reform_vars = pickle.load(open(reform_ss, "rb"))
        SS_values = (ss_reform_vars['Kss'],ss_reform_vars['Bss'], ss_reform_vars['Lss'], ss_reform_vars['rss'],
                 ss_reform_vars['wss'], ss_reform_vars['BQss'], ss_reform_vars['T_Hss'], ss_reform_vars['revenue_ss'],
                 ss_reform_vars['bssmat_splus1'], ss_reform_vars['nssmat'], ss_reform_vars['Yss'], ss_reform_vars['Gss'])
        theta = tax.replacement_rate_vals(ss_reform_vars['nssmat'], ss_reform_vars['wss'], factor, theta_params)

    # Make a vector of all one dimensional parameters, to be used in the
    # following functions
    wealth_tax_params = [sim_params['h_wealth'], sim_params['p_wealth'], sim_params['m_wealth']]
    ellipse_params = [sim_params['b_ellipse'], sim_params['upsilon']]
    chi_params = [sim_params['chi_b_guess'], sim_params['chi_n_guess']]

    N_tilde = sim_params['omega'].sum(1) #this should just be one in each year given how we've constructed omega
    sim_params['omega'] = sim_params['omega'] / N_tilde.reshape(sim_params['T'] + sim_params['S'], 1)



    tpi_params = [sim_params['J'], sim_params['S'], sim_params['T'], sim_params['BW'],
                  sim_params['beta'], sim_params['sigma'], sim_params['alpha'],
                  sim_params['gamma'], sim_params['epsilon'],
                  sim_params['Z'], sim_params['delta'], sim_params['ltilde'],
                  sim_params['nu'], sim_params['g_y'], sim_params['g_n_vector'],
                  sim_params['tau_payroll'], sim_params['tau_bq'], sim_params['rho'], sim_params['omega'], N_tilde,
                  sim_params['lambdas'], sim_params['imm_rates'], sim_params['e'], sim_params['retire'], sim_params['mean_income_data'], factor] + \
                  wealth_tax_params + ellipse_params + chi_params + [theta]
    iterative_params = [sim_params['maxiter'], sim_params['mindist_SS'], sim_params['mindist_TPI']]
    small_open_params = [sim_params['small_open'], sim_params['tpi_firm_r'], sim_params['tpi_hh_r']]


    J, S, T, BW, beta, sigma, alpha, gamma, epsilon, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, imm_rates, e, retire, mean_income_data,\
                  factor, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n, theta = tpi_params

    ## Assumption for tax functions is that policy in last year of BW is
    # extended permanently
    etr_params_TP = np.zeros((S,T+S,sim_params['etr_params'].shape[2]))
    etr_params_TP[:,:BW,:] = sim_params['etr_params']
    etr_params_TP[:,BW:,:] = np.reshape(sim_params['etr_params'][:,BW-1,:],(S,1,sim_params['etr_params'].shape[2]))

    mtrx_params_TP = np.zeros((S,T+S,sim_params['mtrx_params'].shape[2]))
    mtrx_params_TP[:,:BW,:] = sim_params['mtrx_params']
    mtrx_params_TP[:,BW:,:] = np.reshape(sim_params['mtrx_params'][:,BW-1,:],(S,1,sim_params['mtrx_params'].shape[2]))

    mtry_params_TP = np.zeros((S,T+S,sim_params['mtry_params'].shape[2]))
    mtry_params_TP[:,:BW,:] = sim_params['mtry_params']
    mtry_params_TP[:,BW:,:] = np.reshape(sim_params['mtry_params'][:,BW-1,:],(S,1,sim_params['mtry_params'].shape[2]))

    income_tax_params = (sim_params['analytical_mtrs'], etr_params_TP, mtrx_params_TP, mtry_params_TP)

    '''
    ------------------------------------------------------------------------
    Set government finance parameters
    ------------------------------------------------------------------------
    '''
    budget_balance = sim_params['budget_balance']
    ALPHA_T        = sim_params['ALPHA_T']
    ALPHA_G        = sim_params['ALPHA_G']
    tG1            = sim_params['tG1']
    tG2            = sim_params['tG2']
    rho_G          = sim_params['rho_G']
    debt_ratio_ss  = sim_params['debt_ratio_ss']
    if sim_params['baseline_spending']==False:
        fiscal_params  = (budget_balance, ALPHA_T, ALPHA_G, tG1, tG2, rho_G, debt_ratio_ss)
    else:
        fiscal_params  = (budget_balance, ALPHA_T, ALPHA_G, tG1, tG2, rho_G, debt_ratio_ss, T_Hbaseline, Gbaseline)

    initial_debt  = sim_params['initial_debt']

    '''
    ------------------------------------------------------------------------
    Set business tax parameters
    ------------------------------------------------------------------------
    '''
    tau_b = sim_params['tau_b']
    delta_tau = sim_params['delta_tau']
    biz_tax_params  = (tau_b, delta_tau)

    initial_debt  = sim_params['initial_debt']

    '''
    ------------------------------------------------------------------------
    Set other parameters and initial values
    ------------------------------------------------------------------------
    '''
    # Get an initial distribution of wealth with the initial population
    # distribution. When small_open=True, the value of K0 is used as a placeholder for first-period wealth (B0)
    omega_S_preTP = sim_params['omega_S_preTP']
    B0_params = (omega_S_preTP.reshape(S, 1), lambdas, imm_rates[0].reshape(S,1), g_n_vector[0], 'SS')
    B0 = household.get_K(initial_b, B0_params)

    b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1]))
    b_splus1init = initial_b

    initial_values = (B0, b_sinit, b_splus1init, factor, initial_b, initial_n, omega_S_preTP, initial_debt)

    return (income_tax_params, tpi_params, iterative_params, small_open_params, initial_values, SS_values, fiscal_params, biz_tax_params)
Example #14
0
def run_TPI(income_tax_params, tpi_params, iterative_params, small_open_params, initial_values, SS_values, fiscal_params, biz_tax_params, output_dir="./OUTPUT", baseline_spending=False):

    # unpack tuples of parameters
    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    maxiter, mindist_SS, mindist_TPI = iterative_params
    J, S, T, BW, beta, sigma, alpha, gamma, epsilon, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, imm_rates, e, retire, mean_income_data,\
                  factor, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n, theta = tpi_params
    # K0, b_sinit, b_splus1init, L0, Y0,\
    #         w0, r0, BQ0, T_H_0, factor, tax0, c0, initial_b, initial_n, omega_S_preTP = initial_values
    small_open, tpi_firm_r, tpi_hh_r = small_open_params
    B0, b_sinit, b_splus1init, factor, initial_b, initial_n, omega_S_preTP, initial_debt = initial_values
    Kss, Bss, Lss, rss, wss, BQss, T_Hss, revenue_ss, bssmat_splus1, nssmat, Yss, Gss = SS_values
    tau_b, delta_tau = biz_tax_params
    if baseline_spending==False:
        budget_balance, ALPHA_T, ALPHA_G, tG1, tG2, rho_G, debt_ratio_ss = fiscal_params
    else:
        budget_balance, ALPHA_T, ALPHA_G, tG1, tG2, rho_G, debt_ratio_ss, T_Hbaseline, Gbaseline = fiscal_params

    print 'Government spending breakpoints are tG1: ', tG1, '; and tG2:', tG2

    TPI_FIG_DIR = output_dir
    # Initialize guesses at time paths
    # Make array of initial guesses for labor supply and savings
    domain = np.linspace(0, T, T)
    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 = guesses_b#np.zeros((T + S, S, J))
    n_mat = guesses_n#np.zeros((T + S, S, J))
    ind = np.arange(S)

    L_init = np.ones((T+S,))*Lss
    B_init = np.ones((T+S,))*Bss
    L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI')
    L_init[:T]  = firm.get_L(n_mat[:T], L_params)
    B_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T-1].reshape(T-1,S,1), g_n_vector[1:T], 'TPI')
    B_init[1:T] = household.get_K(b_mat[:T-1], B_params)
    B_init[0] = B0

    if small_open == False:
        if budget_balance:
            K_init = B_init
        else:
            K_init = B_init * Kss/Bss
    else:
        K_params = (Z, gamma, epsilon, delta, tau_b, delta_tau)
        K_init = firm.get_K(L_init, tpi_firm_r, K_params)

    K = K_init
#    if np.any(K < 0):
#        print 'K_init has negative elements. Setting them positive to prevent NAN.'
#        K[:T] = np.fmax(K[:T], 0.05*B[:T])

    L = L_init
    B = B_init
    Y_params = (Z, gamma, epsilon)
    Y = firm.get_Y(K, L, Y_params)
    w_params = (Z, gamma, epsilon)
    w = firm.get_w(Y, L, w_params)
    if small_open == False:
        r_params = (Z, gamma, epsilon, delta, tau_b, delta_tau)
        r = firm.get_r(Y, K, r_params)
    else:
        r = tpi_hh_r

    BQ = np.zeros((T + S, J))
    BQ0_params = (omega_S_preTP.reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS')
    BQ0 = household.get_BQ(r[0], initial_b, BQ0_params)
    for j in xrange(J):
        BQ[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S
    BQ = np.array(BQ)
    if 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(T + S) * T_Hss2
        REVENUE = T_H
        G = np.zeros(T + S)
    elif baseline_spending==False:
        T_H = ALPHA_T * Y
    elif baseline_spending==True:
        T_H = T_Hbaseline
        T_H_new = T_H   # Need to set T_H_new for later reference
        G   = Gbaseline
        G_0 = Gbaseline[0]

    # Initialize some inputs
    # D = np.zeros(T + S)
    D = debt_ratio_ss*Y
    omega_shift = np.append(omega_S_preTP.reshape(1,S),omega[:T-1,:],axis=0)
    BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1),
                     g_n_vector[:T].reshape(T, 1), 'TPI')
    tax_params = np.zeros((T,S,J,etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))
    REVENUE_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI',
                      tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau)


    # print 'D/Y:', D[:T]/Y[:T]
    # print 'T/Y:', T_H[:T]/Y[:T]
    # print 'G/Y:', G[:T]/Y[:T]
    # print 'Int payments to GDP:', (r[:T]*D[:T])/Y[:T]
    # quit()


    TPIiter = 0
    TPIdist = 10
    PLOT_TPI = False
    report_tG1 = False

    euler_errors = np.zeros((T, 2 * S, J))
    TPIdist_vec = np.zeros(maxiter)

    print 'analytical mtrs in tpi = ', analytical_mtrs


    while (TPIiter < maxiter) and (TPIdist >= mindist_TPI):

        # Plot TPI for K for each iteration, so we can see if there is a
        # problem
        if PLOT_TPI is True:
            #K_plot = list(K) + list(np.ones(10) * Kss)
            D_plot = list(D) + list(np.ones(10) * Yss * debt_ratio_ss)
            plt.figure()
            plt.axhline(
                y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--')
            plt.plot(np.arange(
                T + 10), D_plot[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$")
            plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_D"))

        if report_tG1 is True:
            print '\tAt time tG1-1:'
            print '\t\tG = ', G[tG1-1]
            print '\t\tK = ', K[tG1-1]
            print '\t\tr = ', r[tG1-1]
            print '\t\tD = ', D[tG1-1]


        guesses = (guesses_b, guesses_n)
        outer_loop_vars = (r, w, K, BQ, T_H)
        inner_loop_params = (income_tax_params, tpi_params, initial_values, ind)

        # Solve HH problem in inner loop
        euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params)

        bmat_s = np.zeros((T, S, J))
        bmat_s[0, 1:, :] = initial_b[:-1, :]
        bmat_s[1:, 1:, :] = b_mat[:T-1, :-1, :]
        bmat_splus1 = np.zeros((T, S, J))
        bmat_splus1[:, :, :] = b_mat[:T, :, :]

        #L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') # defined above
        L[:T]  = firm.get_L(n_mat[:T], L_params)
        #B_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T-1].reshape(T-1,S,1), g_n_vector[1:T], 'TPI') # defined above
        B[1:T] = household.get_K(bmat_splus1[:T-1], B_params)
        if np.any(B) < 0:
            print 'B has negative elements. B[0:9]:', B[0:9]
            print 'B[T-2:T]:', B[T-2,T]

        if small_open == False:
            if budget_balance:
                K[:T] = B[:T]
            else:
                if baseline_spending == False:
                    Y = T_H/ALPHA_T  #SBF 3/3: This seems totally unnecessary as both these variables are defined above.

#                tax_params = np.zeros((T,S,J,etr_params.shape[2]))
#                for i in range(etr_params.shape[2]):
#                    tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))

#                REVENUE_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI',
#                        tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau) # define above
                REVENUE = np.array(list(tax.revenue(np.tile(r[:T].reshape(T, 1, 1),(1,S,J)), np.tile(w[:T].reshape(T, 1, 1),(1,S,J)),
                       bmat_s, n_mat[:T,:,:], BQ[:T].reshape(T, 1, J), Y[:T], L[:T], K[:T], factor, REVENUE_params)) + [revenue_ss] * S)

                D_0    = initial_debt * Y[0]
                other_dg_params = (T, r, g_n_vector, g_y)
                if baseline_spending==False:
                    G_0    = ALPHA_G[0] * Y[0]
                dg_fixed_values = (Y, REVENUE, T_H, D_0,G_0)
                Dnew, G = fiscal.D_G_path(dg_fixed_values, fiscal_params, other_dg_params, baseline_spending=baseline_spending)
                K[:T] = B[:T] - Dnew[:T]
                if np.any(K < 0):
                    print 'K has negative elements. Setting them positive to prevent NAN.'
                    K[:T] = np.fmax(K[:T], 0.05*B[:T])
        else:
            # K_params previously set to =  (Z, gamma, epsilon, delta, tau_b, delta_tau)
            K[:T] = firm.get_K(L[:T], tpi_firm_r[:T], K_params)
        Y_params = (Z, gamma, epsilon)
        Ynew = firm.get_Y(K[:T], L[:T], Y_params)
        Y = Ynew
        w_params = (Z, gamma, epsilon)
        wnew = firm.get_w(Ynew[:T], L[:T], w_params)
        if small_open == False:
            r_params = (Z, gamma, epsilon, delta, tau_b, delta_tau)
            rnew = firm.get_r(Ynew[:T], K[:T], r_params)
        else:
            rnew = r.copy()

        print 'Y and T_H: ', Y[3], T_H[3]
#        omega_shift = np.append(omega_S_preTP.reshape(1,S),omega[:T-1,:],axis=0)  # defined above
#        BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1),
#                     g_n_vector[:T].reshape(T, 1), 'TPI')  # defined above
        b_mat_shift = np.append(np.reshape(initial_b,(1,S,J)),b_mat[:T-1,:,:],axis=0)
        BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift, BQ_params)

#        tax_params = np.zeros((T,S,J,etr_params.shape[2]))
#        for i in range(etr_params.shape[2]):
#            tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))

#        REVENUE_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI',
#                tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau) # defined above
        REVENUE = np.array(list(tax.revenue(np.tile(rnew[:T].reshape(T, 1, 1),(1,S,J)), np.tile(wnew[:T].reshape(T, 1, 1),(1,S,J)),
               bmat_s, n_mat[:T,:,:], BQnew[:T].reshape(T, 1, J), Y[:T], L[:T], K[:T], factor, REVENUE_params)) + [revenue_ss] * S)

        if budget_balance:
            T_H_new = REVENUE
        elif baseline_spending==False:
            T_H_new = ALPHA_T[:T] * Y[:T]
        # If baseline_spending==True, no need to update T_H, which remains fixed.

        if small_open==True and budget_balance==False:
            # Loop through years to calculate debt and gov't spending. This is done earlier when small_open=False.
            D_0    = initial_debt * Y[0]
            other_dg_params = (T, r, g_n_vector, g_y)
            if baseline_spending==False:
                G_0    = ALPHA_G[0] * Y[0]
            dg_fixed_values = (Y, REVENUE, T_H, D_0,G_0)
            Dnew, G = fiscal.D_G_path(dg_fixed_values, fiscal_params, other_dg_params, baseline_spending=baseline_spending)

        w[:T] = utils.convex_combo(wnew[:T], w[:T], nu)
        r[:T] = utils.convex_combo(rnew[:T], r[:T], nu)
        BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu)
        # D[:T] = utils.convex_combo(Dnew[:T], D[:T], nu)
        D = Dnew
        Y[:T] = utils.convex_combo(Ynew[:T], Y[:T], nu)
        if baseline_spending==False:
            T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[:T], nu)
        guesses_b = utils.convex_combo(b_mat, guesses_b, nu)
        guesses_n = utils.convex_combo(n_mat, guesses_n, nu)

        print 'r diff: ', (rnew[:T]-r[:T]).max(), (rnew[:T]-r[:T]).min()
        print 'w diff: ', (wnew[:T]-w[:T]).max(), (wnew[:T]-w[:T]).min()
        print 'BQ diff: ', (BQnew[:T]-BQ[:T]).max(), (BQnew[:T]-BQ[:T]).min()
        print 'T_H diff: ', (T_H_new[:T]-T_H[:T]).max(), (T_H_new[:T]-T_H[:T]).min()

        if baseline_spending==False:
            if T_H.all() != 0:
                TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(
                    utils.pct_diff_func(wnew[:T], w[:T])) + list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max()
            else:
                TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(
                    utils.pct_diff_func(wnew[:T], w[:T])) + list(np.abs(T_H[:T]))).max()
        else:
            # TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(
            #     utils.pct_diff_func(wnew[:T], w[:T])) + list(utils.pct_diff_func(Dnew[:T], D[:T]))).max()
            TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(
                utils.pct_diff_func(wnew[:T], w[:T])) + list(utils.pct_diff_func(Ynew[:T], Y[: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

        # print 'D/Y:', (D[:T]/Ynew[:T]).max(), (D[:T]/Ynew[:T]).min(), np.median(D[:T]/Ynew[:T])
        # print 'T/Y:', (T_H_new[:T]/Ynew[:T]).max(), (T_H_new[:T]/Ynew[:T]).min(), np.median(T_H_new[:T]/Ynew[:T])
        # print 'G/Y:', (G[:T]/Ynew[:T]).max(), (G[:T]/Ynew[:T]).min(), np.median(G[:T]/Ynew[:T])
        # print 'Int payments to GDP:', ((r[:T]*D[:T])/Ynew[:T]).max(), ((r[:T]*D[:T])/Ynew[:T]).min(), np.median((r[:T]*D[:T])/Ynew[:T])
        #
        # print 'D/Y:', (D[:T]/Ynew[:T])
        # print 'T/Y:', (T_H_new[:T]/Ynew[:T])
        # print 'G/Y:', (G[:T]/Ynew[:T])
        #
        # print 'deficit: ', REVENUE[:T] - T_H_new[:T] - G[:T]

    # Loop through years to calculate debt and gov't spending. The re-assignment of G0 & D0 is necessary because Y0 may change in the TPI loop.
    if budget_balance == False:
        D_0    = initial_debt * Y[0]
        other_dg_params = (T, r, g_n_vector, g_y)
        if baseline_spending==False:
            G_0    = ALPHA_G[0] * Y[0]
        dg_fixed_values = (Y, REVENUE, T_H, D_0,G_0)
        D, G = fiscal.D_G_path(dg_fixed_values, fiscal_params, other_dg_params, baseline_spending=baseline_spending)

    # Solve HH problem in inner loop
    guesses = (guesses_b, guesses_n)
    outer_loop_vars = (r, w, K, BQ, T_H)
    inner_loop_params = (income_tax_params, tpi_params, initial_values, ind)
    euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params)

    bmat_s = np.zeros((T, S, J))
    bmat_s[0, 1:, :] = initial_b[:-1, :]
    bmat_s[1:, 1:, :] = b_mat[:T-1, :-1, :]
    bmat_splus1 = np.zeros((T, S, J))
    bmat_splus1[:, :, :] = b_mat[:T, :, :]

    #L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI') # defined above
    L[:T]  = firm.get_L(n_mat[:T], L_params)
    #B_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T-1].reshape(T-1,S,1), g_n_vector[1:T], 'TPI') # defined above
    B[1:T] = household.get_K(bmat_splus1[:T-1], B_params)

    if small_open == False:
        K[:T] = B[:T] - D[:T]
    else:
        # K_params previously set to = (Z, gamma, epsilon, delta, tau_b, delta_tau)
        K[:T] = firm.get_K(L[:T], tpi_firm_r[:T], K_params)
    # Y_params previously set to = (Z, gamma, epsilon)
    Ynew = firm.get_Y(K[:T], L[:T], Y_params)

    # testing for change in Y
    ydiff = Ynew[:T] - Y[:T]
    ydiff_max = np.amax(np.abs(ydiff))
    print 'ydiff_max = ', ydiff_max

    w_params = (Z, gamma, epsilon)
    wnew = firm.get_w(Ynew[:T], L[:T], w_params)
    if small_open == False:
        # r_params previously set to = (Z, gamma, epsilon, delta, tau_b, delta_tau)
        rnew = firm.get_r(Ynew[:T], K[:T], r_params)
    else:
        rnew = r

    # Note: previously, Y was not reassigned to equal Ynew at this point.
    Y = Ynew[:]

#    omega_shift = np.append(omega_S_preTP.reshape(1,S),omega[:T-1,:],axis=0)
#    BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1),
#                 g_n_vector[:T].reshape(T, 1), 'TPI')
    b_mat_shift = np.append(np.reshape(initial_b,(1,S,J)),b_mat[:T-1,:,:],axis=0)
    BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift, BQ_params)

#    tax_params = np.zeros((T,S,J,etr_params.shape[2]))
#    for i in range(etr_params.shape[2]):
#        tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))

#    REVENUE_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI',
#            tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau)
    REVENUE = np.array(list(tax.revenue(np.tile(rnew[:T].reshape(T, 1, 1),(1,S,J)), np.tile(wnew[:T].reshape(T, 1, 1),(1,S,J)),
           bmat_s, n_mat[:T,:,:], BQnew[:T].reshape(T, 1, J), Ynew[:T], L[:T], K[:T], factor, REVENUE_params)) + [revenue_ss] * S)

    etr_params_path = np.zeros((T,S,J,etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        etr_params_path[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))
    tax_path_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas, 'TPI', retire, etr_params_path, h_wealth,
                       p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S)
    tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1),(1,S,J)), np.tile(w[:T].reshape(T, 1, 1),(1,S,J)), bmat_s,
                               n_mat[:T,:,:], BQ[:T, :].reshape(T, 1, J), factor, T_H[:T].reshape(T, 1, 1), None, False, tax_path_params)

    cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y)
    c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1), bmat_s, bmat_splus1, n_mat[:T,:,:],
                   BQ[:T].reshape(T, 1, J), tax_path, cons_params)
    C_params = (omega[:T].reshape(T, S, 1), lambdas, 'TPI')
    C = household.get_C(c_path, C_params)

    if budget_balance==False:
        D_0    = initial_debt * Y[0]
        other_dg_params = (T, r, g_n_vector, g_y)
        if baseline_spending==False:
            G_0    = ALPHA_G[0] * Y[0]
        dg_fixed_values = (Y, REVENUE, T_H, D_0,G_0)
        D, G = fiscal.D_G_path(dg_fixed_values, fiscal_params, other_dg_params, baseline_spending=baseline_spending)


    if small_open == False:
        I_params = (delta, g_y, omega[:T].reshape(T, S, 1), lambdas, imm_rates[:T].reshape(T, S, 1), g_n_vector[1:T+1], 'TPI')
        I = firm.get_I(bmat_splus1[:T], K[1:T+1], K[:T], I_params)
        rc_error = Y[:T] - C[:T] - I[:T] - G[:T]
    else:
        #InvestmentPlaceholder = np.zeros(bmat_splus1[:T].shape)
        #I_params = (delta, g_y, omega[:T].reshape(T, S, 1), lambdas, imm_rates[:T].reshape(T, S, 1), g_n_vector[1:T+1], 'TPI')
        I = (1+g_n_vector[:T])*np.exp(g_y)*K[1:T+1] - (1.0 - delta) * K[:T] #firm.get_I(InvestmentPlaceholder, K[1:T+1], K[:T], I_params)
        BI_params = (0.0, g_y, omega[:T].reshape(T, S, 1), lambdas, imm_rates[:T].reshape(T, S, 1), g_n_vector[1:T+1], 'TPI')
        BI = firm.get_I(bmat_splus1[:T], B[1:T+1], B[:T], BI_params)
        new_borrowing = D[1:T]*(1+g_n_vector[1:T])*np.exp(g_y) - D[:T-1]
        rc_error = Y[:T-1] + new_borrowing - (C[:T-1] + BI[:T-1] + G[:T-1] ) + (tpi_hh_r[:T-1] * B[:T-1] - (delta + tpi_firm_r[:T-1])*K[:T-1] - tpi_hh_r[:T-1]*D[:T-1])
        #print 'Y(T-1):', Y[T-1], '\n','C(T-1):', C[T-1], '\n','K(T-1):', K[T-1], '\n','B(T-1):', B[T-1], '\n','BI(T-1):', BI[T-1], '\n','I(T-1):', I[T-1]

    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 xrange(T):
        household.constraint_checker_TPI(
            b_mat[t], n_mat[t], c_path[t], t, ltilde)

    eul_savings = euler_errors[:, :S, :].max(1).max(1)
    eul_laborleisure = euler_errors[:, 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, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ,
              'REVENUE': REVENUE, 'T_H': T_H, 'G': G, 'D': D,
              'r': r, 'w': w, 'b_mat': b_mat, 'n_mat': n_mat,
              'c_path': c_path, 'tax_path': tax_path,
              'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure}

    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"))

    macro_output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I,
                    'BQ': BQ, 'T_H': T_H, 'r': r, 'w': w,
                    'tax_path': tax_path}

    growth = (1+g_n_vector)*np.exp(g_y)
    with open('TPI_output.csv', 'wb') as csvfile:
        tpiwriter = csv.writer(csvfile)
        tpiwriter.writerow(Y)
        tpiwriter.writerow(D)
        tpiwriter.writerow(REVENUE)
        tpiwriter.writerow(G)
        tpiwriter.writerow(T_H)
        tpiwriter.writerow(C)
        tpiwriter.writerow(K)
        tpiwriter.writerow(I)
        tpiwriter.writerow(r)
        if small_open == True:
            tpiwriter.writerow(B)
            tpiwriter.writerow(BI)
            tpiwriter.writerow(new_borrowing)
        tpiwriter.writerow(growth)
        tpiwriter.writerow(rc_error)
        tpiwriter.writerow(ydiff)


    if np.any(G) < 0:
        print 'Government spending is negative along transition path to satisfy budget'

    if ((TPIiter >= maxiter) or (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS :
        raise RuntimeError("Transition path equlibrium not found (TPIdist)")

    if ((np.any(np.absolute(rc_error) >= mindist_TPI))
        and ENFORCE_SOLUTION_CHECKS):
        raise RuntimeError("Transition path equlibrium not found (rc_error)")

    if ((np.any(np.absolute(eul_savings) >= mindist_TPI) or
        (np.any(np.absolute(eul_laborleisure) > mindist_TPI)))
        and ENFORCE_SOLUTION_CHECKS):
        raise RuntimeError("Transition path equlibrium not found (eulers)")

    # Non-stationary output
    # macro_ns_output = {'K_ns_path': K_ns_path, 'C_ns_path': C_ns_path, 'I_ns_path': I_ns_path,
    #           'L_ns_path': L_ns_path, 'BQ_ns_path': BQ_ns_path,
    #           'rinit': rinit, 'Y_ns_path': Y_ns_path, 'T_H_ns_path': T_H_ns_path,
    #           'w_ns_path': w_ns_path}


    return output, macro_output
Example #15
0
def run_TPI(income_tax_params, tpi_params, iterative_params, initial_values, SS_values, output_dir="./OUTPUT"):

    # unpack tuples of parameters
    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    maxiter, mindist_SS, mindist_TPI = iterative_params
    J, S, T, BQ_dist, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, e, retire, mean_income_data,\
                  factor, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n = tpi_params
    K0, b_sinit, b_splus1init, L0, Y0,\
            w0, r0, BQ0, T_H_0, factor, tax0, c0, initial_b, initial_n = initial_values
    Kss, Lss, rss, wss, BQss, T_Hss, bssmat_splus1, nssmat = SS_values


    TPI_FIG_DIR = output_dir
    # Initialize guesses at time paths
    domain = np.linspace(0, T, T)
    K_init = (-1 / (domain + 1)) * (Kss - K0) + Kss
    K_init[-1] = Kss
    K_init = np.array(list(K_init) + list(np.ones(S) * Kss))
    L_init = np.ones(T + S) * Lss

    K = K_init
    L = L_init
    Y_params = (alpha, Z)
    Y = firm.get_Y(K, L, Y_params)
    w = firm.get_w(Y, L, alpha)
    r_params = (alpha, delta)
    r = firm.get_r(Y, K, r_params)
    BQ = np.zeros((T + S, J))
    for j in xrange(J):
        BQ[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S
    BQ = np.array(BQ)
    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 = np.ones(T + S) * T_Hss2

    # Make array of initial guesses for labor supply and savings
    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
    PLOT_TPI = False

    euler_errors = np.zeros((T, 2 * S, J))
    TPIdist_vec = np.zeros(maxiter)


    while (TPIiter < maxiter) and (TPIdist >= mindist_TPI):
        # Plot TPI for K for each iteration, so we can see if there is a
        # problem
        if PLOT_TPI is True:
            K_plot = list(K) + list(np.ones(10) * Kss)
            L_plot = list(L) + list(np.ones(10) * Lss)
            plt.figure()
            plt.axhline(
                y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--')
            plt.plot(np.arange(
                T + 10), Kpath_plot[: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.

        # theta_params = (e[-1, j], 1, omega[0].reshape(S, 1), lambdas[j])
        # theta = tax.replacement_rate_vals(n, w, factor, theta_params)
        theta = np.zeros((J,)) 

        guesses = (guesses_b, guesses_n)
        outer_loop_vars = (r, w, K, BQ, T_H)
        inner_loop_params = (income_tax_params, tpi_params, initial_values, theta, ind)

        # Solve HH problem in inner loop
        euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params)


        # 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
        K_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI')
        K[:T] = household.get_K(b_mat[:T], K_params)
        L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI')
        L[:T]  = firm.get_L(n_mat[:T], L_params)

        Y_params = (alpha, Z)
        Ynew = firm.get_Y(K[:T], L[:T], Y_params)
        wnew = firm.get_w(Ynew[:T], L[:T], alpha)
        r_params = (alpha, delta)
        rnew = firm.get_r(Ynew[:T], K[:T], r_params)

        BQ_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1), 
                    g_n_vector[:T].reshape(T, 1), 'TPI')
        BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat[:T,:,:], BQ_params)
        bmat_s = np.zeros((T, S, J))
        bmat_s[:, 1:, :] = b_mat[:T, :-1, :]
        bmat_splus1 = np.zeros((T, S, J))
        bmat_splus1[:, :, :] = b_mat[1:T + 1, :, :]

        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_params = (np.tile(e.reshape(1, S, J),(T,1,1)), BQ_dist, lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI', 
                TH_tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J)
        T_H_new = np.array(list(tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1),(1,S,J)), np.tile(wnew[:T].reshape(T, 1, 1),(1,S,J)),
               bmat_s, n_mat[:T,:,:], BQnew[:T].reshape(T, 1, J), factor, T_H_params)) + [T_Hss] * S)

        w[:T] = utils.convex_combo(wnew[:T], w[:T], nu)
        r[:T] = utils.convex_combo(rnew[:T], r[:T], nu)
        BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu)
        T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[: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.all() != 0:
            TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(
                utils.pct_diff_func(wnew[:T], w[:T])) + list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max()
        else:
            TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) + list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) + list(
                utils.pct_diff_func(wnew[:T], w[:T])) + list(np.abs(T_H_new[:T], T_H[: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 '\tIteration:', TPIiter
        print '\t\tDistance:', TPIdist

    if ((TPIiter >= maxiter) or (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS :
        raise RuntimeError("Transition path equlibrium not found")


    Y[:T] = Ynew


    # Solve HH problem in inner loop
    guesses = (guesses_b, guesses_n)
    outer_loop_vars = (r, w, K, BQ, T_H)
    inner_loop_params = (income_tax_params, tpi_params, initial_values, theta, ind)
    euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params)
    b_mat[0, :, :] = initial_b

    K_params = (omega[:T].reshape(T, S, 1), lambdas.reshape(1, 1, J), g_n_vector[:T], 'TPI')
    K[:T] = household.get_K(b_mat[:T], K_params) # this is what old code does, but it's strange - why use 
    # b_mat -- what is going on with initial period, etc.

    etr_params_path = np.zeros((T,S,J,etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        etr_params_path[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))
    tax_path_params = (np.tile(e.reshape(1, S, J),(T,1,1)), BQ_dist, lambdas, 'TPI', retire, etr_params_path, h_wealth, 
                       p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S)
    tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1),(1,S,J)), np.tile(w[:T].reshape(T, 1, 1),(1,S,J)), bmat_s, 
                               n_mat[:T,:,:], BQ[:T, :].reshape(T, 1, J), factor, T_H[:T].reshape(T, 1, 1), None, False, tax_path_params) 

    cons_params = (e.reshape(1, S, J), BQ_dist, lambdas.reshape(1, 1, J), g_y)
    c_path = household.get_cons(omega[:T].reshape(T,S,1), r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1), bmat_s, bmat_splus1, n_mat[:T,:,:], 
                   BQ[:T].reshape(T, 1, J), tax_path, cons_params)
    C_params = (omega[:T].reshape(T, S, 1), lambdas, 'TPI')
    C = household.get_C(c_path, C_params)
    I_params = (delta, g_y, g_n_vector[:T])
    I = firm.get_I(K[1:T+1], K[:T], I_params)
    print 'Resource Constraint Difference:', Y[:T] - C[:T] - I[:T]


    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, ltilde)

    eul_savings = euler_errors[:, :S, :].max(1).max(1)
    eul_laborleisure = euler_errors[:, S:, :].max(1).max(1)

    print 'Max Euler error, savings: ', eul_savings
    print 'Max Euler error labor supply: ', eul_laborleisure

    if ((np.any(np.absolute(eul_savings) >= mindist_TPI) or
        (np.any(np.absolute(eul_laborleisure) > mindist_TPI)))
        and ENFORCE_SOLUTION_CHECKS):
        raise RuntimeError("Transition path equlibrium not found")

    '''
    ------------------------------------------------------------------------
    Save variables/values so they can be used in other modules
    ------------------------------------------------------------------------
    '''

    output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 
              'T_H': T_H, 'r': r, 'w': w, 'b_mat': b_mat, 'n_mat': n_mat, 
              'c_path': c_path, 'tax_path': tax_path,
              'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure}

    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"))
    
    macro_output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I,
                    'BQ': BQ, 'T_H': T_H, 'r': r, 'w': w, 
                    'tax_path': tax_path}

    # Non-stationary output
    # macro_ns_output = {'K_ns_path': K_ns_path, 'C_ns_path': C_ns_path, 'I_ns_path': I_ns_path,
    #           'L_ns_path': L_ns_path, 'BQ_ns_path': BQ_ns_path,
    #           'rinit': rinit, 'Y_ns_path': Y_ns_path, 'T_H_ns_path': T_H_ns_path,
    #           'w_ns_path': w_ns_path}


    return output, macro_output
Example #16
0
def TP_solutions(winit, rinit, T_H_init, BQinit2, 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):


    '''
    This function returns the solutions for all variables along the time path.

    
    '''

    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

    print 'Computing final solutions'

    # Extend time paths past T
    winit = np.array(list(winit) + list(np.ones(S) * wss))
    rinit = np.array(list(rinit) + list(np.ones(S) * rss))
    T_H_init = np.array(list(T_H_init) + list(np.ones(S) * T_Hss))
    BQinit = np.zeros((T + S, J))
    for j in xrange(J):
        BQinit[:, j] = list(BQinit2[:,j]) + [BQss[j]] * S
    BQinit = np.array(BQinit)

    # Make array of initial guesses
    domain = np.linspace(0, T, T)
    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)


    # initialize array of Euler errors
    euler_errors = np.zeros((T, 2 * S, J))

    # 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, income_tax_params, 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))

            # 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
        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))

    b_mat[0, :, :] = initial_b

    '''
    ------------------------------------------------------------------------
    Generate variables/values so they can be used in other modules
    ------------------------------------------------------------------------
    '''
    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')

    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, :, :]

    # initialize array 
    etr_params_path = np.zeros((T,S,J,etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        etr_params_path[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))

    tax_path_params = J, S, retire, etr_params_path, h_wealth, p_wealth, m_wealth, tau_payroll
    tax_path = tax.total_taxes(np.tile(rinit[:T].reshape(T, 1, 1),(1,S,J)), b_s, np.tile(winit[:T].reshape(T, 1, 1),(1,S,J)), 
                               np.tile(e.reshape(1, S, J),(T,1,1)), n_mat[:T,:,:], BQinit[:T, :].reshape(T, 1, J), lambdas, 
                               factor_ss, T_H_init[:T].reshape(T, 1, 1), None, 'TPI', False, tax_path_params, 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.'
    hh_constraint_params = ltilde
    for t in xrange(T):
        household.constraint_checker_TPI(
            b_mat[t], n_mat[t], c_path[t], t, hh_constraint_params)

    eul_savings = euler_errors[:, :S, :].max(1).max(1)
    eul_laborleisure = euler_errors[:, S:, :].max(1).max(1)

    print 'Max Euler error, savings: ', eul_savings
    print 'Max Euler error labor supply: ', eul_laborleisure

    '''
    ------------------------------------------------------------------------
    Create the unstationarized versions of the paths of macro aggregates
    ------------------------------------------------------------------------
    '''
    # tvec = np.linspace(0, len(C_path), len(C_path))
    # growth_path = np.exp(g_y*tvec)
    # pop_path = np.zeros(len(C_path))
    # for i in range(0,len(C_path)):
    #     pop_path[i] = np.exp(g_n_vector[:i].sum())   # note that this normalizes the pop in the initial period to one

    # growth_pop_path = growth_path*pop_path 

    # C_ns_path = C_path * growth_pop_path
    # K_ns_path = Kinit * growth_pop_path
    # BQ_ns_path = growth_pop_path * BQinit[:T]
    # L_ns_path = Linit * pop_path 
    # T_H_ns_path = T_H_init[:T] * growth_pop_path
    # w_ns_path = winit*growth_path
    # I_ns_path = I_path * growth_pop_path
    # Y_ns_path = Y_path * growth_pop_path 
    


    '''
    ------------------------------------------------------------------------
    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, 'Y_path': Y_path, 'T_H_init': T_H_init,
              'tax_path': tax_path, 'winit': winit}
    
    macro_output = {'Kpath_TPI': Kpath_TPI, 'C_path': C_path, 'I_path': I_path,
              'Lpath_TPI': Lpath_TPI, 'BQpath_TPI': BQpath_TPI,
              'rinit': rinit, 'Y_path': Y_path, 'T_H_init': T_H_init,
              'winit': winit, 'tax_path': tax_path}

    # macro_ns_output = {'K_ns_path': K_ns_path, 'C_ns_path': C_ns_path, 'I_ns_path': I_ns_path,
    #           'L_ns_path': L_ns_path, 'BQ_ns_path': BQ_ns_path,
    #           'rinit': rinit, 'Y_ns_path': Y_ns_path, 'T_H_ns_path': T_H_ns_path,
    #           'w_ns_path': w_ns_path}


    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"))

    tpi_dir = os.path.join(output_dir, "TPI")
    utils.mkdirs(tpi_dir)
    tpi_vars = os.path.join(tpi_dir, "TPI_macro_vars.pkl")
    pickle.dump(macro_output, open(tpi_vars, "wb"))
Example #17
0
def create_tpi_params(**sim_params):

    '''
    ------------------------------------------------------------------------
    Set factor and initial capital stock to SS from baseline
    ------------------------------------------------------------------------
    '''
    baseline_ss = os.path.join(sim_params['baseline_dir'], "SS/SS_vars.pkl")
    ss_baseline_vars = pickle.load(open(baseline_ss, "rb"))
    factor = ss_baseline_vars['factor_ss']
    #initial_b = ss_baseline_vars['bssmat_s'] + ss_baseline_vars['BQss']/lambdas
    initial_b = ss_baseline_vars['bssmat_splus1']
    initial_n = ss_baseline_vars['nssmat']

    SS_values = (ss_baseline_vars['Kss'],ss_baseline_vars['Lss'], ss_baseline_vars['rss'], 
                 ss_baseline_vars['wss'], ss_baseline_vars['BQss'], ss_baseline_vars['T_Hss'],
                 ss_baseline_vars['bssmat_splus1'], ss_baseline_vars['nssmat'])

    # Make a vector of all one dimensional parameters, to be used in the
    # following functions
    wealth_tax_params = [sim_params['h_wealth'], sim_params['p_wealth'], sim_params['m_wealth']]
    ellipse_params = [sim_params['b_ellipse'], sim_params['upsilon']]
    chi_params = [sim_params['chi_b_guess'], sim_params['chi_n_guess']]

    N_tilde = sim_params['omega'].sum(1) #this should just be one in each year given how we've constructed omega
    sim_params['omega'] = sim_params['omega'] / N_tilde.reshape(sim_params['T'] + sim_params['S'], 1)

    tpi_params = [sim_params['J'], sim_params['S'], sim_params['T'], sim_params['BQ_dist'], sim_params['BW'], 
                  sim_params['beta'], sim_params['sigma'], sim_params['alpha'], 
                  sim_params['Z'], sim_params['delta'], sim_params['ltilde'], 
                  sim_params['nu'], sim_params['g_y'], sim_params['g_n_vector'], 
                  sim_params['tau_payroll'], sim_params['tau_bq'], sim_params['rho'], sim_params['omega'], N_tilde,
                  sim_params['lambdas'], sim_params['e'], sim_params['retire'], sim_params['mean_income_data'], factor] + \
                  wealth_tax_params + ellipse_params + chi_params
    iterative_params = [sim_params['maxiter'], sim_params['mindist_SS'], sim_params['mindist_TPI']]
    

    J, S, T, BQ_dist, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, e, retire, mean_income_data,\
                  factor, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n = tpi_params

    ## Assumption for tax functions is that policy in last year of BW is 
    # extended permanently
    etr_params_TP = np.zeros((S,T+S,sim_params['etr_params'].shape[2]))
    etr_params_TP[:,:BW,:] = sim_params['etr_params']
    etr_params_TP[:,BW:,:] = np.reshape(sim_params['etr_params'][:,BW-1,:],(S,1,sim_params['etr_params'].shape[2]))

    mtrx_params_TP = np.zeros((S,T+S,sim_params['mtrx_params'].shape[2]))
    mtrx_params_TP[:,:BW,:] = sim_params['mtrx_params']
    mtrx_params_TP[:,BW:,:] = np.reshape(sim_params['mtrx_params'][:,BW-1,:],(S,1,sim_params['mtrx_params'].shape[2]))

    mtry_params_TP = np.zeros((S,T+S,sim_params['mtry_params'].shape[2]))
    mtry_params_TP[:,:BW,:] = sim_params['mtry_params']
    mtry_params_TP[:,BW:,:] = np.reshape(sim_params['mtry_params'][:,BW-1,:],(S,1,sim_params['mtry_params'].shape[2]))

    income_tax_params = (sim_params['analytical_mtrs'], etr_params_TP, mtrx_params_TP, mtry_params_TP)

    '''
    ------------------------------------------------------------------------
    Set other parameters and initial values
    ------------------------------------------------------------------------
    '''
    # Get an initial distribution of capital with the initial population
    # distribution
    K0_params = (omega[0].reshape(S, 1), lambdas, g_n_vector[0], 'SS')
    K0 = household.get_K(initial_b, K0_params)

    b_sinit = np.array(list(np.zeros(J).reshape(1, J)) + list(initial_b[:-1]))
    b_splus1init = initial_b
    L0_params = (e, omega[0].reshape(S, 1), lambdas, 'SS')
    L0 = firm.get_L(initial_n, L0_params)
    Y0_params = (alpha, Z)
    Y0 = firm.get_Y(K0, L0, Y0_params)
    w0 = firm.get_w(Y0, L0, alpha)
    r0_params = (alpha, delta)
    r0 = firm.get_r(Y0, K0, r0_params)

    BQ0_params = (omega[0].reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS')
    BQ0 = household.get_BQ(r0, initial_b, BQ0_params)

    theta_params = (e, J, omega[0].reshape(S, 1), lambdas)
    theta = tax.replacement_rate_vals(initial_n, w0, factor, theta_params)

    T_H_params = (e, BQ_dist, lambdas, omega[0].reshape(S, 1), 'SS', etr_params_TP[:,0,:], 
                    theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J)
    T_H_0 = tax.get_lump_sum(r0, w0, b_sinit, initial_n, BQ0, factor, T_H_params)

    etr_params_3D = np.tile(np.reshape(etr_params_TP[:,0,:],(S,1,etr_params_TP.shape[2])),(1,J,1))
    tax0_params = (e, BQ_dist, lambdas, 'SS', retire, etr_params_3D, h_wealth, p_wealth, m_wealth, 
                    tau_payroll, theta, tau_bq, J, S)
    tax0 = tax.total_taxes(r0, w0, b_sinit, initial_n, BQ0, factor, T_H_0, None, False, tax0_params)

    c0_params = (e, BQ_dist, lambdas.reshape(1, J), g_y)
    c0 = household.get_cons(omega[0].reshape(S, 1), r0, w0, b_sinit, b_splus1init, initial_n, BQ0.reshape(
        1, J), tax0, c0_params)

    initial_values = (K0, b_sinit, b_splus1init, L0, Y0,
            w0, r0, BQ0, T_H_0, factor, tax0, c0, initial_b, initial_n)

    return (income_tax_params, tpi_params, iterative_params, initial_values, SS_values)
Example #18
0
def run_TPI(income_tax_params, tpi_params, iterative_params,
            initial_values, SS_values, fix_transfers=False,
            output_dir="./OUTPUT"):

    # unpack tuples of parameters
    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    maxiter, mindist_SS, mindist_TPI = iterative_params
    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_vector, tau_payroll, tau_bq, rho, omega, N_tilde, lambdas, imm_rates, e, retire, mean_income_data,\
                  factor, T_H_baseline, h_wealth, p_wealth, m_wealth, b_ellipse, upsilon, chi_b, chi_n, theta = tpi_params
    K0, b_sinit, b_splus1init, factor, initial_b, initial_n, omega_S_preTP = initial_values
    Kss, Lss, rss, wss, BQss, T_Hss, Gss, bssmat_splus1, nssmat = SS_values


    TPI_FIG_DIR = output_dir
    # Initialize guesses at time paths
    domain = np.linspace(0, T, T)
    r = np.ones(T + S) * rss
    BQ = np.zeros((T + S, J))
    BQ0_params = (omega_S_preTP.reshape(S, 1), lambdas, rho.reshape(S, 1), g_n_vector[0], 'SS')
    BQ0 = household.get_BQ(r[0], initial_b, BQ0_params)
    for j in xrange(J):
        BQ[:, j] = list(np.linspace(BQ0[j], BQss[j], T)) + [BQss[j]] * S
    BQ = np.array(BQ)
    # print "BQ values = ", BQ[0, :], BQ[100, :], BQ[-1, :], BQss
    # print "K0 vs Kss = ", K0-Kss

    if fix_transfers:
        T_H = T_H_baseline
    else:
        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(T + S) * T_Hss2 * (r/rss)
    G = np.ones(T + S) * Gss
    # # print "T_H values = ", T_H[0], T_H[100], T_H[-1], T_Hss
    # # print "omega diffs = ", (omega_S_preTP-omega[-1]).max(), (omega[10]-omega[-1]).max()
    #
    # Make array of initial guesses for labor supply and savings
    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)
    # print 'diff btwn start and end b: ', (guesses_b[0]-guesses_b[-1]).max()
    #
    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)
    # # print 'diff btwn start and end n: ', (guesses_n[0]-guesses_n[-1]).max()
    #
    # # find economic aggregates
    K = np.zeros(T+S)
    L = np.zeros(T+S)
    K[0] = K0
    K_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T-1].reshape(T-1,S,1), g_n_vector[1:T], 'TPI')
    K[1:T] = household.get_K(guesses_b[:T-1], K_params)
    K[T:] = Kss
    L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI')
    L[:T] = firm.get_L(guesses_n[:T], L_params)
    L[T:] = Lss
    Y_params = (alpha, Z)
    Y = firm.get_Y(K, L, Y_params)
    r_params = (alpha, delta)
    r[:T] = firm.get_r(Y[:T], K[:T], r_params)

    # uncomment lines below if want to use starting values from prior run
    r = TPI_START_VALUES['r']
    K = TPI_START_VALUES['K']
    L = TPI_START_VALUES['L']
    Y = TPI_START_VALUES['Y']
    T_H = TPI_START_VALUES['T_H']
    BQ = TPI_START_VALUES['BQ']
    G = TPI_START_VALUES['G']

    guesses_b = TPI_START_VALUES['b_mat']
    guesses_n = TPI_START_VALUES['n_mat']


    TPIiter = 0
    TPIdist = 10
    PLOT_TPI = False

    euler_errors = np.zeros((T, 2 * S, J))
    TPIdist_vec = np.zeros(maxiter)

    # print 'analytical mtrs in tpi = ', analytical_mtrs

    while (TPIiter < maxiter) and (TPIdist >= mindist_TPI):
        # Plot TPI for K for each iteration, so we can see if there is a
        # problem
        if PLOT_TPI is True:
            K_plot = list(K) + list(np.ones(10) * Kss)
            L_plot = list(L) + list(np.ones(10) * Lss)
            plt.figure()
            plt.axhline(
                y=Kss, color='black', linewidth=2, label=r"Steady State $\hat{K}$", ls='--')
            plt.plot(np.arange(
                T + 10), Kpath_plot[:T + 10], 'b', linewidth=2, label=r"TPI time path $\hat{K}_t$")
            plt.savefig(os.path.join(TPI_FIG_DIR, "TPI_K"))


        guesses = (guesses_b, guesses_n)
        w_params = (Z, alpha, delta)
        w = firm.get_w_from_r(r, w_params)
        # print 'r and rss diff = ', r-rss
        # print 'w and wss diff = ', w-wss
        # print 'BQ and BQss diff = ', BQ-BQss
        # print 'T_H and T_Hss diff = ', T_H - T_Hss
        # print 'guess b and bss = ', (bssmat_splus1 - guesses_b).max()
        # print 'guess n and nss = ', (nssmat - guesses_n).max()
        outer_loop_vars = (r, w, BQ, T_H)
        inner_loop_params = (income_tax_params, tpi_params, initial_values, ind)

        # Solve HH problem in inner loop
        euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params)

        # print 'guess b and bss = ', (b_mat - guesses_b).max()
        # print 'guess n and nss over time = ', (n_mat - guesses_n).max(axis=2).max(axis=1)
        # print 'guess n and nss over age = ', (n_mat - guesses_n).max(axis=0).max(axis=1)
        # print 'guess n and nss over ability = ', (n_mat - guesses_n).max(axis=0).max(axis=0)
        # quit()

        print 'Max Euler error: ', (np.abs(euler_errors)).max()

        bmat_s = np.zeros((T, S, J))
        bmat_s[0, 1:, :] = initial_b[:-1, :]
        bmat_s[1:, 1:, :] = b_mat[:T-1, :-1, :]
        bmat_splus1 = np.zeros((T, S, J))
        bmat_splus1[:, :, :] = b_mat[:T, :, :]

        K[0] = K0
        K_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J),
                    imm_rates[:T-1].reshape(T-1, S, 1), g_n_vector[1:T], 'TPI')
        K[1:T] = household.get_K(bmat_splus1[:T-1], K_params)
        L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1),
                    lambdas.reshape(1, 1, J), 'TPI')
        L[:T] = firm.get_L(n_mat[:T], L_params)
        # print 'K diffs = ', K-K0
        # print 'L diffs = ', L-L[0]

        Y_params = (alpha, Z)
        Ynew = firm.get_Y(K[:T], L[:T], Y_params)
        r_params = (alpha, delta)
        rnew = firm.get_r(Ynew[:T], K[:T], r_params)
        wnew = firm.get_w_from_r(rnew, w_params)

        omega_shift = np.append(omega_S_preTP.reshape(1, S),
                                omega[:T-1, :], axis=0)
        BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J),
                     rho.reshape(1, S, 1), g_n_vector[:T].reshape(T, 1), 'TPI')
        # b_mat_shift = np.append(np.reshape(initial_b, (1, S, J)),
        #                         b_mat[:T-1, :, :], axis=0)
        b_mat_shift = bmat_splus1[:T, :, :]
        # print 'b diffs = ', (bmat_splus1[100, :, :] - initial_b).max(), (bmat_splus1[0, :, :] - initial_b).max(), (bmat_splus1[1, :, :] - initial_b).max()
        # print 'r diffs = ', rnew[1]-r[1], rnew[100]-r[100], rnew[-1]-r[-1]
        BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift,
                                 BQ_params)
        BQss2 = np.empty(J)
        for j in range(J):
            BQss_params = (omega[1, :], lambdas[j], rho, g_n_vector[1], 'SS')
            BQss2[j] = household.get_BQ(rnew[1], bmat_splus1[1, :, j],
                                        BQss_params)
        # print 'BQ test = ', BQss2-BQss, BQss-BQnew[1], BQss-BQnew[100], BQss-BQnew[-1]

        total_tax_params = np.zeros((T, S, J, etr_params.shape[2]))
        for i in range(etr_params.shape[2]):
            total_tax_params[:, :, :, i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))

        tax_receipt_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI',
                total_tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J)
        net_tax_receipts = np.array(list(tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1),(1,S,J)), np.tile(wnew[:T].reshape(T, 1, 1),(1,S,J)),
               bmat_s, n_mat[:T,:,:], BQnew[:T].reshape(T, 1, J), factor, tax_receipt_params)) + [T_Hss] * S)

        r[:T] = utils.convex_combo(rnew[:T], r[:T], nu)
        BQ[:T] = utils.convex_combo(BQnew[:T], BQ[:T], nu)
        if fix_transfers:
            T_H_new = T_H
            G[:T] = net_tax_receipts[:T] - T_H[:T]
        else:
            T_H_new = net_tax_receipts
            T_H[:T] = utils.convex_combo(T_H_new[:T], T_H[:T], nu)
            G[:T] = 0.0

        etr_params_path = np.zeros((T,S,J,etr_params.shape[2]))
        for i in range(etr_params.shape[2]):
            etr_params_path[:,:,:,i] = np.tile(
                np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))
        tax_path_params = (np.tile(e.reshape(1, S, J),(T,1,1)),
                           lambdas, 'TPI', retire, etr_params_path, h_wealth,
                           p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S)
        b_to_use = np.zeros((T, S, J))
        b_to_use[0, 1:, :] = initial_b[:-1, :]
        b_to_use[1:, 1:, :] = b_mat[:T-1, :-1, :]
        tax_path = tax.total_taxes(
            np.tile(r[:T].reshape(T, 1, 1),(1,S,J)),
            np.tile(w[:T].reshape(T, 1, 1),(1,S,J)), b_to_use,
            n_mat[:T,:,:], BQ[:T, :].reshape(T, 1, J), factor,
            T_H[:T].reshape(T, 1, 1), None, False, tax_path_params)

        y_path = (np.tile(r[:T].reshape(T, 1, 1), (1, S, J)) * b_to_use[:T, :, :] +
                  np.tile(w[:T].reshape(T, 1, 1), (1, S, J)) *
                  np.tile(e.reshape(1, S, J), (T, 1, 1)) * n_mat[:T, :, :])
        cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y)
        c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1), b_to_use[:T,:,:], b_mat[:T,:,:], n_mat[:T,:,:],
                       BQ[:T].reshape(T, 1, J), tax_path, cons_params)


        guesses_b = utils.convex_combo(b_mat, guesses_b, nu)
        guesses_n = utils.convex_combo(n_mat, guesses_n, nu)
        if T_H.all() != 0:
            TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) +
                               list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) +
                               list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max()
            print 'r dist = ', np.array(list(utils.pct_diff_func(rnew[:T], r[:T]))).max()
            print 'BQ dist = ', np.array(list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten())).max()
            print 'T_H dist = ', np.array(list(utils.pct_diff_func(T_H_new[:T], T_H[:T]))).max()
            print 'T_H path = ', T_H[:20]
            # print 'r old = ', r[:T]
            # print 'r new = ', rnew[:T]
            # print 'K old = ', K[:T]
            # print 'L old = ', L[:T]
            # print 'income = ', y_path[:, :, -1]
            # print 'taxes = ', tax_path[:, :, -1]
            # print 'labor supply = ', n_mat[:, :, -1]
            # print 'max and min labor = ', n_mat.max(), n_mat.min()
            # print 'max and min labor = ', np.argmax(n_mat), np.argmin(n_mat)
            # print 'max and min labor, j = 7 = ', n_mat[:,:,-1].max(), n_mat[:,:,-1].min()
            # print 'max and min labor, j = 6 = ', n_mat[:,:,-2].max(), n_mat[:,:,-2].min()
            # print 'max and min labor, j = 5 = ', n_mat[:,:,4].max(), n_mat[:,:,4].min()
            # print 'max and min labor, j = 4 = ', n_mat[:,:,3].max(), n_mat[:,:,3].min()
            # print 'max and min labor, j = 3 = ', n_mat[:,:,2].max(), n_mat[:,:,2].min()
            # print 'max and min labor, j = 2 = ', n_mat[:,:,1].max(), n_mat[:,:,1].min()
            # print 'max and min labor, j = 1 = ', n_mat[:,:,0].max(), n_mat[:,:,0].min()
            # print 'max and min labor, S = 80 = ', n_mat[:,-1,-1].max(), n_mat[:,-1,-1].min()
            # print "number  > 1 = ", (n_mat > 1).sum()
            # print "number  < 0, = ", (n_mat < 0).sum()
            # print "number  > 1, j=7 = ", (n_mat[:T,:,-1] > 1).sum()
            # print "number  < 0, j=7 = ", (n_mat[:T,:,-1] < 0).sum()
            # print "number  > 1, s=80, j=7 = ", (n_mat[:T,-1,-1] > 1).sum()
            # print "number  < 0, s=80, j=7 = ", (n_mat[:T,-1,-1] < 0).sum()
            # print "number  > 1, j= 7, age 80= ", (n_mat[:T,-1,-1] > 1).sum()
            # print "number  < 0, j = 7, age 80= ", (n_mat[:T,-1,-1] < 0).sum()
            # print "number  > 1, j= 7, age 80, period 0 to 10= ", (n_mat[:30,-1,-1] > 1).sum()
            # print "number  < 0, j = 7, age 80, period 0 to 10= ", (n_mat[:30,-1,-1] < 0).sum()
            # print "number  > 1, j= 7, age 70-79, period 0 to 10= ", (n_mat[:30,70:80,-1] > 1).sum()
            # print "number  < 0, j = 7, age 70-79, period 0 to 10= ", (n_mat[:30,70:80   ,-1] < 0).sum()
            # diag_dict = {'n_mat': n_mat, 'b_mat': b_mat, 'y_path': y_path, 'c_path': c_path}
            # pickle.dump(diag_dict, open('tpi_iter1.pkl', 'wb'))

        else:
            TPIdist = np.array(list(utils.pct_diff_func(rnew[:T], r[:T])) +
                               list(utils.pct_diff_func(BQnew[:T], BQ[:T]).flatten()) +
                               list(np.abs(T_H_new[:T]-T_H[: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 '\tIteration:', TPIiter
        print '\t\tDistance:', TPIdist

    Y[:T] = Ynew


    # Solve HH problem in inner loop
    guesses = (guesses_b, guesses_n)
    outer_loop_vars = (r, w, BQ, T_H)
    inner_loop_params = (income_tax_params, tpi_params, initial_values, ind)
    euler_errors, b_mat, n_mat = inner_loop(guesses, outer_loop_vars, inner_loop_params)

    bmat_s = np.zeros((T, S, J))
    bmat_s[0, 1:, :] = initial_b[:-1, :]
    bmat_s[1:, 1:, :] = b_mat[:T-1, :-1, :]
    bmat_splus1 = np.zeros((T, S, J))
    bmat_splus1[:, :, :] = b_mat[:T, :, :]

    K[0] = K0
    K_params = (omega[:T-1].reshape(T-1, S, 1), lambdas.reshape(1, 1, J), imm_rates[:T-1].reshape(T-1,S,1), g_n_vector[1:T], 'TPI')
    K[1:T] = household.get_K(bmat_splus1[:T-1], K_params)
    L_params = (e.reshape(1, S, J), omega[:T, :].reshape(T, S, 1), lambdas.reshape(1, 1, J), 'TPI')
    L[:T]  = firm.get_L(n_mat[:T], L_params)

    Y_params = (alpha, Z)
    Ynew = firm.get_Y(K[:T], L[:T], Y_params)
    r_params = (alpha, delta)
    rnew = firm.get_r(Ynew[:T], K[:T], r_params)
    wnew = firm.get_w_from_r(rnew, w_params)

    omega_shift = np.append(omega_S_preTP.reshape(1,S),omega[:T-1,:],axis=0)
    BQ_params = (omega_shift.reshape(T, S, 1), lambdas.reshape(1, 1, J), rho.reshape(1, S, 1),
                 g_n_vector[:T].reshape(T, 1), 'TPI')
    b_mat_shift = np.append(np.reshape(initial_b,(1,S,J)),b_mat[:T-1,:,:],axis=0)
    BQnew = household.get_BQ(rnew[:T].reshape(T, 1), b_mat_shift, BQ_params)

    total_tax_params = np.zeros((T,S,J,etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        total_tax_params[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))

    tax_receipt_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas.reshape(1, 1, J), omega[:T].reshape(T, S, 1), 'TPI',
            total_tax_params, theta, tau_bq, tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J)
    net_tax_receipts = np.array(list(tax.get_lump_sum(np.tile(rnew[:T].reshape(T, 1, 1),(1,S,J)), np.tile(wnew[:T].reshape(T, 1, 1),(1,S,J)),
           bmat_s, n_mat[:T,:,:], BQnew[:T].reshape(T, 1, J), factor, tax_receipt_params)) + [T_Hss] * S)

    if fix_transfers:
        G[:T] = net_tax_receipts[:T] - T_H[:T]
    else:
        T_H[:T] = net_tax_receipts[:T]
        G[:T] = 0.0

    etr_params_path = np.zeros((T,S,J,etr_params.shape[2]))
    for i in range(etr_params.shape[2]):
        etr_params_path[:,:,:,i] = np.tile(np.reshape(np.transpose(etr_params[:,:T,i]),(T,S,1)),(1,1,J))
    tax_path_params = (np.tile(e.reshape(1, S, J),(T,1,1)), lambdas, 'TPI', retire, etr_params_path, h_wealth,
                       p_wealth, m_wealth, tau_payroll, theta, tau_bq, J, S)
    tax_path = tax.total_taxes(np.tile(r[:T].reshape(T, 1, 1),(1,S,J)), np.tile(w[:T].reshape(T, 1, 1),(1,S,J)), bmat_s,
                               n_mat[:T,:,:], BQ[:T, :].reshape(T, 1, J), factor, T_H[:T].reshape(T, 1, 1), None, False, tax_path_params)

    cons_params = (e.reshape(1, S, J), lambdas.reshape(1, 1, J), g_y)
    c_path = household.get_cons(r[:T].reshape(T, 1, 1), w[:T].reshape(T, 1, 1), bmat_s, bmat_splus1, n_mat[:T,:,:],
                   BQ[:T].reshape(T, 1, J), tax_path, cons_params)
    C_params = (omega[:T].reshape(T, S, 1), lambdas, 'TPI')
    C = household.get_C(c_path, C_params)
    I_params = (delta, g_y, omega[:T].reshape(T, S, 1), lambdas, imm_rates[:T].reshape(T, S, 1), g_n_vector[1:T+1], 'TPI')
    I = firm.get_I(bmat_splus1[:T], K[1:T+1], K[:T], I_params)
    rc_error = Y[:T] - C[:T] - I[:T] - G[:T]
    print 'Resource Constraint Difference:', rc_error

    # compute utility
    u_params = (sigma, np.tile(chi_n.reshape(1, S, 1), (T, 1, J)),
                b_ellipse, ltilde, upsilon,
                np.tile(rho.reshape(1, S, 1), (T, 1, J)),
                np.tile(chi_b.reshape(1, 1, J), (T, S, 1)))
    utility_path = household.get_u(c_path[:T, :, :], n_mat[:T, :, :],
                                   bmat_splus1[:T, :, :], u_params)

    # compute before and after-tax income
    y_path = (np.tile(r[:T].reshape(T, 1, 1), (1, S, J)) * bmat_s[:T, :, :] +
              np.tile(w[:T].reshape(T, 1, 1), (1, S, J)) *
              np.tile(e.reshape(1, S, J), (T, 1, 1)) * n_mat[:T, :, :])
    inctax_params = (np.tile(e.reshape(1, S, J), (T, 1, 1)), etr_params_path)
    y_aftertax_path = (y_path -
                       tax.tau_income(np.tile(r[:T].reshape(T, 1, 1), (1, S, J)),
                                      np.tile(w[:T].reshape(T, 1, 1), (1, S, J)),
                                      bmat_s[:T,:,:], n_mat[:T,:,:], factor, inctax_params))

    # compute after-tax wealth
    wtax_params = (h_wealth, p_wealth, m_wealth)
    b_aftertax_path = bmat_s[:T,:,:] - tax.tau_wealth(bmat_s[:T,:,:], wtax_params)

    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, ltilde)

    eul_savings = euler_errors[:, :S, :].max(1).max(1)
    eul_laborleisure = euler_errors[:, 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, 'K': K, 'L': L, 'C': C, 'I': I, 'BQ': BQ, 'G': G,
              'T_H': T_H, 'r': r, 'w': w, 'b_mat': b_mat, 'n_mat': n_mat,
              'c_path': c_path, 'tax_path': tax_path, 'bmat_s': bmat_s,
              'utility_path': utility_path, 'b_aftertax_path': b_aftertax_path,
              'y_aftertax_path': y_aftertax_path, 'y_path': y_path,
              'eul_savings': eul_savings, 'eul_laborleisure': eul_laborleisure}

    macro_output = {'Y': Y, 'K': K, 'L': L, 'C': C, 'I': I,
                    'BQ': BQ, 'G': G, 'T_H': T_H, 'r': r, 'w': w,
                    'tax_path': tax_path}


    # if ((TPIiter >= maxiter) or (np.absolute(TPIdist) > mindist_TPI)) and ENFORCE_SOLUTION_CHECKS :
    #     raise RuntimeError("Transition path equlibrium not found")
    #
    # if ((np.any(np.absolute(rc_error) >= 1e-6))
    #     and ENFORCE_SOLUTION_CHECKS):
    #     raise RuntimeError("Transition path equlibrium not found")
    #
    # if ((np.any(np.absolute(eul_savings) >= mindist_TPI) or
    #     (np.any(np.absolute(eul_laborleisure) > mindist_TPI)))
    #     and ENFORCE_SOLUTION_CHECKS):
    #     raise RuntimeError("Transition path equlibrium not found")

    return output, macro_output