Ejemplo n.º 1
0
def EGM_loop(sol, t, par):
    for i_a, a in enumerate(par.grid_a[t, :]):

        if t + 1 <= par.Tr:  # No pension in the next period
            fac = par.G * par.L[t] * par.psi_vec
            w = par.w
            xi = par.xi_vec
            inv_fac = 1 / fac

            # Futute m and c
            m_plus = inv_fac * par.R * a + xi
            c_plus = tools.interp_linear_1d(sol.m[t + 1, :], sol.c[t + 1, :],
                                            m_plus)
        else:
            fac = par.G * par.L[t]
            w = 1
            xi = 1
            inv_fac = 1 / fac

            # Futute m and c
            m_plus = inv_fac * par.R * a + xi
            c_plus = tools.interp_linear_1d_scalar(sol.m[t + 1, :],
                                                   sol.c[t + 1, :], m_plus)

        # Future marginal utility
        marg_u_plus = marg_util(fac * c_plus, par)
        avg_marg_u_plus = np.sum(w * marg_u_plus)

        # Currect C and m
        sol.c[t, i_a + 1] = inv_marg_util(par.beta * par.R * avg_marg_u_plus,
                                          par)
        sol.m[t, i_a + 1] = a + sol.c[t, i_a + 1]

    return sol
Ejemplo n.º 2
0
def value_of_choice(x,m,M_next,t,V1_next,V2_next,V_pens,par,N,p):

    #"unpack" c1
    if type(x) == np.ndarray: # vector-type: depends on the type of solver used
        c1 = x[0] 
        c2 = x[1]
    else:
        c = x
    
    # define assets
    a = m - c1 - c2
    
    EV_next = 0.0 #Initialize
    if t+1<= par.Tr: # No pension in the next period

        for i,psi in enumerate(par.psi_vec):
            fac = par.G*psi
            w = par.w[i]
            xi = par.xi_vec[i]
            inv_fac = 1/fac

            # Future m and c
            M_plus = inv_fac*par.R*a+xi
            V1_plus = tools.interp_linear_1d_scalar(M_next,V1_next,M_plus) 
            V2_plus = tools.interp_linear_1d_scalar(M_next,V2_next,M_plus)

            EV_next += p[N,t]*w*V1_plus + (1-p[N,t])*w*V2_plus

    else:
        N = 0
        fac = par.G_ret
        w = 1
        nu = par.nu
        inv_fac = 1/fac

        # Future m and c
        M_plus = inv_fac*par.R*a+nu
        V_plus = tools.interp_linear_1d_scalar(M_next,V_pens,M_plus) 
        EV_next += w*V_plus

    # Value of choice
    V_guess = util(c1,c2,par,N)+par.beta*EV_next

    return V_guess
Ejemplo n.º 3
0
def value_of_choice(x, m, M_next, t, V1_next, V2_next, N, par):

    #"unpack" c1
    if type(x
            ) == np.ndarray:  # vector-type: depends on the type of solver used
        c1 = x[0]
        c2 = x[1]
    else:
        c = x

    a = m - c1 - c2

    p = child_prob(par)

    EV_next = 0.0  #Initialize
    if t + 1 <= par.Tr:  # No pension in the next period
        for i in range(0, len(par.w)):
            fac = par.G * par.psi_vec[i]
            w = par.w[i]
            xi = par.xi_vec[i]
            inv_fac = 1 / fac

            # Future m and c
            M_plus = inv_fac * par.R * a + par.xi_vec[i]
            V1_plus = tools.interp_linear_1d_scalar(M_next, V1_next, M_plus)
            V2_plus = tools.interp_linear_1d_scalar(M_next, V2_next, M_plus)
            EV_next += p[N, t] * w * V1_plus + (1 - p[N, t]) * w * V2_plus

    else:
        fac = par.G
        w = 1
        xi = 1
        inv_fac = 1 / fac

        # Future m and c
        M_plus = inv_fac * par.R * a + xi
        V_plus = tools.interp_linear_1d_scalar(M_next, V2_next, M_plus)
        EV_next += w * V_plus

    # Value of choice
    V_guess = util(c1, c2, N, par) + par.beta * EV_next

    return V_guess
Ejemplo n.º 4
0
def value_of_choice_2d(x, a, a_next, v_next, par, state):

    # Unpack consumption (choice variable)
    c = x

    # Intialize expected continuation value
    Ev_next = 0.0

    # Compute value of choice conditional on being in state 1 (unemployment state)
    ###### VECTORIZE THIS
    if state == 1:
        # Loop over each possible state
        for i in [0, 1]:

            # Next periods state for each income level
            a_plus = par.y[i] + (1 + par.r) * (a - c)

            #Interpolate continuation given state a_plus
            v_plus = tools.interp_linear_1d_scalar(a_next, v_next, a_plus)

            # Append continuation value to calculate expected value
            Ev_next += par.P[0, i] * v_plus
    # Compute value of choice conditional on being in state 2 (employment state)
    else:
        # Loop over each possible state
        ###### VECTORIZE THIS
        for i in [0, 1]:

            # Next periods state for each income level
            a_plus = par.y[i] + (1 + par.r) * (a - c)

            #Interpolate continuation given state a_plus
            v_plus = tools.interp_linear_1d_scalar(a_next, v_next, a_plus)

            # Append continuation value to calculate expected value
            Ev_next += par.P[1, i] * v_plus
    # Value of choice
    v_guess = util.u(c, par) + par.beta * Ev_next

    return v_guess
Ejemplo n.º 5
0
def EGM (sol,t,par):
    for i_a,a in enumerate(par.grid_a[t,:]):

        if t+1<= par.Tr: # No pension in the next period
            fac = par.G*par.psi_vec
            w = par.w
            xi = par.xi_vec
            inv_fac = 1/fac

            # Future m and c
            m_plus = inv_fac*par.R*a+xi
            c1_plus = tools.interp_linear_1d(sol.m[t+1,:],sol.c1[t+1,:], m_plus) 
            c2_plus = tools.interp_linear_1d(sol.m[t+1,:],sol.c2[t+1,:], m_plus)
        else:
            fac = par.G
            w = 1
            xi = 1
            inv_fac = 1/fac

            # Future m and c
            m_plus = inv_fac*par.R*a+xi
            c1_plus = tools.interp_linear_1d_scalar(sol.m[t+1,:],sol.c1[t+1,:], m_plus)
            c2_plus = tools.interp_linear_1d_scalar(sol.m[t+1,:],sol.c2[t+1,:], m_plus)

        # Future marginal utility
        marg_u_plus1 = marg_util_c1(fac*c1_plus,par)
        marg_u_plus2 = marg_util_c2(fac*c2_plus,par)
        avg_marg_u_plus1 = np.sum(w*marg_u_plus1)
        avg_marg_u_plus2 = np.sum(w*marg_u_plus2)

        # Current C and m
        sol.c1[t,i_a+1]=inv_marg_util(par.beta*par.R*avg_marg_u_plus1,par)
        sol.c2[t,i_a+1]=inv_marg_util(par.beta*par.R*avg_marg_u_plus2,par)
        sol.m[t,i_a+1]=a+sol.c1[t,i_a+1]+sol.c2[t,i_a+1]

    return sol
Ejemplo n.º 6
0
def obj_keep(
    arg, n, m, v_next, par, m_next
):  # I have added m_next to the interpolation since it changes throughout iterations

    # Unpack
    c = arg

    # End of period assets
    m_plus = (1 + par.r) * (m - c) + par.y1

    # Continuation value
    v_plus = tools.interp_linear_1d_scalar(m_next, v_next, m_plus)

    # Value of choice
    value = util.u_h(c, n, par) + par.beta * v_plus

    return value
Ejemplo n.º 7
0
def obj_keep(arg, n, m, v_next, par):

    # Unpack
    c = arg

    # End of period assets
    m_plus = (1 + par.r) * (m - c) + par.y1

    # Continuation value
    v_plus = tools.interp_linear_1d_scalar(par.grid_m, v_next, m_plus)

    # Value of choice
    value = util.u_h(c, n, par) + par.beta * v_plus

    return value

    #def solve_NEGM(par,sol):

    # a. next-period cash-on-hand
    m_plus = par['R'] * par['grid_a'] + par['y']

    # b. post-decision value function
    sol['w_vec'] = np.empty(m_plus.size)
    linear_interp.interp_1d_vec(par['grid_m'], sol['v_next'], m_plus,
                                sol['w_vec'])

    # c. post-decision marginal value of cash
    c_next_interp = np.empty(m_plus.size)
    linear_interp.interp_1d_vec(par['grid_m'], sol['c_next'], m_plus,
                                c_next_interp)
    q = par['beta'] * par['R'] * marg_u(c_next_interp, par)

    # d. EGM
    sol['c_vec'] = inv_marg_u(q, par)
    sol['m_vec'] = par['grid_a'] + sol['c_vec']

    myupperenvelope = upperenvelope.create(u)  # where is the utility function

    # b. apply upperenvelope
    c_ast_vec = np.empty(par['grid_m'].size)  # output
    v_ast_vec = np.empty(par['grid_m'].size)  # output
    myupperenvelope(par['grid_a'], sol['m_vec'], sol['c_vec'], sol['w_vec'],
                    par['grid_m'], c_ast_vec, v_ast_vec, par['rho'])

    return  #sol from upperenvelope
Ejemplo n.º 8
0
def value_of_choice(x, a, a_next, v_next, par):

    # Unpack consumption (choice variable)
    c = x

    # Intialize expected continuation value
    Ev_next = 0.0

    # Loop over each possible state
    for i in [0, 1]:

        # Next periods state for each income level
        a_plus = par.y[i] + (1 + par.r) * (a - c)

        #Interpolate continuation given state a_plus
        v_plus = tools.interp_linear_1d_scalar(a_next, v_next, a_plus)

        # Append continuation value to calculate expected value
        Ev_next += par.Pi[i] * v_plus

    # Value of choice
    v_guess = util.u(c, par) + par.beta * Ev_next

    return v_guess
Ejemplo n.º 9
0
    def value_functions(par, sol, sim):
        # Compute value function
        for z in [0, 1]:
            for i_h in prange(par.Nh):
                for i, c in enumerate(par.grid_m):
                    sol.inv_v[-1, i, z, i_h] = 1.0 / utility(c, par.rho)

            # Before last period
            for t in range(par.T - 2, -1, -1):
                for i_h in range(par.Nh):  #prange
                    h = par.grid_h[i_h]
                    if t >= par.TR and i_h != 0:  # After retirement, solution is independent of z and h
                        sol.inv_v[t, :, z, i_h] = sol.inv_v[t, :, 0, 0]
                    elif t >= par.TH and z == 1 and i_h != 0:  # After early holiday pay, solution is independent of h
                        sol.inv_v[t, :, z, i_h] = sol.inv_v[t, :, z, 0]
                    elif t < par.TH - 1 and i_h != 0:  # Before holiday pay decision, solution is indenpendent of z and h
                        sol.inv_v[t, :, z, i_h] = sol.inv_v[t, :, 0, 0]
                    else:
                        for i_m in prange(par.Nm):
                            m = par.grid_m[i_m]
                            c = tools.interp_linear_1d_scalar(
                                sol.m[t, :, z, i_h], sol.c[t, :, z, i_h], m)
                            v = value_of_choice(c, t, m, h, z, par, sol)
                            sol.inv_v[t, i_m, z, i_h] = -1.0 / v
Ejemplo n.º 10
0
def solve_dc(sol, par, v_next, c_next, h_next, m_next):

    # a. Solve the keeper problem

    shape = (
        2, np.size(par.grid_a)
    )  # Row for each state of housing and colums for exogenous end-of-period assets grid

    # Intialize
    v_keep = np.zeros(shape) + np.nan
    c_keep = np.zeros(shape) + np.nan
    h_keep = np.zeros(shape) + np.nan

    # Loop over housing states
    for n in range(2):

        # Loop over exogenous states (post decision states)
        for a_i, a in enumerate(par.grid_a):

            #Next periods assets and consumption
            m_plus = (1 + par.r) * a + par.y1

            # Interpolate next periods consumption
            c_plus = tools.interp_linear_1d_scalar(m_next[n, :], c_next[n, :],
                                                   m_plus)

            # Marginal utility
            marg_u_plus = util.marg_u(c_plus, par)
            #av_marg_u_plus = np.sum(par.P*marg_u_plus, axis = 1) # Dot product by row (axis = 1) #### no average

            # Add optimal consumption and endogenous state using Euler equation
            c_keep[n, a_i] = util.inv_marg_u(
                (1 + par.r) * par.beta * marg_u_plus, par)  #### no average
            # v_keep[n,a_i] = obj_keep(c_keep[n,a_i], n, c_keep[n,a_i] + a, v_next[n,:], par, m_next[n, :])
            # The line below is faster and more precise as it avoids numerical errors
            v_keep[n, a_i] = util.u_h(
                c_keep[n, a_i], n,
                par) + par.beta * tools.interp_linear_1d_scalar(
                    m_next[n, :], v_next[n, :], m_plus)
            h_keep[n, a_i] = n

    ### UPPER ENVELOPE ###

    c_keep, v_keep, m_grid = upper_envelope(c_keep, v_keep, v_next, m_next,
                                            shape, par)

    ### Add points at the constraints ###

    m_con = np.array([
        np.linspace(0 + 1e-8, m_grid[0, 0] - 1e-4, par.N_bottom),
        np.linspace(0 + 1e-8, m_grid[1, 0] - 1e-4, par.N_bottom)
    ])
    c_con = m_con.copy()
    v_con_0 = [
        obj_keep(c_con[0, i], 0, m_con[0, i], v_next[0, :], par, m_next[0, :])
        for i in range(par.N_bottom)
    ]  # From N_bottom or whole
    v_con_1 = [
        obj_keep(c_con[1, i], 1, m_con[1, i], v_next[1, :], par, m_next[1, :])
        for i in range(par.N_bottom)
    ]  # From N_bottom or whole
    v_con = np.array([v_con_0, v_con_1])

    # initialize new larger keeper containers

    new_shape = (2, np.size(par.grid_a) + par.N_bottom)
    c_keep_append = np.zeros(new_shape) + np.nan
    v_keep_append = np.zeros(new_shape) + np.nan
    m_grid_append = np.zeros(new_shape) + np.nan

    # append

    for i in range(2):
        c_keep_append[i, :] = np.append(c_con[i, :], c_keep[i, :])
        v_keep_append[i, :] = np.append(v_con[i, :], v_keep[i, :])
        m_grid_append[i, :] = np.append(m_con[i, :], m_grid[i, :])

    # b. Solve the adjuster problem

    # Initialize
    v_adj = np.zeros(new_shape) + np.nan
    c_adj = np.zeros(new_shape) + np.nan
    h_adj = np.zeros(new_shape) + np.nan

    # Loop over housing state
    for n in range(2):

        # Housing choice is reverse of state n if adjusting
        h = 1 - n

        # Loop over asset grid
        for a_i, m in enumerate(m_grid_append[n]):  # endogenous grid

            # If adjustment is not possible
            if n == 0 and m < par.ph:
                v_adj[n, a_i] = -np.inf
                c_adj[n, a_i] = 0
                h_adj[n, a_i] = np.nan

            else:

                # Assets available after adjusting
                if n == 1:
                    p = par.p1
                else:
                    p = par.ph

                x = m - p * (h - n)

                # Value of choice
                v_adj[n, a_i] = tools.interp_linear_1d_scalar(
                    m_grid_append[h], v_keep_append[h, :], x)
                c_adj[n, a_i] = tools.interp_linear_1d_scalar(
                    m_grid_append[h], c_keep_append[h, :], x)
                h_adj[n, a_i] = h

    # c. Combine solutions

    # Loop over asset grid again
    for n in range(2):
        for a_i, m in enumerate(m_grid_append[n]):  # endogenous grid

            # If keeping is optimal
            if v_keep_append[n, a_i] > v_adj[n, a_i]:
                sol.v[n, a_i] = v_keep_append[n, a_i]
                sol.c[n, a_i] = c_keep_append[n, a_i]
                sol.h[n, a_i] = n
                sol.m[n, a_i] = m_grid_append[n, a_i]  # added

            # If adjusting is optimal
            else:
                sol.v[n, a_i] = v_adj[n, a_i]
                sol.c[n, a_i] = c_adj[n, a_i]
                sol.h[n, a_i] = 1 - n
                sol.m[n, a_i] = m_grid_append[n, a_i]  # added

    for i in range(2):
        sol.delta_save[i, sol.it] = max(abs(sol.v[i] - v_next[i]))

    return sol
Ejemplo n.º 11
0
def solve_NEGM(sol, par, v_next, c_next, h_next):

    # a. Solve the keeper problem

    shape = (2, np.size(par.grid_m)
             )  # Row for each state of housing - move to model.py file

    # Intialize
    v_keep = np.zeros(shape) + np.nan
    c_keep = np.zeros(shape) + np.nan
    h_keep = np.zeros(shape) + np.nan

    # Loop over housing states
    for n in range(2):

        # Loop over asset grid
        for m_i, m in enumerate(par.grid_m):

            # Use euler equation
            v_keep[n, m_i] = -res.fun
            c_keep[n, m_i] = res.x
            h_keep[n, m_i] = n

    # b. Solve the adjuster problem

    # Intialize
    v_adj = np.zeros(shape) + np.nan
    c_adj = np.zeros(shape) + np.nan
    h_adj = np.zeros(shape) + np.nan

    # Loop over housing state
    for n in range(2):

        # Housing choice is reverse of state n if adjusting
        h = 1 - n

        # Loop over asset grid
        for m_i, m in enumerate(par.grid_m):

            # If adjustment is not possible
            if n == 0 and m < par.ph:
                v_adj[n, m_i] = -np.inf
                c_adj[n, m_i] = 0
                h_adj[n, m_i] = np.nan

            else:

                # Assets available after adjusting
                x = m - par.ph * (h - n)

                # Value of choice
                v_adj[n, m_i] = tools.interp_linear_1d_scalar(
                    par.grid_m, v_keep[h, :], x)
                c_adj[n, m_i] = tools.interp_linear_1d_scalar(
                    par.grid_m, c_keep[h, :], x)
                h_adj[n, m_i] = h

    # c. Combine solutions

    # Loop over asset grid again
    for n in range(2):
        for m_i, m in enumerate(par.grid_m):

            # If keeping is optimal
            if v_keep[n, m_i] > v_adj[n, m_i]:
                sol.v[n, m_i] = v_keep[n, m_i]
                sol.c[n, m_i] = c_keep[n, m_i]
                sol.h[n, m_i] = n

            # If ajusting is optimal
            else:
                sol.v[n, m_i] = v_adj[n, m_i]
                sol.c[n, m_i] = c_adj[n, m_i]
                sol.h[n, m_i] = 1 - n

    return sol