def find_PFd(A, B, Q, R, Rf, beta=.95): """ Taking the parameters A, B, Q, R as found in the `setup_matrices`, we find the value function of the optimal linear regulator problem. This is steps 2 and 3 in the lecture notes. Parameters ---------- (A, B, Q, R) : Array(Float, ndim=2) The matrices that describe the oligopoly problem Returns ------- (P, F, d) : Array(Float, ndim=2) The matrix that describes the value function of the optimal linear regulator problem. """ lq = LQ(Q, -R, A, B, beta=beta) P, F, d = lq.stationary_values() Af = np.vstack((np.hstack([A-np.dot(B,F), np.array([[0., 0., 0., 0., 0.]]).T]),np.array([[0., 0., 0., 0., 0., 1.]]))) Bf = np.array([[0., 0., 0., 0., 0., 1.]]).T lqf = LQ(Q, -Rf, Af, Bf, beta=beta) Pf, Ff, df = lqf.stationary_values() return P, F, d, Pf, Ff, df
def canonical(self): """ Compute canonical preference representation Uses auxiliary problem of 9.4.2, with the preference shock process reintroduced Calculates pihat, llambdahat and ubhat for the equivalent canonical household technology """ Ac1 = np.hstack((self.deltah,np.zeros((self.nh,self.nz)))) Ac2 = np.hstack((np.zeros((self.nz,self.nh)),self.a22)) Ac = np.vstack((Ac1,Ac2)) Bc = np.vstack((self.thetah,np.zeros((self.nz,self.nc)))) Cc = np.vstack((np.zeros((self.nh,self.nw)),self.c2)) Rc1 = np.hstack((self.llambda.T.dot(self.llambda),-self.llambda.T.dot(self.ub))) Rc2 = np.hstack((-self.ub.T.dot(self.llambda),self.ub.T.dot(self.ub))) Rc = np.vstack((Rc1,Rc2)) Qc = self.pih.T.dot(self.pih) Nc = np.hstack((self.pih.T.dot(self.llambda),-self.pih.T.dot(self.ub))) lq_aux = LQ(Qc, Rc, Ac, Bc, N = Nc, beta=self.beta) P1, F1, d1 = lq_aux.stationary_values() self.F_b = F1[:,0:self.nh] self.F_f = F1[:,self.nh:] self.pihat = np.linalg.cholesky(self.pih.T.dot(self.pih) + self.beta.dot(self.thetah.T).dot(P1[0:self.nh,0:self.nh]).dot(self.thetah)).T self.llambdahat = self.pihat.dot(self.F_b) self.ubhat = - self.pihat.dot(self.F_f) return
def compute_sequence(self, x0, ts_length=None, Pay=None): """ Simulate quantities and prices for our economy """ lq = LQ(self.Q, self.R, self.A, self.B, self.C, N=self.W, beta=self.beta) xp, up, wp = lq.compute_sequence(x0, ts_length) self.h = self.Sh.dot(xp) self.k = self.Sk.dot(xp) self.i = self.Si.dot(xp) self.b = self.Sb.dot(xp) self.d = self.Sd.dot(xp) self.c = self.Sc.dot(xp) self.g = self.Sg.dot(xp) self.s = self.Ss.dot(xp) # === Value of J-period risk-free bonds === # # === See p.145: Equation (7.11.2) === # e1 = np.zeros((1,self.nc)) e1[0,0] = 1 self.R1_Price = np.empty((ts_length+1,1)) self.R2_Price = np.empty((ts_length+1,1)) self.R5_Price = np.empty((ts_length+1,1)) for i in range(ts_length+1): self.R1_Price[i,0] = self.beta*e1.dot(self.Mc).dot(np.linalg.matrix_power(self.A0,1)).dot(xp[:,i])/e1.dot(self.Mc).dot(xp[:,i]) self.R2_Price[i,0] = self.beta**2*e1.dot(self.Mc).dot(np.linalg.matrix_power(self.A0,2)).dot(xp[:,i])/e1.dot(self.Mc).dot(xp[:,i]) self.R5_Price[i,0] = self.beta**5*e1.dot(self.Mc).dot(np.linalg.matrix_power(self.A0,5)).dot(xp[:,i])/e1.dot(self.Mc).dot(xp[:,i]) # === Gross rates of return on 1-period risk-free bonds === # self.R1_Gross = 1/self.R1_Price # === Net rates of return on J-period risk-free bonds === # # === See p.148: log of gross rate of return, divided by j === # self.R1_Net = np.log(1/self.R1_Price)/1 self.R2_Net = np.log(1/self.R2_Price)/2 self.R5_Net = np.log(1/self.R5_Price)/5 # === Value of asset whose payout vector is Pay*xt === # # See p.145: Equation (7.11.1) if isinstance(Pay,np.ndarray) == True: self.Za = Pay.T.dot(self.Mc) self.Q = solve_discrete_lyapunov(self.A0.T*self.beta**0.5,self.Za) self.q = self.beta/(1-self.beta)*np.trace(self.C.T.dot(self.Q).dot(self.C)) self.Pay_Price = np.empty((ts_length+1,1)) self.Pay_Gross = np.empty((ts_length+1,1)) self.Pay_Gross[0,0] = np.nan for i in range(ts_length+1): self.Pay_Price[i,0] = (xp[:,i].T.dot(self.Q).dot(xp[:,i]) + self.q)/e1.dot(self.Mc).dot(xp[:,i]) for i in range(ts_length): self.Pay_Gross[i+1,0] = self.Pay_Price[i+1,0]/(self.Pay_Price[i,0] - Pay.dot(xp[:,i])) return
def find_PFd(A, B, Q, R, beta=.95): """ Taking the parameters A, B, Q, R as found in the `setup_matrices`, we find the value function of the optimal linear regulator problem. This is steps 2 and 3 in the lecture notes. Parameters ---------- (A, B, Q, R) : Array(Float, ndim=2) The matrices that describe the oligopoly problem Returns ------- (P, F, d) : Array(Float, ndim=2) The matrix that describes the value function of the optimal linear regulator problem. """ lq = LQ(Q, -R, A, B, beta=beta) P, F, d = lq.stationary_values() return P, F, d
def computeG(A0, A1, d, Q0, tau0, beta, mu): """ Compute government income given mu and return tax revenues and policy matrixes for the planner. Parameters ---------- A0 : float A constant parameter for the inverse demand function A1 : float A constant parameter for the inverse demand function d : float A constant parameter for quadratic adjustment cost of production Q0 : float An initial condition for production tau0 : float An initial condition for taxes beta : float A constant parameter for discounting mu : float Lagrange multiplier Returns ------- T0 : array(float) Present discounted value of government spending A : array(float) One of the transition matrices for the states B : array(float) Another transition matrix for the states F : array(float) Policy rule matrix P : array(float) Value function matrix """ # Create Matrices for solving Ramsey problem R = np.array([[0, -A0 / 2, 0, 0], [-A0 / 2, A1 / 2, -mu / 2, 0], [0, -mu / 2, 0, 0], [0, 0, 0, d / 2]]) A = np.array([[1, 0, 0, 0], [0, 1, 0, 1], [0, 0, 0, 0], [-A0 / d, A1 / d, 0, A1 / d + 1 / beta]]) B = np.array([0, 0, 1, 1 / d]).reshape(-1, 1) Q = 0 # Use LQ to solve the Ramsey Problem. lq = LQ(Q, -R, A, B, beta=beta) P, F, d = lq.stationary_values() # Need y_0 to compute government tax revenue. P21 = P[3, :3] P22 = P[3, 3] z0 = np.array([1, Q0, tau0]).reshape(-1, 1) u0 = -P22**(-1) * P21.dot(z0) y0 = np.vstack([z0, u0]) # Define A_F and S matricies AF = A - B.dot(F) S = np.array([0, 1, 0, 0]).reshape(-1, 1).dot(np.array([[0, 0, 1, 0]])) # Solves equation (25) temp = beta * AF.T.dot(S).dot(AF) Omega = solve_discrete_lyapunov(np.sqrt(beta) * AF.T, temp) T0 = y0.T.dot(Omega).dot(y0) return T0, A, B, F, P
q = 1e6 # == Formulate as an LQ problem == # Q = 1 R = np.zeros((2, 2)) Rf = np.zeros((2, 2)) Rf[0, 0] = q A = [[1 + r, -c_bar + mu], [0, 1]] B = [[-1], [0]] C = [[sigma], [0]] # == Compute solutions and simulate == # lq = LQ(Q, R, A, B, C, beta=beta, T=T, Rf=Rf) x0 = (0, 1) xp, up, wp = lq.compute_sequence(x0) # == Convert back to assets, consumption and income == # assets = xp[0, :] # a_t c = up.flatten() + c_bar # c_t income = wp[0, 1:] + mu # y_t # == Plot results == # n_rows = 2 fig, axes = plt.subplots(n_rows, 1, figsize=(12, 10)) plt.subplots_adjust(hspace=0.5) for i in range(n_rows): axes[i].grid()
def computeG(A0, A1, d, Q0, tau0, beta, mu): """ Compute government income given mu and return tax revenues and policy matrixes for the planner. Parameters ---------- A0 : float A constant parameter for the inverse demand function A1 : float A constant parameter for the inverse demand function d : float A constant parameter for quadratic adjustment cost of production Q0 : float An initial condition for production tau0 : float An initial condition for taxes beta : float A constant parameter for discounting mu : float Lagrange multiplier Returns ------- T0 : array(float) Present discounted value of government spending A : array(float) One of the transition matrices for the states B : array(float) Another transition matrix for the states F : array(float) Policy rule matrix P : array(float) Value function matrix """ # Create Matrices for solving Ramsey problem R = np.array([[0, -A0/2, 0, 0], [-A0/2, A1/2, -mu/2, 0], [0, -mu/2, 0, 0], [0, 0, 0, d/2]]) A = np.array([[1, 0, 0, 0], [0, 1, 0, 1], [0, 0, 0, 0], [-A0/d, A1/d, 0, A1/d+1/beta]]) B = np.array([0, 0, 1, 1/d]).reshape(-1, 1) Q = 0 # Use LQ to solve the Ramsey Problem. lq = LQ(Q, -R, A, B, beta=beta) P, F, d = lq.stationary_values() # Need y_0 to compute government tax revenue. P21 = P[3, :3] P22 = P[3, 3] z0 = np.array([1, Q0, tau0]).reshape(-1, 1) u0 = -P22**(-1) * P21.dot(z0) y0 = np.vstack([z0, u0]) # Define A_F and S matricies AF = A - B.dot(F) S = np.array([0, 1, 0, 0]).reshape(-1, 1).dot(np.array([[0, 0, 1, 0]])) # Solves equation (25) temp = beta * AF.T.dot(S).dot(AF) Omega = solve_discrete_lyapunov(np.sqrt(beta) * AF.T, temp) T0 = y0.T.dot(Omega).dot(y0) return T0, A, B, F, P
def __init__(self, information, technology, preferences): # === Unpack the tuples which define information, technology and preferences === # self.a22, self.c2, self.ub, self.ud = information self.phic, self.phig, self.phii, self.gamma, self.deltak, self.thetak = technology self.beta, self.llambda, self.pih, self.deltah, self.thetah = preferences # === Computation of the dimension of the structural parameter matrices === # self.nb,self.nh = self.llambda.shape self.nd,self.nc = self.phic.shape self.nz,self.nw = self.c2.shape junk,self.ng = self.phig.shape self.nk,self.ni = self.thetak.shape # === Creation of various useful matrices === # uc = np.hstack((np.eye(self.nc),np.zeros((self.nc,self.ng)))) ug = np.hstack((np.zeros((self.ng,self.nc)),np.eye(self.ng))) phiin = np.linalg.inv(np.hstack((self.phic,self.phig))) phiinc = uc.dot(phiin) phiing = ug.dot(phiin) b11 = - self.thetah.dot(phiinc).dot(self.phii) a1 = self.thetah.dot(phiinc).dot(self.gamma) a12 = np.vstack((self.thetah.dot(phiinc).dot(self.ud), np.zeros((self.nk,self.nz)))) # === Creation of the A Matrix for the state transition of the LQ problem === # a11 = np.vstack((np.hstack((self.deltah,a1)), np.hstack((np.zeros((self.nk,self.nh)),self.deltak)))) self.A = np.vstack((np.hstack((a11,a12)), np.hstack((np.zeros((self.nz,self.nk+self.nh)),self.a22)))) # === Creation of the B Matrix for the state transition of the LQ problem === # b1 = np.vstack((b11,self.thetak)) self.B = np.vstack((b1,np.zeros((self.nz,self.ni)))) # === Creation of the C Matrix for the state transition of the LQ problem === # self.C = np.vstack((np.zeros((self.nk+self.nh,self.nw)),self.c2)) # === Define R,W and Q for the payoff function of the LQ problem === # self.H = np.hstack((self.llambda,self.pih.dot(uc).dot(phiin).dot(self.gamma),self.pih.dot(uc).dot(phiin).dot(self.ud)-self.ub,-self.pih.dot(uc).dot(phiin).dot(self.phii))) self.G = ug.dot(phiin).dot(np.hstack((np.zeros((self.nd,self.nh)),self.gamma,self.ud,-self.phii))) self.S = (self.G.T.dot(self.G) + self.H.T.dot(self.H))/2 self.nx = self.nh+self.nk+self.nz self.n = self.ni+self.nh+self.nk+self.nz self.R = self.S[0:self.nx,0:self.nx] self.W = self.S[self.nx:self.n,0:self.nx] self.Q = self.S[self.nx:self.n,self.nx:self.n] # === Use quantecon's LQ code to solve our LQ problem === # lq = LQ(self.Q, self.R, self.A, self.B, self.C, N=self.W, beta=self.beta) self.P, self.F, self.d = lq.stationary_values() # === Construct output matrices for our economy using the solution to the LQ problem === # self.A0 = self.A - self.B.dot(self.F) self.Sh = self.A0[0:self.nh,0:self.nx] self.Sk = self.A0[self.nh:self.nh+self.nk,0:self.nx] self.Sk1 = np.hstack((np.zeros((self.nk,self.nh)),np.eye(self.nk),np.zeros((self.nk,self.nz)))) self.Si = -self.F self.Sd = np.hstack((np.zeros((self.nd,self.nh+self.nk)),self.ud)) self.Sb = np.hstack((np.zeros((self.nb,self.nh+self.nk)),self.ub)) self.Sc = uc.dot(phiin).dot(-self.phii.dot(self.Si) + self.gamma.dot(self.Sk1) + self.Sd) self.Sg = ug.dot(phiin).dot(-self.phii.dot(self.Si) + self.gamma.dot(self.Sk1) + self.Sd) self.Ss = self.llambda.dot(np.hstack((np.eye(self.nh),np.zeros((self.nh,self.nk+self.nz))))) + self.pih.dot(self.Sc) # === Calculate eigenvalues of A0 === # self.A110 = self.A0[0:self.nh+self.nk,0:self.nh+self.nk] self.endo = np.linalg.eigvals(self.A110) self.exo = np.linalg.eigvals(self.a22) # === Construct matrices for Lagrange Multipliers === # self.Mk = -2*np.asscalar(self.beta)*(np.hstack((np.zeros((self.nk,self.nh)),np.eye(self.nk),np.zeros((self.nk,self.nz))))).dot(self.P).dot(self.A0) self.Mh = -2*np.asscalar(self.beta)*(np.hstack((np.eye(self.nh),np.zeros((self.nh,self.nk)),np.zeros((self.nh,self.nz))))).dot(self.P).dot(self.A0) self.Ms = -(self.Sb - self.Ss) self.Md = -(np.linalg.inv(np.vstack((self.phic.T,self.phig.T))).dot(np.vstack((self.thetah.T.dot(self.Mh) + self.pih.T.dot(self.Ms),-self.Sg)))) self.Mc = -(self.thetah.T.dot(self.Mh) + self.pih.T.dot(self.Ms)) self.Mi = -(self.thetak.T.dot(self.Mk))