gusucode.com > 信号处理工具箱 - signal源码程序 > signal\signal\signal\private\adesc.m

    function [h,a,delta,HH,EE] = ...
     adesc( L, Lf, Lb, Ls, Lc, sym, indx_edges, iext, HH, EE, a,...
            M_str, HH_str, h_str, A, delta, PLOTS, TRACE )
%ADESC Second-stage ascent-descent algorithm for CREMEZ
%  Solve problem on sets of extremal points using a descent method
%  based on the work of Demjanov & Malozemov and Wolfe. 

%   Authors: L. Karam, J. McClellan
%   Revised: 22-Oct-96, D. Orofino
%
%   Copyright (c) 1988-98 by The MathWorks, Inc.
%   $Revision: 1.1 $  $Date: 1998/06/03 16:14:35 $

global DES_CRMZ WT_CRMZ GRID_CRMZ TGRID_CRMZ IFGRD_CRMZ

% This parameter can be set to the desired accuracy:
ACCURACY = 0.01;

J = 1i;
is_odd = rem(L,2);
Lfft = length(TGRID_CRMZ);

% Set the variable "bands".
vec_edges = TGRID_CRMZ(indx_edges);
bands = zeros(size(vec_edges));
for k = 1:length(vec_edges),
  if vec_edges(k)~=1,
    bands(k) = find(vec_edges(k)==GRID_CRMZ);
  else 
    bands(k) = length(GRID_CRMZ);
  end
end

no_stp = 1;
a = a(1:Lb);
a = a(:);
n2 = length(a);
n = 2*length(a);
mxl = 2*L+1;
maj_it = 0;
alpha = 1;
nu = 0; 

% Set initial accuracy parameters:
acc_scale = max(abs(WT_CRMZ.*A)); 
acc_min =  ACCURACY;
acc = acc_min;
if acc < acc_min,
  acc = acc_min; 
end
r_min = 0.5;
r_o = acc_scale * r_min;
if r_o < r_min,
  r_o = r_min;
end
r = r_o;
epsi_min = ACCURACY;
epsi_o = acc_scale * epsi_min;
epsil = epsi_o; 
epsilon = 1-0.005;

% Construct initial subset:
HH_o = HH;
e_max = max(abs(EE)); 
[iext] = adesc_findset(EE,iext,bands,delta);
sub_EE = EE(iext);
sub_grd = GRID_CRMZ(iext);
sub_WT = WT_CRMZ(iext);
sub_max = max(abs(sub_EE));
fmax = iext;
[jext] = adesc_findextr(EE,bands,epsilon); 

% Check optimality of initial approximation:
gext = adesc_grad(EE, jext, GRID_CRMZ, WT_CRMZ, M_str, Lf, is_odd);
[rext] = adesc_minpolytope(gext, TRACE);
no_stp = (norm(rext) > acc);

% Begin major iteration:
while no_stp,

  jext     = find( (max(abs(sub_EE))-abs(sub_EE)) <= epsil );
  G        = adesc_grad(sub_EE, jext, sub_grd, sub_WT, M_str, Lf, is_odd);
  [NrG]    = adesc_minpolytope(G, TRACE);
  norm_NrG = norm(NrG);

  if (norm_NrG <= r)  
    nu = nu + 1; 
    epsil = epsi_o./(2^nu);
    r = r_o./(2^nu);
    f_extr = find(abs(sub_EE)/sub_max >= epsilon);
    gext = adesc_grad(sub_EE,f_extr,sub_grd,sub_WT,M_str,Lf,is_odd);
    [rext] = adesc_minpolytope(gext, TRACE);
    if norm(rext) < acc,
      maj_it = maj_it + 1;
      nu = 0;
      epsil = epsi_o; 
      r = r_o;  

      if TRACE,
        fprintf('iter: %3.0f   ',maj_it)
        fprintf('peak wgt error:  %5.2e  ',e_max)
        fprintf('subset peak wgt err: %5.2e\n',sub_max)
      end

      [iext] = adesc_findset(EE,iext,bands,sub_max);
      sub_EE = EE(iext);
      sub_grd = GRID_CRMZ(iext);
      sub_WT = WT_CRMZ(iext);
      sub_max = max(abs(sub_EE));

      if (length(iext) == length(fmax)),
        no_stp = ~all(iext==fmax);
      end

      fmax = iext;
    end

  else 
    d = - NrG./norm_NrG;
    d2 = d(1:n2)+J*d(n2+1:n);
    [HH_d] = adesc_reconst(d2,h_str,HH_str,M_str,TGRID_CRMZ,Lfft,...
                           L,Lf,Lc,Ls,Lb,is_odd,vec_edges,indx_edges );
    [HH_n,EE,e_max,alpha] = adesc_linsearch(alpha,iext,HH_o,HH_d,...
                                            sub_max,A,WT_CRMZ,IFGRD_CRMZ );
    a = a + alpha*d2;
    HH_o = HH_n;
    sub_EE = EE(iext);
    sub_max = max(abs(sub_EE));
  end

end % while no_stp

% end major iteration

HH = HH_n;
a = a(:); 
h = eval(h_str);
epsilon = 0.9*sub_max/e_max;
iext = adesc_findextr(EE,bands,epsilon);
jext = iext';
delta = max(abs(EE));

if TRACE,
  fprintf('Optimal Solution Obtained !\n')
end
% End Ascent-Descent Stage

%========================================================

function [fmax] = adesc_findextr(error,indx_edges,epsilon)
%ADESC_FINDEXTR
% returns indices of the extremals in "fmax".
%
error = error(:);
indx_edges = indx_edges(:);
Ngrid = length(error);
abs_e = abs(error);
abs_e = [abs_e(2); abs_e; abs_e(Ngrid-1)];
fmax = find( (abs_e(2:Ngrid+1) >= abs_e(1:Ngrid)) & ...
             (abs_e(2:Ngrid+1) > abs_e(3:Ngrid+2)) ); 
fmax = fmax(:);
fmax = sort([fmax; indx_edges]);
abs_e([1;Ngrid+2]) = [];
fmax(find(~(fmax(1:length(fmax)-1)-fmax(2:length(fmax)))))=[];
if (length(fmax) > 1)
  fmax(find(abs_e(fmax)/max(abs_e) < epsilon)) = []; 
end;

%========================================================

function [fmax] = adesc_findset(error,iext,indx_edges,delta)
% 
% Construct new set fmax of frequency points.  
% fmax: All local maxima including the set "iext".
%       Points with small deviation removed.
%
error = error(:);
indx_edges = indx_edges(:);
Ngrid = length(error);
abs_e = abs(error);
abs_e = [abs_e(2); abs_e; abs_e(Ngrid-1)];
fmax = find( (abs_e(2:Ngrid+1) >= abs_e(1:Ngrid)) & ...
             (abs_e(2:Ngrid+1) >= abs_e(3:Ngrid+2)) ); 
fmax = fmax(:);
fmax = sort([fmax; indx_edges; iext]);
abs_e([1;Ngrid+2]) = [];
fmax(find( fmax(1:length(fmax)-1) == fmax(2:length(fmax)) )) = [];
fmax(find( abs_e(fmax) < 0.9*abs(delta) )) = [];

%========================================================

function G = adesc_grad(EE, iext, grd, WT, M_str, Lf, is_odd)
%ADESC_GRAD Calculate gradients at the points iext.

J    = 1i;  % for use in M_str
fext = grd(iext);
W    = 2*pi*fext*([0:(Lf-1)]+(~is_odd)*0.5);
Mb   = -eval(M_str)';
MWT  = diag(2.*WT(iext).*EE(iext));
M    = Mb*MWT;
G    = [real(M);imag(M)];

%========================================================

function [HHt,EEt,emxt,t] = ...
     adesc_linsearch(t0,iext,HH_o,d,emx,DD,WT,ifgrid)
%ADESC_LINSEARCH Performs a simple line search for step size. 
%  Efficiency of search can be improved by implementing 
%  method suggested in book "Introduction To Minimax" 
%  by V. F. Demjanov and V. N. Malozemov, pp. 109-112. 

t    = t0;
HH_o = HH_o(:);
d    = d(:);
no_stp = 1;
r_flg  = 0;
t_flg  = 1;
h_flg  = 0;
i_flg  = 0;
grtr   = 1;
c      = 2;
acc    = 1 - 10^(-0.1/10);
while grtr,
  HHt = HH_o + t*d; 
  EEt = WT .* (DD - HHt(ifgrid));
  emxt = max(abs(EEt(iext)));
  if (emxt <= emx),
    grtr = 0; 
  else
    t = t/2;
  end
end
tmin = t; HHt_min = HHt; EEt_min = EEt;
emin = emxt; I = 2*t*ones(2,1);
while no_stp,
  if (~i_flg), t = c*t; end
  HHt = HH_o + t*d; 
  EEt = WT .* (DD - HHt(ifgrid));
  emxt = max(abs(EEt(iext)));
  R = (emxt <= emin);
  if (R)
    tmin = t; HHt_min = HHt; EEt_min = EEt; emin = emxt;
    t_flg = 0; h_flg = 0;
    if (i_flg)
      I = sort([t;I(2)]);
      t = (t+I(2))/2;
    end
    r_flg = 1;
  elseif ((~R) & (i_flg))
      I = sort([I(1);t]);
      t = (t+I(1))/2;
  elseif (t_flg)
    t1 = t;
    t_flg = 0;
  elseif (r_flg)
    if (r_flg) t1 = t; end;
    I = sort([tmin,t1]);
    t = (tmin+t1)/2;
    i_flg = 1;
  else
    no_stp = 0;
  end
  if  ( i_flg & ((I(2) - t) < acc*I(2)) ) no_stp = 0; end;
end
HHt = HHt_min; EEt = EEt_min; emxt = max(abs(EEt)); t = tmin;

%========================================================

function [HH] = adesc_reconst(at,h_str,HH_str,M_str,tgrid,Lfft,... 
                L, Lf, Lc, Ls, Lb,is_odd, v_edges, in_edges)
%  Reconstructs the frequency response "HH" from the basis 
%  coefficients "at". 
%

global DES_CRMZ WT_CRMZ GRID_CRMZ TGRID_CRMZ IFGRD_CRMZ

J  = 1i;  % For possible use when evaluating HH_str
a  = at(:);
h  = eval(h_str);
hc = crmz_rotate(zeropad(h,Lfft-L), -Ls);
eval(HH_str);
W  = 2*pi*v_edges*([0:(Lf-1)]+(~is_odd)*0.5);
Mb = eval(M_str);
HH(in_edges) = Mb * a;

%========================================================

function  Ptmin = adesc_minpolytope(P, TRACE);
%ADESC_MINPOLYTOPE
% Finds the nearest point Ptmin (smallest norm)
% in the convex hull of the set of points P1,...,PM
% given by the columns of the N x M matrix P.
%
% NOTE: the input matrix P is real-valued
%
% Implementation of a method by P. Wolfe presented in 
% "Mathematical Programming", vol. 11, 1976, pp. 128-149. 
%
[N,M] = size(P);
if (M==1)
  Ptmin = P;
  return
end

Z1 = 1e-10;     % could be Z1 = 1e-12
Z2 = 1e-10;
Z3 = 1e-10;

P_norm = sum(abs(P).^2);
[pmn,J] = min(P_norm);
S = J;
w = 1;
no_stp = 1;
while (no_stp)
  X = P(:,S)*w;
  [pmn,J] = min(X'*P);
  PS_norm = max(sum(abs(P(:,S)).^2));
  PJ_norm = P(:,J)'*P(:,J);
  no_stp = (X'*P(:,J) <= (X'*X - Z1*max([PJ_norm;PS_norm])));
 if (no_stp)
    I = find(~(S-J));
    if (length(I) > 0)
      no_stp = 0;
      if TRACE, disp('Temporary disaster while computing the minimum polytope'); end
    end
 end
 if (no_stp)
  S = [S;J];
  w = [w;0];
  flg = 1;
  while (flg)
    e = ones(size(S));
    A = ones(length(S)) + P(:,S)'*P(:,S);
    u = A \ e;
    v = u./(e'*u);
    I = find(v <= Z2);
    if ~(length(I))
      w = v;
      flg = 0;
    else
      I = find((w-v) > Z3);
      t = w(I)./(w(I)-v(I));
      theta = min([1;1-min(t)]);
      w = theta*w + (1-theta)*v;
      I = find(w <= Z2);
      if (length(I) > 0)
        w(I) = zeros(length(I),1);
        w(I(1)) = [];
        S(I(1)) = [];
      end
    end
  end
 end
end
Ptmin = X;

%========================================================

function z_out = zeropad(x,L)
%ZEROPAD ZEROPAD(X,L) will append L zeros to each column of X.
%
[M,N] = size(x);
if M==1,
   z_out = [x zeros(1,L)];
else
   z_out = [x; zeros(L,N)];
end

%========================================================

function rotated = crmz_rotate(x,num_places)
%CRMZ_ROTATE     circular shift of columns in a matrix
%    crmz_rotate(V,r)
%        circularly shifts the elements in the columns of V
%        by r places right (r>0); or r places left (r<0).
%           (Right is down; left is up.)
%        If the input is a row or column vector, the shift is
%        performed on the vector.
%        If the input is a signal matrix, each column is shifted
%
[M,N] = size(x);
if M > 1              % ------- rotate columns ----------------
   num_places = mod(num_places,M);  % make num_places in range [0,M-1]
   rotated = [ x(M-num_places+1:M,:); x(1:M-num_places,:) ];
elseif N > 1          % ------- rotate row vector -------------
   num_places = mod(num_places,N);  % make num_places in range [0,N-1]
   rotated = [ x(N-num_places+1:N) x(1:N-num_places) ];
end

%========================================================