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
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 }