function [x,u] = lyapunov_symm(a,b,lyapunov_fixed_point_tol,qz_criterium,lyapunov_complex_threshold,method,debug) % Solves the Lyapunov equation x-a*x*a' = b, for b and x symmetric matrices. % If a has some unit roots, the function computes only the solution of the stable subsystem. % % INPUTS: % a [double] n*n matrix. % b [double] n*n matrix. % qz_criterium [double] unit root threshold for eigenvalues % lyapunov_fixed_point_tol [double] convergence criteria for fixed_point algorithm. % lyapunov_complex_threshold [double] scalar, complex block threshold for the upper triangular matrix T. % method [integer] Scalar, if method=0 [default] then U, T, n and k are not persistent. % method=1 then U, T, n and k are declared as persistent % variables and the Schur decomposition is triggered. % method=2 then U, T, n and k are declared as persistent % variables and the Schur decomposition is not performed. % method=3 fixed point method % OUTPUTS % x: [double] m*m solution matrix of the lyapunov equation, where m is the dimension of the stable subsystem. % u: [double] Schur vectors associated with unit roots % % ALGORITHM % Uses reordered Schur decomposition (Bartels-Stewart algorithm) % [method<3] or a fixed point algorithm (method==3) % % SPECIAL REQUIREMENTS % None % Copyright © 2006-2023 Dynare Team % % This file is part of Dynare. % % Dynare is free software: you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation, either version 3 of the License, or % (at your option) any later version. % % Dynare is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with Dynare. If not, see . if nargin<6 || isempty(method) method = 0; end if nargin<7 debug = 0; end if method == 3 persistent X method1; if ~isempty(method1) method = method1; end if debug fprintf('lyapunov_symm:: [method=%d] \n',method); end if method == 3 %tol = 1e-10; it_fp = 0; evol = 100; if isempty(X) || length(X)~=length(b) X = b; max_it_fp = 2000; else max_it_fp = 300; end at = a'; %fixed point iterations while evol > lyapunov_fixed_point_tol && it_fp < max_it_fp X_old = X; X = a * X * at + b; evol = max(sum(abs(X - X_old))); %norm_1 %evol = max(sum(abs(X - X_old)')); %norm_inf it_fp = it_fp + 1; end if debug fprintf('lyapunov_symm:: lyapunov fixed_point iterations=%d norm=%g\n',it_fp,evol); end if it_fp >= max_it_fp disp(['lyapunov_symm:: convergence not achieved in solution of Lyapunov equation after ' int2str(it_fp) ' iterations, switching method from 3 to 0']); method1 = 0; method = 0; else method1 = 3; x = X; return end end end if method persistent U T k n else % if exist('U','var') % clear('U','T','k','n') % end end u = []; if size(a,1) == 1 x=b/(1-a*a); return end if method<2 [U,T] = schur(full(a)); e1 = abs(ordeig(T)) > 2-qz_criterium; k = sum(e1); % Number of unit roots. n = length(e1)-k; % Number of stationary variables. if k > 0 % Selects stable roots [U,T] = ordschur(U,T,e1); T = T(k+1:end,k+1:end); end end B = U(:,k+1:end)'*b*U(:,k+1:end); x = zeros(n,n); i = n; while i >= 2 if abs(T(i,i-1))