# Minimize sidelobe level of a uniform linear array via spectral factorization

    % "FIR Filter Design via Spectral Factorization and Convex Optimization" example
    % by S.-P. Wu, S. Boyd, and L. Vandenberghe
    % (figures are generated)
    %
    % Designs a uniform linear antenna array using spectral factorization method where:
    % - it minimizes sidelobe level outside the beamwidth of the pattern
    % - it has a constraint on the maximum ripple around unit gain in the beamwidth
    %
    %   minimize   max |y(theta)|                   for theta in the stop-beamwidth
    %       s.t.   1/delta <= |y(theta)| <= delta   for theta in the pass-beamwidth
    %
    % We first replace the look-angle variable theta with the "frequency"
    % variable omega, defined by omega = -2*pi*d/lambda*cos(theta).
    % This transforms the antenna pattern y(theta) into a standard discrete
    % Fourier transform of array weights w. Then we apply another change of
    % variables: we replace w with its auto-correlation coefficients r.
    %
    % Now the problem can be solved via spectral factorization approach:
    %
    %   minimize   max R(omega)                        for omega in the stopband
    %       s.t.   (1/delta)^2 <= R(omega) <= delta^2  for omega in the passband
    %              R(omega) >= 0                       for all omega
    %
    % where R(omega) is the squared magnitude of the y(theta) array response
    % (and the Fourier transform of the autocorrelation coefficients r).
    % Variables are coefficients r. delta is the allowed passband ripple.
    % This is a convex problem (can be formulated as an LP after sampling).
    %
    % Written for CVX by Almir Mutapcic 02/02/06

    %********************************************************************
    % problem specs: a uniform line array with inter-element spacing d
    %                antenna element locations are at d*[0:n-1]
    %                (the array pattern will be symmetric around origin)
    %********************************************************************
    n = 20;               % number of antenna elements
    lambda = 1;           % wavelength
    d = 0.45*lambda;      % inter-element spacing

    % passband direction from 30 to 60 degrees (30 degrees bandwidth)
    % transition band is 15 degrees on both sides of the passband
    theta_pass = 40;
    theta_stop = 50;

    % passband max allowed ripple
    ripple = 0.1; % in dB (+/- around the unit gain)

    %********************************************************************
    % construct optimization data
    %********************************************************************
    % number of frequency samples
    m = 30*n;

    % convert passband and stopband angles into omega frequencies
    omega_zero = -2*pi*d/lambda;
    omega_pass = -2*pi*d/lambda*cos(theta_pass*pi/180);
    omega_stop = -2*pi*d/lambda*cos(theta_stop*pi/180);
    omega_pi   = +2*pi*d/lambda;

    % build matrix A that relates R(omega) and r, ie, R = A*r
    omega = linspace(-pi,pi,m)';
    A = exp( -j*kron( omega, [-(n-1):n-1] ) );

    % passband constraint matrix
    indp = find( omega >= omega_zero & omega <= omega_pass );
    Ap   = A(indp,:);

    % stopband constraint matrix
    inds = find( omega >= omega_stop & omega <= omega_pi );
    As   = A(inds,:);

    %********************************************************************
    % formulate and solve the magnitude design problem
    %********************************************************************
    cvx_begin
      variable r(2*n-1,1) complex

      minimize( max( abs( As*r ) ) )
      subject to
        % passband constraints
        real( Ap*r ) >= (10^(-ripple/20))^2;
        real( Ap*r ) <= (10^(+ripple/20))^2;
        % nonnegative-real constraint for all frequencies (a bit redundant)
        real( A*r ) >= 0;
        % auto-correlation constraints
        r(n) == conj(r(n));
        r(n-1:-1:1) == conj(r(n+1:end));
    cvx_end

    % check if problem was successfully solved
    disp(['Problem is ' cvx_status])
    if ~strcmp(cvx_status,'Solved')
      return
    end

    % find antenna weights by computing the spectral factorization
    w = spectral_fact(r);

    % divided by 2 since this is in PSD domain
    min_sidelobe_level = 10*log10( cvx_optval );
    fprintf(1,'The minimum sidelobe level is %3.2f dB.\n\n',...
              min_sidelobe_level);

    %********************************************************************
    % plots
    %********************************************************************
    % build matrix G that relates y(theta) and w, ie, y = G*w
    theta = [-180:180]';
    G = kron( cos(pi*theta/180), [0:n-1] );
    G = exp(2*pi*i*d/lambda*G);
    y = G*w;

    % plot array pattern
    figure(1), clf
    ymin = -40; ymax = 5;
    plot([-180:180], 20*log10(abs(y)), ...
         [theta_stop theta_stop],[ymin ymax],'r--',...
         [-theta_pass -theta_pass],[ymin ymax],'r--',...
         [-theta_stop -theta_stop],[ymin ymax],'r--',...
         [theta_pass theta_pass],[ymin ymax],'r--');
    xlabel('look angle'), ylabel('mag y(theta) in dB');
    axis([-180 180 ymin ymax]);

    % polar plot
    figure(2), clf
    zerodB = 50;
    dBY = 20*log10(abs(y)) + zerodB;
    plot(dBY.*cos(pi*theta/180), dBY.*sin(pi*theta/180), '-');
    axis([-zerodB zerodB -zerodB zerodB]), axis('off'), axis('square')
    hold on
    plot(zerodB*cos(pi*theta/180),zerodB*sin(pi*theta/180),'k:') % 0 dB
    plot( (min_sidelobe_level + zerodB)*cos(pi*theta/180), ...
          (min_sidelobe_level + zerodB)*sin(pi*theta/180),'k:')  % min level
    text(-zerodB,0,'0 dB')
    text(-(min_sidelobe_level + zerodB),0,sprintf('%0.1f dB',min_sidelobe_level));
    plot([0 60*cos(theta_pass*pi/180)], [0 60*sin(theta_pass*pi/180)], 'k:')
    plot([0 60*cos(-theta_pass*pi/180)],[0 60*sin(-theta_pass*pi/180)],'k:')
    plot([0 60*cos(theta_stop*pi/180)], [0 60*sin(theta_stop*pi/180)], 'k:')
    plot([0 60*cos(-theta_stop*pi/180)],[0 60*sin(-theta_stop*pi/180)],'k:')
    hold off

    Calling SeDuMi: 2096 variables (39 free), 2056 equality constraints
    ------------------------------------------------------------------------
    SeDuMi 1.1 by AdvOL, 2005 and Jos F. Sturm, 1998, 2001-2003.
    Alg = 2: xz-corrector, Adaptive Step-Differentiation, theta = 0.250, beta = 0.500
    Split 39 free variables
    eqs m = 2056, order n = 1693, dim = 2136, blocks = 444
    nnz(A) = 2056 + 91780, nnz(ADA) = 4708, nnz(L) = 3382
    Handling 79 + 1 dense columns.
     it :     b*y       gap    delta  rate   t/tP*  t/tD*   feas cg cg  prec
      0 :            2.36E-002 0.000
      1 :  2.76E+000 4.62E-003 0.000 0.1960 0.9000 0.9000   3.21  1  1  5.5E-001
      2 :  1.00E+000 1.36E-003 0.000 0.2940 0.9000 0.9000   1.82  1  1  1.0E-001
      3 :  3.95E-001 6.50E-004 0.000 0.4792 0.9000 0.9000   3.21  1  1  2.4E-002
      4 :  1.21E-001 3.41E-004 0.000 0.5237 0.9000 0.9000   3.12  1  1  6.9E-003
      5 :  2.90E-002 1.43E-004 0.000 0.4205 0.9000 0.9000   2.50  1  1  2.2E-003
      6 :  1.03E-002 5.15E-005 0.000 0.3596 0.9000 0.9000   1.47  1  1  1.5E-003
      7 :  7.31E-003 3.53E-005 0.000 0.6847 0.9000 0.9000   1.15  1  1  1.3E-003
      8 :  5.53E-003 2.45E-005 0.000 0.6952 0.9000 0.9000   1.10  1  1  1.2E-003
      9 :  4.50E-003 1.68E-005 0.000 0.6857 0.9000 0.9000   1.06  1  1  9.9E-004
     10 :  4.09E-003 1.22E-005 0.000 0.7244 0.9000 0.9000   1.01  1  1  8.1E-004
     11 :  3.79E-003 7.78E-006 0.000 0.6388 0.9008 0.9000   0.99  1  1  5.8E-004
     12 :  3.79E-003 9.48E-007 0.000 0.1219 0.9000 0.0000   1.01  1  1  4.5E-005
     13 :  3.67E-003 4.13E-007 0.000 0.4350 0.9432 0.9000   0.99  1  1  2.3E-005
     14 :  3.50E-003 9.81E-008 0.000 0.2379 0.9058 0.9000   1.00  1  1  5.6E-006
     15 :  3.44E-003 1.55E-008 0.000 0.1584 0.9000 0.9086   1.00  1  1  8.6E-007
     16 :  3.43E-003 2.64E-009 0.000 0.1701 0.9000 0.9131   1.00  2  2  1.3E-007
     17 :  3.43E-003 6.45E-010 0.000 0.2440 0.9000 0.7986   1.00  2  2  3.2E-008
     18 :  3.43E-003 2.72E-011 0.000 0.0422 0.9903 0.9900   1.00  2  2  1.6E-009

    iter seconds digits       c*x               b*y
     18      8.5   Inf  3.4281493042e-003  3.4281554908e-003
    |Ax-b| =  5.2e-009, [Ay-c]_+ =  8.6E-010, |x|= 9.3e+000, |y|= 7.8e-001

    Detailed timing (sec)
       Pre          IPM          Post
    4.106E-001    8.472E+000    3.004E-002
    Max-norms: ||b||=1.023293e+000, ||c|| = 1,
    Cholesky |add|=0, |skip| = 0, ||L.L|| = 1.
    ------------------------------------------------------------------------
    Status: Solved
    Optimal value (cvx_optval): +0.00342815
    Problem is Solved
    The minimum sidelobe level is -24.65 dB.