def get_preconditioner(): """Compute the preconditioner M""" diags_x = zeros((3, nx)) diags_x[0, :] = 1 / hx / hx diags_x[1, :] = -2 / hx / hx diags_x[2, :] = 1 / hx / hx Lx = spdiags(diags_x, [-1, 0, 1], nx, nx) diags_y = zeros((3, ny)) diags_y[0, :] = 1 / hy / hy diags_y[1, :] = -2 / hy / hy diags_y[2, :] = 1 / hy / hy Ly = spdiags(diags_y, [-1, 0, 1], ny, ny) J1 = spkron(Lx, eye(ny)) + spkron(eye(nx), Ly) # Now we have the matrix `J_1`. We need to find its inverse `M` -- # however, since an approximate inverse is enough, we can use # the *incomplete LU* decomposition J1_ilu = spilu(J1) # This returns an object with a method .solve() that evaluates # the corresponding matrix-vector product. We need to wrap it into # a LinearOperator before it can be passed to the Krylov methods: M = LinearOperator(shape=(nx * ny, nx * ny), matvec=J1_ilu.solve) return M
def prepareJacMatrices(self): m = self.mesh matL = accumarray(m.e[:,2], m.t.shape[0]).mat.T.tolil() matR = accumarray(m.e[:,3], m.t.shape[0]).mat.T.tolil() # WL on far bc is freestream isFar = m.isFar(m.v[m.e[m.ieBnd,:2],:].mean(1)) matL[m.ieBnd[isFar],:] = 0 # average and difference self.matJacWL = spkron(matL, eye(4)).tocsr() self.matJacWR = spkron(matR, eye(4)).tocsr() self.matJacWE = spkron(0.5 * (matL + matR), eye(4)).tocsr() self.matJacdW = spkron(matR - matL, eye(4)).tocsr() # distribute flux matrix D = block_diags(1./ m.a[:,newaxis,newaxis]) self.matJacDistFlux = spkron(D * m.matDistFlux, eye(4)).tocsr() # Tri to edg gradient with boundary copy matTriToBnd = accumarray(m.e[m.ieBnd,2], m.t.shape[0]).mat.T matGradTriEdg = m.matGradTriEdg + m.bcmatGradTriEdg * matTriToBnd # left and right gradient in cells edgOfTri = invertMap(m.e[:,2:])[1].reshape([-1, 3]) avgEdgToTri = (accumarray(edgOfTri[:,0], m.e.shape[0]).mat.T + \ accumarray(edgOfTri[:,1], m.e.shape[0]).mat.T + \ accumarray(edgOfTri[:,2], m.e.shape[0]).mat.T) / 3. matGradTri = spkron(avgEdgToTri, eye(2)) * matGradTriEdg xt = m.xt(); dxt = xt[m.e[:,3],:] - xt[m.e[:,2],:] matL = spkron(accumarray(m.e[:,2], m.t.shape[0]).mat.T, eye(2)) matR = spkron(accumarray(m.e[:,3], m.t.shape[0]).mat.T, eye(2)) matJacdWL = block_diags(dxt[:,newaxis,:]) * matL * matGradTri matJacdWR = block_diags(dxt[:,newaxis,:]) * matR * matGradTri self.matJacdWL = spkron(matJacdWL, eye(4)).tocsr() self.matJacdWR = spkron(matJacdWR, eye(4)).tocsr()
def test_wave_st_2d(): T_end = 2.0 geo = geometry.unit_cube(dim=1).extrude(0.0, T_end, support=(0.0,T_end)) kv_t = bspline.make_knots(2, 0.0, T_end, 6) # time axis kv = bspline.make_knots(3, 0.0, 1.0, 8) # space axis kvs = (kv_t, kv) M = mass(kv) DxDx = stiffness(kv) D0Dt = bsp_mixed_deriv_biform_1d(kv_t, 0, 1) DttDt = bsp_mixed_deriv_biform_1d(kv_t, 2, 1) A_ref = (spkron(DttDt, M) + spkron(D0Dt, DxDx)).tocsr() A = assemble(assemblers.WaveAssembler_ST2D(kvs, geo)) assert abs(A_ref - A).max() < 1e-14
def prepareJacMatricesVisc(self): m = self.mesh # velocity gradient operator matrix xeBnd = m.v[m.e[m.ieBnd,:2],:].mean(1) isFar = m.isFar(xeBnd) ieFar = m.ieBnd[isFar] indi, indj = isFar.nonzero()[0], m.e[ieFar,3] shape = (isFar.size, m.t.shape[0]) matJacUBc = csr_matrix((ones(isFar.sum()), (indi, indj)), shape) matGradU = m.matGradTriEdg + m.bcmatGradTriEdg * matJacUBc self.matGradU = spkron(matGradU, eye(2)).tocsr() # velocity avarage matrix #matL = accumarray(m.e[:,2], m.t.shape[0]).mat.T #matR = accumarray(m.e[:,3], m.t.shape[0]).mat.T self.matJacUE = spkron( m.e_map, eye(2), format='csr')
def prepareJacMatricesVisc(self): m = self.mesh # velocity gradient operator matrix xeBnd = m.v[m.e[m.ieBnd, :2], :].mean(1) isFar = m.isFar(xeBnd) ieFar = m.ieBnd[isFar] indi, indj = isFar.nonzero()[0], m.e[ieFar, 3] shape = (isFar.size, m.t.shape[0]) matJacUBc = csr_matrix((ones(isFar.sum()), (indi, indj)), shape) matGradU = m.matGradTriEdg + m.bcmatGradTriEdg * matJacUBc self.matGradU = spkron(matGradU, eye(2)).tocsr() # velocity avarage matrix #matL = accumarray(m.e[:,2], m.t.shape[0]).mat.T #matR = accumarray(m.e[:,3], m.t.shape[0]).mat.T self.matJacUE = spkron(m.e_map, eye(2), format='csr')
def test_heat_st_2d(): T_end = 2.0 geo = geometry.unit_cube(dim=1).cylinderize(0.0, T_end, support=(0.0,T_end)) kv_t = bspline.make_knots(2, 0.0, T_end, 6) # time axis kv = bspline.make_knots(3, 0.0, 1.0, 8) # space axis kvs = (kv_t, kv) M = mass(kv) M_t = mass(kv_t) DxDx = stiffness(kv) DtD0 = bsp_mixed_deriv_biform_1d(kv_t, 1, 0) A_ref = (spkron(DtD0, M) + spkron(M_t, DxDx)).tocsr() A = assemble_entries(assemblers.HeatAssembler_ST2D(kvs, geo)) assert abs(A_ref - A).max() < 1e-14
def test_canonical_op(): N = (3, 4, 5) I = CanonicalOperator.eye(N) assert I.shape[0] == I.shape[1] == N X = _random_tucker(N, 2) Y = I.apply(X) assert Y.R == (2, 2, 2) assert np.allclose(X.asarray(), Y.asarray()) # multiplication A = CanonicalOperator( [tuple(_random_banded(n, 1) for n in N) for k in range(3)]) B = CanonicalOperator( [tuple(_random_banded(n, 1) for n in N) for k in range(2)]) AB = A * B assert AB.R == 6 assert scipy.sparse.linalg.norm(AB.asmatrix() - (A.asmatrix().dot(B.asmatrix()))) < 1e-6 Y1 = A.apply(B.apply(X)) Y2 = AB.apply(X) assert np.allclose(Y1.asarray(), Y2.asarray()) assert np.allclose(((A @ B) @ X).asarray(), (A @ (B @ X)).asarray()) # arithmetic assert np.allclose(((A + B) @ X).asarray(), (A @ X + B @ X).asarray()) assert np.allclose(((A - B) @ X).asarray(), (A @ X - B @ X).asarray()) assert np.allclose(((-A) @ X).asarray(), -(A @ X).asarray()) # kron assert scipy.sparse.linalg.norm((A.kron(B)).asmatrix() - spkron(A.asmatrix(), B.asmatrix())) < 1e-10
def _prepare_b_jkl_mn(readout_povm, pauli_basis, pre_channel_ops, post_channel_ops, rho0): """ Prepare the coefficient matrix for process tomography. This function uses sparse matrices for much greater efficiency. The coefficient matrix is defined as: .. math:: B_{(jkl)(mn)}=\sum_{r,q}\pi_{jr}(\mathcal{R}_{k})_{rm} (\mathcal{R}_{l})_{nq} (\rho_0)_q where :math:`\mathcal{R}_{k}` is the transfer matrix of the quantum map corresponding to the k-th pre-measurement channel, while :math:`\mathcal{R}_{l}` is the transfer matrix of the l-th state preparation process. We also require the overlap between the (generalized) Pauli basis ops and the projection operators :math:`\pi_{jl}:=\sbraket{\Pi_j}{P_l} = \tr{\Pi_j P_l}`. See the grove documentation on tomography for detailed information. :param DiagonalPOVM readout_povm: The POVM corresponding to the readout plus classifier. :param OperatorBasis pauli_basis: The (generalized) Pauli basis employed in the estimation. :param list pre_channel_ops: The state preparation channel operators as `qutip.Qobj` :param list post_channel_ops: The pre-measurement (post circuit) channel operators as `qutip.Qobj` :param qutip.Qobj rho0: The initial state as a density matrix. :return: The coefficient matrix necessary to set up the binomial state tomography problem. :rtype: scipy.sparse.csr_matrix """ c_jk_m = state_tomography._prepare_c_jk_m(readout_povm, pauli_basis, post_channel_ops) pre_channel_transfer_matrices = [pauli_basis.transfer_matrix(qt.to_super(ek)) for ek in pre_channel_ops] rho0_q = pauli_basis.project_op(rho0) # These next lines hide some very serious (sparse-)matrix index magic, # basically we exploit the same index math as in `qutip.sprepost()` # i.e., if a matrix X is linearly mapped `X -> A.dot(X).dot(B)` # then this can be rewritten as # `np.kron(B.T, A).dot(X.T.ravel()).reshape((B.shape[1], A.shape[0])).T` # The extra matrix transpose operations are necessary because numpy by default # uses row-major storage, whereas these operations are conventionally defined for column-major # storage. d_ln = spvstack([(rlnq * rho0_q).T for rlnq in pre_channel_transfer_matrices]).tocoo() b_jkl_mn = spkron(d_ln, c_jk_m).real return b_jkl_mn
def extend_to_nd(from_small, to_small, n_prior, n_post): from_approx = spkron(spkron(speye(n_post), from_small), speye(n_prior)) to_approx = spkron(spkron(speye(n_post), to_small), speye(n_prior)) return from_approx, to_approx
def eqcond(model): """ Compute equilibirum of HANK model Written based on NYFED-DSGE's Julia-language implementation. """ nstates = len(util.flatten_indices(model.endog_states)) # 406 n_s_exp = len(util.flatten_indices(model.expected_shocks)) # 201 n_s_exo = len(util.flatten_indices(model.exog_shocks)) # 1 x = np.zeros(2 * nstates + n_s_exp + n_s_exo) # Read in parameters, settings niter_hours = model.settings['niter_hours'].value n_v = model.settings['n_jump_vars'].value n_g = model.settings['n_state_vars'].value ymarkov_combined = model.settings['ymarkov_combined'].value zz = model.settings['zz'].value a = model.settings['a'].value I, J = zz.shape amax = model.settings['amax'].value amin = model.settings['amin'].value aa = np.repeat(a.reshape(-1, 1), J, axis=1) A_switch = spkron(ymarkov_combined, speye(I, dtype=float, format='csc')) daf, dab, azdelta = aux.initialize_diff_grids(a, I, J) # Set up steady state parameters V_ss = model.steady_state['V_ss'].value g_ss = model.steady_state['g_ss'].value G_ss = model.steady_state['G_ss'].value w_ss = model.steady_state['w_ss'].value N_ss = model.steady_state['N_ss'].value C_ss = model.steady_state['C_ss'].value Y_ss = model.steady_state['Y_ss'].value B_ss = model.steady_state['B_ss'].value r_ss = model.steady_state['r_ss'].value rho_ss = model.steady_state['rho_ss'].value sig_MP = model.params['sig_MP'].value theta_MP = model.params['theta_MP'].value # sig_FP = model.params['sig_FP'].value # theta_FP = model.params['theta_FP'].value # sig_PS = model.params['sig_PS'].value # theta_PS = model.params['theta_PS'].value h_ss = model.steady_state['h_ss'].value.reshape(I, J, order='F') ceselast = model.params['ceselast'].value inflation_ss = model.steady_state['inflation_ss'].value maxhours = model.params['maxhours'].value govbcrule_fixnomB = model.params['govbcrule_fixnomB'].value priceadjust = model.params['priceadjust'].value taylor_inflation = model.params['taylor_inflation'].value taylor_outputgap = model.params['taylor_outputgap'].value meanlabeff = model.params['meanlabeff'].value # Necessary for construction of household problem functions labtax = model.params['labtax'].value coefrra = model.params['coefrra'].value frisch = model.params['frisch'].value labdisutil = model.params['labdisutil'].value TFP = 1.0 def _get_residuals(x): #x = x.toarray().flatten() # Prepare steady state deviations V = (x[:n_v - 1] + V_ss).reshape(I, J, order='F') inflation = x[n_v - 1] + inflation_ss gg = x[n_v:n_v + n_g - 1] + g_ss[:-1] MP = x[n_v + n_g - 1] w = x[n_v + n_g] + w_ss hours = x[n_v + n_g + 1] + N_ss consumption = x[n_v + n_g + 2] + C_ss output = x[n_v + n_g + 3] + Y_ss assets = x[n_v + n_g + 4] + B_ss #government = x[n_v + n_g + 5] + G_ss V_dot = x[nstates:nstates + n_v - 1] inflation_dot = x[nstates + n_v - 1] g_dot = x[nstates + n_v:nstates + n_v + n_g - 1] mp_dot = x[nstates + n_g + n_v - 1] #fp_dot = x[nstates + n_g + n_v + 5] #ps_dot = x[nstates + n_g + n_v + 3] VEErrors = x[2 * nstates:2 * nstates + n_v - 1] inflation_error = x[2 * nstates + n_v - 1] mp_shock = x[2 * nstates + n_v] #fp_shock = x[2*nstates + n_v + 1] #ps_shock = x[2*nstates + n_v + 2] g_end = (1 - gg @ azdelta[:-1]) / azdelta[-1] g = np.append(gg, g_end) g[g < 1e-19] = 0.0 #----------------------------------------------------------------- # Get equilibrium values, given steady state values normalized_wage = w / TFP profshare = (zz / meanlabeff) * ((1.0 - normalized_wage) * output) r_nominal = r_ss + taylor_inflation * inflation \ + taylor_outputgap * (np.log(output)-np.log(Y_ss)) + MP r = r_nominal - inflation lumptransfer = labtax * w * hours - G_ss - \ (r_nominal - (1-govbcrule_fixnomB) * inflation) * assets #----------------------------------------------------------------- # Compute one iteration of the HJB ## Get flow utility, income, and labor hour functions util, income, labor = \ aux.construct_household_problem_functions(V, w, coefrra, frisch, labtax, labdisutil) ## Initialize other variables, using V to ensure everything is a dual number Vaf = np.copy(V) Vab = np.copy(V) #h0 = np.array([h_ss[i, j] for i in range(I) for j in range(J)]).reshape(I, J) h0 = np.copy(h_ss) #----------------------------------------------------------------- # Construct Initial Difference Matrices # hf = np.empty_like(V) # hb = np.empty_like(V) Vaf[-1, :] = income(h_ss[-1, :], zz[-1, :], profshare[-1, :], lumptransfer, r, amax)**(-coefrra) Vab[-1, :] = (V[-1, :] - V[-2, :]) / dab[-1] Vaf[0, :] = (V[1, :] - V[0, :]) / daf[0] Vab[0, :] = income(h_ss[0, :], zz[0, :], profshare[0, :], lumptransfer, r, amin)**(-coefrra) Vaf[1:-1] = (V[2:, :] - V[1:-1, :]) / daf[0] Vab[1:-1] = (V[1:-1, :] - V[:-2, :]) / dab[0] # idx = ((i,j) for i in range(I) for j in range(J)) # for t in idx: # hf[t] = min(abs(labor(zz[t], Vaf[t])), maxhours) # hb[t] = min(abs(labor(zz[t], Vab[t])), maxhours) hf = np.minimum(abs(labor(zz, Vaf)), maxhours) hb = np.minimum(abs(labor(zz, Vab)), maxhours) cf = Vaf**(-1 / coefrra) cb = Vab**(-1 / coefrra) #----------------------------------------------------------------- # Hours Iteration idx = ((i, j) for i in range(I) for j in range(J)) for ih in range(niter_hours): for t in idx: if t[0] == I - 1: cf[t] = income(hf[t], zz[t], profshare[t], lumptransfer, r, aa[t]) hf[t] = labor(zz[t], cf[t]**(-coefrra)) hf[t] = min(abs(hf[t]), maxhours) if ih == niter_hours - 1: Vaf[t] = cf[t]**(-coefrra) elif t[0] == 0: cb[t] = income(hb[t], zz[t], profshare[t], lumptransfer, r, aa[t]) hb[t] = labor(zz[t], cb[t]**(-coefrra)) hb[t] = min(abs(hb[t]), maxhours) if ih == niter_hours: Vab[t] = cb[t]**(-coefrra) c0 = income(h0, zz, profshare, lumptransfer, r, aa) h0 = labor(zz, c0**(-coefrra)) h0 = np.minimum(abs(h0.flatten()), maxhours).reshape(I, J) c0 = income(h0, zz, profshare, lumptransfer, r, aa) sf = income(hf, zz, profshare, lumptransfer, r, aa) - cf sb = income(hb, zz, profshare, lumptransfer, r, aa) - cb #----------------------------------------------------------------- # Upwind #T = sb[0,0].dtype Vf = (cf > 0) * (util(cf, hf) + sf * Vaf) + (cf <= 0) * (-1e12) Vb = (cb > 0) * (util(cb, hb) + sb * Vab) + (cb <= 0) * (-1e12) V0 = (c0 > 0) * util(c0, h0) + (c0 <= 0) * (-1e12) Iunique = (sb < 0) * (1 - (sf > 0)) + (1 - (sb < 0)) * (sf > 0) Iboth = (sb < 0) * (sf > 0) Ib = Iunique * (sb < 0) * (Vb > V0) + Iboth * (Vb == np.maximum( np.maximum(Vb, Vf), V0)) If = Iunique * (sf > 0) * (Vf > V0) + Iboth * (Vf == np.maximum( np.maximum(Vb, Vf), V0)) I0 = 1 - Ib - If h = hf * If + hb * Ib + h0 * I0 c = cf * If + cb * Ib + c0 * I0 s = sf * If + sb * Ib u = util(c, h) X = -Ib * sb / np.array([dab, dab]).reshape(I, J) Z = If * sf / np.array([daf, daf]).reshape(I, J) Y = -Z - X X[0, :] = 0. Z[I - 1, :] = 0. A = spdiag([ X.reshape(I * J, order='F')[1:], Y.reshape(I * J, order='F'), Z.reshape(I * J, order='F')[:I * J - 1] ], offsets=[-1, 0, 1], shape=(I * J, I * J), format='csc') + A_switch #----------------------------------------------------------------- # Collect/calculate Residuals hjb_residual = u.flatten(order='F') + A * V.flatten(order='F') \ + V_dot + VEErrors - rho_ss * V.flatten(order='F') pc_residual = -((r - 0) * inflation - (ceselast / priceadjust * \ (w / TFP - (ceselast-1) / ceselast) + \ inflation_dot - inflation_error)) g_azdelta = g.flatten() * azdelta.flatten() g_intermediate = spdiag(1 / azdelta) * A.T @ g_azdelta g_residual = g_dot - g_intermediate[:-1] mp_residual = mp_dot - (-theta_MP * MP + sig_MP * mp_shock) realsav = sum( aa.flatten(order='F') * g.flatten(order='F') * azdelta.flatten(order='F')) realsav_dot = sum( s.flatten(order='F') * g.flatten(order='F') * azdelta.flatten(order='F')) bondmarket_residual = realsav_dot / realsav + govbcrule_fixnomB * inflation labmarket_residual = sum(zz.flatten(order='F') * h.flatten(order='F') \ * g.flatten(order='F') * azdelta.flatten(order='F')) - hours consumption_residual = sum(c.flatten(order='F') * g.flatten(order='F') \ * azdelta.flatten(order='F')) - consumption output_residual = TFP * hours - output #output_residual = TFP * hours - (-theta_PS * output + sig_PS * ps_shock) assets_residual = assets - realsav #government_residual = fp_dot - (-theta_FP * government + sig_FP * fp_shock) # Return equilibrium conditions return np.hstack( (hjb_residual, pc_residual, g_residual, mp_residual, bondmarket_residual, labmarket_residual, consumption_residual, output_residual, assets_residual)) # return np.hstack((hjb_residual, pc_residual, g_residual, # mp_residual, # bondmarket_residual, labmarket_residual, consumption_residual, # output_residual, assets_residual, government_residual)) derivs = jacob_mat(_get_residuals, x, nstates, h=1e-10) GAM1 = -derivs[:, :nstates] GAM0 = derivs[:, nstates:2 * nstates] PI = -derivs[:, 2 * nstates:2 * nstates + n_s_exp] PSI = -derivs[:, 2 * nstates + n_s_exp:2 * nstates + n_s_exp + n_s_exo] C = np.zeros(nstates) return GAM0, GAM1, PSI, PI, C
def steadystate(model): # Read in parameters coefrra = model.params['coefrra'].value frisch = model.params['frisch'].value meanlabeff = model.params['meanlabeff'].value maxhours = model.params['maxhours'].value ceselast = model.params['ceselast'].value labtax = model.params['labtax'].value govbondtarget = model.params['govbondtarget'].value labdisutil = model.params['labdisutil'].value lumptransferpc = model.params['lumptransferpc'].value # Read in grids I = model.settings['I'].value J = model.settings['J'].value a = model.settings['a'].value g_z = model.settings['g_z'].value zz = model.settings['zz'].value ymarkov_combined = model.settings['ymarkov_combined'].value # Set necessary variables aa = np.repeat(a.reshape(-1, 1), J, axis=1) amax = np.max(a) amin = np.min(a) # Read in initial rates iterate_r = model.settings['iterate_r'].value r = model.settings['r0'].value rmin = model.settings['rmin'].value rmax = model.settings['rmax'].value iterate_rho = model.settings['iterate_rho'].value rho = model.settings['rho0'].value rhomin = model.settings['rhomin'].value rhomax = model.settings['rhomax'].value # Read in approximation parameters Ir = model.settings['Ir'].value maxit_HJB = model.settings['maxit_HJB'].value tol_HJB = model.settings['tol_HJB'].value d_HJB = model.settings['d_HJB'].value maxit_kfe = model.settings['maxit_kfe'].value tol_kfe = model.settings['tol_kfe'].value d_kfe = model.settings['d_kfe'].value niter_hours = model.settings['niter_hours'].value crit_S = model.settings['crit_S'].value # Initializing equilibrium objects labor_share_ss = (ceselast - 1) / ceselast w = w_ss = labor_share_ss # compute initial guesses at steady state values given zz, labor_share_ss, etc. N_ss, Y_ss, B_ss, profit_ss, profshare, lumptransfer = \ aux.calculate_ss_equil_vars_init(zz, labor_share_ss, meanlabeff, lumptransferpc, govbondtarget) # Initialize matrices for finite differences Vaf = np.empty((I, J), dtype=np.complex64) Vab = np.empty((I, J), dtype=np.complex64) cf = np.empty((I, J), dtype=np.complex64) # forward consumption difference hf = np.empty((I, J), dtype=np.complex64) # forward hours difference sf = np.empty((I, J), dtype=np.complex64) # forward saving difference cb = np.empty((I, J), dtype=np.complex64) # backward consumption difference hb = np.empty((I, J), dtype=np.complex64) # backward hours difference sb = np.empty((I, J), dtype=np.complex64) # backward saving difference c0 = np.empty((I, J), dtype=np.complex64) A = np.empty((I * J, J * J), dtype=np.complex64) Aswitch = spkron(ymarkov_combined, speye(I, dtype='complex64')) # Initialize steady state variables V = np.empty((I, J), dtype=np.complex64) # value function u = np.empty((I, J), dtype=np.complex64) # flow utility across state space s = np.empty((I, J), dtype=np.complex64) # savings across state space c = np.empty((I, J), dtype=np.complex64) # flow consumption h = np.empty((I, J), dtype=np.complex64) # flow hours of labor h0 = np.empty((I, J), dtype=np.complex64) # guess of what h will be # Creates functions for computing flow utility, income earned, and labor done given # CRRA + frisch elasticity style labor disutility util, income, labor = \ aux.construct_household_problem_functions(V, w, coefrra, frisch, labtax, labdisutil) # Setting up forward/backward difference grids for a. daf, dab, azdelta = aux.initialize_diff_grids(a, I, J) for ir in range(Ir): c.fill(np.complex(0.)) h.fill(np.complex(1 / 3)) h0.fill(np.complex(1.)) # Initial guess inc = income(h, zz, profshare, lumptransfer, r, aa) # get income v = util(inc, h) / rho # value function guess # Iterate HJB for ihjb in range(maxit_HJB): V = v Vaf, Vab, cf, hf, cb, hb = aux.construct_initial_diff_matrices( V, Vaf, Vab, income, labor, h, h0, zz, profshare, lumptransfer, amax, amin, coefrra, r, daf, dab, maxhours) # Iterative method to find consistent forward/backward/neutral # difference matrices for c and h cf, hf, cb, hb, c0, h0 = aux.hours_iteration( income, labor, zz, profshare, lumptransfer, aa, coefrra, r, cf, hf, cb, hb, c0, h0, maxhours, niter_hours) c0 = income(h0, zz, profshare, lumptransfer, r, aa) sf = income(hf, zz, profshare, lumptransfer, r, aa) - cf sb = income(hb, zz, profshare, lumptransfer, r, aa) - cb Vaf[I - 1, :] = cf[I - 1, :]**( -coefrra ) # Forward difference for value function w.r.t. wealth Vab[0, :] = cb[0, :]**( -coefrra ) # Backward difference for value function w.r.t. wealth V, A, u, h, c, s = aux.upwind(rho, V, util, Aswitch, cf, cb, c0, hf, hb, h0, sf, sb, Vaf, Vab, daf, dab, d_HJB=d_HJB) # Check for convergence Vchange = V - v v = V err_HJB = np.max(np.abs(Vchange)) if err_HJB < tol_HJB: break # Create initial guess for g0 g0 = np.zeros((I, J), dtype=np.complex64) # Assign stationary income distribution weight at a = 0, zero elsewhere g0[a == 0, :] = g_z # g_z is marginal distribution, so re-weight by some multiplier of Lebesgue measure g0 = g0 / azdelta.reshape(I, J) # Solve for distribution g = aux.solve_kfe(A, g0, spdiag(azdelta), maxit_kfe=maxit_kfe, tol_kfe=tol_kfe, d_kfe=d_kfe) # Back out static conditions/steady state values given our value function and distribution N_ss, Y_ss, B_ss, profit_ss, profshare, lumptransfer, bond_err = \ aux.calculate_ss_equil_vars(zz, h, g, azdelta, aa, labor_share_ss, meanlabeff, lumptransferpc, govbondtarget) # Check bond market for market clearing r, rmin, rmax, rho, rhomin, rhomax, clear_cond = \ aux.check_bond_market_clearing(bond_err, crit_S, r, rmin, rmax, rho, rhomin, rhomax, iterate_r, iterate_rho) if clear_cond: # Set steady state values model.steady_state['V_ss'].value = np.real(V.flatten(order='F')) model.steady_state['inflation_ss'].value = 0. model.steady_state['g_ss'].value = np.real(g.flatten(order='F')) model.steady_state['r_ss'].value = r model.steady_state['u_ss'].value = np.real(u.flatten(order='F')) model.steady_state['c_ss'].value = np.real(c.flatten(order='F')) model.steady_state['h_ss'].value = np.real(h.flatten(order='F')) model.steady_state['s_ss'].value = np.real(s.flatten(order='F')) model.steady_state['rnom_ss'].value = model.steady_state['r_ss'].value \ + model.steady_state['inflation_ss'].value model.steady_state['B_ss'].value = sum( model.steady_state['g_ss'].value * aa.flatten(order='F') * azdelta) model.steady_state['N_ss'].value = np.real(sum(zz.flatten(order='F') * model.steady_state['h_ss'].value \ * model.steady_state['g_ss'].value * azdelta)) model.steady_state['Y_ss'].value = model.steady_state['N_ss'].value model.steady_state['labor_share_ss'].value = (ceselast - 1) / ceselast model.steady_state['w_ss'].value = model.steady_state[ 'labor_share_ss'].value model.steady_state['profit_ss'].value = (1 - model.steady_state['labor_share_ss'].value) \ * model.steady_state['Y_ss'].value model.steady_state['C_ss'].value = sum( model.steady_state['c_ss'].value * model.steady_state['g_ss'].value * azdelta) model.steady_state['T_ss'].value = np.real(lumptransfer) model.steady_state['rho_ss'].value = rho model.steady_state['G_ss'].value = labtax * model.steady_state['w_ss'].value * model.steady_state['N_ss'].value \ - model.steady_state['T_ss'].value - model.steady_state['r_ss'].value * model.steady_state['B_ss'].value break return model
def slra_by_factorization(x, m, k, PRINT=0, x_0=None, Omega=None, N=None, PCA_INIT=False): if Omega is None: # assume x is the full data vector x = x N = x.size M_bar = None else: x_Omega = x if N is None: N = Omega.max() else: N = N x = np.zeros((N, )) x[Omega] = x_Omega entries = np.zeros((N, )) entries[Omega] = 1.0 M_bar = lil_matrix((N, N)) M_bar.setdiag(entries) n = N - m + 1 hankel = Hankel(m, n) if PCA_INIT: X_full = hankel.struct_from_vec(x) P, _, _ = svds(X_full, k) else: P, _ = np.linalg.qr(np.random.rand(m, k)) L = None if M_bar is None: b = np.hstack((x, np.zeros((m * n, )))) else: b = np.hstack((M_bar.dot(x), np.zeros((m * n, )))) X = hankel.struct_from_vec(x) if x_0 is not None: X_0 = hankel.struct_from_vec(x_0) else: X_0 = None Pi_S_orth = speye(m * n) - hankel.Pi_S II_max = 1000 I_max = 1000 # Ishteva et al. propose to choose rho in the range (1, 1e14), but the values below work better in practice rho_start = 1e-5 rho_end = 1e6 c_rho_slow = 1.5 c_rho_fast = 10 rho = rho_start printit = 0 II = 0 for i in xrange(I_max): print "Iteration ", i, ", rho = ", rho for j in xrange(II_max): P_old = P if M_bar is None: M = vstack((hankel.S_pinv, np.sqrt(rho) * Pi_S_orth)) else: M = vstack( (M_bar.dot(hankel.S_pinv), np.sqrt(rho) * Pi_S_orth)) A_L = M.dot(spkron(speye(n), P)) L = np.reshape(lsqr(A_L, b)[0], (k, n), order='F') A_P = M.dot(spkron(L.T, speye(m))) P = np.reshape(lsqr(A_P, b)[0], (m, k), order='F') # Ishteva et al. propose to evaluate the change in the column space of P (such as the angle between subsequent subspaces), but it is not working well in practice # Instead, measure the relative difference between old and new estimate of P diff_P = np.linalg.norm(P - P_old, 'fro') / np.linalg.norm( P_old, 'fro') print diff_P if diff_P < 0.1: II = j break if II > 5: rho *= c_rho_slow else: rho *= c_rho_fast if rho >= rho_end: break if PRINT > 1: PL = np.dot(P, L) if X_0 is None: plot_matrices(1, (1, 3), X, "$\mathbf{X}$", (X.min(), X.max()), PL, "PL", (X.min(), X.max()), X - PL, "$\mathbf{X} - \mathbf{P}\mathbf{L}$", (-X.max(), X.max()), filename="/tmp/figures/matrices/slrabyF_" + '{:03d}'.format(printit) + ".png", visible=False) else: plot_matrices(1, (1, 4), X, "$\mathbf{X}$", (X.min(), X.max()), PL, "PL", (X.min(), X.max()), X - PL, "$\mathbf{X} - \mathbf{P}\mathbf{L}$", (-X.max(), X.max()), X_0 - PL, "$\mathbf{X}_0 - \mathbf{P}\mathbf{L}$", (-X.max(), X.max()), filename="/tmp/figures/matrices/slrabyF_" + '{:03d}'.format(printit) + ".png", visible=False) printit += 1 Y = np.dot(P, L) y = hankel.S_pinv.dot(Y.flatten('F')) return y