2023-01-02 16:57:08 +01:00
function [X, info] = cycle_reduction ( A0, A1, A2, cvg_tol, ch)
2012-07-11 16:30:01 +02:00
%@info:
%! @deftypefn {Function File} {[@var{X}, @var{info}] =} cycle_reduction (@var{A0},@var{A1},@var{A2},@var{cvg_tol},@var{ch})
%! @anchor{cycle_reduction}
%! @sp 1
%! Solves the quadratic matrix equation A2*X^2 + A1*X + A0 = 0.
%! @sp 2
%! @strong{Inputs}
%! @sp 1
%! @table @ @var
%! @item A0
%! Square matrix of doubles, n*n.
%! @item A1
%! Square matrix of doubles, n*n.
%! @item A2
%! Square matrix of doubles, n*n.
%! @item cvg_tol
%! Scalar double, tolerance parameter.
%! @item ch
%! Any matlab object, if not empty the solution is checked.
%! @end table
%! @sp 1
%! @strong{Outputs}
%! @sp 1
%! @table @ @var
%! @item X
%! Square matrix of doubles, n*n, solution of the matrix equation.
%! @item info
%! Scalar integer, if nonzero the algorithm failed in finding the solution of the matrix equation.
%! @end table
%! @sp 2
%! @strong{This function is called by:}
%! @sp 2
%! @strong{This function calls:}
%! @sp 2
%! @strong{References:}
%! @sp 1
%! D.A. Bini, G. Latouche, B. Meini (2002), "Solving matrix polynomial equations arising in queueing problems", Linear Algebra and its Applications 340, pp. 222-244
%! @sp 1
%! D.A. Bini, B. Meini (1996), "On the solution of a nonlinear matrix equation arising in queueing problems", SIAM J. Matrix Anal. Appl. 17, pp. 906-926.
%! @sp 2
%! @end deftypefn
%@eod:
2012-07-01 15:15:52 +02:00
2023-01-02 16:57:08 +01:00
% Copyright © 2013-2023 Dynare Team
2012-07-01 15:15:52 +02:00
%
% 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
2021-06-09 17:33:48 +02:00
% along with Dynare. If not, see <https://www.gnu.org/licenses/>.
2012-07-01 15:15:52 +02:00
2012-07-09 16:00:04 +02:00
max_it = 300 ;
it = 0 ;
info = 0 ;
2012-07-22 12:51:55 +02:00
X = [ ] ;
crit = Inf ;
2012-07-09 16:00:04 +02:00
A0_0 = A0 ;
2012-07-22 19:54:12 +02:00
Ahat1 = A1 ;
2012-07-22 12:51:55 +02:00
if ( nargin == 5 && ~ isempty ( ch ) )
A1_0 = A1 ;
A2_0 = A2 ;
end
2012-07-09 16:00:04 +02:00
n = length ( A0 ) ;
2012-07-22 12:51:55 +02:00
id0 = 1 : n ;
id2 = id0 + n ;
2012-07-09 16:00:04 +02:00
2012-07-22 12:51:55 +02:00
cont = 1 ;
2017-05-16 15:10:20 +02:00
while cont
2012-07-22 12:51:55 +02:00
tmp = ( [ A0 ; A2 ] / A1 ) * [ A0 A2 ] ;
A1 = A1 - tmp ( id0 , id2 ) - tmp ( id2 , id0 ) ;
A0 = - tmp ( id0 , id0 ) ;
A2 = - tmp ( id2 , id2 ) ;
2012-07-22 19:54:12 +02:00
Ahat1 = Ahat1 - tmp ( id2 , id0 ) ;
2012-07-22 12:51:55 +02:00
crit = norm ( A0 , 1 ) ;
if crit < cvg_tol
% keep iterating until condition on A2 is met
if norm ( A2 , 1 ) < cvg_tol
cont = 0 ;
end
2022-09-27 04:43:37 +02:00
elseif it == max_it
info ( 1 ) = 401 ;
info ( 2 ) = log ( norm ( A1 , 1 ) ) ;
return
elseif isnan ( crit )
info ( 1 ) = 402 ;
info ( 2 ) = log ( norm ( A1 , 1 ) )
2012-07-22 12:51:55 +02:00
return
2017-05-16 15:10:20 +02:00
end
2012-07-09 16:00:04 +02:00
it = it + 1 ;
end
2012-07-01 15:15:52 +02:00
2012-07-22 19:54:12 +02:00
X = - Ahat1 \ A0_0 ;
2012-07-01 15:15:52 +02:00
2012-07-11 16:30:01 +02:00
if ( nargin == 5 && ~ isempty ( ch ) )
2012-07-09 16:00:04 +02:00
%check the solution
2022-09-27 04:43:37 +02:00
res = norm ( A0_0 + A1_0 * X + A2_0 * X * X , 1 ) ;
if ( res > cvg_tol )
info ( 1 ) = 403
info ( 2 ) = log ( res )
2022-10-04 22:37:40 +02:00
dprintf ( ' The norm of the residual is %s whereas the tolerance criterion is %s' , num2str ( res ) , num2str ( cvg_tol ) ) ;
2012-07-09 16:00:04 +02:00
end
2012-07-11 17:00:38 +02:00
end
2023-01-02 16:57:08 +01:00
return % --*-- Unit tests --*--
2012-07-11 17:00:38 +02:00
%@test:1
2023-01-02 16:57:08 +01:00
t = zeros ( 3 , 1 ) ;
% Set the dimension of the problem to be solved.
n = 500 ;
% Set the equation to be solved
A = eye ( n ) ;
B = diag ( 30 * ones ( n , 1 ) ) ; B ( 1 , 1 ) = 20 ; B ( end , end ) = 20 ; B = B - diag ( 10 * ones ( n - 1 , 1 ) , - 1 ) ; B = B - diag ( 10 * ones ( n - 1 , 1 ) , 1 ) ;
C = diag ( 15 * ones ( n , 1 ) ) ; C = C - diag ( 5 * ones ( n - 1 , 1 ) , - 1 ) ; C = C - diag ( 5 * ones ( n - 1 , 1 ) , 1 ) ;
% Solve the equation with the cycle reduction algorithm
try
tic ; X1 = cycle_reduction ( C , B , A , 1e-7 ) ; elapsedtime = toc ;
disp ( [ ' Elapsed time for cycle reduction algorithm is: ' num2str ( elapsedtime ) ' (n=' int2str ( n ) ' ).' ] )
t ( 1 ) = 1 ;
catch
% nothing to do here.
end
% Solve the equation with the logarithmic reduction algorithm
try
tic ; X2 = logarithmic_reduction ( A , B , C , 1e-16 , 100 ) ; elapsedtime = toc ;
disp ( [ ' Elapsed time for logarithmic reduction algorithm is: ' num2str ( elapsedtime ) ' (n=' int2str ( n ) ' ).' ] )
t ( 2 ) = 1 ;
catch
% nothing to do here.
end
% Check the results.
if t ( 1 ) && t ( 2 )
t ( 3 ) = dassert ( X1 , X2 , 1e-12 ) ;
end
T = all ( t ) ;
2012-07-11 17:00:38 +02:00
%@eof:1