def lifecycle(sim, sol, par):
    """ simulate full life-cycle """

    # unpack
    p = sim.p
    n = sim.n
    m = sim.m
    x = sim.x
    c = sim.c
    d = sim.d
    a = sim.a
    discrete = sim.discrete

    for t in range(par.simT):
        for i in prange(par.simN):

            # a. beginning of period states
            if t == 0:
                p[t, i] = trans.p_plus_func(sim.p0[i], sim.psi[t, i], par)
                n[t, i] = trans.n_plus_func(sim.d0[i], par)
                m[t, i] = trans.m_plus_func(sim.a0[i], p[t, i], sim.xi[t, i],
                                            par)
            else:
                p[t, i] = trans.p_plus_func(p[t - 1, i], sim.psi[t, i], par)
                n[t, i] = trans.n_plus_func(d[t - 1, i], par)
                m[t, i] = trans.m_plus_func(a[t - 1, i], p[t, i], sim.xi[t, i],
                                            par)
            x[t, i] = trans.x_plus_func(m[t, i], n[t, i], par)

            optimal_choice(t, p[t, i], n[t, i], m[t, i], x[t, i], discrete[t,
                                                                           i:],
                           d[t, i:], c[t, i:], a[t, i:], sol, par)
예제 #2
0
def lifecycle(sim, sol, par):
    """ simulate full life-cycle """

    # unpack
    p = sim.p
    n = sim.n
    n1 = sim.n1
    n2 = sim.n2
    m = sim.m
    c = sim.c
    d = sim.d
    d1 = sim.d1
    d2 = sim.d2
    a = sim.a
    discrete = sim.discrete

    for t in range(par.T):
        for i in prange(par.simN):

            # a. beginning of period states
            if t == 0:
                p[t, i] = trans.p_plus_func(sim.p0[i], sim.psi[t, i], par)
                if par.do_2d:
                    n1[t, i] = trans.n1_plus_func(sim.d10[i], par)
                    n2[t, i] = trans.n2_plus_func(sim.d20[i], par)
                else:
                    n[t, i] = trans.n_plus_func(sim.d0[i], par)
                m[t, i] = trans.m_plus_func(sim.a0[i], p[t, i], sim.xi[t, i],
                                            par)
            else:
                p[t, i] = trans.p_plus_func(p[t - 1, i], sim.psi[t, i], par)
                if par.do_2d:
                    n1[t, i] = trans.n1_plus_func(d1[t - 1, i], par)
                    n2[t, i] = trans.n2_plus_func(d2[t - 1, i], par)
                else:
                    n[t, i] = trans.n_plus_func(d[t - 1, i], par)
                m[t, i] = trans.m_plus_func(a[t - 1, i], p[t, i], sim.xi[t, i],
                                            par)

            # b. optimal choices and post decision states
            if par.do_2d:
                optimal_choice_2d(t, p[t, i], n1[t, i], n2[t, i], m[t, i],
                                  discrete[t, i:], d1[t, i:], d2[t, i:],
                                  c[t, i:], a[t, i:], sol, par)
            else:
                optimal_choice(t, p[t, i], n[t, i], m[t, i], discrete[t, i:],
                               d[t, i:], c[t, i:], a[t, i:], sol, par)
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 value_of_choice(t, c, d, p, x, inv_v_keep, inv_v_adj, par):

    # a. end-of-period-assets
    a = x - c - d

    # b. continuation value
    w = 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(p, psi, par)
        n_plus = trans.n_plus_func(d, par)
        m_plus = trans.m_plus_func(a, p_plus, xi, par)
        x_plus = trans.x_plus_func(m_plus, n_plus, par)

        # iii. weight
        weight = psi_w * xi_w

        # iv. update
        inv_v_plus_keep_now = linear_interp.interp_3d(par.grid_p, par.grid_n,
                                                      par.grid_m,
                                                      inv_v_keep[t + 1],
                                                      p_plus, n_plus, m_plus)

        inv_v_plus_adj_now = linear_interp.interp_2d(par.grid_p, par.grid_x,
                                                     inv_v_adj[t + 1], p_plus,
                                                     x_plus)

        v_plus_now = -np.inf  # huge negative value

        if inv_v_plus_keep_now > inv_v_plus_adj_now and inv_v_plus_keep_now > 0:
            v_plus_now = -1 / inv_v_plus_keep_now
        elif inv_v_plus_adj_now > 0:
            v_plus_now = -1 / inv_v_plus_adj_now

        w += weight * par.beta * v_plus_now

    # v. total value
    v = utility.func(c, d, par) + w

    return v  # we are minimizing
예제 #5
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]
예제 #6
0
def compute_wq(t,sol,par,compute_q=False):
    """ compute the post-decision functions w and/or q """

    # unpack
    inv_w = sol.inv_w[t]
    q = sol.q[t]

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

        # allocate temporary containers
        m_plus = np.zeros(par.Na) # container, same lenght as grid_a
        x_plus = np.zeros(par.Na)
        w = np.zeros(par.Na) 
        inv_v_keep_plus = np.zeros(par.Na)
        inv_marg_u_keep_plus = np.zeros(par.Na)
        inv_v_adj_plus = np.zeros(par.Na)
        inv_marg_u_adj_plus = np.zeros(par.Na)
        
        # loop over other outer post-decision states
        for i_n in range(par.Nn):

            # a. permanent income and durable stock
            p = par.grid_p[i_p]
            n = par.grid_n[i_n]

            # b. initialize at zero
            for i_a in range(par.Na):
                w[i_a] = 0.0
                q[i_p,i_n,i_a] = 0.0

            # c. loop over shocks and then end-of-period assets
            for ishock in range(par.Nshocks):
                
                # i. shocks
                psi_plus = par.psi[ishock]
                psi_plus_w = par.psi_w[ishock]
                xi_plus = par.xi[ishock]
                xi_plus_w = par.xi_w[ishock]

                # ii. next-period income and durables
                p_plus = trans.p_plus_func(p,psi_plus,par)
                n_plus = trans.n_plus_func(n,par)

                # iii. prepare interpolators
                prep_keep = linear_interp.interp_3d_prep(par.grid_p,par.grid_n,p_plus,n_plus,par.Na)
                prep_adj = linear_interp.interp_2d_prep(par.grid_p,p_plus,par.Na)

                # iv. weight
                weight = psi_plus_w*xi_plus_w

                # v. next-period cash-on-hand and total resources
                for i_a in range(par.Na):
        
                    m_plus[i_a] = trans.m_plus_func(par.grid_a[i_a],p_plus,xi_plus,par)
                    x_plus[i_a] = trans.x_plus_func(m_plus[i_a],n_plus,par)
                
                # vi. interpolate
                linear_interp.interp_3d_only_last_vec_mon(prep_keep,par.grid_p,par.grid_n,par.grid_m,sol.inv_v_keep[t+1],p_plus,n_plus,m_plus,inv_v_keep_plus)
                linear_interp.interp_2d_only_last_vec_mon(prep_adj,par.grid_p,par.grid_x,sol.inv_v_adj[t+1],p_plus,x_plus,inv_v_adj_plus)
                if compute_q:
                    linear_interp.interp_3d_only_last_vec_mon_rep(prep_keep,par.grid_p,par.grid_n,par.grid_m,sol.inv_marg_u_keep[t+1],p_plus,n_plus,m_plus,inv_marg_u_keep_plus)
                    linear_interp.interp_2d_only_last_vec_mon_rep(prep_adj,par.grid_p,par.grid_x,sol.inv_marg_u_adj[t+1],p_plus,x_plus,inv_marg_u_adj_plus)
                     
                # vii. max and accumulate
                if compute_q:

                    for i_a in range(par.Na):                                

                        keep = inv_v_keep_plus[i_a] > inv_v_adj_plus[i_a]
                        if keep:
                            v_plus = -1/inv_v_keep_plus[i_a]
                            marg_u_plus = 1/inv_marg_u_keep_plus[i_a]
                        else:
                            v_plus = -1/inv_v_adj_plus[i_a]
                            marg_u_plus = 1/inv_marg_u_adj_plus[i_a]

                        w[i_a] += weight*par.beta*v_plus
                        q[i_p,i_n,i_a] += weight*par.beta*par.R*marg_u_plus

                else:

                    for i_a in range(par.Na):
                        w[i_a] += weight*par.beta*(-1.0/np.fmax(inv_v_keep_plus[i_a],inv_v_adj_plus[i_a]))
        
            # d. transform post decision value function
            for i_a in range(par.Na):
                inv_w[i_p,i_n,i_a] = -1/w[i_a]