def JDiteration(self, m_star, P_H, mpar, grid):
        '''
        Iterates the joint distribution over m,k,h using a transition matrix
        obtained from the house distributing the households optimal choices. 
        It distributes off-grid policies to the nearest on grid values.
        
        parameters
        ------------
        m_star :np.array
            optimal m func
        P_H : np.array
            transition probability    
        mpar : dict
             parameters    
        grid : dict
             grids
             
        returns
        ------------
        joint_distr : np.array
            joint distribution of m and h
        
        '''
        ## find next smallest on-grid value for money and capital choices
        weight11 = np.zeros((mpar['nm'], mpar['nh'], mpar['nh']))
        weight12 = np.zeros((mpar['nm'], mpar['nh'], mpar['nh']))

        # Adjustment case
        resultGW = GenWeight(m_star, grid['m'])
        Dist_m = resultGW['weight'].copy()
        idm = resultGW['index'].copy()

        idm = np.transpose(np.tile(idm.flatten(order='F'), (mpar['nh'], 1)))
        idh = np.kron(range(mpar['nh']), np.ones((1, mpar['nm'] * mpar['nh'])))
        idm = idm.copy().astype(int)
        idh = idh.copy().astype(int)

        index11 = np.ravel_multi_index(
            [idm.flatten(order='F'),
             idh.flatten(order='F')], (mpar['nm'], mpar['nh']),
            order='F')
        index12 = np.ravel_multi_index(
            [idm.flatten(order='F') + 1,
             idh.flatten(order='F')], (mpar['nm'], mpar['nh']),
            order='F')

        for hh in range(mpar['nh']):

            # Corresponding weights
            weight11_aux = (1. - Dist_m[:, hh].copy())
            weight12_aux = (Dist_m[:, hh].copy())

            # Dimensions (mxk,h',h)
            weight11[:, :, hh] = np.outer(weight11_aux.flatten(order='F'),
                                          P_H[hh, :].copy())
            weight12[:, :, hh] = np.outer(weight12_aux.flatten(order='F'),
                                          P_H[hh, :].copy())

        weight11 = np.ndarray.transpose(weight11.copy(), (0, 2, 1))
        weight12 = np.ndarray.transpose(weight12.copy(), (0, 2, 1))

        rowindex = np.tile(range(mpar['nm'] * mpar['nh']), (1, 2 * mpar['nh']))

        H = sp.coo_matrix(
            (np.concatenate(
                (weight11.flatten(order='F'), weight12.flatten(order='F'))),
             (rowindex.flatten(),
              np.concatenate(
                  (index11.flatten(order='F'), index12.flatten(order='F'))))),
            shape=(mpar['nm'] * mpar['nh'], mpar['nm'] * mpar['nh']))

        ## Joint transition matrix and transitions

        distJD = 9999.
        countJD = 1

        eigen, joint_distr = sp.linalg.eigs(H.transpose(), k=1, which='LM')
        joint_distr = joint_distr.copy().real
        joint_distr = joint_distr.copy().transpose() / (
            joint_distr.copy().sum())

        while (distJD > 10**(-14) or countJD < 50) and countJD < 10000:

            joint_distr_next = joint_distr.copy().dot(H.copy().todense())

            joint_distr_next = joint_distr_next.copy() / joint_distr_next.copy(
            ).sum(axis=1)
            distJD = np.max((np.abs(joint_distr_next.copy().flatten() -
                                    joint_distr.copy().flatten())))

            countJD = countJD + 1
            joint_distr = joint_distr_next.copy()

        return joint_distr
Пример #2
0
def Fsys(State, Stateminus, Control_sparse, Controlminus_sparse, StateSS,
         ControlSS, Gamma_state, Gamma_control, InvGamma, Copula, par, mpar,
         grid, targets, P, aggrshock, oc):
    '''
    Parameters
    ----------
    par : dict
        par['mu'] = par.mu : float
        par['beta'] = par.beta : float
        par['kappa'] = par.kappa : float
        par['tau'] = par.tau : float
        par['alpha'] = par.alpha : float
        par['gamma'] = par.gamma : float
        par['xi]= par.xi : float
        par['rhoS'] = par.rhoS : float
        par['profitshare'] = par.profitshare : float
        par['borrwedge'] = par.borrwedge : float
        par['RB']
        par['rho_R']
        par['PI']
        par['theta_pi']
    mpar : dict
        mpar['nm']=mparnm : int
        mpar['nh']=mparnh : int
    grid : dict
        grid['m']=grid.m : np.array (row vector)
        grid['h']=grid.h : np.array
        grid['boundsH']=grid.boundsH : np.array (1,mpar['nh'])
        grid['K'] = grid.K : float
    StateSS : np.array (column vector)   
    Copula : function
    targets : dict
        targets['B'] : float
    oc: int
    
    '''

    ## Initialization
    #    mutil = lambda x : 1./(x**par['xi'])
    mutil = lambda x: 1. / np.power(x, par['xi'])
    #    invmutil = lambda x : (1./x)**(1./par['xi'])
    invmutil = lambda x: np.power(1. / x, 1. / par['xi'])

    # Generate meshes for b,k,h
    meshesm, meshesh = np.meshgrid(grid['m'], grid['h'], indexing='ij')
    meshes = {'m': meshesm, 'h': meshesh}

    # number of states, controls
    nx = mpar['numstates']  # number of states
    ny = mpar['numcontrols']  # number of controls
    NxNx = nx - 2  # number of states w/o aggregates
    NN = mpar['nm'] * mpar['nh']  # number of points in the full grid

    ## Indexes for LHS/RHS
    # Indexes for controls
    mutil_cind = np.array(range(NN))
    PIind = 1 * NN
    Yind = 1 * NN + 1
    #Gind = 1*NN+2
    Wind = 1 * NN + 2
    Profitind = 1 * NN + 3
    Nind = 1 * NN + 4
    #Tind = 1*NN+6
    Bind = 1 * NN + 5
    Gind = 1 * NN + 6
    Cind = 1 * NN + 7
    Xind = 1 * NN + 8

    # Initialize LHS and RHS
    LHS = np.zeros((nx + Xind + 1, 1))
    RHS = np.zeros((nx + Xind + 1, 1))

    # Indexes for states
    #distr_ind = np.arange(mpar['nm']*mpar['nh']-mpar['nh']-1)
    marginal_mind = range(mpar['nm'] - 1)
    marginal_hind = range(mpar['nm'] - 1, mpar['nm'] + mpar['nh'] - 3)

    RBind = NxNx
    Sind = NxNx + 1

    ## Control variables
    #Control = ControlSS.copy()+Control_sparse.copy()
    #Controlminus = ControlSS.copy()+Controlminus_sparse.copy()
    Control = np.multiply(
        ControlSS.copy(),
        (1 + Gamma_control.copy().dot(Control_sparse.copy())))
    Controlminus = np.multiply(
        ControlSS.copy(),
        (1 + Gamma_control.copy().dot(Controlminus_sparse.copy())))

    Control[-oc:] = ControlSS[-oc:].copy() + Gamma_control[-oc:, :].copy().dot(
        Control_sparse.copy())
    Controlminus[-oc:] = ControlSS[-oc:].copy() + Gamma_control[
        -oc:, :].copy().dot(Controlminus_sparse.copy())

    ## State variables
    # read out marginal histogram in t+1, t
    Distribution = StateSS[:-2].copy() + Gamma_state.copy().dot(
        State[:NxNx].copy())
    Distributionminus = StateSS[:-2].copy() + Gamma_state.copy().dot(
        Stateminus[:NxNx].copy())

    # Aggregate Endogenous States
    RB = StateSS[-2] + State[-2]
    RBminus = StateSS[-2] + Stateminus[-2]

    # Aggregate Exogenous States
    S = StateSS[-1] + State[-1]
    Sminus = StateSS[-1] + Stateminus[-1]

    ## Split the control vector into items with names
    # Controls
    mutil_c = mutil(Control[mutil_cind].copy())
    mutil_cminus = mutil(Controlminus[mutil_cind].copy())

    # Aggregate Controls (t+1)
    PI = np.exp(Control[PIind])
    Y = np.exp(Control[Yind])
    B = Control[Bind]

    # Aggregate Controls (t)
    PIminus = np.exp(Controlminus[PIind])
    Yminus = np.exp(Controlminus[Yind])
    #Gminus = np.exp(Controlminus[Gind])
    Wminus = np.asarray(np.exp(Controlminus[Wind]))
    Profitminus = np.exp(Controlminus[Profitind])
    Nminus = np.asarray(np.exp(Controlminus[Nind]))
    #Tminus = np.exp(Controlminus[Tind])
    Bminus = Controlminus[Bind]
    Gminus = Controlminus[Gind]
    Cminus = np.exp(Controlminus[Cind])
    Xminus = np.exp(Controlminus[Xind])

    ## Write LHS values
    # Controls
    LHS[nx + mutil_cind.copy()] = invmutil(mutil_cminus.copy())
    LHS[nx + Yind] = Yminus
    LHS[nx + Wind] = Wminus
    LHS[nx + Profitind] = Profitminus
    LHS[nx + Nind] = Nminus
    #LHS[nx+Tind] = Tminus
    LHS[nx + Bind] = Bminus
    LHS[nx + Gind] = Gminus
    LHS[nx + Cind] = Cminus
    LHS[nx + Xind] = Xminus
    # States
    # Marginal Distributions (Marginal histograms)
    #LHS[distr_ind] = Distribution[:mpar['nm']*mpar['nh']-1-mpar['nh']].copy()
    LHS[marginal_mind] = Distribution[:mpar['nm'] - 1]
    LHS[marginal_hind] = Distribution[mpar['nm']:mpar['nm'] + mpar['nh'] - 2]

    LHS[RBind] = RB
    LHS[Sind] = S

    # take into account that RB is in logs
    RB = np.exp(RB)
    RBminus = np.exp(RBminus)

    ## Set of differences for exogenous process
    RHS[Sind] = par['rhoS'] * Sminus

    if aggrshock == 'MP':
        EPS_TAYLOR = Sminus
        TFP = 1.0
    elif aggrshock == 'TFP':
        TFP = np.exp(Sminus)
        EPS_TAYLOR = 0
    elif aggrshock == 'Uncertainty':
        TFP = 1.0
        EPS_TAYLOR = 0

        #Tauchen style for probability distribution next period
        P = ExTransitions(np.exp(Sminus), grid, mpar, par)['P_H']

    marginal_mminus = np.transpose(Distributionminus[:mpar['nm']].copy())
    marginal_hminus = np.transpose(Distributionminus[mpar['nm']:mpar['nm'] +
                                                     mpar['nh']].copy())

    Hminus = np.sum(np.multiply(grid['h'][:-1], marginal_hminus[:, :-1]))
    Lminus = np.sum(np.multiply(grid['m'], marginal_mminus))

    RHS[nx + Bind] = Lminus

    # Calculate joint distributions
    cumdist = np.zeros((mpar['nm'] + 1, mpar['nh'] + 1))
    cumdist[1:,
            1:] = Copula(np.squeeze(np.asarray(np.cumsum(marginal_mminus))),
                         np.squeeze(np.asarray(np.cumsum(marginal_hminus)))).T
    JDminus = np.diff(np.diff(cumdist, axis=0), axis=1)

    ## Aggregate Output
    mc = par['mu'] - (par['beta'] * np.log(PI) * Y / Yminus -
                      np.log(PIminus)) / par['kappa']

    RHS[nx + Nind] = (par['tau'] * TFP * par['alpha'] *
                      grid['K']**(1 - par['alpha']) *
                      np.asarray(mc))**(1 / (1 - par['alpha'] + par['gamma']))
    RHS[nx + Yind] = (TFP * np.asarray(Nminus)**par['alpha'] *
                      grid['K']**(1 - par['alpha']))

    # Wage Rate
    RHS[nx + Wind] = TFP * par['alpha'] * mc * (
        grid['K'] / np.asarray(Nminus))**(1 - par['alpha'])

    # Profits for Enterpreneurs
    RHS[nx + Profitind] = (1 - mc) * Yminus - Yminus * (
        1 / (1 - par['mu'])) / par['kappa'] / 2 * np.log(PIminus)**2

    ## Wages net of leisure services
    WW = par['gamma'] / (1 + par['gamma']) * (
        np.asarray(Nminus) / Hminus) * np.asarray(Wminus) * np.ones(
            (mpar['nm'], mpar['nh']))
    WW[:, -1] = Profitminus * par['profitshare']

    ## Incomes (grids)
    inclabor = par['tau'] * WW.copy() * meshes['h'].copy()
    incmoney = np.multiply(meshes['m'].copy(),
                           (RBminus / PIminus +
                            (meshes['m'] < 0) * par['borrwedge'] / PIminus))
    jd_aux = np.sum(JDminus, axis=0)
    #incprofits = np.sum((1-par['tau'])*par['gamma']/(1+par['gamma'])*(np.asarray(Nminus)/par['H'])*np.asarray(Wminus)*grid['h'][0:-1]*jd_aux[0:-1]) + (1-par['tau'])*np.asarray(Profitminus)*par['profitshare']*jd_aux[-1]
    incprofits = np.sum((1-par['tau'])*(np.asarray(Nminus)/Hminus)*np.asarray(Wminus)*grid['h'][0:-1]*jd_aux[0:-1]) \
                + (1-par['tau'])*np.asarray(Profitminus)*par['profitshare']*jd_aux[-1] \
                - (RBminus/PIminus*Bminus-B)

    inc = {'labor': inclabor, 'money': incmoney, 'profits': incprofits}

    ## Update policies
    RBaux = (RB + (meshes['m'] < 0).copy() * par['borrwedge']) / PI
    EVm = np.reshape(np.reshape(np.multiply(RBaux.flatten().T.copy(), mutil_c),
                                (mpar['nm'], mpar['nh']),
                                order='F').dot(np.transpose(P.copy())),
                     (mpar['nm'], mpar['nh']),
                     order='F')

    result_EGM_policyupdate = EGM_policyupdate(EVm, PIminus, RBminus, inc,
                                               meshes, grid, par, mpar)
    c_star = result_EGM_policyupdate['c_star']
    m_star = result_EGM_policyupdate['m_star']

    aux_x = par['tau'] * (Nminus /
                          Hminus) * Wminus * meshes['h'] / (1 + par['gamma'])
    aux_x[:, -1] = 0

    c = c_star + aux_x

    RHS[nx + Cind] = np.sum(np.sum(np.multiply(JDminus, c)))
    RHS[nx + Xind] = np.sum(np.sum(np.multiply(JDminus, c_star)))

    ## Update Marginal Value Bonds
    mutil_c_aux = mutil(c_star.copy())
    RHS[nx + mutil_cind] = invmutil(
        np.asmatrix(mutil_c_aux.flatten(order='F').copy()).T)

    ## Differences for distriutions
    # find next smallest on-grid value for money choices
    weightl1 = np.zeros((mpar['nm'], mpar['nh'], mpar['nh']))
    weightl2 = np.zeros((mpar['nm'], mpar['nh'], mpar['nh']))

    # Adjustment case
    result_genweight = GenWeight(m_star, grid['m'])
    Dist_m = result_genweight['weight'].copy()
    idm = result_genweight['index'].copy()

    idm = np.tile(np.asmatrix(idm.copy().flatten('F')).T, (1, mpar['nh']))
    idh = np.kron(range(mpar['nh']), np.ones(
        (1, mpar['nm'] * mpar['nh']))).astype(np.int64)

    indexl1 = np.ravel_multi_index(
        [idm.flatten(order='F'),
         idh.flatten(order='F')], (mpar['nm'], mpar['nh']),
        order='F')
    indexl2 = np.ravel_multi_index(
        [idm.flatten(order='F') + 1,
         idh.flatten(order='F')], (mpar['nm'], mpar['nh']),
        order='F')

    for hh in range(mpar['nh']):

        # corresponding weights
        weightl1_aux = (1 - Dist_m[:, hh])  ## dimension of Dist_m :1
        weightl2_aux = Dist_m[:, hh]  ## dimension of Dist_m :1

        # dimensions (m*k,h',h)
        weightl1[:, :, hh] = np.outer(weightl1_aux, P[hh, :])
        weightl2[:, :, hh] = np.outer(weightl2_aux, P[hh, :])

    weightl1 = np.ndarray.transpose(weightl1.copy(), (0, 2, 1))
    weightl2 = np.ndarray.transpose(weightl2.copy(), (0, 2, 1))

    rowindex = np.tile(range(mpar['nm'] * mpar['nh']), (1, 2 * mpar['nh']))

    H = sp.coo_matrix(
        (np.hstack((weightl1.flatten(order='F'), weightl2.flatten(order='F'))),
         (np.squeeze(rowindex),
          np.hstack((np.squeeze(
              np.asarray(indexl1)), np.squeeze(np.asarray(indexl2)))))),
        shape=(mpar['nm'] * mpar['nh'], mpar['nm'] * mpar['nh']))

    JD_new = JDminus.flatten(order='F').copy().dot(H.todense())
    JD_new = np.reshape(JD_new.copy(), (mpar['nm'], mpar['nh']), order='F')

    # Next period marginal histograms
    # liquid assets
    aux_m = np.sum(JD_new.copy(), 1)
    RHS[marginal_mind] = aux_m[:-1].copy()

    # human capital
    aux_h = np.sum(JD_new.copy(), 0)
    RHS[marginal_hind] = aux_h[:, :-2].copy().T

    ## Third Set: Government Budget constraint
    # Return on bonds (Taylor Rule)
    RHS[RBind] = np.log(par['RB']) + par['rho_R'] * np.log(
        RBminus / par['RB']) + np.log(PIminus / par['PI']) * (
            (1. - par['rho_R']) * par['theta_pi']) + EPS_TAYLOR

    # Fiscal rule

    # Inflation jumps to equilibrate real bond supply and demand

    #    if par['tau'] < 1:
    #       RHS[nx+Gind] = B - Bminus*RBminus/PIminus
    #
    #       RHS[nx+PIind] = par['rho_B'] * np.log((Bminus)/(targets['B'])) + par['rho_B'] * np.log(RBminus/par['RB'])-(par['rho_B']+par['gamma_pi']) * np.log(PIminus/par['PI'])
    #       LHS[nx+PIind] = np.log((B)/(targets['B']))
    #    else:
    #       RHS[nx+Gind] = targets['G']
    #       RHS[nx+PIind] = targets['B']
    #       LHS[nx+PIind] = B
    taxes = (1 - par['tau']) * Yminus
    RHS[nx + Gind] = B - Bminus * RBminus / PIminus + taxes
    RHS[nx + PIind] = par['RB'] * targets['B']
    LHS[nx +
        PIind] = RB / PI * B  # Govt always expects to owe the same amount in the next period

    ## Difference
    Difference = InvGamma.dot((LHS - RHS) / np.vstack((np.ones(
        (nx, 1)), ControlSS[:-oc], np.ones((oc, 1)))))

    return {
        'Difference': Difference,
        'LHS': LHS,
        'RHS': RHS,
        'JD_new': JD_new,
        'c_star': c_star,
        'm_star': m_star,
        'P': P
    }