Ejemplo n.º 1
0
def solve_bellman(t, sol, par):
    """solve bellman equation using vfi"""

    # unpack (helps numba optimize)
    c = sol.c[t]
    v = sol.v[t]

    # loop over outer states
    for ip in prange(par.Np):  # in parallel

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

        # d. loop over cash-on-hand
        for im in range(par.Nm):

            # a. cash-on-hand
            m = par.grid_m[im]

            # b. optimal choice
            c_low = np.fmin(m / 2, 1e-8)
            c_high = m
            c[ip,
              im] = golden_section_search.optimizer(obj_bellman,
                                                    c_low,
                                                    c_high,
                                                    args=(p, m, sol.v[t + 1],
                                                          par),
                                                    tol=par.tol)

            # note: the above finds the minimum of obj_bellman in range [c_low,c_high] with a tolerance of par.tol
            # and arguments (except for c) as specified

            # c. optimal value
            v[ip, im] = -obj_bellman(c[ip, im], p, m, sol.v[t + 1], par)
Ejemplo n.º 2
0
def solve_adj(inv_v_keep,c_keep,d_ubar,sigma,n_max,Np,Nx,grid_n,grid_m,grid_x,P_d_p): # P_d_p,
    """solve bellman equation for adjusters using nvfi"""

    # unpack output
    adj_shape = (Np,Nx)
    inv_v_adj = np.zeros(adj_shape)
    d_adj = np.zeros(adj_shape)
    c_adj = np.zeros(adj_shape)

    # loop over outer states
    for i_p in prange(Np):
            
        # loop over x state
        for i_x in range(Nx):
            
            # a. cash-on-hand
            x = grid_x[i_x]
            if i_x == 0:
                d_adj[i_p,i_x] = 0
                c_adj[i_p,i_x] = 0
                inv_v_adj[i_p,i_x] = 0
      
                continue

            # b. optimal choice
            d_low = np.fmin(x/2,1e-8)
            d_high = np.fmin(x/P_d_p,n_max) # cash on hand grid now x = m + (1-tau)*n + B.C. (eg 0.5, or collateral eg. coll_ratio*n)
            d_adj[i_p,i_x] = golden_section_search.optimizer(obj_adj,d_low,d_high,args=(x,inv_v_keep[i_p],grid_n,grid_m,P_d_p),tol=1e-8)

            # c. optimal value
            m = x - P_d_p*d_adj[i_p,i_x]
            c_adj[i_p,i_x] = linear_interp.interp_2d(grid_n,grid_m,c_keep[i_p],d_adj[i_p,i_x],m)
            inv_v_adj[i_p,i_x] = -obj_adj(d_adj[i_p,i_x],x,inv_v_keep[i_p],grid_n,grid_m,P_d_p)

    return inv_v_adj, d_adj, c_adj
Ejemplo n.º 3
0
def solve_keep(inv_w,grid_b,grid_m,grid_n,d_ubar,sigma,Np,Nn,Nm,P_n_p): # P_n_p
    """solve bellman equation for keepers using nvfi"""

    # unpack output
    keep_shape = (Np,Nn,Nm)
    inv_v_keep = np.zeros(keep_shape)
    c_keep = np.zeros(keep_shape)

    # loop over outer states
    for i_p in prange(Np):
        for i_n in range(Nn):
            
            # outer states
            n = grid_n[i_n]

            # loop over m state
            for i_m in range(Nm):
                
                # a. cash-on-hand
                m = grid_m[i_m]
                if i_m == 0:
                    c_keep[i_p,i_n,i_m] = 0
                    inv_v_keep[i_p,i_n,i_m] = 0

                # b. optimal choice b = m - c, b <=-0.5.m min 
                c_low = np.fmin(m/2,1e-8)
                c_high = m/P_n_p # m = P_n_p*c (if using everything)
                c_keep[i_p,i_n,i_m] = golden_section_search.optimizer(obj_keep,c_low,c_high,args=(n,m,inv_w[i_p,i_n],grid_b,d_ubar,sigma,P_n_p),tol=1e-8)

                # c. optimal value
                v = -obj_keep(c_keep[i_p,i_n,i_m],n,m,inv_w[i_p,i_n],grid_b,d_ubar,sigma,P_n_p)
                inv_v_keep[i_p,i_n,i_m] = -1.0/v

    return inv_v_keep,c_keep
Ejemplo n.º 4
0
def last_period(sigma,d_ubar,Np,Nn,Nm,Nx,grid_n,grid_m,grid_x,n_max,P_n_p,P_d_p): # P_n_p, P_d_p
    """ solve the problem in the last period """

    # unpack
    keep_shape = (Np,Nn,Nm)
    c_keep = np.zeros(keep_shape)
    inv_v_keep = np.zeros(keep_shape)
    
    adj_shape = (Np,Nx)
    d_adj = np.zeros(adj_shape)
    c_adj = np.zeros(adj_shape)
    inv_v_adj = np.zeros(adj_shape)
    

    # a. keep
    for i_p in prange(Np):
        for i_n in range(Nn):
            for i_m in range(Nm):
                            
                # i. states
                n = grid_n[i_n]
                m = grid_m[i_m]

                if i_m == 0: # forced c = 0 
                    c_keep[i_p,i_n,i_m] = 0
                    inv_v_keep[i_p,i_n,i_m] = 0
                    continue
                
                # ii. optimal choice
                c_keep[i_p,i_n,i_m] = m/P_n_p

                # iii. optimal value
                v_keep = utility(c_keep[i_p,i_n,i_m],n,d_ubar,sigma)
                inv_v_keep[i_p,i_n,i_m] = -1.0/v_keep

    # b. adj
    for i_p in prange(Np):
        for i_x in range(Nx):
            
            # i. states
            x = grid_x[i_x]

            if i_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
                continue

            # ii. optimal choices
            d_low = np.fmin(x/2,1e-8)
            d_high = np.fmin(x/P_d_p,n_max)            
            d_adj[i_p,i_x] = golden_section_search.optimizer(obj_last_period,d_low,d_high,args=(x,sigma,d_ubar,P_n_p,P_d_p),tol=1e-8)
            c_adj[i_p,i_x] = (x-P_d_p*d_adj[i_p,i_x])/P_n_p # x - P_n_p*c - P_n_d*d = 0 =>  c=(x- P_n_d*d)/P_n_p

            # iii. optimal value
            v_adj = -obj_last_period(d_adj[i_p,i_x],x,sigma,d_ubar,P_n_p,P_d_p)
            inv_v_adj[i_p,i_x] = -1.0/v_adj
        
    return c_keep, c_adj, d_adj, inv_v_keep, inv_v_adj
Ejemplo n.º 5
0
def solve_adj(t, sol, par):
    """solve bellman equation for adjusters using nvfi"""

    # unpack output
    inv_v = sol.inv_v_adj[t]
    inv_marg_u = sol.inv_marg_u_adj[t]
    d = sol.d_adj[t]
    c = sol.c_adj[t]

    # unpack input
    inv_v_keep = sol.inv_v_keep[t]
    c_keep = sol.c_keep[t]
    grid_n = par.grid_n
    grid_m = par.grid_m
    d_ubar = par.d_ubar
    alpha = par.alpha
    rho = par.rho

    # loop over outer states
    for i_p in prange(par.Np):

        # loop over x state
        for i_x in range(par.Nx):

            # a. cash-on-hand
            x = par.grid_x[i_x]
            if i_x == 0:
                d[i_p, i_x] = 0
                c[i_p, i_x] = 0
                inv_v[i_p, i_x] = 0
                if par.do_marg_u:
                    inv_marg_u[i_p, i_x] = 0
                continue

            # b. optimal choice
            d_low = np.fmin(x / 2, 1e-8)
            d_high = np.fmin(x, par.n_max)
            d[i_p,
              i_x] = golden_section_search.optimizer(obj_adj,
                                                     d_low,
                                                     d_high,
                                                     args=(x, inv_v_keep[i_p],
                                                           grid_n, grid_m),
                                                     tol=par.tol)

            # c. optimal value
            m = x - d[i_p, i_x]
            c[i_p, i_x] = linear_interp.interp_2d(par.grid_n, par.grid_m,
                                                  c_keep[i_p], d[i_p, i_x], m)
            inv_v[i_p, i_x] = -obj_adj(d[i_p, i_x], x, inv_v_keep[i_p], grid_n,
                                       grid_m)
            if par.do_marg_u:
                inv_marg_u[i_p, i_x] = 1 / utility.marg_func_nopar(
                    c[i_p, i_x], d[i_p, i_x], d_ubar, alpha, rho)
Ejemplo n.º 6
0
def solve_keep(t, sol, par):
    """solve bellman equation for keepers using nvfi"""

    # unpack output
    inv_v = sol.inv_v_keep[t]
    inv_marg_u = sol.inv_marg_u_keep[t]
    c = sol.c_keep[t]

    # unpack input
    inv_w = sol.inv_w[t]
    grid_a = par.grid_a
    d_ubar = par.d_ubar
    alpha = par.alpha
    rho = par.rho

    # loop over outer states
    for i_p in prange(par.Np):
        for i_n in range(par.Nn):

            # outer states
            n = par.grid_n[i_n]

            # loop over m state
            for i_m in range(par.Nm):

                # a. cash-on-hand
                m = par.grid_m[i_m]
                if i_m == 0:
                    c[i_p, i_n, i_m] = 0
                    inv_v[i_p, i_n, i_m] = 0
                    if par.do_marg_u:
                        inv_marg_u[i_p, i_n, i_m] = 0
                    continue

                # b. optimal choice
                c_low = np.fmin(m / 2, 1e-8)
                c_high = m
                c[i_p, i_n, i_m] = golden_section_search.optimizer(
                    obj_keep,
                    c_low,
                    c_high,
                    args=(n, m, inv_w[i_p, i_n], grid_a, d_ubar, alpha, rho),
                    tol=par.tol)

                # c. optimal value
                v = -obj_keep(c[i_p, i_n, i_m], n, m, inv_w[i_p, i_n], grid_a,
                              d_ubar, alpha, rho)
                inv_v[i_p, i_n, i_m] = -1 / v
                if par.do_marg_u:
                    inv_marg_u[i_p, i_n, i_m] = 1 / utility.marg_func_nopar(
                        c[i_p, i_n, i_m], n, d_ubar, alpha, rho)
Ejemplo n.º 7
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)
def solve_keep(t, sol, par):
    """solve bellman equation for keepers using vfi"""

    # unpack (helps numba optimize)
    inv_v = sol.inv_v_keep[t]
    c = sol.c_keep[t]

    # keep: loop over outer states
    for i_p in prange(par.Np):  # loop in parallel
        for i_n in range(par.Nn):

            p = par.grid_p[i_p]
            n = par.grid_n[i_n]

            # loop over cash-on-hand
            for i_m in range(par.Nm):

                # a. cash-on-hand
                m = par.grid_m[i_m]
                if i_m == 0:
                    c[i_p, i_n, i_m] = 0
                    inv_v[i_p, i_n, i_m] = 0
                    continue

                # b. optimal choice
                c_low = np.fmin(m / 2, 1e-8)
                c_high = m
                c_opt = golden_section_search.optimizer(
                    obj_keep,
                    c_low,
                    c_high,
                    args=(t, n, p, m, sol.inv_v_keep, sol.inv_v_adj, par),
                    tol=par.tol)
                c[i_p, i_n, i_m] = c_opt

                # c. optimal value
                v = -obj_keep(c[i_p, i_n, i_m], t, n, p, m, sol.inv_v_keep,
                              sol.inv_v_adj, par)
                inv_v[i_p, i_n, i_m] = -1 / v
Ejemplo n.º 9
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)
def solve_2d(t, sol, par):
    """ solve the problem in the last period """

    # unpack
    inv_v_keep = sol.inv_v_keep_2d[t]
    inv_marg_u_keep = sol.inv_marg_u_keep_2d[t]
    c_keep = sol.c_keep_2d[t]

    inv_v_adj_full = sol.inv_v_adj_full_2d[t]
    inv_marg_u_adj_full = sol.inv_marg_u_adj_full_2d[t]
    d1_adj_full = sol.d1_adj_full_2d[t]
    d2_adj_full = sol.d2_adj_full_2d[t]
    c_adj_full = sol.c_adj_full_2d[t]

    inv_v_adj_d1 = sol.inv_v_adj_d1_2d[t]
    inv_marg_u_adj_d1 = sol.inv_marg_u_adj_d1_2d[t]
    d1_adj_d1 = sol.d1_adj_d1_2d[t]
    c_adj_d1 = sol.c_adj_d1_2d[t]

    inv_v_adj_d2 = sol.inv_v_adj_d2_2d[t]
    inv_marg_u_adj_d2 = sol.inv_marg_u_adj_d2_2d[t]
    d2_adj_d2 = sol.d2_adj_d2_2d[t]
    c_adj_d2 = sol.c_adj_d2_2d[t]

    # a. keep
    for i_p in prange(par.Np):

        for i_n1 in range(par.Nn):
            for i_n2 in range(par.Nn):
                for i_m in range(par.Nm):

                    # i. states
                    n1 = par.grid_n[i_n1]
                    n2 = par.grid_n[i_n2]
                    m = par.grid_m[i_m]

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

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

                    # iii. optimal value
                    v_keep = utility.func_2d(c_keep[i_p, i_n1, i_n2, i_m], n1,
                                             n2, par)
                    inv_v_keep[i_p, i_n1, i_n2, i_m] = -1.0 / v_keep
                    inv_marg_u_keep[i_p, i_n1, i_n2,
                                    i_m] = 1.0 / utility.marg_func_2d(
                                        c_keep[i_p, i_n1, i_n2, i_m], n1, n2,
                                        par)

    # b. adj full (use gamma = 0.5)
    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 = d1 = d2 = 0
                d1_adj_full[i_p, i_x] = 0
                d2_adj_full[i_p, i_x] = 0
                c_adj_full[i_p, i_x] = 0
                inv_v_adj_full[i_p, i_x] = 0
                inv_marg_u_adj_full[i_p, i_x] = 0
                continue

            # ii. optimal choices
            d_low = np.fmin(x / 2, 1e-8)
            d_high = np.fmin(x / 2, par.n_max)
            d1_adj_full[i_p, i_x] = golden_section_search.optimizer(
                obj_last_period_full_2d,
                d_low,
                d_high,
                args=(x, par),
                tol=par.tol)
            d2_adj_full[i_p, i_x] = d1_adj_full[i_p, i_x]
            c_adj_full[i_p, i_x] = x - 2 * d1_adj_full[i_p, i_x]

            # iii. optimal value
            v_adj = -obj_last_period_full_2d(d1_adj_full[i_p, i_x], x, par)
            inv_v_adj_full[i_p, i_x] = -1.0 / v_adj
            inv_marg_u_adj_full[i_p, i_x] = 1.0 / utility.marg_func_2d(
                c_adj_full[i_p, i_x], d1_adj_full[i_p, i_x],
                d2_adj_full[i_p, i_x], par)

    # c. adj d1
    for i_p in prange(par.Np):

        for i_n2 in range(par.Nn):
            for i_x in range(par.Nx):

                # i. states
                n2 = par.grid_n[i_n2]
                x = par.grid_x[i_x]

                if x == 0:  # forced c = d1 = 0
                    d1_adj_d1[i_p, i_n2, i_x] = 0
                    c_adj_d1[i_p, i_n2, i_x] = 0
                    inv_v_adj_d1[i_p, i_n2, i_x] = 0
                    inv_marg_u_adj_d1[i_p, i_n2, i_x] = 0
                    continue

                # ii. optimal choices
                d_low = np.fmin(x / 2, 1e-8)
                d_high = np.fmin(x, par.n_max)
                d1_adj_d1[i_p, i_n2, i_x] = golden_section_search.optimizer(
                    obj_last_period_d1_2d,
                    d_low,
                    d_high,
                    args=(n2, x, par),
                    tol=par.tol)
                c_adj_d1[i_p, i_n2, i_x] = x - d1_adj_d1[i_p, i_n2, i_x]

                # iii. optimal value
                v_adj = -obj_last_period_d1_2d(d1_adj_d1[i_p, i_n2, i_x], n2,
                                               x, par)
                inv_v_adj_d1[i_p, i_n2, i_x] = -1.0 / v_adj
                inv_marg_u_adj_d1[i_p, i_n2, i_x] = 1.0 / utility.marg_func_2d(
                    c_adj_d1[i_p, i_n2, i_x], d1_adj_d1[i_p, i_n2, i_x], n2,
                    par)

    # d. adj d2
    for i_p in prange(par.Np):
        for i_n1 in range(par.Nn):
            for i_x in range(par.Nx):

                # i. states
                n1 = par.grid_n[i_n1]
                x = par.grid_x[i_x]

                if x == 0:  # forced c = d2 = 0
                    d2_adj_d2[i_p, i_n1, i_x] = 0
                    c_adj_d2[i_p, i_n1, i_x] = 0
                    inv_v_adj_d2[i_p, i_n1, i_x] = 0
                    inv_marg_u_adj_d2[i_p, i_n1, i_x] = 0
                    continue

                # ii. optimal choices
                d_low = np.fmin(x / 2, 1e-8)
                d_high = np.fmin(x, par.n_max)
                d2_adj_d2[i_p, i_n1, i_x] = golden_section_search.optimizer(
                    obj_last_period_d2_2d,
                    d_low,
                    d_high,
                    args=(n1, x, par),
                    tol=par.tol)
                c_adj_d2[i_p, i_n1, i_x] = x - d2_adj_d2[i_p, i_n1, i_x]

                # iii. optimal value
                v_adj = -obj_last_period_d2_2d(d2_adj_d2[i_p, i_n1, i_x], n1,
                                               x, par)
                inv_v_adj_d2[i_p, i_n1, i_x] = -1.0 / v_adj
                inv_marg_u_adj_d2[i_p, i_n1, i_x] = 1.0 / utility.marg_func_2d(
                    c_adj_d2[i_p, i_n1, i_x], n1, d2_adj_d2[i_p, i_n1, i_x],
                    par)