Exemplo n.º 1
0
def feasible(bmat, nmat, rpath, args):
    '''
    --------------------------------------------------------------------
    This function checks whether any constraints are violated by
    matrices for savings and labor supply given a time path for interest
    rates
    --------------------------------------------------------------------
    --------------------------------------------------------------------
    '''
    (lambdas, emat, omega_vec, mort_rates, zeta_mat, g_y, l_tilde, g_n_SS, Z,
     gamma, delta) = args
    J = len(lambdas)
    b_feas = bmat > 0.0
    if (bmat <= 0.0).sum() > 0.0:
        err_msg = ('SS ERROR: Some value of initial guess for ' +
                   'bmat_ss is less than or equal to zero. ' +
                   'b_{j,s}<=0 for some j and s.')
        print('b_feas:', b_feas)
        raise RuntimeError(err_msg)
    n_feas = (nmat > 0.0) & (nmat < l_tilde)
    if ((nmat <= 0.0) | (nmat >= l_tilde)).sum() > 0.0:
        err_msg = ('SS ERROR: Some value of initial guess for ' +
                   'nmat_ss is less than or equal to zero or greater ' +
                   'than or equal to l_tilde. n_{j,s}<=0 or ' +
                   'n_{j,s}>=l_tildefor some j and s.')
        print('n_feas:', n_feas)
        raise RuntimeError(err_msg)
    w_params = (Z, gamma, delta)
    wpath = firms.get_w(rpath, w_params)
    b_s_mat = np.vstack((np.zeros(J), bmat[:-1, :]))
    b_sp1_mat = bmat
    BQ_args = (lambdas, omega_vec, mort_rates, g_n_SS)
    BQ = aggr.get_BQ(bmat, rpath, BQ_args)
    c_args = (emat, zeta_mat, lambdas, omega_vec, g_y)
    cmat = get_cons(rpath, wpath, b_s_mat, b_sp1_mat, nmat, BQ, c_args)
    c_feas = cmat > 0.0
    if (cmat <= 0.0).sum() > 0.0:
        err_msg = ('SS ERROR: Some value of initial guess for ' +
                   'bmat_ss or nmat_ss is not feasible because ' +
                   'resulting cmat_ss has a value that is less than ' +
                   'or equal to zero. c_{j,s}<=0 for some j and s.')
        print('c_feas:', c_feas)
        raise RuntimeError(err_msg)

    return b_feas, n_feas, c_feas
Exemplo n.º 2
0
def FOCs(b_sp1, n_s, *args):
    (b_init, BQ, rho_s, omega, g_n, beta, sigma, l_tilde, chi, b_ellipse,
     upsilon, r, w, method) = args
    b_s = np.append(b_init, b_sp1)
    b_sp1 = np.append(b_sp1, 0.0)
    if method == 'SS':
        # if method is SS, solve for BQ, else (case of TPI), use BQ
        # as guessed in the "outer loop"
        BQ_params = (omega, g_n, rho_s)
        BQ = agg.get_BQ(b_s, r, BQ_params, method)
    c = get_c(r, w, n_s, b_s, b_sp1, BQ)
    b_args = (rho_s, beta, sigma, r)
    b_errors = FOC_save(c, b_args)
    n_args = (sigma, w, l_tilde, chi, b_ellipse, upsilon)
    n_errors = FOC_labor(c, n_s, n_args)
    errors = np.append(b_errors, n_errors)

    return errors
Exemplo n.º 3
0
def solve_tp(g_n_path, omega_S_preTP, rho_s, imm_rates_path, omega_SS, omega_path_S, params):
    '''
    Solves for the time path equilibrium using TPI
    '''
    # Missing some elements of params
    b_ss, r_ss, n_s, r_11, alpha, A, delta, beta, sigma, T, S = params
    dist = 8.0
    mindist = 1e-08
    maxiter = 300
    tpi_iter = 0
    xi = 0.2
    while dist > mindist and tpi_iter < maxiter:

        # Define paths
        b_11 = 1.1 * b_ss
        BQ_params = (g_n_path[0], omega_S_preTP, rho_s)
        K_params = (g_n_path[0], omega_S_preTP, imm_rates_path[0, :])
        BQ_11 = agg.get_BQ(b_11, r_11, BQ_params, method = "TPI")
        BQ_ss = agg.get_BQ(b_ss, r_ss, BQ_params, method = "SS")
        K_11 = agg.get_K(b_11, K_params)
        BQpath_init = np.zeros(T + S - 1)
        BQpath_init[:T] = np.linspace(BQ_11, BQ_ss, T)
        BQpath_init[T:] = BQ_ss
        L_ss = agg.get_L(n_s, omega_SS)
        r_11 = firm.get_r(L_ss, K_11, alpha, A, delta)
        # I can't figure out how r_11 and r_path differ
        ''' Is r_11 an initial guess? Depending on how you're defining
        r_11, the arguments passed to the function call above and below
        will vary
        ''' 
        r_path = firm.get_r(L_ss, K_11, alpha, A, delta)
        w_path = firm.get_w(r_path, alpha, A, delta)
        bmat = np.zeros((S - 1, T + S - 1))
        # What is b_1 supposed to be?
        bmat[:, 0] = b_1

        # Solve for households
        for p in range(2, S):
            b_guess = np.diagonal(bmat[S - p:, :p - 1])
            b_init = bmat[S - p - 1, 0]
            b_params = (b_init, n_s[-p:], r_path[:p], w_path[:p],
                        BQpath_init[:p], rho_s[-p:], beta, sigma)
            results_bp = opt.root(hh.FOCs, b_guess, args=(b_params))
            b_solve_p = results_bp.x
            DiagMaskbp = np.eye(p - 1, dtype=bool)
            bmat[S - p:, 1:p] = DiagMaskbp * b_solve_p + bmat[S - p:, 1:p]

        for t in range(1, T + 1):
            b_guess = np.diagonal(bmat[:, t - 1:t + S - 2])
            b_init = 0.0
            b_params = (b_init, n_s, r_path[t - 1:t + S - 1],
                        w_path[t - 1:t + S - 1], BQpath_init[t - 1:t + S - 1],
                        rho_s, beta, sigma)
            results_bt = opt.root(hh.FOCs, b_guess, args=(b_params))
            b_solve_t = results_bt.x
            DiagMaskbt = np.eye(S - 1, dtype=bool)
            bmat[:, t:t + S - 1] = (DiagMaskbt * b_solve_t +
                                    bmat[:, t:t + S - 1])

        new_Kpath = np.zeros(T)
        new_Kpath[0] = K_11
        new_Kpath[1:] = \
            (1 / (omega_path_S[:T - 1, :-1]) *
                bmat[:, 1:T].T +
                imm_rates_path[:T - 1, 1:] *
                omega_path_S[:T - 1, 1:] * bmat[:, 1:T].T).sum(axis=1)
        new_BQpath = np.zeros(T)
        new_BQpath[0] = BQ_11
        new_BQpath[1:] = \
            ((1 + r_path[1:T]) / (rho_s[:-1]) *
                omega_path_S[:T - 1, :-1] * bmat[:, 1:T].T).sum(axis=1)

        dist = ((BQ_init - new_BQ) ** 2).sum()
        BQpath_init[:T] = xi * new_BQpath[:T] + (1 - xi) * BQpath_init[:T]
        # update iteration counter
        tpi_iter += 1

    if tpi_iter < maxiter:
        print('The time path solved! ->', ' iter:', tpi_iter, ', dist: ', dist)
    else:
        print('The time path did not solve.')

    return [new_Kpath, new_BQpath]
Exemplo n.º 4
0
def get_SS(init_vals, args, graphs=False):
    '''
    --------------------------------------------------------------------
    Solve for the steady-state solution of the S-period-lived agent OG
    model with endogenous labor supply using the bisection method in K
    and L for the outer loop
    --------------------------------------------------------------------
    INPUTS:
    init_vals = length 3 tuple, (r_init, c1_init, factor_init)
    args      = length 19 tuple, (J, S, lambdas, emat, beta, sigma,
                l_tilde, b_ellip, upsilon, chi_n_vec_hat, Z, gamma,
                delta, Bsct_Tol, Eul_Tol, xi, maxiter, mean_ydata,
                init_calc)
    graphs    = boolean, =True if output steady-state graphs

    OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION:
        firms.get_r()
        firms.get_w()
        utils.print_time()
        inner_loop()
        creat_graphs()

    OBJECTS CREATED WITHIN FUNCTION:
    start_time    = scalar > 0, clock time at beginning of program
    r_init        = scalar > -delta, initial guess for steady-state
                    interest rate
    c1_init       = (J,) vector, initial guess for first period
                    consumption by all J ability types
    factor_init   = scalar > 0, initial guess for factor that scales
                    model units to data units
    J             = integer >= 1, number of heterogeneous ability groups
    S             = integer in [3, 80], number of periods an individual
                    lives
    lambdas       = (J,) vector, income percentiles for distribution of
                    ability within each cohort
    emat          = (S, J) matrix, lifetime ability profiles for each
                    lifetime income group j
    beta          = scalar in (0,1), discount factor for each model per
    sigma         = scalar > 0, coefficient of relative risk aversion
    l_tilde       = scalar > 0, time endowment of each agent each period
    b_ellip       = scalar > 0, fitted value of b for elliptical
                    disutility of labor
    upsilon       = scalar > 1, fitted value of upsilon for elliptical
                    disutility of labor
    chi_n_vec_hat = (S,) vector, values for chi^n_s hat from data
    Z             = scalar > 0, total factor productivity parameter in
                    firms' production function
    gamma         = scalar in (0,1), capital share of income
    delta         = scalar in [0,1], model-period depreciation rate of
                    capital
    Bsct_Tol      = scalar > 0, tolerance level for outer-loop bisection
                    method
    Eul_Tol       = scalar > 0, tolerance level for inner-loop root
                    finder
    xi            = scalar in (0, 1], SS updating parameter in outer-
                    loop bisection method
    maxiter       = integer >= 1, maximum number of iterations in outer-
                    loop bisection method
    mean_ydata    = scalar > 0, average household income from the data
    init_calc     = boolean, =True if initial steady-state calculation
                    with chi_n_vec = 1 for all s
    iter_SS       = integer >= 0, index of iteration number
    dist          = scalar > 0, distance metric for current iteration
    c1_options    = length 1 dict, options to pass into
                    opt.root(c1_bSp1err,...)
    rw_params     = length 3 tuple, (Z, gamma, delta) args to pass into
                    firms.get_w()
    c1ss_init     = (J,) vector, initial guess for css_{j,1}, updates
                    each iteration
    lambda_mat    = (S, J) matrix, lambdas vector copied down S rows
    w_init        = scalar, initial value for wage
    chi_n_vec     = (S,) vector, chi^n_s values that scale the
                    disutility of labor supply
    inner_args    = length 16 tuple, args to pass into inner_loop()
    K_new         = scalar > 0, updated K given r_init and w_init
    L_new         = scalar > 0, updated L given r_init and w_init
    cmat          = (S, J) matrix, lifetime household consumption by age
                    s and ability j
    nmat          = (S, J) matrix, lifetime household labor supply by
                    age s and ability j
    bmat          = (S, J) matrix, lifetime household savings by age s
                    and ability j (b1, b2,...bS)
    b_Sp1_vec     = (J,) vector, household savings in last period for
                    each ability type, should be arbitrarily close to 0
    r_new         = scalar > 0, updated interest rate given nmat, bmat
    w_new         = scalar > 0, updated wage given nmat and bmat
    n_err_mat     = (S, J) matrix, labor supply Euler errors given
                    r_init and w_init
    b_err_mat     = (S, J) matrix, savings Euler errors given r_init
                    and w_init. First row is identically zeros
    all_errors    = (2JS + J,) vector, (n_errors, b_errors, b_Sp1_vec)
    avg_inc_model = scalar > 0, average household income in model
    factor_new    = scalar > 0, updated factor value given nmat, bmat,
                    r_new, and w_new
    c_ss          = (S, J) matrix, steady-state lifetime consumption
    n_ss          = (S, J) matrix, steady-state lifetime labor supply
    b_ss          = (S, J) matrix, steady-state wealth (savings) at
                    beginning of each period (b1, b2, ...bS)
    b_Sp1_ss      = (J,) vector, steady-state savings in last period of
                    life for all J ability types, approx. 0 in equilbrm
    n_err_ss      = (S, J) matrix, lifetime labor supply Euler errors
    b_err_ss      = (S, J) matrix, lifetime savings Euler errors
    r_ss          = scalar > 0, steady-state interest rate
    w_ss          = scalar > 0, steady-state wage
    K_ss          = scalar > 0, steady-state aggregate capital stock
    L_ss          = scalar > 0, steady-state aggregate labor
    Y_params      = length 2 tuple, (Z, gamma)
    Y_ss          = scalar > 0, steady-state aggregate output (GDP)
    C_ss          = scalar > 0, steady-state aggregate consumption
    RCerr_ss      = scalar, resource constraint error
    ss_time       = scalar, seconds elapsed for steady-state computation
    ss_output     = length 16 dict, steady-state objects {c_ss, n_ss,
                    b_ss, b_Sp1_ss, w_ss, r_ss, K_ss, L_ss, Y_ss, C_ss,
                    n_err_ss, b_err_ss, RCerr_ss, ss_time, chi_n_vec,
                    factor_ss}

    FILES CREATED BY THIS FUNCTION: None

    RETURNS: ss_output
    --------------------------------------------------------------------
    '''
    start_time = time.clock()
    r_init, BQ_init, factor_init, bmat_init, nmat_init = init_vals
    (J, E, S, lambdas, emat, mort_rates, imm_rates, omega_SS, g_n_SS, zeta_mat,
     chi_n_vec_hat, chi_b_vec, beta, sigma, l_tilde, b_ellip, upsilon, g_y, Z,
     gamma, delta, SS_tol_outer, SS_tol_inner, xi, maxiter, mean_ydata,
     init_calc) = args
    iter_SS = 0
    dist = 10
    rw_params = (Z, gamma, delta)
    BQ_args = (lambdas, omega_SS, mort_rates, g_n_SS)
    lambda_mat = np.tile(lambdas.reshape((1, J)), (S, 1))
    omega_mat = np.tile(omega_SS.reshape((S, 1)), (1, J))

    while (iter_SS < maxiter) and (dist >= SS_tol_outer):
        iter_SS += 1
        w_init = firms.get_w(r_init, rw_params)
        if init_calc:
            print('Factor init is one. No modification performed to ' +
                  'chi_n_vec. Dist calculated without factor.')
            chi_n_vec = chi_n_vec_hat
        else:
            chi_n_vec = chi_n_vec_hat * (factor_init**(sigma - 1))

        rpath = r_init * np.ones(S)
        wpath = w_init * np.ones(S)
        BQpath = BQ_init * np.ones(S)
        cnb_args = (S, lambdas, emat, mort_rates, omega_SS, zeta_mat,
                    chi_n_vec, chi_b_vec, beta, sigma, l_tilde, b_ellip,
                    upsilon, g_y, g_n_SS, SS_tol_inner)
        cmat, nmat, bmat, n_err_mat, b_err_mat = \
            hh.get_cnb_mats(bmat_init, nmat_init, np.zeros(J), rpath,
                            wpath, BQpath, cnb_args)
        K_args = (lambdas, omega_SS, imm_rates, g_n_SS)
        K_new, K_cstr = aggr.get_K(bmat, K_args)
        L_args = (emat, lambdas, omega_SS)
        L_new, L_cstr = aggr.get_L(nmat, L_args)
        r_new = firms.get_r(K_new, L_new, rw_params)
        w_new = firms.get_w(r_new, rw_params)
        BQ_new = aggr.get_BQ(bmat, r_new, BQ_args)

        all_errors = \
            np.hstack((b_err_mat.flatten(), n_err_mat.flatten()))
        if init_calc:
            dist = max(np.absolute((r_new - r_init) / r_init),
                       np.absolute((BQ_new - BQ_init) / BQ_init))
        else:
            avg_inc_model = (omega_mat * lambda_mat *
                             (r_new * bmat + w_new * emat * nmat)).sum()
            factor_new = mean_ydata / avg_inc_model
            print('mean_ydata: ', mean_ydata, ', avg_inc_model: ',
                  avg_inc_model)
            print('r_new: ', r_new, 'BQ_new', BQ_new, 'factor_new: ',
                  factor_new)
            dist = max(np.absolute((r_new - r_init) / r_init),
                       np.absolute((BQ_new - BQ_init) / BQ_init),
                       np.absolute((factor_new - factor_init) / factor_init))
            factor_init = xi * factor_new + (1 - xi) * factor_init

        r_init = xi * r_new + (1 - xi) * r_init
        BQ_init = xi * BQ_new + (1 - xi) * BQ_init
        print('SS Iter=', iter_SS, ', SS Dist=', '%10.4e' % (dist),
              ', Max Abs Err=', '%10.4e' % (np.absolute(all_errors).max()))
        bmat_init = bmat
        nmat_init = nmat

    chi_n_vec = chi_n_vec_hat * (factor_init**(sigma - 1))
    c_ss = cmat.copy()
    n_ss = nmat.copy()
    b_ss = bmat.copy()
    n_err_ss = n_err_mat.copy()
    b_err_ss = b_err_mat.copy()
    r_ss = r_new.copy()
    w_ss = w_new.copy()
    BQ_ss = BQ_new.copy()
    K_ss = K_new.copy()
    L_ss = L_new.copy()
    factor_ss = factor_init
    I_args = (lambdas, omega_SS, imm_rates, g_n_SS, g_y, delta)
    I_ss = aggr.get_I(b_ss, I_args)
    NX_args = (lambdas, omega_SS, imm_rates, g_y)
    NX_ss = aggr.get_NX(b_ss, NX_args)
    Y_params = (Z, gamma)
    Y_ss = aggr.get_Y(K_ss, L_ss, Y_params)
    C_args = (lambdas, omega_SS)
    C_ss = aggr.get_C(c_ss, C_args)
    RCerr_ss = Y_ss - C_ss - I_ss - NX_ss

    ss_time = time.clock() - start_time

    ss_output = {
        'c_ss': c_ss,
        'n_ss': n_ss,
        'b_ss': b_ss,
        'BQ_ss': BQ_ss,
        'w_ss': w_ss,
        'r_ss': r_ss,
        'K_ss': K_ss,
        'L_ss': L_ss,
        'I_ss': I_ss,
        'Y_ss': Y_ss,
        'C_ss': C_ss,
        'NX_ss': NX_ss,
        'n_err_ss': n_err_ss,
        'b_err_ss': b_err_ss,
        'RCerr_ss': RCerr_ss,
        'ss_time': ss_time,
        'chi_n_vec': chi_n_vec,
        'factor_ss': factor_ss
    }
    print('n_ss is: ', n_ss)
    print('b_ss is: ', b_ss)
    print('c_ss is: ', c_ss)
    print('K_ss=', K_ss, ', L_ss=', L_ss, 'Y_ss=', Y_ss)
    print('r_ss=', r_ss, ', w_ss=', w_ss, 'C_ss=', C_ss)
    print('BQ_ss=', BQ_ss, ', I_ss=', I_ss, ', NX_ss=', NX_ss)
    print('Maximum abs. labor supply Euler error is: ',
          np.absolute(n_err_ss).max())
    print('Maximum abs. savings Euler error is: ', np.absolute(b_err_ss).max())
    print('Resource constraint error is: ', RCerr_ss)
    print('Final chi_n_vec from SS:', chi_n_vec)
    print('SS factor is: ', factor_ss)

    # Print SS computation time
    utils.print_time(ss_time, 'SS')

    if graphs:
        gr_args = (E, S, J, chi_n_vec, lambdas)
        create_graphs(c_ss, b_ss, n_ss, gr_args)

    return ss_output
Exemplo n.º 5
0
def get_TPI(bmat1, args, graphs):
    '''
    --------------------------------------------------------------------
    Solves for transition path equilibrium using time path iteration
    (TPI)
    --------------------------------------------------------------------
    INPUTS:
    bmat1 = (S, J) matrix, initial period wealth (savings) distribution
    args  = length 25 tuple, (J, S, T1, T2, lambdas, emat, beta, sigma,
            l_tilde, b_ellip, upsilon, chi_n_vec, Z, gamma, delta, r_ss,
            K_ss, L_ss, C_ss, b_ss, n_ss, maxiter, Out_Tol, In_Tol, xi)
    graphs = Boolean, =True if want graphs of TPI objects

    OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION:
        get_path()
        firms.get_r()
        firms.get_w()
        get_cnbpath()
        aggr.get_K()
        aggr.get_L()
        aggr.get_Y()
        aggr.get_C()
        utils.print_time()
        create_graphs()

    OBJECTS CREATED WITHIN FUNCTION:
    start_time   = scalar, current processor time in seconds (float)
    J            = integer >= 1, number of heterogeneous ability groups
    S            = integer in [3,80], number of periods an individual
                   lives
    T1           = integer > S, number of time periods until steady
                   state is assumed to be reached
    T2           = integer > T1, number of time periods after which
                   steady-state is forced in TPI
    lambdas      = (J,) vector, income percentiles for distribution of
                   ability within each cohort
    emat         = (S, J) matrix, lifetime ability profiles for each
                   lifetime income group j
    beta         = scalar in (0,1), discount factor for model period
    sigma        = scalar > 0, coefficient of relative risk aversion
    l_tilde      = scalar > 0, time endowment for each agent each
                   period
    b_ellip      = scalar > 0, fitted value of b for elliptical
                   disutility of labor
    upsilon      = scalar > 1, fitted value of upsilon for elliptical
                   disutility of labor
    chi_n_vec    = (S,) vector, values for chi^n_s
    Z            = scalar > 0, total factor productivity parameter in
                   firms' production function
    gamma        = scalar in (0,1), capital share of income
    delta        = scalar in [0,1], per-period capital depreciation rt
    r_ss         = scalar > 0, steady-state aggregate interest rate
    K_ss         = scalar > 0, steady-state aggregate capital stock
    L_ss         = scalar > 0, steady-state aggregate labor
    C_ss         = scalar > 0, steady-state aggregate consumption
    b_ss         = (S,) vector, steady-state savings distribution
                   (b1, b2,... bS)
    n_ss         = (S,) vector, steady-state labor supply distribution
                   (n1, n2,... nS)
    maxiter      = integer >= 1, Maximum number of iterations for TPI
    Out_Tol      = scalar > 0, convergence criterion for TPI outer loop
    In_Tol       = scalar > 0, tolerance level for TPI inner-loop root
                   finders
    xi           = scalar in (0,1], TPI path updating parameter
    K1           = scalar > 0, initial aggregate capital stock
    K1_cnstr     = Boolean, =True if K1 <= 0
    rpath_init   = (T2+S-1,) vector, initial guess for the time path of
                   interest rates
    iter_TPI     = integer >= 0, current iteration of TPI
    dist         = scalar >= 0, distance measure between initial and
                   new paths
    rw_params    = length 3 tuple, (Z, gamma, delta)
    Y_params     = length 2 tuple, (Z, gamma)
    cnb_args     = length 13 tuple, args to pass into get_cnbpath()
    rpath        = (T2+S-1,) vector, time path of the interest rates
    wpath        = (T2+S-1,) vector, time path of the wages
    cpath        = (S, J, T2+S-1) array, time path of distribution of
                   household consumption c_{j,s,t}
    npath        = (S, J, T2+S-1) matrix, time path of distribution of
                   household labor supply n_{j,s,t}
    bpath        = (S, J, T2+S-1) matrix, time path of distribution of
                   household savings b_{j,s,t}
    n_err_path   = (S, J, T2+S-1) matrix, time path of distribution of
                   household labor supply Euler errors
    b_err_path   = (S, J, T2+S-1) matrix, time path of distribution of
                   household savings Euler errors. b_{j,1,t} = 0 for all
                   j and t
    Kpath_new    = (T2+S-1,) vector, new path of aggregate capital stock
                   implied by household and firm optimization
    Kpath_cnstr  = (T2+S-1,) Boolean vector, =True if K_t<=epsilon
    Lpath_new    = (T2+S-1,) vector, new path of aggregate labor implied
                   by household and firm optimization
    Lpath_cstr   = (T2+S-1,) Boolean vector, =True if L_t<=epsilon
    rpath_new    = (T2+S-1,) vector, updated time path of interest rate
    Ypath        = (T2+S-1,) vector, equilibrium time path of aggregate
                   output (GDP) Y_t
    Cpath        = (T2+S-1,) vector, equilibrium time path of aggregate
                   consumption C_t
    RCerrPath    = (T2+S-2,) vector, equilibrium time path of the
                   resource constraint error. Should be 0 in eqlb'm
                   Y_t - C_t - K_{t+1} + (1-delta)*K_t
    MaxAbsEulErr = scalar > 0, maximum absolute Euler error. Includes
                   both labor supply and savings Euler errors
    Kpath        = (T2+S-1,) vector, equilibrium time path of aggregate
                   capital stock K_t
    Lpath        = (T2+S-1,) vector, equilibrium time path of aggregate
                   labor L_t
    tpi_time     = scalar, time to compute TPI solution (seconds)
    tpi_output   = length 13 dictionary, {cpath, npath, bpath, wpath,
                   rpath, Kpath, Lpath, Ypath, Cpath, n_err_path,
                   b_err_path, RCerrPath, tpi_time}
    graph_args   = length 4 tuple, (J, S, T2, lambdas)

    FILES CREATED BY THIS FUNCTION:
        Kpath.png
        Lpath.png
        rpath.png
        wpath.png
        Ypath.png
        C_aggr_path.png
        cpath_avg_s.png
        cpath_avg_j.png
        npath_avg_s.png
        npath_avg_j.png
        bpath_avg_s.png
        bpath_avg_j.png

    RETURNS: tpi_output
    --------------------------------------------------------------------
    '''
    start_time = time.clock()
    (J, E, S, T1, T2, lambdas, emat, mort_rates, imm_rates_mat, omega_path,
     g_n_path, zeta_mat, chi_n_vec, chi_b_vec, beta, sigma, l_tilde, b_ellip,
     upsilon, g_y, Z, gamma, delta, r_ss, BQ_ss, K_ss, L_ss, C_ss, b_ss, n_ss,
     maxiter, Out_Tol, In_Tol, xi) = args
    K1, K1_cnstr = aggr.get_K(bmat1, lambdas)

    # Create time paths for r and BQ
    rpath_init = np.zeros(T2 + S - 1)
    BQpath_init = np.zeros(T2 + S - 1)
    rpath_init[:T1] = get_path(r_ss, r_ss, T1, 'quadratic')
    rpath_init[T1:] = r_ss
    BQ_args = (lambdas, omega_path[0, :], mort_rates, g_n_path[0])
    BQ_1 = aggr.get_BQ(bmat1, r_ss, BQ_args)
    BQpath_init[:T1] = get_path(BQ_1, BQ_ss, T1, 'quadratic')
    BQpath_init[T1:] = BQ_ss

    iter_TPI = int(0)
    dist = 10.0
    rw_params = (Z, gamma, delta)
    Y_params = (Z, gamma)
    cnb_args = (J, S, T2, lambdas, emat, omega_path, beta, sigma, l_tilde,
                b_ellip, upsilon, chi_n_vec, bmat1, n_ss, In_Tol)
    while (iter_TPI < maxiter) and (dist >= Out_Tol):
        iter_TPI += 1
        rpath = rpath_init
        BQpath = BQpath_init
        wpath = firms.get_w(rpath_init, rw_params)
        cpath, npath, bpath, n_err_path, b_err_path = \
            get_cnbpath(rpath, wpath, cnb_args)
        Kpath_new = np.zeros(T2 + S - 1)
        Kpath_new[:T2], Kpath_cstr = aggr.get_K(bpath[:, :, :T2], lambdas)
        Kpath_new[T2:] = K_ss
        Kpath_cstr = np.append(Kpath_cstr, np.zeros(S - 1, dtype=bool))
        Lpath_new = np.zeros(T2 + S - 1)
        Lpath_new[:T2], Lpath_cstr = aggr.get_L(npath[:, :, :T2], lambdas,
                                                emat)
        Lpath_new[T2:] = L_ss
        Lpath_cstr = np.append(Lpath_cstr, np.zeros(S - 1, dtype=bool))
        rpath_new = firms.get_r(Kpath_new, Lpath_new, rw_params)
        BQpath_new = aggr.get_BQ()
        Ypath = aggr.get_Y(Kpath_new, Lpath_new, Y_params)
        Cpath = np.zeros(T2 + S - 1)
        Cpath[:T2] = aggr.get_C(cpath[:, :, :T2], lambdas)
        Cpath[T2:] = C_ss
        RCerrPath = np.zeros(T2 + S - 1)
        RCerrPath[:-1] = (Ypath[:-1] - Cpath[:-1] - Kpath_new[1:] +
                          (1 - delta) * Kpath_new[:-1])
        RCerrPath[-1] = RCerrPath[-2]
        # Check the distance of rpath_new
        dist = (np.absolute(rpath_new[:T2] - rpath_init[:T2])).max()
        MaxAbsEulErr = np.absolute(np.hstack((n_err_path, b_err_path))).max()
        print('TPI iter: ', iter_TPI, ', dist: ', "%10.4e" % (dist),
              ', max abs all errs: ', "%10.4e" % MaxAbsEulErr)
        # The resource constraint does not bind across the transition
        # path until the equilibrium is solved
        rpath_init[:T2] = (xi * rpath_new[:T2] + (1 - xi) * rpath_init[:T2])
    if (iter_TPI == maxiter) and (dist > Out_Tol):
        print('TPI reached maxiter and did not converge.')
    elif (iter_TPI == maxiter) and (dist <= Out_Tol):
        print('TPI converged in the last iteration. ' +
              'Should probably increase maxiter_TPI.')
    Kpath = Kpath_new
    Lpath = Lpath_new

    tpi_time = time.clock() - start_time

    tpi_output = {
        'cpath': cpath,
        'npath': npath,
        'bpath': bpath,
        'wpath': wpath,
        'rpath': rpath,
        'Kpath': Kpath,
        'Lpath': Lpath,
        'Ypath': Ypath,
        'Cpath': Cpath,
        'n_err_path': n_err_path,
        'b_err_path': b_err_path,
        'RCerrPath': RCerrPath,
        'tpi_time': tpi_time
    }

    # Print maximum resource constraint error. Only look at resource
    # constraint up to period T2 - 1 because period T2 includes K_{t+1},
    # which was forced to be the steady-state
    print('Max abs. RC error: ',
          "%10.4e" % (np.absolute(RCerrPath[:T2 - 1]).max()))

    # Print TPI computation time
    utils.print_time(tpi_time, 'TPI')

    if graphs:
        graph_args = (J, S, T2, lambdas)
        create_graphs(tpi_output, graph_args)

    return tpi_output
Exemplo n.º 6
0
                  Frisch_elast, CFE_scale)
    calibrate = pjp.process_calibration_parameters()
    init_chi1 = pickle.load(open('init_chi1.pkl', 'rb'))
    # rss_init = 0.15
    rss_init = init_chi1['r_ss']
    # bmat_init = 0.01 * np.ones((S, J))
    bmat_init = init_chi1['b_ss']
    # nmat_init = 0.5 * l_tilde * np.ones((S, J))
    nmat_init = init_chi1['n_ss']
    rss_path = rss_init * np.ones(S)
    f_args = (lambdas, emat, omega_SS, mort_rates, zeta_mat, g_y, l_tilde,
              g_n_SS, Z, gamma, delta)
    b_feas, n_feas, c_feas = hh.feasible(bmat_init, nmat_init, rss_path,
                                         f_args)
    BQ_args = (lambdas, omega_SS, mort_rates, g_n_SS)
    BQ_init = aggr.get_BQ(bmat_init, rss_init, BQ_args)
    factor_init = 1.0
    init_calc = True
    mean_ydata = calibrate.get_avg_ydata()

    chi_n_vec = 1.0 * np.ones(S)
    ss_init_vals = (rss_init, BQ_init, factor_init, bmat_init, nmat_init)
    ss_args_noclb = (J, E, S, lambdas, emat, mort_rates, imm_rates_adj,
                     omega_SS, g_n_SS, zeta_mat, chi_n_vec, chi_b_vec, beta,
                     sigma, l_tilde, b_ellip, upsilon, g_y, Z, gamma, delta,
                     SS_tol_outer, SS_tol_inner, xi_SS, SS_maxiter, mean_ydata,
                     init_calc)
    print(ss_args_noclb)
    ss_output_noclb = ss.get_SS(ss_init_vals, ss_args_noclb, False)
    # Save ss_output as pickle
    pickle.dump(ss_output_noclb, open(ss_outfile_noclb, 'wb'))
Exemplo n.º 7
0
def solve_tp(g_n_path, omega_S_preTP, rho_s, imm_rates_path, params):
    '''
    Solves for the time path equilibrium using TPI
    '''
    # Missing some elements of params
    b_ss, r_11, T, S = params
    dist = 8.0
    mindist = 1e-08
    maxiter = 300
    tpi_iter = 0
    xi = 0.2
    while dist > mindist and tpi_iter < maxiter:

        # Define paths
        b_11 = 1.1 * b_ss
        BQ_params = (g_n_path[0], omega_S_preTP, rho_s)
        K_params = (g_n_path[0], omega_S_preTP, imm_rates_path[0, :])
        BQ_11 = agg.get_BQ(b_11, r_11, BQ_params)
        K_11 = agg.get_K(b_11, K_params)
        BQpath_init = np.zeros(T + S - 1)
        BQpath_init[:T] = np.linspace(BQ_11, BQ_ss, T)
        BQpath_init[T:] = BQ_ss
        r_11 = firm.get_r(K_11, L_ss, r_params)
        r_path = firm.get_r(L_ss, r_params)
        w_path = firm.get_w(L_ss, w_params)
        bmat = np.zeros((S - 1, T + S - 1))
        bmat[:, 0] = b_1

        # Solve for households
        for p in range(2, S):
            b_guess = np.diagonal(bmat[S - p:, :p - 1])
            b_init = bmat[S - p - 1, 0]
            b_params = (b_init, n[-p:], r_path[:p], w_path[:p],
                        BQpath_init[:p], rho_s[-p:], beta, sigma)
            results_bp = opt.root(hh.FOCs, b_guess, args=(b_params))
            b_solve_p = results_bp.x
            DiagMaskbp = np.eye(p - 1, dtype=bool)
            bmat[S - p:, 1:p] = DiagMaskbp * b_solve_p + bmat[S - p:, 1:p]

        for t in range(1, T + 1):
            b_guess = np.diagonal(bmat[:, t - 1:t + S - 2])
            b_init = 0.0
            b_params = (b_init, n, r_path[t - 1:t + S - 1],
                        w_path[t - 1:t + S - 1], BQpath_init[t - 1:t + S - 1],
                        rho_s, beta, sigma)
            results_bt = opt.root(hh.FOCs, b_guess, args=(b_params))
            b_solve_t = results_bt.x
            DiagMaskbt = np.eye(S - 1, dtype=bool)
            bmat[:,
                 t:t + S - 1] = (DiagMaskbt * b_solve_t + bmat[:, t:t + S - 1])

        new_Kpath = np.zeros(T)
        new_Kpath[0] = K_1
        new_Kpath[1:] = \
            (1 / (omega_path_S[:T - 1, :-1]) *
                bmat[:, 1:T].T +
                imm_rates_path[:T - 1, 1:] *
                omega_path_S[:T - 1, 1:] * bmat[:, 1:T].T).sum(axis=1)
        new_BQpath = np.zeros(T)
        new_BQpath[0] = BQ_1
        new_BQpath[1:] = \
            ((1 + r_path[1:T]) / (rho_s[:-1]) *
                omega_path_S[:T - 1, :-1] * bmat[:, 1:T].T).sum(axis=1)

        dist = ((BQ_init - new_BQ)**2).sum()
        BQpath_init[:T] = xi * new_BQpath[:T] + (1 - xi) * BQpath_init[:T]
        # update iteration counter
        tpi_iter += 1

    if tpi_iter < maxiter:
        print('The time path solved! ->', ' iter:', tpi_iter, ', dist: ', dist)
    else:
        print('The time path did not solve.')

    return [new_Kpath, new_BQpath]
Exemplo n.º 8
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]  = aggr.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] = aggr.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 = aggr.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]  = aggr.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] = aggr.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(aggr.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 = aggr.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(aggr.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]  = aggr.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] = aggr.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 = aggr.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(aggr.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 = aggr.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 = aggr.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] #aggr.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 = aggr.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, 'REVENUE': REVENUE, '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