def simulation(simu_size = 100):
    income_path = np.ones((simu_size,1)) 
    location_path = 0 * np.ones((simu_size,1))
    citizenship_path = 0 *np.ones((simu_size,1))
    liquid_path = 0 *np.ones((simu_size,1))
    illiquid_path = 0 *np.ones((simu_size,1))
    for t in range(simu_size-1):
        skill_it = int(income_path[t,0])
        co1 = int(location_path[t,0])
        co2 = int(citizenship_path[t,0])
        index_tod = skill_it + co1 * Skill_level_no + co2 * No_countries * Skill_level_no
        income_tmp = Skill_level1[skill_it,co1]
        illiquid_weight = ip.spli_basex(illiquid_param_asset,illiquid_path[t,0,None],deg = degree,knots = illiquid_asset_grid_fine )
        liquid_weight = ip.spli_basex(liquid_param_asset,liquid_path[t,0,None],deg = degree,knots = liquid_asset_grid_fine)
        weights_combined = ip.dprod(liquid_weight,illiquid_weight)
        nonzero_weight = (weights_combined > 1e-10)
        state_approx = s_fine[nonzero_weight[0,:] ==1,:]
        a_prime_approx = a_prime_fine[nonzero_weight[0,:] ==1,index_tod]
        m_prime_approx = m_prime_fine[nonzero_weight[0,:] ==1,index_tod]
        m_next = np.sum(weights_combined[0,nonzero_weight[0,:] ==1] * m_prime_approx)
        a_next = np.sum(weights_combined[0,nonzero_weight[0,:] ==1] * a_prime_approx)
        location_path[t+1,0] = np.min(index_max[nonzero_weight[0,:] ==1,index_tod])
        illiquid_path[t+1,0] = a_next
        liquid_path[t+1,0] = m_next
    plt.plot(illiquid_path)
    plt.plot(liquid_path)
    plt.plot(location_path)
    return 1
Example #2
0
 def current_util_xy(m_prime, a_prime, income, coeff1, rel_price_a,
                     rel_price_m, Phi_prime_a):
     Phi_prime_m = ip.spli_basex(liquid_param_asset,
                                 m_prime,
                                 deg=degree,
                                 knots=knots_liquid)
     Phi_prime = ip.dprod(Phi_prime_m, Phi_prime_a)
     EV = Beta * (Phi_prime @ coeff1)
     V_fut = util(income - rel_price_a * a_prime -
                  rel_price_m * m_prime) + EV
     return V_fut
 def current_util_x(a_prime,income,coeff1,rel_price_a,rel_price_m,quad_cost_param,cap):
     Phi_prime_a = ip.spli_basex(illiquid_param_asset,a_prime,deg = degree,knots = knots_illiquid)
     if quad_cost_param >0:
         income_cost = np.float_power( np.maximum((cap - a_prime),0),AdjustCost_curve)
         liquid_lower_bound_applied=M_lower_search_adj
         upper_bound_applied1=M_upper_search_adj
         quad_cost_param=quad_cost_param-1.
     else:
         income_cost = 0
         liquid_lower_bound_applied=M_lower_search_NOadj
         upper_bound_applied1=M_upper_search_NOadj        
     income1 = income - quad_cost_param *income_cost
     m_prime, V_fut = ip.goldenx(current_util_xy,liquid_lower_bound_applied,upper_bound_applied1,max_tol,a_prime,income1,coeff1,rel_price_a,rel_price_m,Phi_prime_a)
     return V_fut
Example #4
0
def main_loop(coeff,coeff_e,c_vec = c_guess,outer_loop = None,n_a1 = n_a,dampen_coeff = dampen_coeff_start):
    'Quantities'
    conv1 = 2.0
    iteration = 0
    agrid = np.linspace(a_lower,a_upper, n_a1)
    agrid = np.reshape(agrid,(n_a1,1))
    s =  np.concatenate((np.kron(np.ones((n_z,1)),agrid),np.kron(zgrid,np.ones((n_a1,1)))),1)
    c_vec = np.minimum(c_vec,c_bounds(s,c_vec))
    c_vec = np.maximum(c_vec,c_bounds(s,c_vec , 'upper'))
    aprime = aprimefunc(s,c_vec)
    while conv1 > 1e-3:
        conv2 = 10.0
        iteration = iteration + 1
        if iteration > fast_coeff:
            dampen_coeff = 1.0
        while conv2 > 1e-3:
            aprime_c = aprimefunc_x(s,c_vec)
            aprime_cc = aprimefunc_xx(s,c_vec)        
            sprime = np.concatenate((aprime,s[:,1,None]),axis = 1)
            Phi_xps1 = ip.funbas(P,sprime,(1,0),Polyname)
            Phi_xps2 = ip.funbas(P,sprime,(2,0),Polyname)
            
            
            Hessian = F_xx(s,c_vec) + beta *( np.multiply(Phi_xps1@coeff_e,aprime_cc ) + np.multiply(Phi_xps2@coeff_e, (aprime_c)**2 ))
            Jacobian = F_x(s,c_vec) + beta *( np.multiply(Phi_xps1@coeff_e,aprime_c )) 
            
            c_vec_next = np.minimum(newton_method(c_vec,Jacobian,Hessian,dampen_newton),c_bounds(s,c_vec))
            c_vec_next = np.maximum(c_vec_next,c_bounds(s,c_vec , 'upper'))
            #c_vec_next = newton_method(c_vec,Jacobian,Hessian,dampen_newton)
            conv2 = np.max( np.absolute (c_vec_next - c_vec ))
            c_vec = c_vec_next
            aprime = aprimefunc(s,c_vec)
            print(conv2)
        if outer_loop == 1:
            'Computing the stationary distribution'
            conv1 = 0
            Q_x = ip.spli_basex((n_a1,a_lower,a_upper),aprime[:,0],knots = None , deg= 1,order = 0)
            Q_z = np.kron(T,np.ones((n_a1,1)))
            Q = ip.dprod(Q_z,Q_x)
            w , v = slin.eig(Q.transpose())
            L = (v[:,0] / v[:,0].real.sum(0)).real
            agra = np.dot(L,aprime) # Aggregate asset level
            Res = (L,agra,c_vec)
        else:
            conv1, coeff , coeff_e = newton_iter(coeff,coeff_e,dampen_coeff,s,c_vec,sprime,Phi_s,F)
            Res = (coeff, coeff_e,c_vec)
        print((conv1,conv2))
    return Res
Example #5
0
def LoopFunc(x, gamma, Skill_level_no, Beta, degree, No_countries, coeff_e,
             liquid_param_asset, illiquid_param_asset, liquid_lower_bound,
             liquid_upper_bound, max_tol, Wage, Skill_level1, price,
             AdjustCost, Bond, illiquid_upper_bound, illiquid_lower_bound,
             CapLimiter, r, s, AdjustCost_quad, AdjustCost_curve, knots_liquid,
             knots_illiquid, Cons_NOadj, Cons_adj, Phi_fine, AssetMultiplied,
             conv, s_fine, fine_grid_no, illiquid_param_asset_fine, Profits,
             Czship):
    #def util(cons):
    #    return cons**(1 - gamma) / (1 - gamma)

    skill_it = int(x[0])
    co1 = int(x[1])
    co2 = int(x[2])
    checkerror_value = -5000
    index_tod = skill_it + co1 * Skill_level_no + co2 * No_countries * Skill_level_no
    Cap_adj_lim = s[:, 0] * (
        1 + r[co2])  #np.minimum(s[:,0]*(1+r[co2]),illiquid_upper_bound)#
    # Gridsearch
    EV_grid = Beta * np.tile((Phi_fine @ coeff_e[:, index_tod, None]).T,
                             (AssetMultiplied, 1))
    V_adj = Cons_adj[:, :, index_tod] + EV_grid
    adjust_state_index = V_adj.argmax(1)
    V_NOadj = Cons_NOadj[:, :, index_tod] + EV_grid
    NOadjust_state_index = V_NOadj.argmax(1)
    center_grid_adj = s_fine[adjust_state_index, :]
    center_grid_NOadj = s_fine[NOadjust_state_index, :]

    #Bounds for goldenx
    if conv < 0.0000000001:

        s_min = s_fine.min(0)
        s_max = s_fine.max(0)
        above_min_adj = (center_grid_adj > s_min)
        min_grid_adj = above_min_adj * np.concatenate(
            (s_fine[adjust_state_index - 1, 0, None], s_fine[
                adjust_state_index - illiquid_param_asset_fine[0], 1, None]),
            axis=1) + (1 - above_min_adj) * s_min
        below_max_adj = (center_grid_adj < s_max)
        max_grid_adj = below_max_adj * np.concatenate(
            (s_fine[np.minimum(adjust_state_index + 1, fine_grid_no - 1), 0,
                    None], s_fine[np.minimum(
                        adjust_state_index +
                        illiquid_param_asset_fine[0], fine_grid_no - 1), 1,
                                  None]),
            axis=1) + (1 - below_max_adj) * s_max
        max_grid_adj = np.concatenate(
            (np.minimum(max_grid_adj[:, 0, None],
                        Cap_adj_lim[:, None]), max_grid_adj[:, 1, None]),
            axis=1)
        min_grid_adj = np.minimum(min_grid_adj, max_grid_adj)
        above_min_NOadj = (center_grid_NOadj > s_min)
        min_grid_NOadj = above_min_NOadj * np.concatenate(
            (s_fine[NOadjust_state_index - 1, 0, None], s_fine[
                NOadjust_state_index - illiquid_param_asset_fine[0], 1, None]),
            axis=1) + (1 - above_min_NOadj) * s_min
        below_max_NOadj = (center_grid_NOadj < s_max)
        max_grid_NOadj = below_max_NOadj * np.concatenate(
            (s_fine[np.minimum(NOadjust_state_index + 1, fine_grid_no - 1), 0,
                    None], s_fine[np.minimum(
                        NOadjust_state_index +
                        illiquid_param_asset_fine[0], fine_grid_no - 1), 1,
                                  None]),
            axis=1) + (1 - below_max_NOadj) * s_max
        min_grid_NOadj = np.concatenate(
            (np.maximum(min_grid_NOadj[:, 0, None],
                        Cap_adj_lim[:, None]), min_grid_NOadj[:, 1, None]),
            axis=1)
        max_grid_NOadj = np.concatenate((np.maximum(
            min_grid_NOadj[:, 0, None],
            max_grid_NOadj[:, 0, None]), max_grid_NOadj[:, 1, None]),
                                        axis=1)
        # Saving values for future use and to check if they are admissible as bounds for goldenx
        # Min adj
        a_goldenx_min_grid_adj = sparse.csr_matrix(
            (np.ones(AssetMultiplied),
             (np.arange(0, AssetMultiplied, 1), above_min_adj[:, 0] *
              (adjust_state_index - 1) +
              (1 - above_min_adj[:, 0]) * adjust_state_index)),
            (AssetMultiplied, fine_grid_no))
        V_grid_adj_a_min = (a_goldenx_min_grid_adj.toarray() * V_adj).sum(1)
        m_goldenx_min_grid_adj = sparse.csr_matrix(
            (np.ones(AssetMultiplied),
             (np.arange(0, AssetMultiplied, 1), above_min_adj[:, 1] *
              (adjust_state_index - illiquid_param_asset_fine[0]) +
              (1 - above_min_adj[:, 1]) * adjust_state_index)),
            (AssetMultiplied, fine_grid_no))
        V_grid_adj_m_min = (m_goldenx_min_grid_adj.toarray() * V_adj).sum(1)
        gridsearch_nonsensical_adjust_a_min = V_grid_adj_a_min < checkerror_value
        gridsearch_nonsensical_adjust_m_min = V_grid_adj_m_min < checkerror_value
        # Max adj
        a_goldenx_max_grid_adj = sparse.csr_matrix(
            (np.ones(AssetMultiplied),
             (np.arange(0, AssetMultiplied, 1), below_max_adj[:, 0] *
              (np.minimum(adjust_state_index + 1, fine_grid_no - 1)) +
              (1 - below_max_adj[:, 0]) * adjust_state_index)),
            (AssetMultiplied, fine_grid_no))
        V_grid_adj_a_max = (a_goldenx_max_grid_adj.toarray() * V_adj).sum(1)
        m_goldenx_max_grid_adj = sparse.csr_matrix(
            (np.ones(AssetMultiplied),
             (np.arange(0, AssetMultiplied, 1), below_max_adj[:, 1] *
              (np.minimum(adjust_state_index + illiquid_param_asset_fine[0],
                          fine_grid_no - 1)) +
              (1 - below_max_adj[:, 1]) * adjust_state_index)),
            (AssetMultiplied, fine_grid_no))
        V_grid_adj_m_max = (m_goldenx_max_grid_adj.toarray() * V_adj).sum(1)
        gridsearch_nonsensical_adjust_a_max = V_grid_adj_a_max < checkerror_value
        gridsearch_nonsensical_adjust_m_max = V_grid_adj_m_max < checkerror_value
        # Min NOadj
        a_goldenx_min_grid_NOadj = sparse.csr_matrix(
            (np.ones(AssetMultiplied),
             (np.arange(0, AssetMultiplied, 1), above_min_NOadj[:, 0] *
              (NOadjust_state_index - 1) +
              (1 - above_min_NOadj[:, 0]) * NOadjust_state_index)),
            (AssetMultiplied, fine_grid_no))
        V_grid_NOadj_a_min = (a_goldenx_min_grid_NOadj.toarray() *
                              V_NOadj).sum(1)
        m_goldenx_min_grid_NOadj = sparse.csr_matrix(
            (np.ones(AssetMultiplied),
             (np.arange(0, AssetMultiplied, 1), above_min_NOadj[:, 1] *
              (NOadjust_state_index - illiquid_param_asset_fine[0]) +
              (1 - above_min_NOadj[:, 1]) * NOadjust_state_index)),
            (AssetMultiplied, fine_grid_no))
        V_grid_NOadj_m_min = (m_goldenx_min_grid_NOadj.toarray() *
                              V_NOadj).sum(1)
        gridsearch_nonsensical_NOadjust_a_min = V_grid_NOadj_a_min < checkerror_value
        gridsearch_nonsensical_NOadjust_m_min = V_grid_NOadj_m_min < checkerror_value
        # Max NOadj
        a_goldenx_max_grid_NOadj = sparse.csr_matrix(
            (np.ones(AssetMultiplied),
             (np.arange(0, AssetMultiplied, 1), below_max_NOadj[:, 0] *
              (np.minimum(NOadjust_state_index + 1, fine_grid_no - 1)) +
              (1 - below_max_NOadj[:, 0]) * NOadjust_state_index)),
            (AssetMultiplied, fine_grid_no))
        V_grid_NOadj_a_max = (a_goldenx_max_grid_NOadj.toarray() *
                              V_NOadj).sum(1)
        m_goldenx_max_grid_NOadj = sparse.csr_matrix(
            (np.ones(AssetMultiplied),
             (np.arange(0, AssetMultiplied, 1), below_max_NOadj[:, 1] *
              (np.minimum(NOadjust_state_index + illiquid_param_asset_fine[0],
                          fine_grid_no - 1)) +
              (1 - below_max_NOadj[:, 1]) * NOadjust_state_index)),
            (AssetMultiplied, fine_grid_no))
        V_grid_NOadj_m_max = (m_goldenx_max_grid_NOadj.toarray() *
                              V_NOadj).sum(1)
        gridsearch_nonsensical_NOadjust_a_max = V_grid_NOadj_a_max < checkerror_value
        gridsearch_nonsensical_NOadjust_m_max = V_grid_NOadj_m_max < checkerror_value
        #Search For Point
        A_lower_search_adj = (
            1 - gridsearch_nonsensical_adjust_a_min
        ) * min_grid_adj[:,
                         0] + gridsearch_nonsensical_adjust_a_min * center_grid_adj[:,
                                                                                    0]
        A_upper_search_adj = (
            1 - gridsearch_nonsensical_adjust_a_max
        ) * max_grid_adj[:,
                         0] + gridsearch_nonsensical_adjust_a_max * center_grid_adj[:,
                                                                                    0]
        M_lower_search_adj = (
            1 - gridsearch_nonsensical_adjust_m_min
        ) * min_grid_adj[:,
                         1] + gridsearch_nonsensical_adjust_m_min * center_grid_adj[:,
                                                                                    1]
        M_upper_search_adj = (
            1 - gridsearch_nonsensical_adjust_m_max
        ) * max_grid_adj[:,
                         1] + gridsearch_nonsensical_adjust_m_max * center_grid_adj[:,
                                                                                    1]
        #
        A_lower_search_NOadj = (
            1 - gridsearch_nonsensical_NOadjust_a_min
        ) * min_grid_NOadj[:,
                           0] + gridsearch_nonsensical_NOadjust_a_min * center_grid_NOadj[:,
                                                                                          0]
        A_upper_search_NOadj = (
            1 - gridsearch_nonsensical_NOadjust_a_max
        ) * max_grid_NOadj[:,
                           0] + gridsearch_nonsensical_NOadjust_a_max * center_grid_NOadj[:,
                                                                                          0]
        M_lower_search_NOadj = (
            1 - gridsearch_nonsensical_NOadjust_m_min
        ) * min_grid_NOadj[:,
                           1] + gridsearch_nonsensical_NOadjust_m_min * center_grid_NOadj[:,
                                                                                          1]
        M_upper_search_NOadj = (
            1 - gridsearch_nonsensical_NOadjust_m_max
        ) * max_grid_NOadj[:,
                           1] + gridsearch_nonsensical_NOadjust_m_max * center_grid_NOadj[:,
                                                                                          1]
        #Fixed Point
    else:
        A_lower_search_adj = center_grid_adj[:, 0]
        A_upper_search_adj = center_grid_adj[:, 0]
        M_lower_search_adj = center_grid_adj[:, 1]
        M_upper_search_adj = center_grid_adj[:, 1]
        A_lower_search_NOadj = center_grid_NOadj[:, 0]
        A_upper_search_NOadj = center_grid_NOadj[:, 0]
        M_lower_search_NOadj = center_grid_NOadj[:, 1]
        M_upper_search_NOadj = center_grid_NOadj[:, 1]
    goldenx_center_grid_adj = sparse.csr_matrix(
        (np.ones(AssetMultiplied),
         (np.arange(0, AssetMultiplied, 1), adjust_state_index)),
        (AssetMultiplied, fine_grid_no))
    V_grid_adj_opt = (goldenx_center_grid_adj.toarray() * V_adj).sum(1)
    goldenx_center_grid_NOadj = sparse.csr_matrix(
        (np.ones(AssetMultiplied),
         (np.arange(0, AssetMultiplied, 1), NOadjust_state_index)),
        (AssetMultiplied, fine_grid_no))
    V_grid_NOadj_opt = (goldenx_center_grid_NOadj.toarray() * V_NOadj).sum(1)
    gridsearch_nonsensical_NOadjust = V_grid_NOadj_opt < checkerror_value
    gridsearch_nonsensical_adjust = V_grid_adj_opt < checkerror_value

    # Value function approximation
    def util(cons):
        res = cons > 0
        res1 = np.absolute(cons)
        return res1**(1 - gamma) / (1 - gamma) * res - (1 - res) * (10000000 *
                                                                    res1)

    def current_util_xy(m_prime, a_prime, income, coeff1, rel_price_a,
                        rel_price_m, Phi_prime_a):
        Phi_prime_m = ip.spli_basex(liquid_param_asset,
                                    m_prime,
                                    deg=degree,
                                    knots=knots_liquid)
        Phi_prime = ip.dprod(Phi_prime_m, Phi_prime_a)
        EV = Beta * (Phi_prime @ coeff1)
        V_fut = util(income - rel_price_a * a_prime -
                     rel_price_m * m_prime) + EV
        return V_fut

    def current_util_x(a_prime, income, coeff1, rel_price_a, rel_price_m,
                       quad_cost_param, cap):
        Phi_prime_a = ip.spli_basex(illiquid_param_asset,
                                    a_prime,
                                    deg=degree,
                                    knots=knots_illiquid)
        if quad_cost_param > 0:
            income_cost = np.float_power(np.maximum((cap - a_prime), 0),
                                         AdjustCost_curve)
            liquid_lower_bound_applied = M_lower_search_adj
            upper_bound_applied1 = M_upper_search_adj
            quad_cost_param = quad_cost_param - 1.
        else:
            income_cost = 0
            liquid_lower_bound_applied = M_lower_search_NOadj
            upper_bound_applied1 = M_upper_search_NOadj
        income1 = income - quad_cost_param * income_cost
        m_prime, V_fut = ip.goldenx(current_util_xy,
                                    liquid_lower_bound_applied,
                                    upper_bound_applied1, max_tol, a_prime,
                                    income1, coeff1, rel_price_a, rel_price_m,
                                    Phi_prime_a)
        return V_fut

    AdjustCost_applied = price[co2] * AdjustCost[co1 + co2 * No_countries]
    AdjustCost_applied_quad = price[co2] * AdjustCost_quad[
        co1 + co2 * No_countries] / (price[co1])
    #real_income = (Wage[co1] * Skill_level1[skill_it,co1] +price[0]*np.minimum(s[:,1]/Bond,liquid_upper_bound) + price[co2]*Cap_adj_lim)/(price[co1]) - AdjustCost_applied/price[co1]
    real_income = (Wage[co1] * Skill_level1[skill_it, co1] +
                   price[0] * s[:, 1] / Bond + price[co2] * Cap_adj_lim +
                   Profits[co2] / Czship[co2]) / (
                       price[co1]) - AdjustCost_applied / price[co1]
    rel_price_a = price[co2] / (price[co1])
    rel_price_m = price[0] / (price[co1])

    fut_asset_adjust, V_adjust_temp = ip.goldenx(
        current_util_x, A_lower_search_adj, A_upper_search_adj, max_tol,
        real_income, coeff_e[:, index_tod], rel_price_a, rel_price_m,
        AdjustCost_applied_quad + 1., Cap_adj_lim)
    Phi_prime_a_temp_adjust = ip.spli_basex(illiquid_param_asset,
                                            fut_asset_adjust,
                                            deg=degree,
                                            knots=knots_illiquid)
    real_income_adjust1 = real_income - AdjustCost_applied_quad * np.float_power(
        np.maximum((Cap_adj_lim - fut_asset_adjust), 0), AdjustCost_curve)
    #upper_bound_applied2 = np.minimum((real_income_adjust1 - rel_price_a * fut_asset_adjust) / rel_price_m, liquid_upper_bound) #liquid_upper_bound #np.minimum((real_income - rel_price_a *fut_asset_adjust) / rel_price_m, liquid_upper_bound)
    m_prime_adjust, V_adjust_temp1 = ip.goldenx(
        current_util_xy, M_lower_search_adj, M_upper_search_adj, max_tol,
        fut_asset_adjust, real_income_adjust1, coeff_e[:, index_tod],
        rel_price_a, rel_price_m, Phi_prime_a_temp_adjust)

    #Non-adjust
    #real_income_NOadjust = (Wage[co1] * Skill_level1[skill_it,co1] +price[0]*np.minimum(s[:,1]/Bond,liquid_upper_bound) + price[co2]*Cap_adj_lim)/(price[co1])
    real_income_NOadjust = (
        Wage[co1] * Skill_level1[skill_it, co1] + price[0] * s[:, 1] / Bond +
        price[co2] * Cap_adj_lim + Profits[co2] / Czship[co2]) / (price[co1])
    fut_asset_NOadjust, V_NOadjust_temp = ip.goldenx(
        current_util_x, A_lower_search_NOadj, A_upper_search_NOadj, max_tol,
        real_income_NOadjust, coeff_e[:, index_tod], rel_price_a, rel_price_m,
        0, Cap_adj_lim)
    Phi_prime_a_temp_NOadjust = ip.spli_basex(illiquid_param_asset,
                                              fut_asset_NOadjust,
                                              deg=degree,
                                              knots=knots_illiquid)

    m_prime_NOadjust, V_NOadjust_temp1 = ip.goldenx(
        current_util_xy, M_lower_search_NOadj, M_upper_search_NOadj, max_tol,
        fut_asset_NOadjust, real_income_NOadjust, coeff_e[:, index_tod],
        rel_price_a, rel_price_m, Phi_prime_a_temp_NOadjust)

    V_NOadjust_temp_true = V_NOadjust_temp * (
        1 - gridsearch_nonsensical_NOadjust
    ) + checkerror_value * gridsearch_nonsensical_NOadjust

    V_adjust_temp_true = V_adjust_temp * (
        1 - gridsearch_nonsensical_adjust
    ) + checkerror_value * gridsearch_nonsensical_adjust
    index_adjust = np.argmax(np.concatenate(
        (V_NOadjust_temp_true[:, None], V_adjust_temp_true[:, None]), axis=1),
                             axis=1)
    V_val_temp = V_adjust_temp_true * index_adjust + (
        1 - index_adjust) * V_NOadjust_temp_true

    #V_val_temp = (V_adjust_temp * index_adjust + (1 - index_adjust) * V_NOadjust_temp)
    m_prime_final = m_prime_adjust * index_adjust + (
        1 - index_adjust) * m_prime_NOadjust
    a_prime_final = fut_asset_adjust * index_adjust + (
        1 - index_adjust) * fut_asset_NOadjust
    Phi_prime_a_temp = ip.spli_basex(illiquid_param_asset,
                                     a_prime_final,
                                     deg=degree,
                                     knots=knots_illiquid)
    Phi_prime_m_temp = ip.spli_basex(liquid_param_asset,
                                     m_prime_final,
                                     deg=degree,
                                     knots=knots_liquid)
    return V_val_temp, Phi_prime_a_temp, Phi_prime_m_temp
def current_util_simple(fut_asset,income,coeff1,rel_price):
    #fut_asset = rel_price * fut_asset
    #Phi_asset = ip.spli_basex(param_asset,fut_asset.flatten(),knots = knots_a)
    Phi_asset = ip.spli_basex(illiquid_param_asset,fut_asset.flatten(),deg = degree,knots = knots_illiquid)
    V_fut = (Phi_asset @ coeff1).reshape(fut_asset.shape)
    return util(income - rel_price * fut_asset) + Beta * V_fut
                                Transition_Matrix_stacked1[index_tod,index_tod1,co3] = Transition_Matrix_stacked[co1*Skill_level_no + skill_it,co1*Skill_level_no + skill_it2]
                                Transition_Matrix_stacked_stay[index_tod,index_tod1] = Transition_Matrix_stacked[co1*Skill_level_no + skill_it,co1*Skill_level_no + skill_it2]
                            if(co4==co2 and co3 !=co2):# citizenship is unchanged and does not equals the location #1 - citizenship attrition
                                Transition_Matrix_stacked1[index_tod,index_tod1,co3] = (1 - citizenship_attrition) *Transition_Matrix_stacked[co1*Skill_level_no + skill_it,co1*Skill_level_no + skill_it2]
                                Transition_Matrix_stacked_stay[index_tod,index_tod1] =  (1 - citizenship_attrition) *Transition_Matrix_stacked[co1*Skill_level_no + skill_it,co1*Skill_level_no + skill_it2]
                            if(co4!=co2 and co3 !=co2):# citizenship has changed as it was not equal to the location # citizenship attrition
                                Transition_Matrix_stacked1[index_tod,index_tod1,co3] = citizenship_attrition *Transition_Matrix_stacked[co1*Skill_level_no + skill_it,co1*Skill_level_no + skill_it2]
                                Transition_Matrix_stacked_stay[index_tod,index_tod1] = citizenship_attrition *Transition_Matrix_stacked[co1*Skill_level_no + skill_it,co1*Skill_level_no + skill_it2]
                        if(co3 != co1): # migration - no citizenship transition possible - still citizenship matters
                            if(co4==co2 and co3 ==co2):# citizenship is unchanged and equals the location #- returning home to co3
                                Transition_Matrix_stacked1[index_tod,index_tod1,co3] = Transition_Matrix_stacked[co3*Skill_level_no + skill_it,co3*Skill_level_no + skill_it2]
                            if(co4==co2 and co3 !=co2):# citizenship is unchanged and does not equal the location # foreingers going to co3
                                Transition_Matrix_stacked1[index_tod,index_tod1,co3] = Transition_Matrix_stacked[co4*Skill_level_no + skill_it,co3*Skill_level_no + skill_it2]

        
Phi_illiquid = ip.spli_basex(illiquid_param_asset,s[:,0],deg = degree,knots = knots_illiquid)
Phi_liquid = ip.spli_basex(liquid_param_asset,s[:,1],deg = degree,knots = knots_liquid)
Phi_fine_illiquid = ip.spli_basex(illiquid_param_asset,s_fine[:,0],deg = degree,knots = knots_illiquid )
Phi_fine_liquid = ip.spli_basex(liquid_param_asset,s_fine[:,1],deg = degree,knots = knots_liquid)

#Phi = ip.spli_basex(param_asset,asset_grid,knots = knots_a)
Phi = ip.dprod(Phi_liquid,Phi_illiquid)
Phi_fine = ip.dprod(Phi_fine_liquid,Phi_fine_illiquid)
#Phi_fine = ip.spli_basex(param_asset,asset_grid_fine,knots = knots_a_fine)
Phi_inv = np.linalg.inv(Phi)
Phi_inv_tile = np.tile(Phi_inv, (1,No_countries**2 * Skill_level_no))
#diag_transf_v = np.kron(np.ones((No_countries**2 * Skill_level_no,1)),np.eye(param_asset[0]))
def diag_mat_block(Mat):
    res = np.zeros((Mat.shape[0] * Mat.shape[1],Mat.shape[1]))
    for ii in range(Mat.shape[1]):
        res[(ii*Mat.shape[0]):((ii + 1)*Mat.shape[0]),ii] = Mat[:,ii]