⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eigifp.m

📁 Frequently used algorithms for numerical analysis and signal processing
💻 M
📖 第 1 页 / 共 3 页
字号:
function [EVals, EVecs] = eigifp(varargin) %%%   EIGIFP (version 2.1.1):  computes a few (algebraically) smallest or largest %       eigenvalues/eigenvectors of the symmetric matrix eigenvalue problem:%%             A x = lambda x   or    A x = lambda B x%%       where A and B are symmetric and B is positive definite.%%   [d, x] = eigifp(A)      => smallest eigenvalue/eigenvector of A;%   [d, X] = eigifp(A,k)    => k smallest eigenvalues/eigenvectors of A;%%   [d, x] = eigifp(A,B)    => smallest eigenvalue/eigenvector of (A,B);%   [d, X] = eigifp(A,B,k)  => k smallest eigenvalue/eigenvector of (A,B);%%   A (and/or B) can be either a sparse matrix or a function that %   returns A*x for x. In the latter case, the dimension of A has %   to be input through options.size (see below). It is also desirable  %   to have an estimate of a norm of A (or B) inputed through %   options.NORMA (or options.NORMB). %%   To compute the largest eigenvalues, one can call as above by adding %   the option options.MAXEIG = 1 (see below). Alternatively, if A is %   numeric, one can do the following.%%   [d, x] = eigifp(-A); d=-d;     => largest eigenvalue/eigenvector of A;%   [d, X] = eigifp(-A,k); d=-d;   => k largest eigenvalues/eigenvectors of A;%%   [d, x] = eigifp(-A,B); d=-d;   => largest eigenvalue/eigenvector of (A,B);%   [d, X] = eigifp(-A,B,k); d=-d; => k largest eigenvalues/eigenvectors of (A,B);%%   Other optional inputs can be provided to use any a priori information,%   to control computational cost, and to optimize performance.%  %   eigifp(A,opt), eigifp(A,k opt), eigifp(A,B,opt), eigifp(A,B,k,opt)%   take the following optional inputs defined by opt:  %%     opt.SIZE:     %       the size of A. %     opt.NORMA:    %       an estimate of the 1-norm of A %     opt.NORMB:    %       an estimate of the 1-norm of B%     opt.INITIALVEC or opt.V0: %       a matrix whose i-th column is the i-th initial eigenvector; %     opt.TOLERANCE or opt.TOL: %       termination tolerance for the 1-norm of residual; %       default: 10*eps*sqrt(n)*(||A||+|lambda|*||B||)%     opt.MAXITERATION or opt.MAXIT: %       set the maximum number of (outer) iterations; default: 500;%     opt.INNERITERATION or opt.INNERIT: %       set a fixed inner iteration to control the memory requirement; %       Default: between 1 and 128 as adaptively determined.   %     opt.USEPRECON:    %       set preconditioning off or completely on:  %           1.  set opt.USEPRECON='NO' to switch off preconditioning; %           2.  set opt.USEPRECON = an approximate eigenvalue %               to start preconditioned iterations with a preconditioner %           computed using the eigenvalue as the shift;              %     opt.ILUTHRESH or opt.ILU:     %       threshold between 0 and 1 used in incomplete LU for computing  %           preconditioner (i.e. used in luinc.m); default: 1e-4; %       Special cases: 0 = exact LU; 1 = 0-level ILU;  %     opt.PRECONDITIONER or opt.PRECON:  %       user supplied preconditioner. It can be a matrix or a function.%     opt.DISP:%       Set to 0 to disable on-screen display of output, and to any other %       numerical value to enable display. Default: 1%     opt.MAXEIG:%       Set to 1 to compute the largest eigenvalues instead of the %       smallest eigenvalue of (A,B). Any other value causes the code to %       compute the smallest eigenvalue. Default: 0%%   %   EIGIFP is based on the algorithm in: G. Golub and Q. Ye, An Inverse %   Free Preconditioned Krylov Subspace Method for Symmetric Generalized%       Eigenvalue Problems,  SIAM J. Sci. Comput., 24(2002):312-334. It also%       incorporates several enhancements. %   %       It is particularly suitable for problems where %       a)  factorization of B is difficult; or%       b)  factorization of A-lambda_k B is difficult; or %       c)  a shift near eigenvalues sought is not known. %%%   EIGIFP is developed by Qiang Ye (qye@ms.uky.edu) with the programming %   assistance provided by James Money. This work was supported by NSF  %   under Grant CCR-0098133. %   %   This program is provided for research and educational use and  %   is distributed through http://www.ms.uky.edu/~qye/software. %   Neither redistribution nor commercial use is permitted without %   consent of the author. %   %   Copyright (c): Qiang Ye%   Version 2.1.1 is dated Oct. 2004%   Version 2.1 is dated July 2004%   Version 2.0 is dated Aug. 2003%   Version 1 is dated Sept. 2002%                    % Process inputs A=varargin{1};n=[]; if ( isnumeric(A) )    n=size(A,1);    if (any(size(A) ~= n))        error('Input Error: Matrix A is not square');    endelseif ( ~isstr(A) )     error('Input Error: A must be either a matrix or a function');end B=[];if ( nargin>1 )    if ( (~ isstruct(varargin{2})) )         if( isstr(varargin{2}) | (any(size(varargin{2}) ~= 1)))        B=varargin{2};        if ( isnumeric(B) )            if ( isempty(n) )                n=size(B,1);            end             if (any(size(B) ~= n))                    error('Input Error: Matrix B must be square and of the size of A');            end        elseif ( ~isstr(B) )             error('Input Error: B must be either a matrix or a function');        end                 end    endend                    % set initial or default values m=0;k=1;X=[];L=[];eta=1e-4;usePrecon=1;iterMax=500;ksetbyuser=0;tolerance=[];normA=[]; normB=[]; outputYes=1;EVals=[];EVecs=[];findMax=0;if ( nargin > 1 + ~isempty(B) )    if ( (~ isstruct(varargin{2+~isempty(B)})) & all(size(varargin{2+~isempty(B)}) == 1))        k=varargin{2+~isempty(B)};        ksetbyuser=1;    endendif ( nargin > 1 + ~isempty(B) + ksetbyuser )    options=varargin{2 + ~isempty(B) + ksetbyuser:nargin};    if ( ~isstruct(options) )         error('Input Error: too many input parameters.');     end    names=fieldnames(options);        I=strmatch('DISP',upper(names),'exact');    if (~isempty(I))        outputYesStr=getfield(options,names{I});        if (isnumeric(outputYesStr))            if (outputYesStr==0)                outputYes=0;            else                outputYes=1;            end        end    end    I=strmatch('SIZE',upper(names),'exact');    if (~isempty(I))        n=getfield(options,names{I});        if( isnumeric(A) & n ~= size(A, 1) )            error('Input Error: options.size not equal to the size of A');        end         if( ~isempty(B) & isnumeric(B) & n ~= size(B, 1) )            error('Input Error: options.size not equal to the size of B');        end     end        I=strmatch('NORMA',upper(names),'exact');    if (~isempty(I))        normA=getfield(options,names{I});    end    I=strmatch('NORMB',upper(names),'exact');    if (~isempty(I))        normB=getfield(options,names{I});    end    I=strmatch('INITIALVEC',upper(names),'exact');    if (isempty(I))        I=strmatch('V0',upper(names),'exact');    end    if (~isempty(I))        X=getfield(options,names{I});        if( isempty(n) )            n=size(X, 1);         elseif ( size(X, 1) ~=n )            error('Input Error: incorrect size of initial vectors');        end         if( size(X, 2) ~=k )            fprintf(1,'Warning: Number of initial vectors not equal to k\n');        end     end        I=strmatch('TOLERANCE',upper(names),'exact');    if (isempty(I))        I=strmatch('TOL',upper(names),'exact');    end    if (~isempty(I))        tolerance=getfield(options,names{I});        if ( tolerance <= 0 )                error('Input Error: Invalid tolerance input.');            end     end        if ( isempty(n) )        error('Input Error: need to input options.size = (dimension of A)');    end         I=strmatch('INNERITERATION',upper(names),'exact');    if (isempty(I))        I=strmatch('INNERIT',upper(names),'exact');    end    if (~isempty(I))        m=getfield(options,names{I});        if ( m < 0 | m >= n )                error('Input Error: Invalid inner iteration number');            end         end        I=strmatch('ILUTHRESH',upper(names),'exact');    if (isempty(I))        I=strmatch('ILU',upper(names),'exact');    end     if (~isempty(I))        eta=getfield(options,names{I});        if ( eta < 0 )                error('Input Error: Invalid incomplete factorization threshold.');            end                 end        I=strmatch('PRECONDITIONER',upper(names),'exact');    if (isempty(I))        I=strmatch('PRECON',upper(names),'exact');    end    if (~isempty(I))        L=getfield(options,names{I});        if ( isnumeric(L) & any(size(L) ~= n))                 error('Input Error: Invalid preconditioner; must be square.');            end                 end        I=strmatch('MAXEIG',upper(names),'exact');    if (~isempty(I))        findMax=getfield(options,names{I});        if ( ~isnumeric(findMax) | ~((findMax==0) | (findMax==1)))            fprintf(1,'Warning: opt.MAXEIG should be either 0 or 1. Reset to 0.\n');        end                 end        I=strmatch('USEPRECON',upper(names),'exact');    if (~isempty(I))        usePreconIn=getfield(options,names{I});        if ( ~isempty(usePreconIn) &  ~isempty(L) )            error('Input Error: input opt.useprecon while a preconditioner has been provided.');         end        if (isstr(usePreconIn))            if (strcmp(upper(usePreconIn),'NO'))                usePrecon=0;                                end        elseif (~isempty(usePreconIn))                  if ( any(size(usePreconIn) > 1) )                     error('Input Error: Invalid shift; must be a real number.');                end                         if ( isnumeric(A) & isnumeric(B) )                if(~issparse(A))                     A=sparse(A);                    fprintf(1,'Warning: A is not in the sparse format.\n');                             end                      if (outputYes ~=0)                     fprintf(1,'Computing threshold ILU factorization using the shift provided.\n');                end                if ( ~isempty(B) )                    if(~issparse(B))                         B=sparse(B);                        fprintf(1,'Warning: B is not in the sparse format.\n');                                 end                      L=ildlte(A-usePreconIn*B,eta);                else                    n=size(A,1);                     L=ildlte(A-usePreconIn*speye(n),eta);                end            else                fprintf(1,'Warning: A (or B) is a function; can not compute preconditioner using opt.useprecon.\n');                        end        end    end    I=strmatch('MAXITERATION',upper(names),'exact');    if (isempty(I))        I=strmatch('MAXIT',upper(names),'exact');    end    if (~isempty(I))        iterMax=getfield(options,names{I});             if (  iterMax <= 0 )                error('Input Error: Invalid maximum iteration.');            end                 endendif ( isempty(normA) )    if ( isnumeric(A) )        normA=norm(A,1);     else        normA=norm(feval(A,ones(n,1)), 1)/n;         fprintf(1,'Warning: options.Anorm (estimate of ||A||_1) is not provided.\n');       endend if ( isempty(normB) )    if ( isempty(B) )        normB=1;    elseif ( isstr(B) )        normB=norm(feval(B,ones(n,1)), 1)/n;         fprintf(1,'Warning: no options.Bnorm (estimate of ||B||_1) is not provided.\n');        elseif ( isnumeric(B) )        normB=norm(B,1);    endend                         % set default tolerance toleranceA=10*eps*normA*sqrt(n);if(~isempty(B))    toleranceB=10*eps*normB*sqrt(n);else    toleranceB=0; end if ( ~isempty(tolerance) )    toleranceVec=[tolerance, 0];    if ( tolerance < toleranceA )          fprintf(1,'Warning: Tolerance may be set too low. Suggested value: %E.\n',toleranceA);    end else    toleranceVec=[toleranceA,toleranceB];endif ( isstr(A) | isstr(B) )     usePrecon=0;endif ( isempty(L) & (usePrecon ~= 0) )     if(~issparse(A))         A=sparse(A);        fprintf(1,'Warning: A is not in the sparse format.\n');                 end      if ( ~isempty(B) & ~issparse(B))         B=sparse(B);        fprintf(1,'Warning: B is not in the sparse format.\n');                 endend                      if (k>n)    error('Error: # of eigenvalues sought is greater than the matrix size');end                        % call the main function ifree.mif (isnumeric(A))       %if given a matrix, use (A,B) or (-A,B) if maxeig =1    if (findMax==1)        if (outputYes)            fprintf(1,'Computing the smallest eigenvalues of (-A,B) first.\n');        end        [EVals, EVecs] = ifree(-A,B,n,m,toleranceVec,iterMax,k,X,eta,L,usePrecon,normA,normB,outputYes);        if (outputYes)            fprintf(1,'  Negating the eigenvalues of (-A, B) => the largest eigenvalues of (A,B):\n');            EVals=-EVals;            fprintf(1,'  %e\n',EVals);        end            else        [EVals, EVecs] = ifree(A,B,n,m,toleranceVec,iterMax,k,X,eta,L,usePrecon,normA,normB,outputYes);    endelse                    % if A is a function     if (findMax==1)     % here we use minusA and negate the results when done        if (outputYes)            fprintf(1,'Computing the smallest eigenvalues of (-A,B) first.\n');        end        saveAfunc=0;        if (exist('Afunc123')==1)   % we don't want to overwrite the user's global, so we save it            saveAfunc=1;            tempFunc=Afunc;            clear Afunc123;        end        global Afunc123;        Afunc123=A;     % this is the function it calls in minusA()        [EVals, EVecs] = ifree('minusA',B,n,m,toleranceVec,iterMax,k,X,eta,L,usePrecon,normA,normB,outputYes);        if (saveAfunc==1)            Afunc123=saveAfunc; %restore the value if the user already defined it        end        if (outputYes)            fprintf(1,'  Negating the eigenvalues of (-A, B) => the largest eigenvalues of (A,B):\n');            EVals=-EVals;            fprintf(1,'  %e\n',EVals);        end          else        [EVals, EVecs] = ifree(A,B,n,m,toleranceVec,iterMax,k,X,eta,L,usePrecon,normA,normB,outputYes);    endendfunction [lambda, x, r, bx, diff, rDiff, bDiff, lam_max, res] = ...     parnob(A, B, L, lambda, x, r, bx, diff, rDiff, bDiff, m, tol, EVecs, BEVecs, lambda_1, lambda_max)%  %   generate B-othonormal basis V of preconditioned (by L) Krylov subspace%   by m steps of Arnoldi algorithm and then compute the Ritz value  %   and Ritz vectors %   %   BEVecs = B*EVecs  with EVecs =  converged eigenvectors%                    % initialization and normalization n=size(x,1);                     V = zeros(n,m);Wr=V; Am = zeros(m,m);temp=bx'*x;if (temp <= 0)    if ( isnumeric(B) )     % double check on x'Bx        bx=B*x;    else        bx=feval(B, x);    end    temp=bx'*x;    if (temp <= 0)        error('Error: B is not positive definite.');    endendtemp=sqrt(temp);V(:,1) = x / temp;r=r/temp; Wr(:,1) = r;bx=bx/temp;if ( ~ isempty(B) )        Wb=V;     Wb(:,1) = bx;endAm(1,1)=0;                    % Loop for Arnoldi iterationfor i = 2:m-1,                                                        % Apply preconditioner if given     if ( isnumeric(L) )                 r=L\r;        r=(L')\r;        else         r=feval(L,r);     end                    % generate new basis vector     for k = 1:(i-1)        if ( ~ isempty(B) )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -