예제 #1
0
파일: SS.py 프로젝트: rickecon/OG-JRC
def inner_loop(r, w, Y, x, params):
    '''
    --------------------------------------------------------------------
    Given values for r and w, solve for equilibrium errors from the two
    first order conditions of the firm
    --------------------------------------------------------------------
    INPUTS:
    r      = scalar > 0, guess at steady-state interest rate
    w      = scalar > 0, guess at steady-state wage
    Y      = scalar > 0, guess steady-state output
    x      = scalar > 0, guess as steady-state transfers per household
    params = length 16 tuple, (c1_init, S, beta, sigma, l_tilde, b_ellip,
                               upsilon, chi_n_vec, A, alpha, delta, tax_params,
                               fiscal_params, diff, hh_fsolve, SS_tol)


    OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION:
        hh.bn_solve()
        hh.c1_bSp1err()
        hh.get_cnb_vecs()
        aggr.get_K()
        aggr.get_L()
        firms.get_r()
        firms.get_w()

    OBJECTS CREATED WITHIN FUNCTION:
    c1_init       = scalar > 0, initial guess for c1
    S             = integer >= 3, number of periods in individual lifetime
    beta          = scalar in (0,1), discount factor
    sigma         = scalar >= 1, coefficient of relative risk aversion
    l_tilde       = scalar > 0, per-period time endowment for every agent
    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
    A             = scalar > 0, total factor productivity parameter in
                    firms' production function
    alpha         = scalar in (0,1), capital share of income
    delta         = scalar in [0,1], model-period depreciation rate of
                    capital
    tax_params    = length 3 tuple, (tau_l, tau_k, tau_c)
    fiscal_params = length 7 tuple, (tG1, tG2, alpha_X, alpha_G, rho_G,
                                     alpha_D, alpha_D0)
    diff          = boolean, =True if simple difference Euler errors,
                    otherwise percent deviation Euler errors
    hh_fsolve     = boolean, =True if solve inner-loop household problem by
                    choosing c_1 to set final period savings b_{S+1}=0.
                    Otherwise, solve the household problem as multivariate
                    root finder with 2S-1 unknowns and equations
    SS_tol        = scalar > 0, tolerance level for steady-state fsolve
    tau_l         = scalar, marginal tax rate on labor income
    tau_k         = scalar, marginal tax rate on capital income
    tau_c         = scalar, marginal tax rate on corporate income
    tG1           = integer, model period when budget closure rule begins
    tG2           = integer, model period when budget is closed
    alpha_X       = scalar, ratio of lump sum transfers to GDP
    alpha_G       = scalar, ratio of government spending to GDP prior to
                            budget closure rule beginning
    rho_G         = scalar in (0,1), rate of convergence to SS budget
    alpha_D       = scalar, steady-state debt to GDP ratio
    alpha_D0      = scalar, debt to GDP ratio in the initial period
    r_params      = length 3 tuple, args to pass into get_r()
    w_params      = length 2 tuple, args to pass into get_w()
    Y_params      = length 2 tuple, args to pass into get_Y()
    b_init        = (S-1,) vector, initial guess at distribution of savings
    n_init        = (S,) vector, initial guess at distribution of labor supply
    guesses       = (2S-1,) vector, initial guesses at b and n
    bn_params     = length 12 tuple, parameters to pass to solve_bn_path()
                    (r, w, x, S, beta, sigma, l_tilde,
                        b_ellip, upsilon, chi_n_vec, tax_params, diff)
    euler_errors  = (2S-1,) vector, Euler errors for FOCs for b and n
    b_splus1_vec  = (S,) vector, optimal savings choice
    nvec          = (S,) vector, optimal labor supply choice
    b_Sp1         = scalar, last period savings
    b_s_vec       = (S,) vector, wealth enter period with
    cvec          = (S,) vector, optimal consumption
    rpath         = (S,) vector, lifetime path of interest rates
    wpath         = (S,) vector, lifetime path of wages
    c1_args       = length 10 tuple, args to pass into c1_bSp1err()
    c1_options    = length 1 dict, options for c1_bSp1err()
    results_c1    = results object, results from c1_bSp1err()
    c1            = scalar > 0, optimal initial period consumption given r
                    and w
    cnb_args      = length 8 tuple, args to pass into get_cnb_vecs()
    cvec          = (S,) vector, lifetime consumption (c1, c2, ...cS)
    nvec          = (S,) vector, lifetime labor supply (n1, n2, ...nS)
    bvec          = (S,) vector, lifetime savings (b1, b2, ...bS) with b1=0
    b_Sp1         = scalar, final period savings, should be close to zero
    B             = scalar > 0, aggregate savings
    B_cnstr       = boolean, =True if B < 0
    L             = scalar > 0, aggregate labor
    debt          = scalar, total government debt
    K             = scalar > 0, aggregate capital stock
    K_cnstr       = boolean, =True if K < 0
    r_new         = scalar > 0, implied steady-state interest rate
    w_new         = scalar > 0, implied steady-state wage
    Y_new         = scalar >0, implied steady-state output
    x_new         = scalar >=0, implied transfers per household


    FILES CREATED BY THIS FUNCTION: None

    RETURNS: B, K, L, Y_new, debt, cvec, nvec, b_s_vec, b_splus1_vec,
                b_Sp1, x_new, r_new, w_new
    --------------------------------------------------------------------
    '''
    c1_init, S, beta, sigma, l_tilde, b_ellip, upsilon,\
        chi_n_vec, A, alpha, delta, tax_params, fiscal_params,\
        diff, hh_fsolve, SS_tol = params
    tau_l, tau_k, tau_c = tax_params
    tG1, tG2, alpha_X, alpha_G, rho_G, alpha_D, alpha_D0 = fiscal_params

    r_params = (A, alpha, delta, tau_c)
    w_params = (A, alpha)
    Y_params = (A, alpha)

    if hh_fsolve:
        b_init = np.ones((S - 1, 1)) * 0.05
        n_init = np.ones((S, 1)) * 0.4
        guesses = np.append(b_init, n_init)
        bn_params = (r, w, x, S, beta, sigma, l_tilde, b_ellip, upsilon,
                     chi_n_vec, tax_params, diff)
        [solutions, infodict, ier, message] = \
            opt.fsolve(hh.bn_solve, guesses, args=bn_params,
                       xtol=SS_tol, full_output=True)
        euler_errors = infodict['fvec']
        print('Max Euler errors: ', np.absolute(euler_errors).max())
        b_splus1_vec = np.append(solutions[:S - 1], 0.0)
        nvec = solutions[S - 1:]
        b_Sp1 = 0.0
        b_s_vec = np.append(0.0, b_splus1_vec[:-1])
        cvec = hh.get_cons(r, w, b_s_vec, b_splus1_vec, nvec, x, tax_params)
    else:
        rpath = r * np.ones(S)
        wpath = w * np.ones(S)
        xpath = x * np.ones(S)
        c1_options = {'maxiter': 500}
        c1_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec,
                   tax_params, xpath, rpath, wpath, diff)
        results_c1 = \
            opt.root(hh.c1_bSp1err, c1_init, args=(c1_args),
                     method='lm', tol=SS_tol,
                     options=(c1_options))
        c1_new = results_c1.x
        cnb_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec,
                    tax_params, diff)
        cvec, nvec, b_s_vec, b_Sp1 = \
            hh.get_cnb_vecs(c1_new, rpath, wpath, xpath, cnb_args)
        b_splus1_vec = np.append(b_s_vec[1:], b_Sp1)

    B, B_cnstr = aggr.get_K(b_s_vec)
    L = aggr.get_L(nvec)
    L = np.maximum(0.0001, L)
    debt = alpha_D * Y
    K = B - debt
    K_cnstr = K < 0
    if K_cnstr:
        print('Aggregate capital constraint is violated K<=0 for ' +
              'in the steady state.')
    r_new = firms.get_r(r_params, K, L)
    w_new = firms.get_w(w_params, K, L)
    Y_new = aggr.get_Y(Y_params, K, L)
    x_new = (alpha_X * Y_new) / S


    return B, K, L, Y_new, debt, cvec, nvec, b_s_vec, b_splus1_vec, \
                b_Sp1, x_new, r_new, w_new
예제 #2
0
파일: TPI.py 프로젝트: LeiliPR/OG-JRC
def get_cnbpath(params, rpath, wpath):
    '''
    --------------------------------------------------------------------
    Given time paths for interest rates and wages, this function
    generates matrices for the time path of the distribution of
    individual consumption, labor supply, savings, the corresponding
    Euler errors for the labor supply decision and the savings decision,
    and the residual error of end-of-life savings associated with
    solving each lifetime decision.
    --------------------------------------------------------------------
    INPUTS:
    params  = length 11 tuple, (S, T2, beta, sigma, l_tilde, b_ellip,
              upsilon, chi_n_vec, bvec1, TPI_tol, diff)
    rpath   = (T2+S-1,) vector, equilibrium time path of interest rate
    wpath   = (T2+S-1,) vector, equilibrium time path of the real wage

    OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION:
        hh.c1_bSp1err()
        hh.get_cnb_vecs()
        hh.get_n_errors()
        hh.get_b_errors()

    OBJECTS CREATED WITHIN FUNCTION:
    S             = integer in [3,80], number of periods an individual
                    lives
    T2            = integer > S, number of periods until steady state
    beta          = scalar in (0,1), discount factor
    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
    bvec1         = (S,) vector, initial period savings distribution
    TPI_tol       = scalar > 0, tolerance level for fsolve's in TPI
    diff          = boolean, =True if want difference version of Euler
                    errors beta*(1+r)*u'(c2) - u'(c1), =False if want
                    ratio version [beta*(1+r)*u'(c2)]/[u'(c1)] - 1
    cpath         = (S, T2+S-1) matrix, time path of the distribution of
                    consumption
    npath         = (S, T2+S-1) matrix, time path of the distribution of
                    labor supply
    bpath         = (S, T2+S-1) matrix, time path of the distribution of
                    savings
    n_err_path    = (S, T2+S-1) matrix, time path of distribution of
                    labor supply Euler errors
    b_err_path    = (S, T2+S-1) matrix, time path of distribution of
                    savings Euler errors
    bSp1_err_path = (S, T2) matrix, residual last period savings, which
                    should be close to zero in equilibrium. Nonzero
                    elements of matrix should only be in first column
                    and first row
    c1_options    = length 1 dict, options for
                    opt.root(hh.c1_bSp1err,...)
    b_err_params  = length 2 tuple, args to pass into
                    hh.get_b_errors()
    p             = integer in [1, S-1], index representing number of
                    periods remaining in a lifetime, used to solve
                    incomplete lifetimes
    c1_init       = scalar > 0, guess for initial period consumption
    c1_args       = length 10 tuple, args to pass into
                    opt.root(hh.c1_bSp1err,...)
    results_c1    = results object, solution from
                    opt.root(hh.c1_bSp1err,...)
    c1            = scalar > 0, optimal initial consumption
    cnb_args      = length 8 tuple, args to pass into
                    hh.get_cnb_vecs()
    cvec          = (p,) vector, individual lifetime consumption
                    decisions
    nvec          = (p,) vector, individual lifetime labor supply
                    decisions
    bvec          = (p,) vector, individual lifetime savings decisions
    b_Sp1         = scalar, savings in last period for next period.
                    Should be zero in equilibrium
    DiagMaskc     = (p, p) boolean identity matrix
    DiagMaskb     = (p-1, p-1) boolean identity matrix
    n_err_params  = length 5 tuple, args to pass into hh.get_n_errors()
    n_err_vec     = (p,) vector, individual lifetime labor supply Euler
                    errors
    b_err_vec     = (p-1,) vector, individual lifetime savings Euler
                    errors
    t             = integer in [0,T2-1], index of time period (minus 1)

    FILES CREATED BY THIS FUNCTION: None

    RETURNS: cpath, npath, bpath, n_err_path, b_err_path, bSp1_err_path
    --------------------------------------------------------------------
    '''
    (S, T2, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, bvec1, TPI_tol,
     diff) = params
    cpath = np.zeros((S, T2 + S - 1))
    npath = np.zeros((S, T2 + S - 1))
    bpath = np.append(bvec1.reshape((S, 1)), np.zeros((S, T2 + S - 2)), axis=1)
    n_err_path = np.zeros((S, T2 + S - 1))
    b_err_path = np.zeros((S, T2 + S - 1))
    bSp1_err_path = np.zeros((S, T2))
    # Solve the incomplete remaining lifetime decisions of agents alive
    # in period t=1 but not born in period t=1
    c1_options = {'maxiter': 500}
    b_err_params = (beta, sigma)
    for p in range(1, S):
        c1_init = 0.1
        c1_args = (bvec1[-p], beta, sigma, l_tilde, b_ellip, upsilon,
                   chi_n_vec[-p:], rpath[:p], wpath[:p], diff)
        results_c1 = \
            opt.root(hh.c1_bSp1err, c1_init, args=(c1_args),
                     method='lm', tol=TPI_tol, options=(c1_options))
        c_1 = results_c1.x
        cnb_args = (bvec1[-p], beta, sigma, l_tilde, b_ellip, upsilon,
                    chi_n_vec[-p:], diff)
        cvec, nvec, bvec, b_Sp1 = \
            hh.get_cnb_vecs(c_1, rpath[:p], wpath[:p], cnb_args)
        DiagMaskc = np.eye(p, dtype=bool)
        DiagMaskb = np.eye(p - 1, dtype=bool)
        cpath[-p:, :p] = DiagMaskc * cvec + cpath[-p:, :p]
        npath[-p:, :p] = DiagMaskc * nvec + npath[-p:, :p]
        n_err_args = (wpath[:p], cvec, sigma, l_tilde, chi_n_vec[-p:], b_ellip,
                      upsilon, diff)
        n_err_vec = hh.get_n_errors(nvec, n_err_args)
        n_err_path[-p:, :p] = (DiagMaskc * n_err_vec + n_err_path[-p:, :p])
        bSp1_err_path[-p, 0] = b_Sp1
        if p > 1:
            bpath[S - p + 1:,
                  1:p] = (DiagMaskb * bvec[1:] + bpath[S - p + 1:, 1:p])
            b_err_vec = hh.get_b_errors(b_err_params, rpath[1:p], cvec, diff)
            b_err_path[S - p + 1:, 1:p] = (DiagMaskb * b_err_vec +
                                           b_err_path[S - p + 1:, 1:p])
            # print('p=', p, ', max. abs. all errs: ',
            #       np.hstack((n_err_vec, b_err_vec, b_Sp1)).max())

    # Solve the remaining lifetime decisions of agents born between
    # period t=1 and t=T (complete lifetimes)
    DiagMaskc = np.eye(S, dtype=bool)
    DiagMaskb = np.eye(S - 1, dtype=bool)
    for t in range(T2):  # Go from periods 1 to T (columns 0 to T-1)
        if t == 0:
            c1_init = 0.1
        else:
            c1_init = cpath[0, t - 1]
        c1_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec,
                   rpath[t:t + S], wpath[t:t + S], diff)
        results_c1 = \
            opt.root(hh.c1_bSp1err, c1_init, args=(c1_args),
                     method='lm', tol=TPI_tol, options=(c1_options))
        c_1 = results_c1.x
        cnb_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec,
                    diff)
        cvec, nvec, bvec, b_Sp1 = \
            hh.get_cnb_vecs(c_1, rpath[t:t + S], wpath[t:t + S],
                            cnb_args)
        cpath[:, t:t + S] = DiagMaskc * cvec + cpath[:, t:t + S]
        npath[:, t:t + S] = DiagMaskc * nvec + npath[:, t:t + S]
        n_err_args = (wpath[t:t + S], cvec, sigma, l_tilde, chi_n_vec, b_ellip,
                      upsilon, diff)
        n_err_vec = hh.get_n_errors(nvec, n_err_args)
        n_err_path[:,
                   t:t + S] = (DiagMaskc * n_err_vec + n_err_path[:, t:t + S])
        bpath[:, t:t + S] = DiagMaskc * bvec + bpath[:, t:t + S]
        b_err_vec = hh.get_b_errors(b_err_params, rpath[t + 1:t + S], cvec,
                                    diff)
        b_err_path[1:, t + 1:t + S] = (DiagMaskb * b_err_vec +
                                       b_err_path[1:, t + 1:t + S])
        bSp1_err_path[0, t] = b_Sp1
        # print('t=', t, ', max. abs. all errs: ',
        #       np.absolute(np.hstack((n_err_vec, b_err_vec,
        #                              b_Sp1))).max())

    return cpath, npath, bpath, n_err_path, b_err_path, bSp1_err_path
예제 #3
0
def rBQ_errors(rBQ_vals, *args):
    '''
    --------------------------------------------------------------------
    Generate interest rate and wage errors from labor market clearing
    and capital market clearing conditions
    --------------------------------------------------------------------
    INPUTS:
    rBQ_vals = (2,) vector, steady-state r value and BQ value
    args     = length 2 tuple, (nb_guess, p)

    OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION:
        firms.get_wt()
        hh.get_cnb_vecs()
        aggr.get_Lt()
        aggr.get_Kt()
        firms.get_rt()
        aggr.get_BQt()

    OBJECTS CREATED WITHIN FUNCTION:
    nb_buess   = (2S,) vector, initial guesses for n_s and b_sp1
    p          = parameters class object
    r_init     = scalar, initial guess for steady-state interest rate
    BQ_init    = scalar, initial guess for steady-state total bequests
    w          = scalar, steady-state wage implied by r_init
    b_init     = scalar = 0, initial wealth of initial age individuals
    r_path     = (S,) vector, constant interest rate time path over
                 lifetime of individual
    w_path     = (S,) vector, constant wage time path over lifetime of
                 individual
    BQ_path    = (S,) vector, constant total bequests time path over
                 lifetime of individual
    c_s        = (S,) vector, steady-state consumption by age
    n_s        = (S,) vector, steady-state labor supply by age
    b_s        = (S+1,) vector, steady-state wealth or savings by age
    n_errors   = (S,) vector, errors associated with optimal labor
                 supply solution
    b_errors   = (S,) vector, errors associated with optimal savings
                 solution
    L          = scalar, aggregate labor implied by household and firm
                 optimization
    K          = scalar, aggregate capital implied by household and firm
                 optimization
    r_new      = scalar, new value of r implied by household and firm
                 optimization
    BQ_new     = scalar, new value of BQ implied by household and firm
                 optimization
    r_error    = scalar, difference between r_new and r_init
    BQ_error   = scalar, difference between BQ_new and BQ_init
    rBQ_errors = (2,) vector, r_error and BQ_error

    FILES CREATED BY THIS FUNCTION: None

    RETURNS: rBQ_errors
    --------------------------------------------------------------------
    '''
    (nb_guess, p) = args
    r_init, BQ_init = rBQ_vals
    # Solve for steady-state wage w implied by r
    w = firms.get_wt(r_init, p)
    # Solve for household steady-state decisions c_s, n_s, b_{s+1} given
    # r, w, and BQ
    b_init = 0.0
    r_path = r_init * np.ones(p.S)
    w_path = w * np.ones(p.S)
    BQ_path = BQ_init * np.ones(p.S)
    c_s, n_s, b_s, n_errors, b_errors = \
        hh.get_cnb_vecs(nb_guess, b_init, r_path, w_path, BQ_path,
                        p.rho_ss, p.SS_EulDif, p, p.SS_EulTol)
    # Solve for aggregate labor and aggregate capital
    L = aggr.get_Lt(n_s, p)
    K = aggr.get_Kt(b_s[1:], p)
    # Solve for updated values of the interest rate r and total bequests
    # BQ
    r_new = firms.get_rt(K, L, p)
    BQ_new = aggr.get_BQt(b_s[1:], r_init, p)
    # solve for errors in interest rate and total bequests guesses
    r_error = r_new - r_init
    BQ_error = BQ_new - BQ_init
    rBQ_errors = np.array([r_error, BQ_error])

    return rBQ_errors
예제 #4
0
def get_SS(rBQ_init, p, graphs=False):
    '''
    --------------------------------------------------------------------
    Solve for the steady-state solution of the S-period-lived agent OG
    model with endogenous labor supply and multiple industries using the
    root finder method in r and w for the outer loop
    --------------------------------------------------------------------
    INPUTS:
    rBQ_init = (2,) vector, initial guesses for (rss_init, BQss_init)
    p        = parameters class object
    graphs   = boolean, =True if output steady-state graphs

    OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION:
        rBQ_errors()
        firms.get_wt()
        hh.get_cnb_vecs()
        aggr.get_Lt()
        aggr.get_Kt()
        firms.get_Yt()
        C_ss = aggr.get_Ct()
        I_ss = aggr.get_It()
        NX_ss = aggr.get_NXt()
        utils.print_time()
        ss_graphs()

    OBJECTS CREATED WITHIN FUNCTION:
    start_time  = scalar > 0, clock time at beginning of program
    nvec_guess  = (S,) vector, initial guess for optimal household labor
                  supply n_s
    bvec_guess  = (S,) vector, initial guess for optimal household
                  savings b_sp1
    nb_guess    = (2S,) vector, initial guesses for optimal household
                  labor supply and savings (n_s, b_sp1)
    rBQ_args    = length 2 tuple, (nb_guess, p)
    results_rBQ = root results object
    err_msg     = string, error message text string
    r_ss        = scalar > -delta, steady-state interest rate
    BQ_ss       = scalar > 0, steady-state total bequests
    r_err_ss    = scalar, error in steady-state optimal solution firm
                  first order condition for r_ss
    BQ_err_ss   = scalar, error in steady-state optimal solution
                  bequests law of motion for BQ_ss
    w_ss        = scalar > 0, steady-state wage
    b_init      = scalar = 0, initial wealth of initial age individuals
    r_path      = (S,) vector, constant interest rate time path over
                  lifetime of individual
    w_path      = (S,) vector, constant wage time path over lifetime of
                  individual
    BQ_path     = (S,) vector, constant total bequests time path over
                  lifetime of individual
    c_ss        = (S,) vector, steady-state consumption by age
    n_ss        = (S,) vector, steady-state labor supply by age
    b_ss        = (S+1,) vector, steady-state wealth or savings by age
    n_err_ss    = (S,) vector, errors associated with optimal labor
                  supply solution
    b_err_ss    = (S,) vector, errors associated with optimal savings
                  solution
    L_ss        = scalar > 0, steady-state aggregate labor
    K_ss        = scalar > 0, steady-state aggregate capital stock
    Y_ss        = scalar > 0, steady-state aggregate output
    C_ss        = scalar > 0, steady-state aggregate consumption
    I_ss        = scalar, steady-state aggregate investment
    NX_ss       = scalar, steady-state net exports
    RCerr_ss    = scalar, steady-state resource constraint (goods market
                  clearing) error
    ss_time     = scalar, seconds elapsed for steady-state computation
    ss_output   = length 18 dictionary, steady-state output {c_ss, n_ss,
                  b_ss, n_err_ss, b_err_ss, r_ss, w_ss, BQ_ss, r_err_ss,
                  BQ_err_ss, L_ss, K_ss, Y_ss, C_ss, I_ss, NX_ss,
                  RCerr_ss, ss_time}

    FILES CREATED BY THIS FUNCTION: None

    RETURNS: ss_output
    --------------------------------------------------------------------
    '''
    start_time = time.clock()
    nvec_guess = 0.4 * p.l_tilde * np.ones(p.S)
    bvec_guess = 0.1 * np.ones(p.S)
    nb_guess = np.append(nvec_guess, bvec_guess)
    rBQ_args = (nb_guess, p)
    results_rBQ = opt.root(rBQ_errors,
                           rBQ_init,
                           args=rBQ_args,
                           tol=p.SS_OutTol)
    if not results_rBQ.success:
        err_msg = ('SS Error: Steady-state root finder did not ' +
                   'solve. results_rBQ.success=False')
        raise ValueError(err_msg)
    else:
        print('SS SUCESSS: steady-state solution converged.')

    # print(results_rw)
    r_ss, BQ_ss = results_rBQ.x
    r_err_ss, BQ_err_ss = results_rBQ.fun
    # Solve for steady-state wage w_ss implied by r_ss
    w_ss = firms.get_wt(r_ss, p)
    # Solve for household steady-state decisions c_s, n_s, b_{s+1} given
    # r, w, and BQ
    b_init = 0.0
    r_path = r_ss * np.ones(p.S)
    w_path = w_ss * np.ones(p.S)
    BQ_path = BQ_ss * np.ones(p.S)
    c_ss, n_ss, b_ss, n_err_ss, b_err_ss = \
        hh.get_cnb_vecs(nb_guess, b_init, r_path, w_path, BQ_path,
                        p.rho_ss, p.SS_EulDif, p, p.SS_EulTol)
    # Solve for steady-state aggregate labor and aggregate capital
    L_ss = aggr.get_Lt(n_ss, p)
    K_ss = aggr.get_Kt(b_ss[1:], p)
    # Solve for steady-state aggregate output Y, consumption C,
    # investment I, and net exports
    Y_ss = firms.get_Yt(K_ss, L_ss, p)
    C_ss = aggr.get_Ct(c_ss, p)
    I_ss = aggr.get_It(K_ss, p)
    NX_ss = aggr.get_NXt(b_ss[1:], p)
    # Solve for steady-state resource constraint error
    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,
        'n_err_ss': n_err_ss,
        'b_err_ss': b_err_ss,
        'r_ss': r_ss,
        'w_ss': w_ss,
        'BQ_ss': BQ_ss,
        'r_err_ss': r_err_ss,
        'BQ_err_ss': BQ_err_ss,
        'L_ss': L_ss,
        'K_ss': K_ss,
        'Y_ss': Y_ss,
        'C_ss': C_ss,
        'I_ss': I_ss,
        'NX_ss': NX_ss,
        'RCerr_ss': RCerr_ss,
        'ss_time': ss_time
    }

    print('n_ss=', n_ss)
    print('b_ss=', b_ss)
    print('K_ss=', K_ss)
    print('L_ss=', L_ss)
    print('r_ss=', r_ss, ', w_ss=', w_ss, ', BQ_ss=', BQ_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('RC error is: ', RCerr_ss)

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

    if graphs:
        ss_graphs(c_ss, n_ss, b_ss, p)

    return ss_output
예제 #5
0
def inner_loop(r, w, args):
    '''
    --------------------------------------------------------------------
    Given values for r and w, solve for equilibrium errors from the two
    first order conditions of the firm
    --------------------------------------------------------------------
    INPUTS:
    r    = scalar > 0, guess at steady-state interest rate
    w    = scalar > 0, guess at steady-state wage
    args = length 14 tuple, (c1_init, S, beta, sigma, l_tilde, b_ellip,
           upsilon, chi_n_vec, A, alpha, delta, EulDiff, Eul_Tol,
           c1_options)

    OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION:
        hh.c1_bSp1err()
        hh.get_cnb_vecs()
        aggr.get_K()
        aggr.get_L()
        firms.get_r()
        firms.get_w()

    OBJECTS CREATED WITHIN FUNCTION:
    c1_init    = scalar > 0, initial guess for c1
    S          = integer >= 3, number of periods in individual lifetime
    beta       = scalar in (0,1), discount factor
    sigma      = scalar >= 1, coefficient of relative risk aversion
    l_tilde    = scalar > 0, per-period time endowment for every agent
    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
    A          = scalar > 0, total factor productivity parameter in
                 firms' production function
    alpha      = scalar in (0,1), capital share of income
    delta      = scalar in [0,1], model-period depreciation rate of
                 capital
    EulDiff    = boolean, =True if simple difference Euler errors,
                 otherwise percent deviation Euler errors
    SS_tol     = scalar > 0, tolerance level for steady-state fsolve
    c1_options = length 1 dict, options for c1_bSp1err()
    rpath      = (S,) vector, lifetime path of interest rates
    wpath      = (S,) vector, lifetime path of wages
    c1_args    = length 10 tuple, args to pass into hh.c1_bSp1err()
    results_c1 = results object, results from c1_bSp1err()
    c1         = scalar > 0, optimal initial period consumption given r
                 and w
    cnb_args   = length 8 tuple, args to pass into get_cnb_vecs()
    cvec       = (S,) vector, lifetime consumption (c1, c2, ...cS)
    nvec       = (S,) vector, lifetime labor supply (n1, n2, ...nS)
    bvec       = (S,) vector, lifetime savings (b1, b2, ...bS) with b1=0
    b_Sp1      = scalar, final period savings, should be close to zero
    n_errors   = (S,) vector, labor supply Euler errors
    b_errors   = (S-1,) vector, savings Euler errors
    K          = scalar > 0, aggregate capital stock
    K_cstr     = boolean, =True if K < epsilon
    L          = scalar > 0, aggregate labor
    L_cstr     = boolean, =True if L < epsilon
    r_params   = length 3 tuple, (A, alpha, delta)
    w_params   = length 2 tuple, (A, alpha)
    r_new      = scalar > 0, guess at steady-state interest rate
    w_new      = scalar > 0, guess at steady-state wage

    FILES CREATED BY THIS FUNCTION: None

    RETURNS: K, L, cvec, nvec, bvec, b_Sp1, r_new, w_new, n_errors,
             b_errors
    --------------------------------------------------------------------
    '''
    (c1_init, S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha,
     delta, EulDiff, SS_tol, c1_options) = args

    rpath = r * np.ones(S)
    wpath = w * np.ones(S)
    c1_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, rpath,
               wpath, EulDiff)
    results_c1 = \
        opt.root(hh.c1_bSp1err, c1_init, args=(c1_args),
                 method='lm', tol=SS_tol, options=(c1_options))
    c1 = results_c1.x
    cnb_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec,
                EulDiff)
    cvec, nvec, bvec, b_Sp1, n_errors, b_errors = \
        hh.get_cnb_vecs(c1, rpath, wpath, cnb_args)
    K, K_cstr = aggr.get_K(bvec)
    L, L_cstr = aggr.get_L(nvec)
    r_params = (A, alpha, delta)
    r_new = firms.get_r(K, L, r_params)
    w_params = (A, alpha, delta)
    w_new = firms.get_w(r_new, w_params)

    return (K, L, cvec, nvec, bvec, b_Sp1, r_new, w_new, n_errors, b_errors)
예제 #6
0
파일: SS.py 프로젝트: rickecon/OG-JRC
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 and a small open economy.
    --------------------------------------------------------------------
    INPUTS:
    init_vals = length 5 tuple,
                (Kss_init, Lss_init, rss_init, wss_init,c1_init)
    args      = length 14 tuple, (S, beta, sigma, l_tilde, b_ellip,
                upsilon, chi_n_vec, A, alpha, delta, SS_tol, EulDiff,
                hh_fsolve, KL_outer)
    graphs    = boolean, =True if output steady-state graphs

    OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION:
        firms.get_r()
        firms.get_w()
        hh.bn_solve()
        hh.c1_bSp1err()
        hh.get_cnb_vecs()
        aggr.get_K()
        aggr.get_L()
        aggr.get_Y()
        aggr.get_C()
        hh.get_cons()
        hh.get_n_errors()
        hh.get_b_errors()
        utils.print_time()

    OBJECTS CREATED WITHIN FUNCTION:
    start_time   = scalar > 0, clock time at beginning of program
    Kss_init     = scalar > 0, initial guess for steady-state aggregate
                   capital stock supplied
    Lss_init     = scalar > 0, initial guess for steady-state aggregate
                   labor
    rss_init     = scalar > 0, initial guess for steady-state interest
                   rate
    wss_init     = scalar > 0, initial guess for steady-state wage
    c1_init      = scalar > 0, initial guess for first period consumpt'n
    S            = integer in [3, 80], number of periods an individual
                   lives
    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 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
    A            = scalar > 0, total factor productivity parameter in
                   firms' production function
    alpha        = scalar in (0,1), capital share of income
    delta        = scalar in [0,1], model-period depreciation rate of
                   capital
    SS_tol       = scalar > 0, tolerance level for steady-state fsolve
    EulDiff      = Boolean, =True if want difference version of Euler
                   errors beta*(1+r)*u'(c2) - u'(c1), =False if want
                   ratio version [beta*(1+r)*u'(c2)]/[u'(c1)] - 1
    maxiter_SS   = integer >= 1, maximum number of iterations in outer
                   loop bisection method
    iter_SS      = integer >= 0, index of iteration number
    mindist_SS   = scalar > 0, minimum distance tolerance for
                   convergence
    dist_SS      = scalar > 0, distance metric for current iteration
    xi_SS        = scalar in (0,1], updating parameter
    KL_init      = (2,) vector, (K_init, L_init)
    c1_options   = length 1 dict, options to pass into
                   opt.root(c1_bSp1err,...)
    cnb_args     = length 8 tuple, args to pass into get_cnb_vecs()
    #r_params     = length 3 tuple, args to pass into get_r()
    w_params     = length 2 tuple, args to pass into get_w()
    K_init       = scalar, initial value of aggregate capital stock supplied
    L_init       = scalar, initial value of aggregate labor
    r_init       = scalar, initial value for interest rate
    w_init       = scalar, initial value for wage
    K_d          = scalar, capital demand
    rpath        = (S,) vector, lifetime path of interest rates
    wpath        = (S,) vector, lifetime path of wages
    c1_args      = length 10 tuple, args to pass into c1_bSp1err()
    results_c1   = results object, root finder results from
                   opt.root(c1_bSp1err,...)
    c1_new       = scalar, updated value of optimal c1 given r_init and
                   w_init
    cvec_new     = (S,) vector, updated values for lifetime consumption
    nvec_new     = (S,) vector, updated values for lifetime labor supply
    b_s_new      = (S,) vector, updated values for lifetime wealth
    b_splus1_new = (S,) vector, updated values for lifetime savings
                   (b1, b2,...bS)
    b_Sp1_new    = scalar, updated value for savings in last period,
                   should be arbitrarily close to zero
    K_new        = scalar, updated K given bvec_new
    K_cnstr      = boolean, =True if K_new <= 0
    L_new        = scalar, updated L given nvec_new
    KL_new       = (2,) vector, updated K and L given bvec_new, nvec_new
    K_ss         = scalar > 0, steady-state aggregate capital stock supplied
    K_d_ss       = scalar > 0, steady-state aggregate capital stock demanded
    L_ss         = scalar > 0, steady-state aggregate labor
    r_ss         = scalar > 0, steady-state interest rate
    w_ss         = scalar > 0, steady-state wage
    c1_ss        = scalar > 0, steady-state consumption in first period
    c_ss         = (S,) vector, steady-state lifetime consumption
    n_ss         = (S,) vector, steady-state lifetime labor supply
    b_s_ss       = (S,) vector, steady-state wealth enter period with
    b_splus1_ss  = (S,) vector, steady-state lifetime savings
                   (b1_ss, b2_ss, ...bS_ss) where b1_ss=0
    b_Sp1_ss     = scalar, steady-state savings for period after last
                   period of life. b_Sp1_ss approx. 0 in equilibrium
    Y_params     = length 2 tuple, (A, alpha)
    Y_ss         = scalar > 0, steady-state aggregate output (GDP)
    C_ss         = scalar > 0, steady-state aggregate consumption
    n_err_params = length 5 tuple, args to pass into get_n_errors()
    n_err_ss     = (S,) vector, lifetime labor supply Euler errors
    b_err_params = length 2 tuple, args to pass into get_b_errors()
    b_err_ss     = (S-1) vector, lifetime savings Euler errors
    RCerr_ss     = scalar, resource constraint error
    ss_time      = scalar, seconds elapsed to run steady-state comput'n
    ss_output    = length 14 dict, steady-state objects {n_ss, b_ss,
                   c_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}

    FILES CREATED BY THIS FUNCTION:
        SS_bc.png
        SS_n.png

    RETURNS: ss_output
    --------------------------------------------------------------------
    '''
    start_time = time.clock()
    c1_init = init_vals
    (S, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta,
     r_star, SS_tol, EulDiff, hh_fsolve) = args
    c1_options = {'maxiter': 500}
    cnb_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec,
                EulDiff)
    w_params = (A, alpha, delta)
    K_params = (A, alpha, delta)
    r_ss = r_star
    w_ss = firms.get_w(r_ss, w_params)

    if hh_fsolve:
        b_init = np.ones((S - 1, 1)) * 0.05
        n_init = np.ones((S, 1)) * 0.4
        guesses = np.append(b_init, n_init)
        bn_params = (r_ss, w_ss, S, beta, sigma, l_tilde, b_ellip, upsilon,
                     chi_n_vec, EulDiff)
        [solutions, infodict, ier, message] = \
            opt.fsolve(hh.bn_solve, guesses, args=bn_params,
                       xtol=SS_tol, full_output=True)
        euler_errors = infodict['fvec']
        print('Max Euler errors: ', np.absolute(euler_errors).max())
        b_splus1_ss = np.append(solutions[:S - 1], 0.0)
        n_ss = solutions[S - 1:]
        b_Sp1_ss = 0.0
        b_s_ss = np.append(0.0, b_splus1_ss[:-1])
        c_ss = hh.get_cons(r_ss, w_ss, b_s_ss, b_splus1_ss, n_ss)
    else:
        rpath = r_ss * np.ones(S)
        wpath = w_ss * np.ones(S)
        c1_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec,
                   rpath, wpath, EulDiff)
        c1_options = {'maxiter': 500}
        results_c1 = \
            opt.root(hh.c1_bSp1err, c1_new, args=(c1_args),
                     method='lm', tol=SS_tol, options=(c1_options))
        c1_ss = results_c1.x
        cnb_args = (0.0, beta, sigma, l_tilde, b_ellip, upsilon, chi_n_vec,
                    EulDiff)
        c_ss, n_ss, b_s_ss, b_Sp1_ss = hh.get_cnb_vecs(c1_ss, rpath, wpath,
                                                       cnb_args)
        b_splus1_ss = np.append(b_s_ss[1:], b_Sp1_ss)

    L_ss = aggr.get_L_s(n_ss)
    K_s_ss, K_cnstr = aggr.get_K_s(b_s_ss)
    K_d_ss = firms.get_K_d(r_ss, L_ss, K_params)
    Y_params = (A, alpha)
    Y_ss = aggr.get_Y(Y_params, K_d_ss, L_ss)
    C_ss = aggr.get_C(c_ss)
    n_err_args = (w_ss, c_ss, sigma, l_tilde, chi_n_vec, b_ellip, upsilon,
                  EulDiff)
    n_err_ss = hh.get_n_errors(n_ss, n_err_args)
    b_err_params = (beta, sigma)
    b_err_ss = hh.get_b_errors(b_err_params, r_ss, c_ss, EulDiff)
    NX_ss = Y_ss - C_ss - delta * K_s_ss
    RCerr_ss = Y_ss - C_ss - delta * K_s_ss - NX_ss

    ss_time = time.clock() - start_time

    ss_output = {
        'n_ss': n_ss,
        'b_s_ss': b_s_ss,
        'b_splus1_ss': b_splus1_ss,
        'c_ss': c_ss,
        'b_Sp1_ss': b_Sp1_ss,
        'w_ss': w_ss,
        'r_ss': r_ss,
        'K_s_ss': K_s_ss,
        'K_d_ss': K_d_ss,
        'L_ss': L_ss,
        'Y_ss': Y_ss,
        'C_ss': C_ss,
        'n_err_ss': n_err_ss,
        'b_err_ss': b_err_ss,
        'RCerr_ss': RCerr_ss,
        'ss_time': ss_time
    }
    print('n_ss is: ', n_ss)
    print('b_splus1_ss is: ', b_splus1_ss)
    print('K_s_ss=', K_s_ss, 'K_d_ss=', K_d_ss, ', L_ss=', L_ss)
    print('r_ss=', r_ss, ', w_ss=', w_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('Net Exports = ', NX_ss)
    print('Output and consumption: ', Y_ss, C_ss)
    print('Steady-state residual savings b_Sp1 is: ', b_Sp1_ss)

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

    if graphs:
        '''
        ----------------------------------------------------------------
        cur_path    = string, path name of current directory
        output_fldr = string, folder in current path to save files
        output_dir  = string, total path of images folder
        output_path = string, path of file name of figure to be saved
        age_pers    = (S,) vector, ages from 1 to S
        ----------------------------------------------------------------
        '''
        # Create directory if images directory does not already exist
        cur_path = os.path.split(os.path.abspath(__file__))[0]
        output_fldr = 'images'
        output_dir = os.path.join(cur_path, output_fldr)
        if not os.access(output_dir, os.F_OK):
            os.makedirs(output_dir)

        # Plot steady-state consumption and savings distributions
        age_pers = np.arange(1, S + 1)
        fig, ax = plt.subplots()
        plt.plot(age_pers, c_ss, marker='D', label='Consumption')
        plt.plot(age_pers, b_splus1_ss, marker='D', label='Savings')
        # for the minor ticks, use no labels; default NullFormatter
        minorLocator = MultipleLocator(1)
        ax.xaxis.set_minor_locator(minorLocator)
        plt.grid(b=True, which='major', color='0.65', linestyle='-')
        # plt.title('Steady-state consumption and savings', fontsize=20)
        plt.xlabel(r'Age $s$')
        plt.ylabel(r'Units of consumption')
        plt.xlim((0, S + 1))
        # plt.ylim((-1.0, 1.15 * (b_ss.max())))
        plt.legend(loc='upper left')
        output_path = os.path.join(output_dir, 'SS_bc')
        plt.savefig(output_path)
        # plt.show()
        plt.close()

        # Plot steady-state labor supply distributions
        fig, ax = plt.subplots()
        plt.plot(age_pers, n_ss, marker='D', label='Labor supply')
        # for the minor ticks, use no labels; default NullFormatter
        minorLocator = MultipleLocator(1)
        ax.xaxis.set_minor_locator(minorLocator)
        plt.grid(b=True, which='major', color='0.65', linestyle='-')
        # plt.title('Steady-state labor supply', fontsize=20)
        plt.xlabel(r'Age $s$')
        plt.ylabel(r'Labor supply')
        plt.xlim((0, S + 1))
        # plt.ylim((-0.1, 1.15 * (n_ss.max())))
        plt.legend(loc='upper right')
        output_path = os.path.join(output_dir, 'SS_n')
        plt.savefig(output_path)
        # plt.show()
        plt.close()

    return ss_output
예제 #7
0
def get_SS_bsct(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 for
    the outer loop
    --------------------------------------------------------------------
    INPUTS:
    init_vals = length 3 tuple, (Kss_init, Lss_init, c1_init)
    args      = length 15 tuple, (J, S, lambdas, emat, beta, sigma,
                l_tilde, b_ellip, upsilon, chi_n_vec, A, alpha, delta,
                SS_tol, EulDiff)
    graphs    = boolean, =True if output steady-state graphs

    OTHER FUNCTIONS AND FILES CALLED BY THIS FUNCTION:
        firms.get_r()
        firms.get_w()
        hh.bn_solve()
        hh.c1_bSp1err()
        hh.get_cnb_vecs()
        aggr.get_K()
        aggr.get_L()
        aggr.get_Y()
        aggr.get_C()
        hh.get_cons()
        hh.get_n_errors()
        hh.get_b_errors()
        utils.print_time()

    OBJECTS CREATED WITHIN FUNCTION:
    start_time   = scalar > 0, clock time at beginning of program
    Kss_init     = scalar > 0, initial guess for steady-state aggregate
                   capital stock
    Lss_init     = scalar > 0, initial guess for steady-state aggregate
                   labor
    rss_init     = scalar > 0, initial guess for steady-state interest
                   rate
    wss_init     = scalar > 0, initial guess for steady-state wage
    c1_init      = scalar > 0, initial guess for first period consumpt'n
    S            = integer in [3, 80], number of periods an individual
                   lives
    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 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
    A            = scalar > 0, total factor productivity parameter in
                   firms' production function
    alpha        = scalar in (0,1), capital share of income
    delta        = scalar in [0,1], model-period depreciation rate of
                   capital
    SS_tol       = scalar > 0, tolerance level for steady-state fsolve
    EulDiff      = Boolean, =True if want difference version of Euler
                   errors beta*(1+r)*u'(c2) - u'(c1), =False if want
                   ratio version [beta*(1+r)*u'(c2)]/[u'(c1)] - 1
    hh_fsolve    = boolean, =True if solve inner-loop household problem
                   by choosing c_1 to set final period savings b_{S+1}=0
    KL_outer     = boolean, =True if guess K and L in outer loop
                   Otherwise, guess r and w in outer loop
    maxiter_SS   = integer >= 1, maximum number of iterations in outer
                   loop bisection method
    iter_SS      = integer >= 0, index of iteration number
    mindist_SS   = scalar > 0, minimum distance tolerance for
                   convergence
    dist_SS      = scalar > 0, distance metric for current iteration
    xi_SS        = scalar in (0,1], updating parameter
    KL_init      = (2,) vector, (K_init, L_init)
    c1_options   = length 1 dict, options to pass into
                   opt.root(c1_bSp1err,...)
    cnb_args     = length 8 tuple, args to pass into get_cnb_vecs()
    r_params     = length 3 tuple, args to pass into get_r()
    w_params     = length 2 tuple, args to pass into get_w()
    K_init       = scalar, initial value of aggregate capital stock
    L_init       = scalar, initial value of aggregate labor
    r_init       = scalar, initial value for interest rate
    w_init       = scalar, initial value for wage
    rpath        = (S,) vector, lifetime path of interest rates
    wpath        = (S,) vector, lifetime path of wages
    c1_args      = length 10 tuple, args to pass into c1_bSp1err()
    results_c1   = results object, root finder results from
                   opt.root(c1_bSp1err,...)
    c1_new       = scalar, updated value of optimal c1 given r_init and
                   w_init
    cvec_new     = (S,) vector, updated values for lifetime consumption
    nvec_new     = (S,) vector, updated values for lifetime labor supply
    bvec_new     = (S,) vector, updated values for lifetime savings
                   (b1, b2,...bS)
    b_Sp1_new    = scalar, updated value for savings in last period,
                   should be arbitrarily close to zero
    K_new        = scalar, updated K given bvec_new
    K_cnstr      = boolean, =True if K_new <= 0
    L_new        = scalar, updated L given nvec_new
    KL_new       = (2,) vector, updated K and L given bvec_new, nvec_new
    K_ss         = scalar > 0, steady-state aggregate capital stock
    L_ss         = scalar > 0, steady-state aggregate labor
    r_ss         = scalar > 0, steady-state interest rate
    w_ss         = scalar > 0, steady-state wage
    c1_ss        = scalar > 0, steady-state consumption in first period
    c_ss         = (S,) vector, steady-state lifetime consumption
    n_ss         = (S,) vector, steady-state lifetime labor supply
    b_ss         = (S,) vector, steady-state lifetime savings
                   (b1_ss, b2_ss, ...bS_ss) where b1_ss=0
    b_Sp1_ss     = scalar, steady-state savings for period after last
                   period of life. b_Sp1_ss approx. 0 in equilibrium
    Y_params     = length 2 tuple, (A, alpha)
    Y_ss         = scalar > 0, steady-state aggregate output (GDP)
    C_ss         = scalar > 0, steady-state aggregate consumption
    n_err_params = length 5 tuple, args to pass into get_n_errors()
    n_err_ss     = (S,) vector, lifetime labor supply Euler errors
    b_err_params = length 2 tuple, args to pass into get_b_errors()
    b_err_ss     = (S-1) vector, lifetime savings Euler errors
    RCerr_ss     = scalar, resource constraint error
    ss_time      = scalar, seconds elapsed to run steady-state comput'n
    ss_output    = length 14 dict, steady-state objects {n_ss, b_ss,
                   c_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}

    FILES CREATED BY THIS FUNCTION:
        SS_bc.png
        SS_n.png

    RETURNS: ss_output
    --------------------------------------------------------------------
    '''
    start_time = time.clock()
    Kss_init, Lss_init, c1_init = init_vals
    (J, S, lambdas, emat, beta, sigma, l_tilde, b_ellip, upsilon,
        chi_n_vec, A, alpha, delta, SS_tol, EulDiff) = args
    maxiter_SS = 200
    iter_SS = 0
    mindist_SS = 1e-12
    dist_SS = 10
    xi_SS = 0.2
    KL_init = np.array([Kss_init, Lss_init])
    c1_options = {'maxiter': 500}
    r_params = (A, alpha, delta)
    w_params = (A, alpha)
    while (iter_SS < maxiter_SS) and (dist_SS >= mindist_SS):
        iter_SS += 1
        K_init, L_init = KL_init
        r_init = firms.get_r(r_params, K_init, L_init)
        w_init = firms.get_w(w_params, K_init, L_init)
        rpath = r_init * np.ones(S)
        wpath = w_init * np.ones(S)
        cmat = np.zeros((S, J))
        nmat = np.zeros((S, J))
        bmat = np.zeros((S, J))
        b_Sp1_vec = np.zeros(J)
        for j in range(J):
            c1_args = (0.0, emat[:, j], beta, sigma, l_tilde, b_ellip,
                       upsilon, chi_n_vec, rpath, wpath, EulDiff)
            results_c1 = \
                opt.root(hh.c1_bSp1err, c1_init, args=(c1_args),
                         method='lm', tol=SS_tol, options=(c1_options))
            c1 = results_c1.x
            cnb_args = (0.0, emat[:, j], beta, sigma, l_tilde, b_ellip,
                        upsilon, chi_n_vec, EulDiff)
            cmat[:, j], nmat[:, j], bmat[:, j], b_Sp1_vec[j] = \
                hh.get_cnb_vecs(c1, rpath, wpath, cnb_args)
        K_new, K_cnstr = aggr.get_K(bmat, lambdas)
        L_new = aggr.get_L(nmat, emat, lambdas)
        KL_new = np.array([K_new, L_new])
        dist_SS = ((KL_new - KL_init) ** 2).sum()
        KL_init = xi_SS * KL_new + (1 - xi_SS) * KL_init
        print('SS Iteration=', iter_SS, ', SS Distance=',
              '%10.4e' % (dist_SS), ',K:', '%10.4e' % (K_new),
              'L:', '%10.4e' % (L_new))

    K_ss, L_ss = KL_init
    r_ss = firms.get_r(r_params, K_ss, L_ss)
    w_ss = firms.get_w(w_params, K_ss, L_ss)
    c_ss = cmat
    n_ss = nmat
    b_ss = bmat
    b_Sp1_ss = b_Sp1_vec
    Y_params = (A, alpha)
    Y_ss = aggr.get_Y(Y_params, K_ss, L_ss)
    C_ss = aggr.get_C(c_ss, lambdas)
    n_err_ss = np.zeros((S, J))
    b_err_ss = np.zeros((S - 1, J))
    for j in range(J):
        n_err_params = (emat[:, j], sigma, l_tilde, chi_n_vec, b_ellip,
                        upsilon)
        n_err_ss[:, j] = hh.get_n_errors(n_err_params, w_ss, c_ss[:, j],
                                         n_ss[:, j], EulDiff)
        b_err_params = (beta, sigma)
        b_err_ss[:, j] = hh.get_b_errors(b_err_params, r_ss, c_ss[:, j],
                                         EulDiff)
    RCerr_ss = Y_ss - C_ss - delta * K_ss

    ss_time = time.clock() - start_time

    ss_output = {
        'n_ss': n_ss, 'b_ss': b_ss, 'c_ss': c_ss, 'b_Sp1_ss': b_Sp1_ss,
        'w_ss': w_ss, 'r_ss': r_ss, 'K_ss': K_ss, 'L_ss': L_ss,
        'Y_ss': Y_ss, 'C_ss': C_ss, 'n_err_ss': n_err_ss,
        'b_err_ss': b_err_ss, 'RCerr_ss': RCerr_ss, 'ss_time': ss_time}
    print('K_ss=', K_ss, ', L_ss=', L_ss)
    print('r_ss=', r_ss, ', w_ss=', w_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('Max. absolute SS residual savings b_Sp1_j is: ',
          np.absolute(b_Sp1_ss).max())

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

    if graphs:
        '''
        ----------------------------------------------------------------
        cur_path    = string, path name of current directory
        output_fldr = string, folder in current path to save files
        output_dir  = string, total path of images folder
        output_path = string, path of file name of figure to be saved
        sgrid       = (S,) vector, ages from 1 to S
        lamcumsum   = (J,) vector, cumulative sum of lambdas vector
        jmidgrid    = (J,) vector, midpoints of ability percentile bins
        smat        = (J, S) matrix, sgrid copied down J rows
        jmat        = (J, S) matrix, jmidgrid copied across S columns
        ----------------------------------------------------------------
        '''
        # Create directory if images directory does not already exist
        cur_path = os.path.split(os.path.abspath(__file__))[0]
        output_fldr = 'images'
        output_dir = os.path.join(cur_path, output_fldr)
        if not os.access(output_dir, os.F_OK):
            os.makedirs(output_dir)

        # Plot 3D steady-state consumption distribution
        sgrid = np.arange(1, S + 1)
        lamcumsum = lambdas.cumsum()
        jmidgrid = 0.5 * lamcumsum + 0.5 * (lamcumsum - lambdas)
        smat, jmat = np.meshgrid(sgrid, jmidgrid)
        cmap_c = cm.get_cmap('summer')
        fig = plt.figure()
        ax = fig.gca(projection='3d')
        ax.set_xlabel(r'age-$s$')
        ax.set_ylabel(r'ability-$j$')
        ax.set_zlabel(r'indiv. consumption $c_{j,s}$')
        ax.plot_surface(smat, jmat, c_ss.T, rstride=1,
                        cstride=6, cmap=cmap_c)
        output_path = os.path.join(output_dir, 'c_ss_3D')
        plt.savefig(output_path)
        # plt.show()
        plt.close()

        # Plot 2D steady-state consumption distribution
        minorLocator = MultipleLocator(1)
        fig, ax = plt.subplots()
        linestyles = np.array(["-", "--", "-.", ":"])
        markers = np.array(["x", "v", "o", "d", ">", "|"])
        pct_lb = 0
        for j in range(J):
            this_label = (str(int(np.rint(pct_lb))) + " - " +
                          str(int(np.rint(pct_lb + 100 * lambdas[j]))) +
                          "%")
            pct_lb += 100 * lambdas[j]
            if j <= 3:
                ax.plot(sgrid, c_ss[:, j], label=this_label,
                        linestyle=linestyles[j], color='black')
            elif j > 3:
                ax.plot(sgrid, c_ss[:, j], label=this_label,
                        marker=markers[j - 4], color='black')
        ax.xaxis.set_minor_locator(minorLocator)
        plt.grid(b=True, which='major', color='0.65', linestyle='-')
        box = ax.get_position()
        ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
        ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
        ax.set_xlabel(r'age-$s$')
        ax.set_ylabel(r'indiv. consumption $c_{j,s}$')
        output_path = os.path.join(output_dir, 'c_ss_2D')
        plt.savefig(output_path)
        # plt.show()
        plt.close()


        # Plot 3D steady-state labor supply distribution
        fig = plt.figure()
        ax = fig.gca(projection='3d')
        ax.set_xlabel(r'age-$s$')
        ax.set_ylabel(r'ability-$j$')
        ax.set_zlabel(r'labor supply $n_{j,s}$')
        ax.plot_surface(smat, jmat, n_ss.T, rstride=1,
                        cstride=6, cmap=cmap_c)
        output_path = os.path.join(output_dir, 'n_ss_3D')
        plt.savefig(output_path)
        # plt.show()
        plt.close()

        # Plot 2D steady-state labor supply distribution
        minorLocator = MultipleLocator(1)
        fig, ax = plt.subplots()
        linestyles = np.array(["-", "--", "-.", ":"])
        markers = np.array(["x", "v", "o", "d", ">", "|"])
        pct_lb = 0
        for j in range(J):
            this_label = (str(int(np.rint(pct_lb))) + " - " +
                          str(int(np.rint(pct_lb + 100 * lambdas[j]))) +
                          "%")
            pct_lb += 100 * lambdas[j]
            if j <= 3:
                ax.plot(sgrid, n_ss[:, j], label=this_label,
                        linestyle=linestyles[j], color='black')
            elif j > 3:
                ax.plot(sgrid, n_ss[:, j], label=this_label,
                        marker=markers[j - 4], color='black')
        ax.xaxis.set_minor_locator(minorLocator)
        plt.grid(b=True, which='major', color='0.65', linestyle='-')
        box = ax.get_position()
        ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
        ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
        ax.set_xlabel(r'age-$s$')
        ax.set_ylabel(r'labor supply $n_{j,s}$')
        output_path = os.path.join(output_dir, 'n_ss_2D')
        plt.savefig(output_path)
        # plt.show()
        plt.close()


        # Plot 3D steady-state savings/wealth distribution
        fig = plt.figure()
        ax = fig.gca(projection='3d')
        ax.set_xlabel(r'age-$s$')
        ax.set_ylabel(r'ability-$j$')
        ax.set_zlabel(r'indiv. savings $b_{j,s}$')
        ax.plot_surface(smat, jmat, b_ss.T, rstride=1,
                        cstride=6, cmap=cmap_c)
        output_path = os.path.join(output_dir, 'b_ss_3D')
        plt.savefig(output_path)
        # plt.show()
        plt.close()

        # Plot 2D steady-state savings/wealth distribution
        fig, ax = plt.subplots()
        linestyles = np.array(["-", "--", "-.", ":"])
        markers = np.array(["x", "v", "o", "d", ">", "|"])
        pct_lb = 0
        for j in range(J):
            this_label = (str(int(np.rint(pct_lb))) + " - " +
                          str(int(np.rint(pct_lb + 100 * lambdas[j]))) +
                          "%")
            pct_lb += 100 * lambdas[j]
            if j <= 3:
                ax.plot(sgrid, b_ss[:, j], label=this_label,
                        linestyle=linestyles[j], color='black')
            elif j > 3:
                ax.plot(sgrid, b_ss[:, j], label=this_label,
                        marker=markers[j - 4], color='black')
        ax.xaxis.set_minor_locator(minorLocator)
        plt.grid(b=True, which='major', color='0.65', linestyle='-')
        box = ax.get_position()
        ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
        ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))
        ax.set_xlabel(r'age-$s$')
        ax.set_ylabel(r'indiv. savings $b_{j,s}$')
        output_path = os.path.join(output_dir, 'b_ss_2D')
        plt.savefig(output_path)
        # plt.show()
        plt.close()

    return ss_output