-
Notifications
You must be signed in to change notification settings - Fork 70
/
Copy pathschur_solver.m
156 lines (146 loc) · 4.68 KB
/
schur_solver.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
function [G1,C,impact,eu,F]=schur_solver(g0,g1,c,psi,pi,continuous,check_exist,check_uniq,n_v)
% Solver based on Schur decomposition (This is based on Sims's gensys, but adjusted
% to take advantage of special case that applies to heterogeneous agent models).
%
% by SeHyoun Ahn, Dec 2016
%
% REFERENCES:
% * Sims, Christopher A. "Solving linear rational expectations models."
% Computational economics 20.1 (2002): 1-20.
% * Ahn, SeHyoun, Greg Kaplan, Benjamin Moll, Thomas Winberry, and
% Christian Wolf. "When Inequality Matters for Macro and Macro Matters
% for Inequality."
%
% PARAMETERS:
% Check Sims's paper for notation or Our Paper for notation
%
% XXXXX DO NOT USE DISCRETE TIME VERSION. IT PROBABLY IS WRONG XXXXXX
% The issue is noted in < https://github.com/gregkaplan/phact/issues/1 >
%
% continuous = 1 for a continuous time problem (default)
% 0 for a discrete time problem
%
% check_exist = 1 check for existence of solution (default)
% 0 existence has been checked before
% check_uniq = 0 do not check for uniqueness (default)
% 1 check for uniqueness
% n_v = number of unstable roots
%
% OUPUTS:
% eu(1) = 1 solution exists
% 0 no stable solution
% -5 Flag for checking existence is off
% eu(2) = 1 solution is unique
% 0 solution is not unique
% -5 Flag for checking uniqueness is off
%
% SYNTAX:
% [G1,C,impact,eu,F]=schur_solver(g0,g1,c,psi,pi,continuous,check_exist,check_uniq,varargin)
%% Set Default Values %%
switch nargin
case 8
n_v = -1;
case 7
check_uniq = 0;
n_v = -1;
case 6
check_uniq = 0;
check_exist = 1;
n_v = -1;
case 5
check_uniq = 0;
check_exist = 1;
continuous = 1;
n_v = -1;
case 1:4
error('Insufficient Number of Input Variables');
end
realsmall = sqrt(eps)*10;
eu = [-5;-5];
n = size(g1,1);
%% Schur Decomposition
[U,T] = schur(full(g1),'real');
if continuous
g_eigs = real(ordeig(T));
nunstab = sum(g_eigs>0);
if n_v > -1
[aux,ind] = sort(g_eigs,'descend');
locs = ones(n,1);
locs(ind(1:n_v)) = 0;
[U,T] = ordschur(U,T,locs);
if nunstab > n_v
warning('<schur_solver>: There are more than n_v number of positive eigenvalues with smallest values:');
disp(aux(n_v+1:nunstab));
elseif nunstab < n_v
warning('<schur_solver>: There are less than n_v number of positive eigenvalues:');
disp(aux(nunstab+1:n_v));
end
nunstab = n_v;
else
[U,T] = ordschur(U,T,'lhp');
end
else
g_eigs = abs(ordeig(T));
nunstab = sum(g_eigs>1);
if n_v > -1
[aux,ind] = sort(g_eigs,'descend');
locs = ones(n,1);
locs(ind(1:n_v)) = 0;
[U,T] = ordschur(U,T,locs);
if nunstab > n_v
warning('<schur_solver>: There are more than n_v number of positive eigenvalues with smallest values:');
disp(aux(n_v+1:nunstab));
elseif nunstab < n_v
warning('<schur_solver>: There are less than n_v number of positive eigenvalues:');
disp(aux(nunstab+1:n_v));
end
nunstab = n_v;
else
[U,T] = ordschru(U,T,'udi');
end
end
u1 = U(:,1:n-nunstab)';
u2 = U(:,n-nunstab+1:n)';
etawt = u2*pi;
[ueta,deta,veta] = svd(etawt);
md = min(size(deta));
bigev = find(diag(deta(1:md,1:md))>realsmall);
ueta = ueta(:,bigev);
veta = veta(:,bigev);
deta = deta(bigev,bigev);
if check_exist
zwt = u2*psi;
[uz,dz,vz] = svd(zwt);
md = min(size(dz));
bigev = find(diag(dz(1:md,1:md))>realsmall);
uz = uz(:,bigev);
vz = vz(:,bigev);
dz = dz(bigev,bigev);
if isempty(bigev)
eu(1) = 1;
else
eu(1) = (norm(uz-ueta*ueta'*uz,'fro') < realsmall*n);
end
if (~eu(1) && (n_v == -1))
warning('<schur_solver>: Solution does not exist');
end
impact = real(-pi*veta*(deta\ueta')*uz*dz*vz'+psi);
else
impact = real(-pi*veta*(deta\ueta')*u2*psi+psi);
end
G1 = U*T*spdiags([ones(n-nunstab,1);zeros(nunstab,1)],0,n,n)*U';
G1 = real(G1);
if check_uniq
[~,deta1,veta1] = svd(u1*pi);
md = min(size(deta1));
bigev = find(diag(deta1(1:md,1:md))>realsmall);
veta1 = veta1(:,bigev);
if isempty(veta1)
eu(2) = 1;
else
eu(2) = norm(veta1-veta*veta'*veta1,'fro')<realsmall*n;
end
end
F = u1(:,1:nunstab)'*inv(u1(:,nunstab+1:end)');
impact = [F*psi(nunstab+1:end,:);psi(nunstab+1:end,:)];
C = c; % constant term is not coded yet