コード例 #1
0
    def solve_egm(self):

        # Initialize
        par = self.par
        sol = self.sol_egm

        # Shape parameter for the solution vector
        shape = (np.size(par.y), 1)

        # Initial guess is like a 'last period' choice - consume everything
        sol.m = np.tile(
            np.linspace(par.a_min, par.a_max, par.Na + 1),
            shape)  # a is pre descision, so for any state consume everything.
        sol.c = sol.m.copy()  # Consume everyting - this could be improved
        sol.v = util.u(sol.c, par)  # Utility of consumption

        sol.it = 0  # Iteration counter
        sol.delta = 1000.0  # Difference between iterations

        # Iterate value function until convergence or break if no convergence
        while (sol.delta >= par.tol_egm and sol.it < par.max_iter):

            # Use last iteration to compute the continuation value
            # therefore, copy c and a grid from last iteration.
            c_next = sol.c.copy()
            m_next = sol.m.copy()

            # Call EGM function here
            sol = egm.solve(sol, par, c_next, m_next)

        # add zero consumption
        sol.m[:, 0] = 1.0e-4
        sol.c[:, 0] = 1.0e-4
コード例 #2
0
    def solve_vfi(self):

        # Initialize
        par = self.par
        sol = self.sol_vfi

        # Initialize
        shape = (np.size(par.y), 1)  # Shape to fit nr of income states
        sol.c = np.tile(par.grid_a.copy(),
                        shape)  # Initial guess - consume all
        sol.v = util.u(sol.c, par)  # Utility of consumption
        sol.m = par.grid_m.copy(
        )  # Copy the exogenous asset grid for consistency (with EGM algortihm)

        state1 = 0  # UNEMPLOYMENT STATE
        state2 = 1  # EMPLOYMENT STATE

        sol.it = 0  # Iteration counters
        sol.delta = 1000.0  # Distance between iterations

        # Iterate untill convergence
        while (sol.delta >= par.tol_vfi and sol.it < par.max_iter):

            # Use last iteration as the continuation value. See slides if confused
            v_next = sol.v.copy()

            # Find optimal c given v_next
            sol = vfi.solve(sol, par, v_next, state1, state2)

            # Update iteration parameters
            sol.it += 1
            sol.delta = max(max(abs(sol.v[0] - v_next[0])),
                            max(abs(sol.v[1] -
                                    v_next[1])))  # Update this maybe
コード例 #3
0
    def solve_vfi(self):

        # Initialize
        par = self.par
        sol = self.sol_vfi

        # Initialize
        shape = (np.size(par.y), 1)  # Shape to fit nr of income states
        sol.c = np.tile(par.grid_m.copy(),
                        shape)  # Initial guess - consume all
        sol.v = util.u(sol.c, par)  # Utility of consumption
        sol.m = par.grid_m

        sol.it = 0  # Iteration counters
        sol.delta = 1000.0  # Distance between iterations

        # Iterate untill convergence
        while (sol.delta >= par.tol_vfi and sol.it < par.max_iter):

            # Use last iteration as the continuation value.
            v_next = sol.v.copy()

            # Find optimal c given v_next
            sol = vfi.solve(sol, par, v_next)

            # Update iteration parameters
            sol.it += 1
            sol.delta = max(max(abs(sol.v[0] - v_next[0])),
                            max(abs(sol.v[1] -
                                    v_next[1])))  # Update this maybe
コード例 #4
0
def solve_VFI_2d(par):

    # Initialize solution class
    class sol:
        pass

    shape = (np.size(par.y), 1)
    sol.c = np.tile(
        par.grid_a.copy(),
        shape)  # Initial guess is to consume everything for each state
    sol.v = util.u(sol.c, par)  # Utility of consumption
    sol.a = par.grid_a.copy(
    )  # Copy the exogenous asset grid for consistency (with EGM algortihm)

    state1 = 1  # UNEMPLOYMENT STATE Used as boolean in "value_of_choice" - Defined here for readability
    state2 = 0  # EMPLOYMENT STATE Used as boolean in "value_of_choice" - Defined here for readability

    sol.it = 0  # Iteration counter
    sol.delta = 1000.0  # Difference between two iterations

    # Iterate value function until convergence or break if no convergence
    while (sol.delta >= par.tol_vfi and sol.it < par.max_iter):

        # Use last iteration as the continuation value. See slides if confused
        v_next = sol.v.copy()

        # Loop over asset grid
        for i_a, a in enumerate(par.grid_a):
            # FUNCTIONS BELOW CAN BE WRITTEN AS LOOP - for i=0,1 - AND BE STORED IN AN ARRAY/LIST WITH TWO ENTRIES - a la res[i]=optimize.minimize....
            # Minimize the minus the value function wrt consumption conditional on unemployment state
            obj_fun = lambda x: -value_of_choice_2d(x, a, par.grid_a, v_next[
                0, :], par, state1)
            res_1 = optimize.minimize_scalar(obj_fun,
                                             bounds=[0, a + 1.0e-4],
                                             method='bounded')

            # Minimize the minus the value function wrt consumption conditional on employment state
            obj_fun = lambda x: -value_of_choice_2d(x, a, par.grid_a, v_next[
                1, :], par, state2)
            res_2 = optimize.minimize_scalar(obj_fun,
                                             bounds=[0, a + 1.0e-4],
                                             method='bounded')

            # Unpack solutions
            # State 1
            sol.v[0, i_a] = -res_1.fun
            sol.c[0, i_a] = res_1.x

            # State 2
            sol.v[1, i_a] = -res_2.fun
            sol.c[1, i_a] = res_2.x

            # Update iteration parameters
        sol.it += 1
        sol.delta = max(max(abs(sol.v[0] - v_next[0])),
                        max(abs(sol.v[1] -
                                v_next[1])))  # check this, is this optimal

    return sol
コード例 #5
0
def solve(sol, par, c_next, m_next):

    # Copy last iteration of the value function
    v_old = sol.v.copy()

    # Expand exogenous asset grid
    a = np.tile(par.grid_a, np.size(par.y))  # 2d end-of-period asset grid

    # m_plus = (1+par.r)

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

        #Next periods assets and consumption
        m_plus = (1 + par.r) * a + np.transpose(
            par.y)  # Transpose for dimension to fit

        # Interpolate next periods consumption - can this be combined?
        c_plus_1 = tools.interp_linear_1d(m_next[0, :], c_next[0, :],
                                          m_plus)  # State 1
        c_plus_2 = tools.interp_linear_1d(m_next[1, :], c_next[1, :],
                                          m_plus)  # State 2

        #Combine into a vector. Rows indicate income state, columns indicate asset state
        c_plus = np.vstack((c_plus_1, c_plus_2))

        # Marginal utility
        marg_u_plus = util.marg_u(c_plus, par)
        # Compute expectation below
        av_marg_u_plus = np.array([
            par.P[0, 0] * marg_u_plus[0, 0] + par.P[0, 1] * marg_u_plus[1, 1],
            par.P[1, 1] * marg_u_plus[1, 1] + par.P[1, 0] * marg_u_plus[0, 0]
        ])
        # Add optimal consumption and endogenous state
        sol.c[:, a_i + 1] = util.inv_marg_u(
            (1 + par.r) * par.beta * av_marg_u_plus, par)
        sol.m[:, a_i + 1] = a + sol.c[:, a_i + 1]
        sol.v = util.u(sol.c, par)

    #Compute value function and update iteration parameters
    sol.delta = max(max(abs(sol.v[0] - v_old[0])),
                    max(abs(sol.v[1] - v_old[1])))
    sol.it += 1

    # sol.delta = max( max(abs(sol.c[0] - c_next[0])), max(abs(sol.c[1] - c_next[1])))

    return sol
コード例 #6
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
コード例 #7
0
def solve_VFI(par):

    # Initialize solution class
    class sol:
        pass

    sol.c = par.grid_a.copy()  # Initial guess is to consume everything
    sol.v = util.u(sol.c, par)  # Utility of consumption
    sol.a = par.grid_a.copy(
    )  # Copy the exogenous asset grid for consistency (with EGM algortihm) -- Jeg kan se, at denne initialisering er nødvendig for at kunne
    # plotte på et a-grid, men vi initialisere jo allerede griddet i setup(), så måske kan man kalde par.grid_a direkte, når der plottes? Har prøvet, men den klager.

    sol.it = 0  # Iteration counter
    sol.delta = 1000.0  # Difference between two iterations

    # Iterate value function until convergence or break if no convergence
    while (sol.delta >= par.tol_vfi and sol.it < par.max_iter):

        # Use last iteration as the continuation value. See slides if confused
        v_next = sol.v.copy()

        # Loop over asset grid
        for i_a, a in enumerate(par.grid_a):

            # Minimize the minus the value function wrt consumption
            obj_fun = lambda x: -value_of_choice(x, a, par.grid_a, v_next, par)
            res = optimize.minimize_scalar(obj_fun,
                                           bounds=[0, a + 1.0e-4],
                                           method='bounded')

            # Unpack solution
            sol.v[i_a] = -res.fun
            sol.c[i_a] = res.x

        # Update iteration parameters
        sol.it += 1
        sol.delta = max(abs(sol.v - v_next))

    return sol
コード例 #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
コード例 #9
0
ファイル: fd.py プロジェクト: madsankern/DynamicProgramming
def solve(par, sol):

    ## SETUP ##

    # Asst grid
    N = par.Nm
    m = par.grid_m.transpose()  # N x 1 vector
    dm = (par.m_max - par.m_min) / (par.Nm - 1)  # Stepsize on m grid
    mm = np.tile(np.array([m]), (2, 1))
    mm = mm.transpose()  # Write this better

    # Income
    y = par.y
    yy = y * np.ones((N, 2))  # 2 dimensional income grid

    Delta_step = 1000  # Stepsize
    delta = 1000  # Distance between iterations - MADS
    it = 0  # Iteration counter

    # Initialize
    v0 = np.zeros((N, 2))
    dVf = np.zeros((N, 2))
    dVb = np.zeros((N, 2))
    c = np.zeros((N, 2))
    u = np.zeros((N, 2))
    V_n = np.zeros((N, 2, par.max_iter))
    A = sparse.eye(2 * N, format='csr')  # Transition matrix

    # Transition matrix for income
    y_transition = sparse.kron(par.pi, sparse.eye(par.Nm), format="csr")

    # Initial guess of value function
    v0[:, 0] = util.u(yy[:, 0] + par.r * mm[:, 0], par) / par.rho
    v0[:, 1] = util.u(yy[:, 1] + par.r * mm[:, 1], par) / par.rho
    v = v0

    while (delta >= par.tol_fd and it < par.max_iter):

        # Redefine
        V = v
        V_n[:, :, it] = V

        # Forward difference
        dVf[:N - 1, :] = (V[1:N, :] - V[0:N - 1, :]) / dm
        dVf[N - 1, :] = util.marg_u(
            y + par.r * mm[N - 1, :], par
        )  #will never be used, but impose state constraint a<=amax just in case

        # Backward difference
        dVb[1:, :] = ((V[1:N, :] - V[0:N - 1, :])) / dm
        dVb[0, :] = util.marg_u(y + par.r * mm[0, :],
                                par)  # state constraint boundary condition

        I_concave = dVb > dVf

        #consumption and savings with forward difference
        cf = util.inv_marg_u(
            dVf,
            par)  # Take inverse marginal utility of value function (c foc)
        ssf = yy + par.r * mm - cf  # Savings from forward difference

        #consumption and savings with backward difference
        cb = util.inv_marg_u(dVb, par)
        ssb = yy + par.r * mm - cb

        #consumption and derivative of value function at steady state
        c0 = yy + par.r * mm
        dV0 = util.marg_u(c0, par)

        # Upwind method makes a choice of forward or backward differences based on the sign of the drift
        If = ssf > 0  #positive drift --> forward difference
        Ib = ssb < 0  #negative drift --> backward difference
        I0 = (1 - If - Ib)  #at steady state

        dV_upwind = dVf * If + dVb * Ib + dV0 * I0
        c = util.inv_marg_u(dV_upwind, par)

        # Utility of choice
        u = util.u(c, par)  # Utility without car

        # Terms to be put into the A matrix
        X = -np.minimum(ssb, 0) / dm
        Y = -np.maximum(ssf, 0) / dm + np.minimum(ssb, 0) / dm
        Z = np.maximum(ssf, 0) / dm
        Z_helper = np.vstack((np.array([0, 0]), Z))

        # Construct A matrix
        A1 = sparse.eye(N, format='csr') * 0  # Intialize sparse zero mat
        A1 += sparse.spdiags(Y[:, 0], 0, N, N)
        A1 += sparse.spdiags(X[1:, 0], -1, N, N)
        A1 += sparse.spdiags(Z_helper[:N - 2, 0], 1, N, N)

        A2 = sparse.eye(N, format='csr') * 0  # Intialize sparse zero mat
        A2 += sparse.spdiags(Y[:, 1], 0, N, N)
        A2 += sparse.spdiags(X[1:, 1], -1, N, N)
        A2 += sparse.spdiags(Z_helper[:N - 2, 1], 1, N, N)

        # Stack A1 and A2
        block_helper = sparse.eye(N, format='csr') * 0
        A_upper = sparse.hstack([A1, block_helper], format='csr')
        A_lower = sparse.hstack([block_helper, A2], format='csr')
        A = sparse.vstack(
            [A_upper, A_lower], format='csr'
        ) + y_transition  # This is the transition matrix used for the problem

        # Write a check for the row sum of A, should be zero

        # B matrix
        B = (par.rho + 1 / Delta_step) * sparse.eye(2 * N) - A

        # Stack utility vector into one long column vector
        u_stacked = np.hstack(([u[:, 0]], [u[:, 1]])).transpose()
        V_stacked = np.hstack(([V[:, 0]], [V[:, 1]])).transpose()

        b = u_stacked + V_stacked / Delta_step

        # Solve system
        V_stacked = spsolve(B, b)

        V_old = V.copy()
        V[:, 0] = V_stacked[:N]
        V[:, 1] = V_stacked[N:2 * N]
        # np.hstack((V_stacked[:N], V_stacked[N:2*N-1]))

        Vchange = V - V_old
        v = V

        delta = abs(
            max(max(Vchange[0, :], key=abs), max(Vchange[1, :], key=abs)))
        it += 1

    # Unpack solution
    sol.dV = dV_upwind.transpose()
    sol.v = v.transpose()
    sol.c = c.transpose()
    sol.m = m

    return sol
コード例 #10
0
ファイル: egm.py プロジェクト: madsankern/DynamicProgramming
def solve(sol, par, c_next, m_next):

    # Copy last iteration of the value function
    v_old = sol.v.copy()

    # Expand exogenous asset grid
    a = np.tile(par.grid_a, np.size(par.y))  # does this work?

    m_plus = (1 + par.r)

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

        #Next periods assets and consumption
        m_plus = (1 + par.r) * a + np.transpose(
            par.y)  # Transpose for dimension to fit

        # Interpolate next periods consumption - can this be combined?
        c_plus_1 = tools.interp_linear_1d(m_next[0, :], c_next[0, :],
                                          m_plus)  # State 1
        c_plus_2 = tools.interp_linear_1d(m_next[1, :], c_next[1, :],
                                          m_plus)  # State 2

        #Combine into a vector. Rows indicate income state, columns indicate asset state
        c_plus = np.vstack((c_plus_1, c_plus_2))

        # 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)

        # Add optimal consumption and endogenous state
        sol.c[:, a_i + 1] = util.inv_marg_u(
            (1 + par.r) * par.beta * av_marg_u_plus, par)
        sol.m[:, a_i + 1] = a + sol.c[:, a_i + 1]
        sol.v = util.u(sol.c, par)

    #Compute valu function and update iteration parameters
    sol.delta = max(max(abs(sol.v[0] - v_old[0])),
                    max(abs(sol.v[1] - v_old[1])))
    sol.it += 1

    # sol.delta = max( max(abs(sol.c[0] - c_next[0])), max(abs(sol.c[1] - c_next[1])))

    return sol

    ## Attempt at vectorizing the code
    # def solve_vec(sol, par, c_next, m_next):

    #     # Copy last iteration of the value function
    #     v_old = sol.v.copy()

    #     # Expand exogenous asset grid
    #     shape = (np.size(par.y),1)

    #     a = np.tile(par.grid_a, shape) # does this work?

    #     y_help = np.array([par.y])
    #     y_help = np.transpose(y_help)
    #     y = np.tile(y_help, (1,par.Na))

    #     m_plus = (1+par.r)*a + y
    #     # m_plus = (1+par.r)*a + np.transpose(par.y)

    #     # Interpolate next periods consumption
    #     c_plus_1 = tools.interp_linear_1d(m_next[0,:], c_next[0,:], m_plus[0,:]) # State 1
    #     c_plus_2 = tools.interp_linear_1d(m_next[1,:], c_next[1,:], m_plus[1,:]) # State 2

    #     #Combine into a vector. Rows indicate income state, columns indicate asset state
    #     c_plus = np.vstack((c_plus_1, c_plus_2))

    #     # Marginal utility
    #     marg_u_plus = util.marg_u(c_plus,par)
    #     av_marg_u_plus = np.sum(par.P*marg_u_plus)

    #     av_marg_u_plus = np.sum(par.P*marg_u_plus, axis = 1) # Dot product by row (axis = 1)

    #     # Add optimal consumption and endogenous state
    #     sol.c = util.inv_marg_u((1+par.r)*par.beta*av_marg_u_plus,par)
    #     sol.m = a + sol.c[:,a_i+1]
    #     sol.v = util.u(sol.c,par)

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

        #Next periods assets and consumption
        m_plus = (1 + par.r) * a + np.transpose(
            par.y)  # Transpose for dimension to fit

        # Interpolate next periods consumption - can this be combined?
        c_plus_1 = tools.interp_linear_1d(m_next[0, :], c_next[0, :],
                                          m_plus)  # State 1
        c_plus_2 = tools.interp_linear_1d(m_next[1, :], c_next[1, :],
                                          m_plus)  # State 2

        #Combine into a vector. Rows indicate income state, columns indicate asset state
        c_plus = np.vstack((c_plus_1, c_plus_2))

        # 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)

        # Add optimal consumption and endogenous state
        sol.c[:, a_i + 1] = util.inv_marg_u(
            (1 + par.r) * par.beta * av_marg_u_plus, par)
        sol.m[:, a_i + 1] = a + sol.c[:, a_i + 1]
        sol.v = util.u(sol.c, par)

    #Compute valu function and update iteration parameters
    sol.delta = max(max(abs(sol.v[0] - v_old[0])),
                    max(abs(sol.v[1] - v_old[1])))
    sol.it += 1

    # sol.delta = max( max(abs(sol.c[0] - c_next[0])), max(abs(sol.c[1] - c_next[1])))

    return sol