def euler_errors(sim, sol, par):

    # unpack
    euler_error = sim.euler_error
    euler_error_c = sim.euler_error_c

    for i in prange(par.simN):

        discrete_plus = np.zeros(1)
        d_plus = np.zeros(1)
        c_plus = np.zeros(1)
        a_plus = np.zeros(1)

        for t in range(par.simT - 1):

            constrained = sim.a[t, i] < par.euler_cutoff

            if constrained:

                euler_error[t, i] = np.nan
                euler_error_c[t, i] = np.nan
                continue

            else:

                LHS = utility.marg_func(sim.c[t, i], sim.d[t, i], par)
                RHS = 0.0

                for ishock in range(par.Nshocks):

                    # i. shocks
                    psi = par.psi[ishock]
                    psi_w = par.psi_w[ishock]
                    xi = par.xi[ishock]
                    xi_w = par.xi_w[ishock]

                    # ii. next-period states
                    p_plus = trans.p_plus_func(sim.p[t, i], psi, par)
                    n_plus = trans.n_plus_func(sim.d[t, i], par)
                    m_plus = trans.m_plus_func(sim.a[t, i], p_plus, xi, par)
                    x_plus = trans.x_plus_func(m_plus, n_plus, par)

                    # iii. weight
                    weight = psi_w * xi_w

                    # iv. next-period choices
                    optimal_choice(t + 1, p_plus, n_plus, m_plus, x_plus,
                                   discrete_plus, d_plus, c_plus, a_plus, sol,
                                   par)

                    # v. next-period marginal utility
                    RHS += weight * par.beta * par.R * utility.marg_func(
                        c_plus[0], d_plus[0], par)

                euler_error[t, i] = LHS - RHS
                euler_error_c[t, i] = sim.c[t, i]
def solve(sol,par,G2EGM=True):

    # a. last_period
    t = par.T-1

    sol.m_ret[t,:] = par.grid_m_ret
    sol.c_ret[t,:] = sol.m_ret[t,:]
    
    v = utility.func_ret(sol.c_ret[t,:],par)
    sol.inv_v_ret[t,:] = -1.0/v
    
    vm = utility.marg_func(sol.c_ret[t,:],par)
    sol.inv_vm_ret[t,:] = 1.0/vm
    if G2EGM:
        sol.inv_vn_ret[t,:] = sol.inv_vm_ret[t,:]

    # b. backwards inducation
    for j in range(2,par.T+1):
        
        t = par.T-j

        # i. optimal c choice
        m_plus = par.Ra*par.grid_a_ret + par.yret
        c_plus = np.zeros(m_plus.shape)
        linear_interp.interp_1d_vec(sol.m_ret[t+1,:],sol.c_ret[t+1,:],m_plus,c_plus)
        
        vm_plus = utility.marg_func(c_plus,par) 
        q = par.beta*par.Ra*vm_plus
        sol.c_ret[t,par.Nmcon_ret:] = utility.inv_marg_func(q,par)

        # ii. constraint            
        sol.c_ret[t,:par.Nmcon_ret] = nonlinspace_jit(1e-6,sol.c_ret[t,par.Nmcon_ret]*0.999,par.Nmcon_ret,par.phi_m)
    
        # iii. end-of-period assets and value-of-choice
        sol.a_ret[t,par.Nmcon_ret:] = par.grid_a_ret
        
        inv_v_plus = np.zeros(m_plus.shape)
        linear_interp.interp_1d_vec(sol.m_ret[t+1,:],sol.inv_v_ret[t+1,:],m_plus,inv_v_plus)
        v_plus = -1.0/inv_v_plus

        v1 = utility.func_ret(sol.c_ret[t,:par.Nmcon_ret],par) + par.beta*v_plus[0] 
        v2 = utility.func_ret(sol.c_ret[t,par.Nmcon_ret:],par) + par.beta*v_plus

        sol.inv_v_ret[t,:par.Nmcon_ret] = -1.0/v1
        sol.inv_v_ret[t,par.Nmcon_ret:] = -1.0/v2
                
        # iv. endogenous grid
        sol.m_ret[t,:] = sol.a_ret[t,:] + sol.c_ret[t,:]

        # v. marginal v
        vm = utility.marg_func(sol.c_ret[t,:],par)
        sol.inv_vm_ret[t,:] = 1.0/vm
        if G2EGM:
            sol.inv_vn_ret[t,:] = sol.inv_vm_ret[t,:]
Esempio n. 3
0
def solve(sol, par, G2EGM=True):

    # unpack
    t = par.T - 1
    c = sol.c[t]
    d = sol.d[t]
    inv_v = sol.inv_v[t]
    inv_vm = sol.inv_vm[t]
    if G2EGM:
        inv_vn = sol.inv_vn[t]

    for i_n in range(par.Nn):

        # i. states
        m = par.grid_m
        n = par.grid_n[i_n]

        # ii. consume everything
        d[i_n, :] = 0
        c[i_n, :] = m + n

        # iii. value function
        v = utility.func(c[i_n, :], par)
        inv_v[i_n, :] = -1.0 / v

        # iv. value function derivatives
        vm = utility.marg_func(c[i_n, :], par)
        inv_vm[i_n, :] = 1.0 / vm
        if G2EGM:
            inv_vn[i_n, :] = inv_vm[i_n, :]
def solve_acon(out_c,out_d,out_v,w,wb,par):

    num = 3

    # i. allocate
    c = np.zeros((par.Nc_acon,par.Nb_acon))
    d = np.zeros((par.Nc_acon,par.Nb_acon))
    a = np.zeros((par.Nc_acon,par.Nb_acon))
    b = np.zeros((par.Nc_acon,par.Nb_acon))
    w_acon = np.zeros((par.Nc_acon,par.Nb_acon))

    for i_b in range(par.Nb_acon):
        
        # ii. setup
        wb_acon = linear_interp.interp_2d(par.grid_b_pd,par.grid_a_pd,wb,par.b_acon[i_b],0)

        c_min = utility.inv_marg_func((par.chi+1)*wb_acon,par)
        c_max = utility.inv_marg_func(wb_acon,par)

        c[:,i_b] = misc.nonlinspace_jit(c_min,c_max,par.Nc_acon,par.phi_m)
        
        # iii. choices
        d[:,i_b] = par.chi/(utility.marg_func(c[:,i_b],par)/(wb_acon)-1)-1
                        
        # iv. post-decision states and value function
        b[:,i_b] = par.b_acon[i_b]
        w_acon[:,i_b] = linear_interp.interp_2d(par.grid_b_pd,par.grid_a_pd,w,par.b_acon[i_b],0)
                
    # v. states and value
    m,n,v = inv_mn_and_v(c,d,a,b,w_acon,par)
                    
    # vi. upperenvelope and interp to common
    upperenvelope.compute(out_c,out_d,out_v,m,n,c,d,v,num,w,par)
def solve(t,sol,par):

    w = sol.w[t]
    wa = sol.wa[t]
    wb = sol.wb[t]

    # a. solve each segment
    solve_ucon(sol.ucon_c[t,:,:],sol.ucon_d[t,:,:],sol.ucon_v[t,:,:],w,wa,wb,par)
    solve_dcon(sol.dcon_c[t,:,:],sol.dcon_d[t,:,:],sol.dcon_v[t,:,:],w,wa,par)
    solve_acon(sol.acon_c[t,:,:],sol.acon_d[t,:,:],sol.acon_v[t,:,:],w,wb,par)
    solve_con(sol.con_c[t,:,:],sol.con_d[t,:,:],sol.con_v[t,:,:],w,par)

    # b. upper envelope    
    seg_max = np.zeros(4)
    for i_n in range(par.Nn):
        for i_m in range(par.Nm):

            # i. find max
            seg_max[0] = sol.ucon_v[t,i_n,i_m]
            seg_max[1] = sol.dcon_v[t,i_n,i_m]
            seg_max[2] = sol.acon_v[t,i_n,i_m]
            seg_max[3] = sol.con_v[t,i_n,i_m]

            i = np.argmax(seg_max)

            # ii. over-arching optimal choices
            sol.inv_v[t,i_n,i_m] = -1.0/seg_max[i]

            if i == 0:
                sol.c[t,i_n,i_m] = sol.ucon_c[t,i_n,i_m]
                sol.d[t,i_n,i_m] = sol.ucon_d[t,i_n,i_m]
            elif i == 1:
                sol.c[t,i_n,i_m] = sol.dcon_c[t,i_n,i_m]
                sol.d[t,i_n,i_m] = sol.dcon_d[t,i_n,i_m]
            elif i == 2:
                sol.c[t,i_n,i_m] = sol.acon_c[t,i_n,i_m]
                sol.d[t,i_n,i_m] = sol.acon_d[t,i_n,i_m]
            elif i == 3:
                sol.c[t,i_n,i_m] = sol.con_c[t,i_n,i_m]
                sol.d[t,i_n,i_m] = sol.con_d[t,i_n,i_m]
        
    # c. derivatives 
    
    # i. m
    vm = utility.marg_func(sol.c[t],par)
    sol.inv_vm[t,:,:] = 1.0/vm

    # ii. n         
    a = par.grid_m_nd - sol.c[t] - sol.d[t]
    b = par.grid_n_nd + sol.d[t] + pens.func(sol.d[t],par)

    wb_now = np.zeros(a.shape)
    linear_interp.interp_2d_vec(par.grid_b_pd,par.grid_a_pd,wb,b.ravel(),a.ravel(),wb_now.ravel())
    
    vn = wb_now
    sol.inv_vn[t,:,:] = 1.0/vn
Esempio n. 6
0
def compute_q(sol, par, t, t_plus):
    """ compute the post-decision function q """

    # unpack (helps numba optimize)
    q = sol.q

    # loop over delta
    for idelta in prange(par.Ndelta):

        # clean-up
        q[t, idelta, :] = 0

        # temp
        m_plus = np.empty(par.Na)
        c_plus = np.empty(par.Na)

        # loop over shock
        for ishock in range(par.Nshocks):

            # i. shocks
            psi = par.psi[ishock]
            psi_w = par.psi_w[ishock]
            xi = par.xi[ishock]
            xi_w = par.xi_w[ishock]
            weight = psi_w * xi_w

            # ii. next-period extra income component
            delta_plus = par.grid_delta[idelta] / (psi * par.G)
            if t == 0:
                delta_plus *= par.zeta

            # ii. next-period cash-on-hand
            for ia in range(par.Na):
                m_plus[ia] = par.R * par.grid_a[ia] / (psi * par.G) + xi

            # iii. next-period consumption
            if par.Ndelta > 1:
                prep = linear_interp.interp_2d_prep(par.grid_delta, delta_plus,
                                                    par.Na)
            else:
                prep = linear_interp.interp_1d_prep(par.Na)

            if par.Ndelta > 1:
                linear_interp.interp_2d_only_last_vec_mon(
                    prep, par.grid_delta, par.grid_m, sol.c[t_plus],
                    delta_plus, m_plus, c_plus)
            else:
                linear_interp.interp_1d_vec_mon(prep, par.grid_m,
                                                sol.c[t_plus,
                                                      idelta], m_plus, c_plus)

            # iv. accumulate all
            for ia in range(par.Na):
                q[t, idelta,
                  ia] += weight * par.R * par.beta * utility.marg_func(
                      par.G * psi * c_plus[ia], par)
def shocks_GH(t, inc_no_shock, inc, w, c, m, v, par, d_plus):
    """ compute v_plus_raw and avg_marg_u_plus using GaussHermite integration if necessary """

    # a. initialize
    c_plus_interp = np.zeros((4, inc_no_shock.size))
    v_plus_interp = np.zeros((4, inc_no_shock.size))
    v_plus_raw = np.zeros(inc_no_shock.size)
    avg_marg_u_plus = np.zeros(inc_no_shock.size)
    prep = linear_interp.interp_1d_prep(
        len(inc_no_shock
            ))  # save the position of numbers to speed up interpolation

    # b. loop over GH-nodes
    for i in range(len(w)):
        m_plus = inc_no_shock + inc[i]

        # 1. interpolate
        for d in d_plus:
            linear_interp.interp_1d_vec_mon(prep, m[:], c[d, :], m_plus,
                                            c_plus_interp[d, :])
            linear_interp.interp_1d_vec_mon_rep(prep, m[:], v[d, :], m_plus,
                                                v_plus_interp[d, :])

        # 2. logsum and v_plus_raw
        if len(d_plus) == 1:  # no taste shocks
            v_plus_raw += w[i] * v_plus_interp[d_plus[0], :]
            avg_marg_u_plus += w[i] * utility.marg_func(
                c_plus_interp[d_plus[0], :], par)

        elif len(d_plus) == 2:  # taste shocks
            logsum, prob = funs.logsum2(v_plus_interp[d_plus, :], par)
            v_plus_raw += w[i] * logsum[0, :]
            marg_u_plus = prob[d_plus[0], :] * utility.marg_func(
                c_plus_interp[d_plus[0], :],
                par) + (1 - prob[d_plus[0], :]) * utility.marg_func(
                    c_plus_interp[d_plus[1], :], par)
            avg_marg_u_plus += w[i] * marg_u_plus

        elif len(d_plus) == 4:  # both are working
            logsum, prob = funs.logsum4(v_plus_interp[d_plus, :], par)
            v_plus_raw += w[i] * logsum[0, :]
            marg_u_plus = (
                prob[0, :] * utility.marg_func(c_plus_interp[0, :], par) +
                prob[1, :] * utility.marg_func(c_plus_interp[1, :], par) +
                prob[2, :] * utility.marg_func(c_plus_interp[2, :], par) +
                prob[3, :] * utility.marg_func(c_plus_interp[3, :], par))
            avg_marg_u_plus += w[i] * marg_u_plus

    # c. return results
    return v_plus_raw, avg_marg_u_plus
def compute_wq_simple(t, sol, par, compute_w=False, compute_q=False):
    """ compute the post-decision functions w and/or q """

    # this is a variant of Algorithm 3 in Druedahl (2019): A Guide to Solve Non-Convex Consumption-Saving Problems

    # note: same result as compute_wq, simpler code, but much slower

    # unpack (helps numba optimize)
    w = sol.w
    q = sol.q

    # loop over outermost post-decision state
    for ip in prange(par.Np):  # in parallel

        for ia in range(par.Na):

            # initialize at zero
            if compute_w:
                w[ip, ia] = 0
            if compute_q:
                q[ip, ia] = 0

            for ishock in range(par.Nshocks):

                # i. shocks
                psi = par.psi[ishock]
                psi_w = par.psi_w[ishock]
                xi = par.xi[ishock]
                xi_w = par.xi_w[ishock]

                # ii. next-period states
                p_plus = par.grid_p[ip] * psi
                y_plus = p_plus * xi
                m_plus = par.R * par.grid_a[ia] + y_plus

                # iii. weights
                weight = psi_w * xi_w

                # iv. interpolate and accumulate
                if compute_w:
                    w[ip, ia] += weight * par.beta * linear_interp.interp_2d(
                        par.grid_p, par.grid_m, sol.v[t + 1], p_plus, m_plus)
                if compute_q:
                    c_plus_temp = linear_interp.interp_2d(
                        par.grid_p, par.grid_m, sol.c[t + 1], p_plus, m_plus)
                    q[ip, ia] += weight * par.R * par.beta * utility.marg_func(
                        c_plus_temp, par)
Esempio n. 9
0
def solve_outer(t,sol,par):

    # unpack output
    inv_v = sol.inv_v[t]
    inv_vm = sol.inv_vm[t]
    c = sol.c[t]
    d = sol.d[t]

    # loop over outer states
    for i_n in range(par.Nn):
            
        n = par.grid_n[i_n]

        # loop over m state
        for i_m in range(par.Nm):
            
            m = par.grid_m[i_m]
            
            # a. optimal choice
            d_low = 1e-8
            d_high = m-1e-8
            d[i_n,i_m] = golden_section_search.optimizer(obj_outer,d_low,d_high,args=(n,m,t,sol,par),tol=1e-8)

            # b. optimal value
            n_pure_c = n + d[i_n,i_m] + pens.func(d[i_n,i_m],par)
            m_pure_c = m - d[i_n,i_m]
            c[i_n,i_m] = np.fmin(linear_interp.interp_2d(par.grid_b_pd,par.grid_l,sol.c_pure_c[t],n_pure_c,m_pure_c),m_pure_c)
            inv_v[i_n,i_m] = -obj_outer(d[i_n,i_m],n,m,t,sol,par)

            # c. dcon
            obj_dcon = -obj_outer(0,n,m,t,sol,par)
            if obj_dcon > inv_v[i_n,i_m]:
                c[i_n,i_m] = linear_interp.interp_2d(par.grid_b_pd,par.grid_l,sol.c_pure_c[t],n,m)
                d[i_n,i_m] = 0
                inv_v[i_n,i_m] = obj_dcon

            # d. con
            w = linear_interp.interp_2d(par.grid_b_pd,par.grid_a_pd,sol.w[t],n,0)
            obj_con = -1.0/(utility.func(m,par) + w)
            if obj_con > inv_v[i_n,i_m]:
                c[i_n,i_m] = m
                d[i_n,i_m] = 0
                inv_v[i_n,i_m] = obj_con

            # e. derivative
            inv_vm[i_n,i_m] = 1.0/utility.marg_func(c[i_n,i_m],par)
Esempio n. 10
0
def euler_error(t, ma, st, ra, euler, sol, par, sim, idx, ds):
    """ compute euler errors for single model"""

    if idx.size > 0:

        # unpack
        sol_m = sol.m[:]
        sol_c = sol.c[:, ma, st]
        sol_v = sol.v[:, ma, st]
        c = sim.c[:, t]
        m = sim.m[:, t]
        a = sim.a[:, t]
        tol = par.tol
        pi_plus = transitions.survival_lookup_single(t + 1, ma, st, par)

        # 1. indices
        idx_in = idx[(tol < c[idx]) &
                     (c[idx] < m[idx] - tol)]  # inner solution

        # 2. prep
        if ds == 1:
            D = np.array([0, 1])
        elif ds == 0:
            D = np.array([0])
        idx_unsort = np.argsort(np.argsort(a[idx_in]))  # indices to unsort a
        a_sort = np.sort(
            a[idx_in]
        )  # sort a since post_decision.compute assumes a is monotone

        # 3. lhs and rhs
        avg_marg_u_plus = post_decision.compute(t, ma, st, ra, D, sol_c, sol_m,
                                                sol_v, a_sort, par)[1]
        lhs = utility.marg_func(c[idx_in], par)
        rhs = par.beta * (
            par.R * pi_plus * np.take(avg_marg_u_plus[ds], idx_unsort) +
            (1 - pi_plus) * par.gamma)
        fill_arr(euler[:, t], idx_in, lhs - rhs)
def euler(sim, sol, par):

    euler = sim.euler

    # a. grids
    min_m = 0.50
    min_n = 0.01

    m_max = 5.00
    n_max = 5.00

    n_grid = np.linspace(min_n, n_max, par.eulerK)
    m_grid = np.linspace(min_m, m_max, par.eulerK)

    # b. loop over time
    for t in range(par.T - 1):
        for i_n in range(par.eulerK):
            for i_m in range(par.eulerK):

                # i. states
                n = n_grid[i_n]
                m = m_grid[i_m]
                m_retire = m_grid[i_m] + n_grid[i_n]

                # ii. discrete choice
                inv_v_retire = linear_interp.interp_1d(sol.m_ret[t],
                                                       sol.inv_v_ret[t],
                                                       m_retire)
                inv_v = linear_interp.interp_2d(par.grid_n, par.grid_m,
                                                sol.inv_v[t], n, m)

                if inv_v_retire > inv_v: continue

                # iii. continuous choice
                c = np.fmin(
                    linear_interp.interp_2d(par.grid_n, par.grid_m, sol.c[t],
                                            n, m), m)
                d = np.fmax(
                    linear_interp.interp_2d(par.grid_n, par.grid_m, sol.d[t],
                                            n, m), 0)
                a = m - c - d
                b = n + d + pens.func(d, par)

                if a < 0.001: continue

                # iv. shocks
                RHS = 0
                for i_eta in range(par.Neta):

                    # o. state variables
                    n_plus = par.Rb * b
                    m_plus = par.Ra * a + par.eta[i_eta]
                    m_retire_plus = m_plus + n_plus

                    # oo. discrete choice
                    inv_v_retire = linear_interp.interp_1d(
                        sol.m_ret[t + 1], sol.inv_v_ret[t + 1], m_retire_plus)
                    inv_v = linear_interp.interp_2d(par.grid_n, par.grid_m,
                                                    sol.inv_v[t + 1], n_plus,
                                                    m_plus)

                    # ooo. continous choice
                    if inv_v_retire > inv_v:
                        c_plus = np.fmin(
                            linear_interp.interp_1d(sol.m_ret[t + 1],
                                                    sol.c_ret[t + 1],
                                                    m_retire_plus),
                            m_retire_plus)
                    else:
                        c_plus = np.fmin(
                            linear_interp.interp_2d(par.grid_n, par.grid_m,
                                                    sol.c[t + 1], n_plus,
                                                    m_plus), m_plus)

                    # oooo. accumulate
                    RHS += par.w_eta[
                        i_eta] * par.beta * par.Ra * utility.marg_func(
                            c_plus, par)

                # v. euler error
                euler_raw = c - utility.inv_marg_func(RHS, par)
                euler[t, i_m, i_n] = np.log10(np.abs(euler_raw / c) + 1e-16)
def compute_wq(t, sol, par, compute_w=False, compute_q=False):
    """ compute the post-decision functions w and/or q """

    # this is a variant of Algorithm 5 in Druedahl (2019): A Guide to Solve Non-Convex Consumption-Saving Problems

    # unpack (helps numba optimize)
    w = sol.w
    q = sol.q

    # loop over outermost post-decision state
    for ip in prange(par.Np):  # in parallel

        # a. permanent income
        p = par.grid_p[ip]

        # b. allocate containers and initialize at zero
        m_plus = np.empty(par.Na)
        if compute_w:
            w[ip, :] = 0
            v_plus = np.empty(par.Na)
        if compute_q:
            q[ip, :] = 0
            c_plus = np.empty(par.Na)

        # c. loop over shocks and then end-of-period assets
        for ishock in range(par.Nshocks):

            # i. shocks
            psi = par.psi[ishock]
            psi_w = par.psi_w[ishock]
            xi = par.xi[ishock]
            xi_w = par.xi_w[ishock]

            # ii. next-period income
            p_plus = p * psi
            y_plus = p_plus * xi

            # iii. prepare interpolation in p direction
            prep = linear_interp.interp_2d_prep(par.grid_p, p_plus, par.Na)

            # iv. weight
            weight = psi_w * xi_w

            # v. next-period cash-on-hand and interpolate
            for ia in range(par.Na):
                m_plus[ia] = par.R * par.grid_a[ia] + y_plus

            # v_plus
            if compute_w:
                linear_interp.interp_2d_only_last_vec_mon(
                    prep, par.grid_p, par.grid_m, sol.v[t + 1], p_plus, m_plus,
                    v_plus)

            # c_plus
            if compute_q:
                linear_interp.interp_2d_only_last_vec_mon(
                    prep, par.grid_p, par.grid_m, sol.c[t + 1], p_plus, m_plus,
                    c_plus)

            # vi. accumulate all
            if compute_w:
                for ia in range(par.Na):
                    w[ip, ia] += weight * par.beta * v_plus[ia]
            if compute_q:
                for ia in range(par.Na):
                    q[ip, ia] += weight * par.R * par.beta * utility.marg_func(
                        c_plus[ia], par)
Esempio n. 13
0
def solve(t, sol, par):
    """ solve the problem in the last period """

    # unpack
    inv_v_keep = sol.inv_v_keep[t]
    inv_marg_u_keep = sol.inv_marg_u_keep[t]
    c_keep = sol.c_keep[t]
    inv_v_adj = sol.inv_v_adj[t]
    inv_marg_u_adj = sol.inv_marg_u_adj[t]
    d_adj = sol.d_adj[t]
    c_adj = sol.c_adj[t]

    # a. keep
    for i_p in prange(par.Np):
        for i_n in range(par.Nn):
            for i_m in range(par.Nm):

                # i. states
                n = par.grid_n[i_n]
                m = par.grid_m[i_m]

                if m == 0:  # forced c = 0
                    c_keep[i_p, i_n, i_m] = 0
                    inv_v_keep[i_p, i_n, i_m] = 0
                    inv_marg_u_keep[i_p, i_n, i_m] = 0
                    continue

                # ii. optimal choice
                c_keep[i_p, i_n, i_m] = m

                # iii. optimal value
                v_keep = utility.func(c_keep[i_p, i_n, i_m], n, par)
                inv_v_keep[i_p, i_n, i_m] = -1.0 / v_keep
                inv_marg_u_keep[i_p, i_n, i_m] = 1.0 / utility.marg_func(
                    c_keep[i_p, i_n, i_m], n, par)

    # b. adj
    for i_p in prange(par.Np):
        for i_x in range(par.Nx):

            # i. states
            x = par.grid_x[i_x]

            if x == 0:  # forced c = d = 0
                d_adj[i_p, i_x] = 0
                c_adj[i_p, i_x] = 0
                inv_v_adj[i_p, i_x] = 0
                inv_marg_u_adj[i_p, i_x] = 0
                continue

            # ii. optimal choices
            d_low = np.fmin(x / 2, 1e-8)
            d_high = np.fmin(x, par.n_max)
            d_adj[i_p, i_x] = golden_section_search.optimizer(
                d_low, d_high, par.tol, obj_last_period, x, par)
            c_adj[i_p, i_x] = x - d_adj[i_p, i_x]

            # iii. optimal value
            v_adj = -obj_last_period(d_adj[i_p, i_x], x, par)
            inv_v_adj[i_p, i_x] = -1.0 / v_adj
            inv_marg_u_adj[i_p, i_x] = 1.0 / utility.marg_func(
                c_adj[i_p, i_x], d_adj[i_p, i_x], par)
Esempio n. 14
0
def euler_errors(sim, sol, par):

    # unpack
    euler_error = sim.euler_error
    euler_error_c = sim.euler_error_c

    for i in prange(par.simN):

        discrete_plus = np.zeros(1)
        d_plus = np.zeros(1)
        d1_plus = np.zeros(1)
        d2_plus = np.zeros(1)
        c_plus = np.zeros(1)
        a_plus = np.zeros(1)

        for t in range(par.T - 1):

            constrained = sim.a[t, i] < par.euler_cutoff

            if constrained:

                euler_error[t, i] = np.nan
                euler_error_c[t, i] = np.nan
                continue

            else:

                RHS = 0.0
                for ishock in range(par.Nshocks):

                    # i. shocks
                    psi = par.psi[ishock]
                    psi_w = par.psi_w[ishock]
                    xi = par.xi[ishock]
                    xi_w = par.xi_w[ishock]

                    # ii. next-period states
                    p_plus = trans.p_plus_func(sim.p[t, i], psi, par)
                    if par.do_2d:
                        n1_plus = trans.n1_plus_func(sim.d1[t, i], par)
                        n2_plus = trans.n2_plus_func(sim.d2[t, i], par)
                    else:
                        n_plus = trans.n_plus_func(sim.d[t, i], par)
                    m_plus = trans.m_plus_func(sim.a[t, i], p_plus, xi, par)

                    # iii. weight
                    weight = psi_w * xi_w

                    # iv. next-period choices
                    if par.do_2d:
                        optimal_choice_2d(t + 1, p_plus, n1_plus, n2_plus,
                                          m_plus, discrete_plus, d1_plus,
                                          d2_plus, c_plus, a_plus, sol, par)
                    else:
                        optimal_choice(t + 1, p_plus, n_plus, m_plus,
                                       discrete_plus, d_plus, c_plus, a_plus,
                                       sol, par)

                    # v. next-period marginal utility
                    if par.do_2d:
                        RHS += weight * par.beta * par.R * utility.marg_func_2d(
                            c_plus[0], d1_plus[0], d2_plus[0], par)
                    else:
                        RHS += weight * par.beta * par.R * utility.marg_func(
                            c_plus[0], d_plus[0], par)

                if par.do_2d:
                    euler_error[t, i] = sim.c[t, i] - utility.inv_marg_func_2d(
                        RHS, sim.d1[t, i], sim.d2[t, i], par)
                else:
                    euler_error[t, i] = sim.c[t, i] - utility.inv_marg_func(
                        RHS, sim.d[t, i], par)

                euler_error_c[t, i] = sim.c[t, i]