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

📄 eigifp.m

📁 Frequently used algorithms for numerical analysis and signal processing
💻 M
📖 第 1 页 / 共 3 页
字号:
conv=ones(itermax,1);rate=ones(10,1);Lambda_1=zeros(k,1);Lambda_Max=zeros(k,1);EVecs=zeros(n,k);BEVecs=EVecs;pertbound=0; shift=0; if ( isempty(L) )    regenL=1;    startL=0;else    regenL=0;    startL=1;end                    % set initial random vector if not givenif (~ isempty(X))    x=X(:,1);    normX=norm(x);    if (normX == 0 | size(x,1) ~= n)        error('Input Error: Invalid input of the initial vector.');    endelse    x=rand(n,1)-0.5*ones(n,1);    normX=norm(x);end x=x/normX;                    % loop for computing k eigenvaluesfor l=1:k        diff=zeros(n,1);        % initialization for each eigenvalue iteration        rDiff=diff;         bDiff=diff;        if ( (~isempty(B)) & isnumeric(B) )        bx=B*x;     elseif ( (~isempty(B)) & isstr(B) )        bx=feval(B, x);    else         bx=x;      end     temp=x'*bx;     if (temp <= 0)        error('Error: B is not positive definite.');    end    if (isstr(A))        r=feval(A, x);    else        r=A*x;    end            lambda=(x'*r)/temp;    r=r-lambda*bx;    res=norm(r);    conv(1)=res;    initialConv=0;     tol0=tol(1) + abs(lambda)*tol(2);        matvecCount=1;    preconCount=0;    changeCounter=-itermax;    mValue=m;    if (mValue < 1)        mValue=min(n-1,2);        if (startL == 1), mValue=1; end        changeCounter=-10;    end    priorM= mValue;         priorRate=-eps;                if (outputYes ~=0)        fprintf(1,'\nComputing Eigenvalue %d:\n',l);        fprintf(1,'  Iteration\tEigenvalue\tResidual\n');        fprintf(1,'  ======================================================\n');        fprintf(1,'  %d\t\t%E\t%E\n',1,lambda,res);     end                        % iteration for computing l-th eigenvalue    for iter=2:itermax                if ( res < tol0 )   % if converged, set parameters for next eigen            lambda_max = normA;             initialConv=1;              break;        end        projSize=mValue+2;                      % compute Ritz value and vector by Krylov projection                       % call lancb if no preconditioning                     % call parnob if using preconditioning        if (l>1)                    % with deflation for l > 1                if ( startL == 0 )                    [lambda, x, r, bx, diff, rDiff, bDiff, d2, lambda_max, res] = ...              lancb(A, B, lambda, x, r, bx, diff, rDiff, bDiff, projSize,  tol,...                          EVecs(:,1:l-1), BEVecs(:,1:l-1), Lambda_1(1:l-1), Lambda_Max(1:l-1,:));          else                    preconCount=preconCount+mValue;                    [lambda, x, r, bx, diff, rDiff, bDiff, lambda_max, res] = ...              parnob(A, B, L, lambda, x, r, bx, diff, rDiff, bDiff, projSize, tol,...                          EVecs(:,1:l-1), BEVecs(:,1:l-1), Lambda_1(1:l-1), Lambda_Max(1:l-1,:));          end                   else                    % no deflation if l=1.           if ( startL == 0 )                    [lambda, x, r, bx, diff, rDiff, bDiff, d2, lambda_max, res] = ...              lancb(A, B, lambda, x, r, bx, diff, rDiff, bDiff, projSize, tol);                       else            preconCount=preconCount+mValue;                    [lambda, x, r, bx, diff, rDiff, bDiff, lambda_max, res] = ...              parnob(A, B, L, lambda, x, r, bx, diff, rDiff, bDiff, projSize, tol);          end                   end                     conv(iter)=res;         matvecCount=matvecCount+mValue;                 if (outputYes ~= 0)            fprintf(1,'  %d\t\t%E\t%E\n',iter,lambda,res);        end                            % update tolerance and check convergence        tol0=tol(1) + abs(lambda)*tol(2);        if ( res <= tol0 )            break;        end                    % check on convergence rate and update mValue        changeCounter=changeCounter+1;        if ( changeCounter >= 19 )                    rate=[rate(2:10); aveRate(conv, iter-changeCounter+4, iter)];                    [mValue, priorM, priorRate, fixM]=updateM(rate,mValue,priorM,priorRate,n);                    changeCounter=(changeCounter+fixM*itermax)*(1-fixM);              elseif ( changeCounter >= 10 )                    rate=[rate(2:10); aveRate(conv, iter-changeCounter+4, iter)];            end                     % estimate error         if ( (startL==0) & (d2>0) )            err=min((res^2 / d2), res)/(bx'*x);         elseif (startL==0)            err =abs(lambda);        end                    % determine whether to switch to preconditioning                    if ((startL==0) & (usePrecon ~= 0) & (err <= (0.01*abs(lambda))) & (err < (0.0001*max(abs(lambda),normA/normB)) ) )            startL=1;            mValue=1;            changeCounter=0;            pertbound=0.0002*max(abs(lambda),normA/normB);                      if (outputYes ~= 0)                fprintf(1,'   \n');                fprintf(1,'    Computing ILU factorization: if it takes too long, try the options:\n');                 fprintf(1,'      opt.iluThresh, opt.Preconditioner, or opt.usePrecon. \n');                         fprintf(1,'   \n');            end            shift=lambda-err;            if ( ~isempty(B) )                L=ildlte(A-shift*B,eta);            else                L=ildlte(A-shift*speye(n),eta);            end            if (outputYes ~= 0)                fprintf(1,'    Done!  Starting preconditioned iterations: \n');                fprintf(1,'      if convergence is not accelerated, try decreasing opt.iluThresh. \n');                fprintf(1,'   \n');                     end             end                        % determine whether to switch off preconditioning        if ((regenL ~= 0) & (startL==1) & (changeCounter>15) & ( abs(shift-lambda) >= min(0.02*abs(shift), pertbound)))            if ( sum(rate) > -0.2)                  startL=0;                changeCounter=-itermax;                mValue=m;                if (mValue < 1)                    mValue=2;                    changeCounter=0;                end                     end         end    end                        % store eigenpairs and others    Lambda_1(l)=lambda;    Lambda_Max(l)=lambda_max;    temp=sqrt(bx'*x);    EVecs(:,l)=x/temp;     BEVecs(:,l)=bx/temp;                        % warn if not converged                             if ( res >= tol0 )        if (isnumeric(A) & nnz(A-A') ~= 0)            error('Input Error: Matrix A is not symmetric');        end        if ( (~isempty(B)) & isnumeric(B) & nnz(B-B') ~= 0)            error('Input Error: Matrix B is not symmetric');        end        fprintf(1,'\n');        fprintf(1,'Warning: Eigenvalue %d not converged to the tolerance within max iteration\n',l);        fprintf(1,'         Residual = %E , the set tolerance = %E \n',res, tol0);        fprintf(1,'         Try setting opt.innerit, a larger tolerance, and/or opt.maxit\n');    end    if (outputYes ~= 0)        fprintf(1,'  ------------\n');        fprintf(1,'  Eigenvalue %d converged. \n',l);               fprintf(1,'  # of multiplications by A (and B):      %d. \n',1+matvecCount);                if (preconCount > 0)            fprintf(1,'  # of multiplications by preconditioner: %d.\n',  preconCount);             end     end                        %  set next initial vector      if ( l<size(X,2) )        x=X(:,l+1);        normX=norm(x);        if (normX == 0)            fprintf(1,'Input Error: Invalid input of initial vector.\n');        end        x=diff;    elseif (initialConv==1)         x=rand(n,1)-0.5*ones(n,1);      else        x=diff;    end    x=x-EVecs(:,1:l)*(BEVecs(:,1:l)'*x);    normX=norm(x);    if (normX == 0)        if (l<k)             error('Error: Fail to form an initial vector.');        end         return;    end    x=x/normX;              endif (outputYes ~= 0)    fprintf(1,'\n-----\n');    fprintf(1,'  CPU Time:%f.\n',cputime-t);endfunction rate=aveRate(conv, k, iter)%% compute average linear convergence rate of conv over steps k+1 to iter %rate=0; if ( iter-k < 2 | k<1 )     return;endy=log10(conv((k+1):iter));xAve=(iter-k+1)/2; xyAve=((1:iter-k)*y)/(iter-k)-xAve*sum(y)/(iter-k); xAve=((iter-k)^2-1)/12;rate=xyAve/xAve;            function L=ildlte(A, eta)%%ILDLT   Threshold incomplete LDL^T  using luinc.m or ilu %n=size(A, 1);                        % compute L U factors options.thresh=0;options.udiag=1;if (eta ==2)    options.milu=1;     [L, U] = luinc(A, options);elseif (eta==1)     [L, U] = ilu(A);else     options.droptol=eta;    [L, U] = luinc(A, options);end                     % scale diagonals to get L d = diag (U);d = sqrt(abs(d));  for k = 1:n,     if ( d(k) < 1e-8)         d(k) = 1e-8;    endend L = L * spdiags(d, 0, n, n);function [L, U] = ilu(A)%% ILU   Incomplete LU factorization with no fill-in.%   No pivoting is used %    n = size(A, 1); M = A; for k = 1:(n-1),     if ( M(k, k) == 0)        M(k, k) = 1e-8;    elseif ( abs(M(k, k)) < 1e-8)         M(k, k) = 1e-8*sign(M(k, k));    end     ind = find( M(:, k) );     ind = ind(find(ind>k))';    for i = ind,            M(i, k) = M(i, k) / M(k, k);     end     ind_j = find( M(k, :) );     ind_j = ind_j(find(ind_j>k))';    for j = ind_j,             for i = ind,                if (M(i, j) ~= 0)                     M(i, j) = M(i, j) - M(i, k)*M(k,j);                 end             end     end end L=tril(M, -1)+speye(n); U=triu(M, 0);function [mValue, priorM, priorRate, fixM]=updateM(rate, mValue, priorM, priorRate,n);          %%  Adaptive update of mValue: inner iteration %fixM=0;maxm=min(n-1, 128);                    % update m when rate stagnates  if ( (max(rate)-min(rate)) < 0.1*(-rate(10)) | min(rate) > 0 )    k=2;                % increase m by k times,                     % use larger k if slower convergence         if ((rate(10) > -0.001) & 8*mValue <= maxm),             k=8;         elseif ((rate(10) > -0.01) & 4*mValue <= maxm),             k=4;        end                        % increase m by testing acceleration rate         incFlag=(rate(10)/priorRate)*(priorM/mValue);         if (incFlag > 1.05)             if(2*mValue > maxm )                fixM=-1;            else                priorM=mValue;                 priorRate=rate(10);                 mValue=k*mValue;                fixM=1;            end          elseif ((rate(10) > -0.001 ) & 2*mValue <= maxm),             mValue=k*mValue;            fixM=1;          elseif ((rate(10) > -0.01 ) & 2*mValue <= maxm),             mValue=k*mValue;            fixM=1;           elseif (incFlag < 0.9)            mValue=priorM;            fixM=-1;           endendfunction lambda=Bisection(T,tol)%% estimate two lowest eigenvalues of tridiagonal T by Bisection %a=diag(T);b=diag(T,1);k=2; lambda=zeros(k,1); xb=norm(T, 1)*1.0000001; xa=-xb; xc=0; p=0;x1=[];x2=[];n1=[];n2=[];na=0; nc=Negcount(a,b,xc);[p,x1,x2,n1,n2]=put(xa,na,xc,nc,p,x1,x2,n1,n2);if( nc < k)    nb=Negcount(a,b,xb);    [p,x1,x2,n1,n2]=put(xc,nc,xb,nb,p,x1,x2,n1,n2);end q=0;while ( (p~=0) & (q < k) )    [low,nlow,up,nup,p,x1,x2,n1,n2]=remove(p,x1,x2,n1,n2);    if(nlow <= k)         if ( abs(up-low)<tol*abs(up) )             ind=q+nup-nlow;             ind=min(ind, k);             q=q+1;            lambda(q:ind)=((up+low)/2)*ones((ind-q+1),1);        else            mid=(low+up)/2;            nmid=Negcount(a,b,mid);              if ( (nup>nmid) & (nmid <k) )                [p,x1,x2,n1,n2]=put(mid,nmid,up,nup,p,x1,x2,n1,n2);            end            if nmid>nlow                  [p,x1,x2,n1,n2]=put(low,nlow,mid,nmid,p,x1,x2,n1,n2);            end        end    end end function [p,x1,x2,n1,n2]=put(xa,na,xb,nb,p,x1,x2,n1,n2)p=p+1;x1(p)=xa;x2(p)=xb;n1(p)=na;n2(p)=nb;function [xa,na,xb,nb,p,x1,x2,n1,n2]=remove(p,x1,x2,n1,n2)xa=x1(p);xb=x2(p);na=n1(p);nb=n2(p);p=p-1; function m=Negcount(a,b,z)%% NEGCOUNT: evaluates the number of eigenvalues that are smaller than z%m=0;n=size(a,1);f=size(b,1);d(1)=a(1)-z;if d(1)<0    m=m+1;elseif d(1)==0,           d(1)=eps^2; endfor i=2:n    d(i)=a(i)-z-b(i-1)^2/d(i-1);    if d(i)<0        m=m+1;        elseif d(i)==0            d(i)=eps^2;     endendfunction x=minusA(x)global Afunc123;x=feval(Afunc123,x);x=-x;

⌨️ 快捷键说明

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