```% "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*omega(:)*[1-n:n-1] );

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

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

%********************************************************************
% formulate and solve the magnitude design problem
%********************************************************************
cvx_begin
variable r(2*n-1,1) complex
% minimize stopband attenuation
minimize( max( real( As*r ) ) )
subject to
% passband ripple constraints
(10^(-ripple/20))^2 <= real( Ap*r ) <= (10^(+ripple/20))^2;
% nonnegative-real constraint for all frequencies
% a bit redundant: the passband frequencies are already constrained
real( A*r ) >= 0;
% auto-correlation symmetry constraints
imag(r(n)) == 0;
r(n-1:-1:1) == conj(r(n+1:end));
cvx_end

% check if problem was successfully solved
if ~strfind(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 SDPT3 4.0: 1171 variables, 40 equality constraints
For improved efficiency, SDPT3 is solving the dual problem.
------------------------------------------------------------

num. of constraints = 40
dim. of linear var  = 1171
*******************************************************************
SDPT3: Infeasible path-following algorithms
*******************************************************************
version  predcorr  gam  expon  scale_data
NT      1      0.000   1        0
it pstep dstep pinfeas dinfeas  gap      prim-obj      dual-obj    cputime
-------------------------------------------------------------------
0|0.000|0.000|1.0e+04|1.4e+02|2.0e+06| 1.008655e+02  0.000000e+00| 0:0:00| chol  1  1
1|0.875|0.762|1.3e+03|3.4e+01|3.1e+05| 1.707706e+03 -8.318726e+01| 0:0:00| chol  1  1
2|0.763|0.812|3.0e+02|6.5e+00|8.5e+04| 2.032831e+03 -1.284834e+02| 0:0:00| chol  1  1
3|0.879|0.798|3.6e+01|1.3e+00|1.4e+04| 1.364175e+03 -1.494646e+02| 0:0:00| chol  1  1
4|0.662|0.834|1.2e+01|2.3e-01|5.5e+03| 8.085569e+02 -2.002852e+02| 0:0:00| chol  1  1
5|0.934|1.000|8.1e-01|2.4e-03|6.0e+02| 1.565080e+02 -1.927015e+02| 0:0:00| chol  2  2
6|0.903|0.981|7.9e-02|2.8e-04|1.1e+02| 2.233473e+01 -7.632890e+01| 0:0:00| chol  2  2
7|0.862|1.000|1.1e-02|1.6e-02|6.9e+01| 1.487219e+01 -5.065246e+01| 0:0:00| chol  1  1
8|0.930|0.941|7.7e-04|3.1e-03|4.5e+00| 1.679599e+00 -2.798362e+00| 0:0:00| chol  1  1
9|0.473|0.949|4.0e-04|3.1e-04|2.4e+00| 9.986219e-01 -1.431647e+00| 0:0:00| chol  1  1
10|0.872|1.000|5.2e-05|8.1e-05|1.2e+00| 2.761667e-01 -8.786424e-01| 0:0:00| chol  1  1
11|0.951|0.988|2.5e-06|1.1e-05|1.9e-01| 6.218113e-02 -1.316351e-01| 0:0:00| chol  1  1
12|0.662|1.000|8.5e-07|5.0e-07|8.7e-02| 2.910117e-02 -5.759656e-02| 0:0:00| chol  1  1
13|0.847|0.705|1.3e-07|3.2e-07|4.4e-02| 8.825548e-03 -3.492830e-02| 0:0:00| chol  1  1
14|1.000|0.570|5.6e-14|1.6e-07|2.9e-02| 4.098110e-03 -2.443245e-02| 0:0:00| chol  1  1
15|1.000|1.000|4.2e-14|1.2e-12|1.4e-02| 2.591040e-03 -1.164488e-02| 0:0:00| chol  1  1
16|1.000|0.990|3.6e-14|1.0e-12|6.3e-03| 3.772454e-04 -5.904202e-03| 0:0:00| chol  1  1
17|0.404|1.000|7.4e-14|1.0e-12|4.7e-03|-4.331405e-04 -5.174142e-03| 0:0:00| chol  1  1
18|0.807|1.000|9.9e-14|1.0e-12|2.4e-03|-1.819613e-03 -4.250844e-03| 0:0:00| chol  1  1
19|0.980|0.981|6.3e-13|1.0e-12|7.3e-04|-2.854651e-03 -3.581003e-03| 0:0:00| chol  1  1
20|0.572|0.971|3.7e-12|1.0e-12|3.6e-04|-3.103962e-03 -3.459133e-03| 0:0:00| chol  1  1
21|0.827|0.950|7.7e-13|1.1e-12|9.7e-05|-3.339091e-03 -3.436323e-03| 0:0:00| chol  1  1
22|0.970|0.894|6.4e-12|1.1e-12|9.6e-06|-3.419536e-03 -3.429101e-03| 0:0:00| chol  1  1
23|0.866|0.886|2.5e-12|1.4e-12|1.8e-06|-3.426509e-03 -3.428273e-03| 0:0:00| chol  1  1
24|0.979|0.983|1.5e-12|1.0e-12|8.9e-08|-3.428062e-03 -3.428151e-03| 0:0:00| chol  1  1
25|0.992|0.993|1.3e-12|1.0e-12|1.8e-09|-3.428145e-03 -3.428147e-03| 0:0:00|
stop: max(relative gap, infeasibilities) < 1.49e-08
-------------------------------------------------------------------
number of iterations   = 25
primal objective value = -3.42814510e-03
dual   objective value = -3.42814686e-03
gap := trace(XZ)       = 1.76e-09
relative gap           = 1.74e-09
actual relative gap    = 1.74e-09
rel. primal infeas (scaled problem)   = 1.30e-12
rel. dual     "        "       "      = 1.01e-12
rel. primal infeas (unscaled problem) = 0.00e+00
rel. dual     "        "       "      = 0.00e+00
norm(X), norm(y), norm(Z) = 7.2e-01, 2.9e-01, 9.2e+00
norm(A), norm(b), norm(C) = 3.0e+02, 2.0e+00, 1.2e+01
Total CPU time (secs)  = 0.31
CPU time per iteration = 0.01
termination code       =  0
DIMACS: 1.3e-12  0.0e+00  6.1e-12  0.0e+00  1.7e-09  1.7e-09
-------------------------------------------------------------------

------------------------------------------------------------
Status: Solved
Optimal value (cvx_optval): +0.00342815

The minimum sidelobe level is -24.65 dB.

```