Example #1
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 #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['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 #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 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 #6
0
def inner_loop(outer_loop_vars, params, baseline, baseline_spending=False):
    '''
    This function solves for the inner loop of
    the SS.  That is, given the guesses of the
    outer loop variables (r, w, Y, factor)
    this function solves the households'
    problems in the SS.

    Inputs:
        r          = [T,] vector, interest rate
        w          = [T,] vector, wage rate
        b          = [T,S,J] array, wealth holdings
        n          = [T,S,J] array, labor supply
        BQ         = [T,J] vector,  bequest amounts
        factor     = scalar, model income scaling factor
        Y        = [T,] vector, lump sum transfer amount(s)


    Functions called:
        euler_equation_solver()
        household.get_K()
        firm.get_L()
        firm.get_Y()
        firm.get_r()
        firm.get_w()
        household.get_BQ()
        tax.replacement_rate_vals()
        tax.revenue()

    Objects in function:


    Returns: euler_errors, bssmat, nssmat, new_r, new_w
             new_T_H, new_factor, new_BQ

    '''

    # unpack variables and parameters pass to function
    ss_params, income_tax_params, chi_params, small_open_params = params
    J, S, T, BW, beta, sigma, alpha, gamma, epsilon, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, tau_bq, rho, omega_SS, budget_balance, \
                  alpha_T, debt_ratio_ss, tau_b, delta_tau,\
                  lambdas, imm_rates, e, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    chi_b, chi_n = chi_params

    small_open, ss_firm_r, ss_hh_r = small_open_params
    if budget_balance:
        bssmat, nssmat, r, w, T_H, factor = outer_loop_vars
    else:
        bssmat, nssmat, r, w, Y, T_H, factor = outer_loop_vars

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



    for j in xrange(J):
        # Solve the euler equations
        if j == 0:
            guesses = np.append(bssmat[:, j], nssmat[:, j])
        else:
            guesses = np.append(bssmat[:, j-1], nssmat[:, j-1])
        euler_params = [r, w, T_H, factor, j, J, S, beta, sigma, ltilde, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\
                  j, chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\
                  analytical_mtrs, etr_params, mtrx_params,\
                  mtry_params]

        [solutions, infodict, ier, message] = opt.fsolve(euler_equation_solver, guesses * .9,
                                   args=euler_params, xtol=MINIMIZER_TOL, full_output=True)

        euler_errors[:,j] = infodict['fvec']
      #  print 'Max Euler errors: ', np.absolute(euler_errors[:,j]).max()

        bssmat[:, j] = solutions[:S]
        nssmat[:, j] = solutions[S:]

    L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS')
    L = firm.get_L(nssmat, L_params)
    if small_open == False:
        K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), imm_rates, g_n_ss, 'SS')
        B = household.get_K(bssmat, K_params)
        if budget_balance:
            K = B
        else:
            K = B - debt_ratio_ss*Y
    else:
        K_params = (Z, gamma, epsilon, delta, tau_b, delta_tau)
        K = firm.get_K(L, ss_firm_r, K_params)
    # Y_params = (alpha, Z)
    Y_params = (Z, gamma, epsilon)
    new_Y = firm.get_Y(K, L, Y_params)
    #print 'inner K, L, Y: ', K, L, new_Y
    if budget_balance:
        Y = new_Y
    if small_open == False:
        r_params = (Z, gamma, epsilon, delta, tau_b, delta_tau)
        new_r = firm.get_r(Y, K, r_params)
    else:
        new_r = ss_hh_r
    w_params = (Z, gamma, epsilon)
    new_w = firm.get_w(Y, L, w_params)
    print 'inner factor prices: ', new_r, new_w

    b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
    average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                            omega_SS.reshape(S, 1) *
                            lambdas.reshape(1, J)).sum()
    if baseline:
        new_factor = mean_income_data / average_income_model
    else:
        new_factor = factor

    BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS')
    new_BQ = household.get_BQ(new_r, bssmat, BQ_params)
    theta_params = (e, S, retire)
    theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params)

    if budget_balance:
        T_H_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq,
                          tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J, tau_b, delta_tau)
        new_T_H = tax.revenue(new_r, new_w, b_s, nssmat, new_BQ, new_Y, L, K, factor, T_H_params)
    elif baseline_spending:
        new_T_H = T_H
    else:
        new_T_H = alpha_T*new_Y

    return euler_errors, bssmat, nssmat, new_r, new_w, \
         new_T_H, new_Y, new_factor, new_BQ, average_income_model
Example #7
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 #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 SS_fsolve(guesses, b_guess_init, n_guess_init, chi_n, chi_b, tax_params, params, iterative_params, tau_bq,
              rho, lambdas, weights, e):
    '''
    Solves for the steady state distribution of capital, labor, as well as
    w, r, T_H and the scaling factor, using an iterative method similar to TPI.
    Inputs:
        b_guess_init = guesses for b (SxJ array)
        n_guess_init = guesses for n (SxJ array)
        wguess = guess for wage rate (scalar)
        rguess = guess for rental rate (scalar)
        T_Hguess = guess for lump sum tax (scalar)
        factorguess = guess for scaling factor to dollars (scalar)
        chi_n = chi^n_s (Sx1 array)
        chi_b = chi^b_j (Jx1 array)
        params = list of parameters (list)
        iterative_params = list of parameters that determine the convergence
                           of the while loop (list)
        tau_bq = bequest tax rate (Jx1 array)
        rho = mortality rates (Sx1 array)
        lambdas = ability weights (Jx1 array)
        weights = population weights (Sx1 array)
        e = ability levels (SxJ array)
    Outputs:
        solutions = steady state values of b, n, w, r, factor,
                    T_H ((2*S*J+4)x1 array)
    '''
    
    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = tax_params

    maxiter, mindist_SS = iterative_params
    # Rename the inputs
    w = guesses[0]
    r = guesses[1]
    T_H = guesses[2]
    factor = guesses[3]
    bssmat = b_guess_init
    nssmat = n_guess_init

    # Solve for the steady state levels of b and n, given w, r, T_H and
    # factor
    for j in xrange(J):
        # Solve the euler equations
        if j == 0:
            guesses = np.append(bssmat[:, j], nssmat[:, j])
        else:
            guesses = np.append(bssmat[:, j-1], nssmat[:, j-1])
        args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n, tau_bq, rho,
                 lambdas, weights, e)
        [solutions, infodict, ier, message] = opt.fsolve(Euler_equation_solver, guesses * .9,
                                   args=args_, xtol=1e-13, full_output=True)

        print 'Max Euler errors: ', np.absolute(infodict['fvec']).max()
        
        bssmat[:, j] = solutions[:S]
        nssmat[:, j] = solutions[S:]
        # print np.array(Euler_equation_solver(np.append(bssmat[:, j],
        # nssmat[:, j]), r, w, T_H, factor, j, params, chi_b, chi_n,
        # theta, tau_bq, rho, lambdas, e)).max()

    K = household.get_K(bssmat, weights.reshape(S, 1),
                        lambdas.reshape(1, J), g_n_ss, 'SS')
    L = firm.get_L(e, nssmat, weights.reshape(S, 1),
                   lambdas.reshape(1, J), 'SS')
    Y = firm.get_Y(K, L, params)
    new_r = firm.get_r(Y, K, params)
    new_w = firm.get_w(Y, L, params)
    b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
    average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                            weights.reshape(S, 1) *
                            lambdas.reshape(1, J)).sum()
    new_factor = mean_income_data / average_income_model
    new_BQ = household.get_BQ(new_r, bssmat, weights.reshape(S, 1),
                              lambdas.reshape(1, J), rho.reshape(S, 1),
                              g_n_ss, 'SS')
    theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, e, J,
                                      weights.reshape(S, 1), lambdas)

    new_T_H = tax.get_lump_sum(new_r, b_s, new_w, e, nssmat, new_BQ,
                               lambdas.reshape(1, J), factor,
                               weights.reshape(S, 1), 'SS', etr_params, params, theta,
                               tau_bq)


    error1 = new_w - w
    error2 = new_r - r
    error3 = new_T_H - T_H
    error4 = new_factor - factor
    print 'errors: ', error1, error2, error3, error4
    print 'T_H: ', new_T_H
    print 'factor: ', new_factor

    # Check and punish violations
    if r <= 0:
        error1 += 1e9
    #if r > 1:
    #    error1 += 1e9
    if w <= 0:
        error2 += 1e9

    return [error1, error2, error3, error4]
Example #10
0
def inner_loop(outer_loop_vars, params, baseline):
    '''
    This function solves for the inner loop of
    the SS.  That is, given the guesses of the
    outer loop variables (r, w, T_H, factor)
    this function solves the households'
    problems in the SS.

    Inputs:
        r          = [T,] vector, interest rate
        w          = [T,] vector, wage rate
        b          = [T,S,J] array, wealth holdings
        n          = [T,S,J] array, labor supply
        BQ         = [T,J] vector,  bequest amounts
        factor     = scalar, model income scaling factor
        T_H        = [T,] vector, lump sum transfer amount(s)


    Functions called:
        euler_equation_solver()
        household.get_K()
        firm.get_L()
        firm.get_Y()
        firm.get_r()
        firm.get_w()
        household.get_BQ()
        tax.replacement_rate_vals()
        tax.get_lump_sum()

    Objects in function:


    Returns: euler_errors, bssmat, nssmat, new_r, new_w
             new_T_H, new_factor, new_BQ

    '''

    # unpack variables and parameters pass to function
    bssmat, nssmat, r, w, T_H, BQ, theta, factor = outer_loop_vars
    ss_params, income_tax_params, chi_params = params

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, tau_bq, rho, omega_SS, lambdas, imm_rates, e, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    chi_b, chi_n = chi_params

    # bssmat = START_VALUES['bssmat_splus1']
    # nssmat = START_VALUES['nssmat']
    cssmat = np.zeros((S,J))
    euler_errors = np.zeros((2*S,J))

    for j in xrange(J):
        # Solve the euler equations
        if j == 0:
            b_Sp1_guess = bssmat[-1, j]
        else:
            b_Sp1_guess = bssmat[-1, j-1]*10

        euler_params = [r, w, T_H, BQ, theta, factor, j, J, S, beta, sigma, ltilde, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\
                  j, chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\
                  analytical_mtrs, etr_params, mtrx_params,\
                  mtry_params]

        [solution, infodict, ier, message] = opt.fsolve(lc_error, b_Sp1_guess,
                                     args=euler_params, xtol=MINIMIZER_TOL, full_output=True)
        # [x0, r_out] = opt.bisect(lc_error, -1.0, 10.0, args=euler_params, xtol=MINIMIZER_TOL, full_output=True, disp=False)
        print 'j = ', j
        print 'b[0] error = ', infodict['fvec']
        print 'message: ', message
        # print 'b[S]= ', x0
        # print 'converged= ', r_out.converged

        b_out, nssmat[:, j], cssmat[:, j] = lifecycle_solver(solution,euler_params)
        bssmat[:, j] = b_out[1:]
        # print solutions
        # quit()
        #
        # euler_errors[:,j] = infodict['fvec']
        # print 'j = ', j
        # print 'Max Euler errors: ', np.absolute(euler_errors[:,j]).max()
    # print 'bssmat: ', bssmat
    # print 'nssmat: ', nssmat
    # print 'cssmat: ', cssmat
    quit()
    K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), imm_rates, g_n_ss, 'SS')
    K = household.get_K(bssmat, K_params)
    L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS')
    L = firm.get_L(nssmat, L_params)
    Y_params = (alpha, Z)
    Y = firm.get_Y(K, L, Y_params)
    r_params = (alpha, delta)
    new_r = firm.get_r(Y, K, r_params)
    new_w = firm.get_w(Y, L, alpha)
    b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
    average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                            omega_SS.reshape(S, 1) *
                            lambdas.reshape(1, J)).sum()
    if baseline:
        new_factor = mean_income_data / average_income_model
    else:
        new_factor = factor

    BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS')
    new_BQ = household.get_BQ(new_r, bssmat, BQ_params)
    theta_params = (e, S, J, omega_SS.reshape(S, 1), lambdas,retire)
    new_theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params)

    T_H_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq,
                      tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J)
    new_T_H = tax.get_lump_sum(new_r, new_w, b_s, nssmat, new_BQ, factor, T_H_params)

    print 'Inner Loop Max Euler Error: ', (np.absolute(euler_errors)).max()
    # print 'K: ', K
    # print 'L: ', L
    #print 'bssmat: ', bssmat
    return euler_errors, bssmat, nssmat, new_r, new_w, \
             new_T_H, new_BQ, new_theta, new_factor, average_income_model
Example #11
0
def SS_solver(b_guess_init, n_guess_init, wguess, rguess, T_Hguess,
              factorguess, chi_n, chi_b, tax_params, params, iterative_params, tau_bq,
              rho, lambdas, weights, e, fsolve_flag=False):
    '''
    Solves for the steady state distribution of capital, labor, as well as
    w, r, T_H and the scaling factor, using an iterative method similar to TPI.
    Inputs:
        b_guess_init = guesses for b (SxJ array)
        n_guess_init = guesses for n (SxJ array)
        wguess = guess for wage rate (scalar)
        rguess = guess for rental rate (scalar)
        T_Hguess = guess for lump sum tax (scalar)
        factorguess = guess for scaling factor to dollars (scalar)
        chi_n = chi^n_s (Sx1 array)
        chi_b = chi^b_j (Jx1 array)
        params = list of parameters (list)
        iterative_params = list of parameters that determine the convergence
                           of the while loop (list)
        tau_bq = bequest tax rate (Jx1 array)
        rho = mortality rates (Sx1 array)
        lambdas = ability weights (Jx1 array)
        weights = population weights (Sx1 array)
        e = ability levels (SxJ array)
    Outputs:
        solutions = steady state values of b, n, w, r, factor,
                    T_H ((2*S*J+4)x1 array)
    '''
    
    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = tax_params

    maxiter, mindist_SS = iterative_params
    # Rename the inputs
    w = wguess
    r = rguess
    T_H = T_Hguess
    factor = factorguess
    bssmat = b_guess_init
    nssmat = n_guess_init

    dist = 10
    iteration = 0
    dist_vec = np.zeros(maxiter)

    if fsolve_flag == True:
        maxiter = 1 


    while (dist > mindist_SS) and (iteration < maxiter):
        # Solve for the steady state levels of b and n, given w, r, T_H and
        # factor
        for j in xrange(J):
            # Solve the euler equations
            if j == 0:
                guesses = np.append(bssmat[:, j], nssmat[:, j])
            else:
                guesses = np.append(bssmat[:, j-1], nssmat[:, j-1])

            args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n, tau_bq, rho,
                     lambdas, weights, e)
            [solutions, infodict, ier, message] = opt.fsolve(Euler_equation_solver, guesses * .9,
                                   args=args_, xtol=1e-13, full_output=True)

            print 'Max Euler errors: ', np.absolute(infodict['fvec']).max()

            bssmat[:, j] = solutions[:S]
            nssmat[:, j] = solutions[S:]
            # print np.array(Euler_equation_solver(np.append(bssmat[:, j],
            # nssmat[:, j]), r, w, T_H, factor, j, params, chi_b, chi_n,
            # theta, tau_bq, rho, lambdas, e)).max()

        K = household.get_K(bssmat, weights.reshape(S, 1),
                            lambdas.reshape(1, J), g_n_ss, 'SS')
        L = firm.get_L(e, nssmat, weights.reshape(S, 1),
                       lambdas.reshape(1, J), 'SS')
        Y = firm.get_Y(K, L, params)
        new_r = firm.get_r(Y, K, params)
        new_w = firm.get_w(Y, L, params)
        b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
        average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                                weights.reshape(S, 1) *
                                lambdas.reshape(1, J)).sum()
        new_factor = mean_income_data / average_income_model
        new_BQ = household.get_BQ(new_r, bssmat, weights.reshape(S, 1),
                                  lambdas.reshape(1, J), rho.reshape(S, 1),
                                  g_n_ss, 'SS')
        theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, e, J,
                                          weights.reshape(S, 1), lambdas)
        # lump_sum_tax_params = (a_etr_income, b_etr_income, c_etr_income, d_etr_income, 
        #                    e_etr_income, f_etr_income, min_x_etr_income, max_x_etr_income, 
        #                    min_y_etr_income, max_y_etr_income)
        new_T_H = tax.get_lump_sum(new_r, b_s, new_w, e, nssmat, new_BQ,
                                   lambdas.reshape(1, J), factor,
                                   weights.reshape(S, 1), 'SS', etr_params, params, theta,
                                   tau_bq)

        r = utils.convex_combo(new_r, r, nu)
        w = utils.convex_combo(new_w, w, nu)
        factor = utils.convex_combo(new_factor, factor, nu)
        T_H = utils.convex_combo(new_T_H, T_H, nu)
        if T_H != 0:
            dist = np.array([utils.perc_dif_func(new_r, r)] +
                            [utils.perc_dif_func(new_w, w)] +
                            [utils.perc_dif_func(new_T_H, T_H)] +
                            [utils.perc_dif_func(new_factor, factor)]).max()
        else:
            # If T_H is zero (if there are no taxes), a percent difference
            # will throw NaN's, so we use an absoluate difference
            dist = np.array([utils.perc_dif_func(new_r, r)] +
                            [utils.perc_dif_func(new_w, w)] +
                            [abs(new_T_H - T_H)] +
                            [utils.perc_dif_func(new_factor, factor)]).max()
        dist_vec[iteration] = dist
        # Similar to TPI: if the distance between iterations increases, then
        # decrease the value of nu to prevent cycling
        if iteration > 10:
            if dist_vec[iteration] - dist_vec[iteration - 1] > 0:
                nu /= 2.0
                print 'New value of nu:', nu
        iteration += 1
        print "Iteration: %02d" % iteration, " Distance: ", dist

    eul_errors = np.ones(J)
    b_mat = np.zeros((S, J))
    n_mat = np.zeros((S, J))
    # Given the final w, r, T_H and factor, solve for the SS b and n (if you
    # don't do a final fsolve, there will be a slight mismatch,
    # with high euler errors)
    for j in xrange(J):
        guesses = np.append(bssmat[:, j], nssmat[:, j])
        args_ = (r, w, T_H, factor, j, tax_params, params, chi_b, chi_n, tau_bq, rho,
                 lambdas, weights, e)
        [solutions1, infodict, ier, message] = opt.fsolve(Euler_equation_solver, guesses * .9,
                                   args=args_, xtol=1e-13, full_output=True)
        eul_errors[j] = np.array(infodict['fvec']).max()
        print 'Max Euler errors: ', np.absolute(infodict['fvec']).max()
        b_mat[:, j] = solutions1[:S]
        n_mat[:, j] = solutions1[S:]
    print 'SS fsolve euler error:', eul_errors.max()
    solutions = np.append(b_mat.flatten(), n_mat.flatten())
    other_vars = np.array([w, r, factor, T_H])
    solutions = np.append(solutions, other_vars)
    return solutions
Example #12
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 #13
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 #14
0
def inner_loop(outer_loop_vars, params):
    '''
    This function solves for the inner loop of 
    the SS.  That is, given the guesses of the
    outer loop variables (r, w, T_H, factor) 
    this function solves the households' 
    problems in the SS.

    Inputs:
        r          = [T,] vector, interest rate 
        w          = [T,] vector, wage rate 
        b          = [T,S,J] array, wealth holdings 
        n          = [T,S,J] array, labor supply
        BQ         = [T,J] vector,  bequest amounts
        factor     = scalar, model income scaling factor
        T_H        = [T,] vector, lump sum transfer amount(s) 


    Functions called: 
        euler_equation_solver()
        household.get_K()
        firm.get_L()
        firm.get_Y()
        firm.get_r()
        firm.get_w()
        household.get_BQ()
        tax.replacement_rate_vals()
        tax.get_lump_sum()

    Objects in function:


    Returns: euler_errors, bssmat, nssmat, new_r, new_w
             new_T_H, new_factor, new_BQ
    
    '''

    # unpack variables and parameters pass to function
    bssmat, nssmat, r, w, T_H, factor = outer_loop_vars
    ss_params, income_tax_params, chi_params = params 

    J, S, T, BQ_dist, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, tau_bq, rho, omega_SS, lambdas, e, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    chi_b, chi_n = chi_params
    etr_params = np.tile(np.reshape(etr_params,(S,1,etr_params.shape[1])),(1,J,1))
    mtrx_params = np.tile(np.reshape(mtrx_params,(S,1,mtrx_params.shape[1])),(1,J,1))
    mtry_params = np.tile(np.reshape(mtry_params,(S,1,mtry_params.shape[1])),(1,J,1))


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

    
    guesses = np.hstack((bssmat, nssmat))
    euler_params = [r, w, T_H, factor, J, S, BQ_dist, beta, sigma, ltilde, g_y,\
              g_n_ss, tau_payroll, retire, mean_income_data,\
              h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\
              chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\
              analytical_mtrs, etr_params, mtrx_params,\
              mtry_params]

    [solutions, infodict, ier, message] = opt.fsolve(euler_equation_solver, guesses * .9,
                               args=euler_params, xtol=MINIMIZER_TOL, full_output=True)

    euler_errors = infodict['fvec']
    print 'Max Euler errors: ', np.absolute(euler_errors).max()
    euler_errors = euler_errors.reshape(S, 2 *J)
    solutions = solutions.reshape(S, 2*J)
    
    bssmat = solutions[:, :J]
    nssmat = solutions[:, J:]

    K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), g_n_ss, 'SS')
    K = household.get_K(bssmat, K_params)
    L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS')
    L = firm.get_L(nssmat, L_params)
    Y_params = (alpha, Z)
    Y = firm.get_Y(K, L, Y_params)
    r_params = (alpha, delta)
    new_r = firm.get_r(Y, K, r_params)
    new_w = firm.get_w(Y, L, alpha)
    b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
    average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                            omega_SS.reshape(S, 1) *
                            lambdas.reshape(1, J)).sum()
    new_factor = mean_income_data / average_income_model
    BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS')
    new_BQ = household.get_BQ(new_r, bssmat, BQ_params)
    theta_params = (e, J, omega_SS.reshape(S, 1), lambdas)
    theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params)

    T_H_params = (e, BQ_dist, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq,
                      tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J)
    new_T_H = tax.get_lump_sum(new_r, new_w, b_s, nssmat, new_BQ, factor, T_H_params)

    return euler_errors, bssmat, nssmat, new_r, new_w, \
             new_T_H, new_factor, new_BQ, average_income_model
Example #15
0
def inner_loop(outer_loop_vars, params, baseline):
    '''
    This function solves for the inner loop of
    the SS.  That is, given the guesses of the
    outer loop variables (r, w, T_H, factor)
    this function solves the households'
    problems in the SS.

    Inputs:
        r          = [T,] vector, interest rate
        w          = [T,] vector, wage rate
        b          = [T,S,J] array, wealth holdings
        n          = [T,S,J] array, labor supply
        BQ         = [T,J] vector,  bequest amounts
        factor     = scalar, model income scaling factor
        T_H        = [T,] vector, lump sum transfer amount(s)


    Functions called:
        euler_equation_solver()
        household.get_K()
        firm.get_L()
        firm.get_Y()
        firm.get_r()
        firm.get_w()
        household.get_BQ()
        tax.replacement_rate_vals()
        tax.get_lump_sum()

    Objects in function:


    Returns: euler_errors, bssmat, nssmat, new_r, new_w
             new_T_H, new_factor, new_BQ

    '''

    # unpack variables and parameters pass to function
    bssmat, nssmat, r, w, T_H, factor = outer_loop_vars
    ss_params, income_tax_params, chi_params = params

    J, S, T, BW, beta, sigma, alpha, Z, delta, ltilde, nu, g_y,\
                  g_n_ss, tau_payroll, tau_bq, rho, omega_SS, lambdas, imm_rates, e, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon = ss_params

    analytical_mtrs, etr_params, mtrx_params, mtry_params = income_tax_params
    chi_b, chi_n = chi_params

    # bssmat = START_VALUES['bssmat_splus1']
    # nssmat = START_VALUES['nssmat']
    euler_errors = np.zeros((2*S,J))

    for j in xrange(J):
        # Solve the euler equations
        # if j == 0:
        #     guesses = np.append(bssmat[:, j], nssmat[:, j])
        # elif j == J - 1:
        #     guesses = np.append(bssmat[:, j-1]*2.0, nssmat[:, j-1])
        # else:
        #     guesses = np.append(bssmat[:, j-1], nssmat[:, j-1])

        guesses = np.append(bssmat[:, j], nssmat[:, j])

        euler_params = [r, w, T_H, factor, j, J, S, beta, sigma, ltilde, g_y,\
                  g_n_ss, tau_payroll, retire, mean_income_data,\
                  h_wealth, p_wealth, m_wealth, b_ellipse, upsilon,\
                  j, chi_b, chi_n, tau_bq, rho, lambdas, omega_SS, e,\
                  analytical_mtrs, etr_params, mtrx_params,\
                  mtry_params]

        [solutions, infodict, ier, message] = opt.fsolve(euler_equation_solver, guesses * .9,
                                    args=euler_params, xtol=MINIMIZER_TOL, full_output=True)

        euler_errors[:,j] = infodict['fvec']
        bssmat[:, j] = solutions[:S]
        nssmat[:, j] = solutions[S:]
    K_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), imm_rates, g_n_ss, 'SS')
    K = household.get_K(bssmat, K_params)
    L_params = (e, omega_SS.reshape(S, 1), lambdas.reshape(1, J), 'SS')
    L = firm.get_L(nssmat, L_params)
    Y_params = (alpha, Z)
    Y = firm.get_Y(K, L, Y_params)
    r_params = (alpha, delta)
    new_r = firm.get_r(Y, K, r_params)
    new_w = firm.get_w(Y, L, alpha)
    b_s = np.array(list(np.zeros(J).reshape(1, J)) + list(bssmat[:-1, :]))
    average_income_model = ((new_r * b_s + new_w * e * nssmat) *
                            omega_SS.reshape(S, 1) *
                            lambdas.reshape(1, J)).sum()
    if baseline:
        new_factor = mean_income_data / average_income_model
    else:
        new_factor = factor

    BQ_params = (omega_SS.reshape(S, 1), lambdas.reshape(1, J), rho.reshape(S, 1), g_n_ss, 'SS')
    new_BQ = household.get_BQ(new_r, bssmat, BQ_params)
    theta_params = (e, S, retire)
    theta = tax.replacement_rate_vals(nssmat, new_w, new_factor, theta_params)

    T_H_params = (e, lambdas.reshape(1, J), omega_SS.reshape(S, 1), 'SS', etr_params, theta, tau_bq,
                      tau_payroll, h_wealth, p_wealth, m_wealth, retire, T, S, J)
    net_tax_receipts = tax.get_lump_sum(new_r, new_w, b_s, nssmat, new_BQ, factor, T_H_params)

    print 'Inner Loop Max Euler Error: ', (np.absolute(euler_errors)).max()

    return euler_errors, bssmat, nssmat, new_r, new_w, \
             net_tax_receipts, new_factor, new_BQ, average_income_model