annotate BP/l1qc_newton.m @ 1:2a2abf5092f8

Organized into test file and lib files Changed sklearn cholesky function to behave as the others: tol does not override number of atoms, but the two conditions work together
author nikcleju
date Thu, 20 Oct 2011 21:06:06 +0000
parents 8346c92b698f
children
rev   line source
nikcleju@0 1 % l1qc_newton.m
nikcleju@0 2 %
nikcleju@0 3 % Newton algorithm for log-barrier subproblems for l1 minimization
nikcleju@0 4 % with quadratic constraints.
nikcleju@0 5 %
nikcleju@0 6 % Usage:
nikcleju@0 7 % [xp,up,niter] = l1qc_newton(x0, u0, A, At, b, epsilon, tau,
nikcleju@0 8 % newtontol, newtonmaxiter, cgtol, cgmaxiter)
nikcleju@0 9 %
nikcleju@0 10 % x0,u0 - starting points
nikcleju@0 11 %
nikcleju@0 12 % A - Either a handle to a function that takes a N vector and returns a K
nikcleju@0 13 % vector , or a KxN matrix. If A is a function handle, the algorithm
nikcleju@0 14 % operates in "largescale" mode, solving the Newton systems via the
nikcleju@0 15 % Conjugate Gradients algorithm.
nikcleju@0 16 %
nikcleju@0 17 % At - Handle to a function that takes a K vector and returns an N vector.
nikcleju@0 18 % If A is a KxN matrix, At is ignored.
nikcleju@0 19 %
nikcleju@0 20 % b - Kx1 vector of observations.
nikcleju@0 21 %
nikcleju@0 22 % epsilon - scalar, constraint relaxation parameter
nikcleju@0 23 %
nikcleju@0 24 % tau - Log barrier parameter.
nikcleju@0 25 %
nikcleju@0 26 % newtontol - Terminate when the Newton decrement is <= newtontol.
nikcleju@0 27 % Default = 1e-3.
nikcleju@0 28 %
nikcleju@0 29 % newtonmaxiter - Maximum number of iterations.
nikcleju@0 30 % Default = 50.
nikcleju@0 31 %
nikcleju@0 32 % cgtol - Tolerance for Conjugate Gradients; ignored if A is a matrix.
nikcleju@0 33 % Default = 1e-8.
nikcleju@0 34 %
nikcleju@0 35 % cgmaxiter - Maximum number of iterations for Conjugate Gradients; ignored
nikcleju@0 36 % if A is a matrix.
nikcleju@0 37 % Default = 200.
nikcleju@0 38 %
nikcleju@0 39 % Written by: Justin Romberg, Caltech
nikcleju@0 40 % Email: jrom@acm.caltech.edu
nikcleju@0 41 % Created: October 2005
nikcleju@0 42 %
nikcleju@0 43
nikcleju@0 44
nikcleju@0 45 function [xp, up, niter] = l1qc_newton(x0, u0, A, At, b, epsilon, tau, newtontol, newtonmaxiter, cgtol, cgmaxiter)
nikcleju@0 46
nikcleju@0 47 % check if the matrix A is implicit or explicit
nikcleju@0 48 largescale = isa(A,'function_handle');
nikcleju@0 49
nikcleju@0 50 % line search parameters
nikcleju@0 51 alpha = 0.01;
nikcleju@0 52 beta = 0.5;
nikcleju@0 53
nikcleju@0 54 if (~largescale), AtA = A'*A; end
nikcleju@0 55
nikcleju@0 56 % initial point
nikcleju@0 57 x = x0;
nikcleju@0 58 u = u0;
nikcleju@0 59 if (largescale), r = A(x) - b; else r = A*x - b; end
nikcleju@0 60 fu1 = x - u;
nikcleju@0 61 fu2 = -x - u;
nikcleju@0 62 fe = 1/2*(r'*r - epsilon^2);
nikcleju@0 63 f = sum(u) - (1/tau)*(sum(log(-fu1)) + sum(log(-fu2)) + log(-fe));
nikcleju@0 64
nikcleju@0 65 niter = 0;
nikcleju@0 66 done = 0;
nikcleju@0 67 while (~done)
nikcleju@0 68
nikcleju@0 69 if (largescale), atr = At(r); else atr = A'*r; end
nikcleju@0 70
nikcleju@0 71 ntgz = 1./fu1 - 1./fu2 + 1/fe*atr;
nikcleju@0 72 ntgu = -tau - 1./fu1 - 1./fu2;
nikcleju@0 73 gradf = -(1/tau)*[ntgz; ntgu];
nikcleju@0 74
nikcleju@0 75 sig11 = 1./fu1.^2 + 1./fu2.^2;
nikcleju@0 76 sig12 = -1./fu1.^2 + 1./fu2.^2;
nikcleju@0 77 sigx = sig11 - sig12.^2./sig11;
nikcleju@0 78
nikcleju@0 79 w1p = ntgz - sig12./sig11.*ntgu;
nikcleju@0 80 if (largescale)
nikcleju@0 81 h11pfun = @(z) sigx.*z - (1/fe)*At(A(z)) + 1/fe^2*(atr'*z)*atr;
nikcleju@0 82 [dx, cgres, cgiter] = cgsolve(h11pfun, w1p, cgtol, cgmaxiter, 0);
nikcleju@0 83 if (cgres > 1/2)
nikcleju@0 84 disp('Cannot solve system. Returning previous iterate. (See Section 4 of notes for more information.)');
nikcleju@0 85 xp = x; up = u;
nikcleju@0 86 return
nikcleju@0 87 end
nikcleju@0 88 Adx = A(dx);
nikcleju@0 89 else
nikcleju@0 90 H11p = diag(sigx) - (1/fe)*AtA + (1/fe)^2*atr*atr';
nikcleju@0 91 opts.POSDEF = true; opts.SYM = true;
nikcleju@0 92 [dx,hcond] = linsolve(H11p, w1p, opts);
nikcleju@0 93 if (hcond < 1e-14)
nikcleju@0 94 disp('Matrix ill-conditioned. Returning previous iterate. (See Section 4 of notes for more information.)');
nikcleju@0 95 xp = x; up = u;
nikcleju@0 96 return
nikcleju@0 97 end
nikcleju@0 98 Adx = A*dx;
nikcleju@0 99 end
nikcleju@0 100 du = (1./sig11).*ntgu - (sig12./sig11).*dx;
nikcleju@0 101
nikcleju@0 102 % minimum step size that stays in the interior
nikcleju@0 103 ifu1 = find((dx-du) > 0); ifu2 = find((-dx-du) > 0);
nikcleju@0 104 aqe = Adx'*Adx; bqe = 2*r'*Adx; cqe = r'*r - epsilon^2;
nikcleju@0 105 smax = min(1,min([...
nikcleju@0 106 -fu1(ifu1)./(dx(ifu1)-du(ifu1)); -fu2(ifu2)./(-dx(ifu2)-du(ifu2)); ...
nikcleju@0 107 (-bqe+sqrt(bqe^2-4*aqe*cqe))/(2*aqe)
nikcleju@0 108 ]));
nikcleju@0 109 s = (0.99)*smax;
nikcleju@0 110
nikcleju@0 111 % backtracking line search
nikcleju@0 112 suffdec = 0;
nikcleju@0 113 backiter = 0;
nikcleju@0 114 while (~suffdec)
nikcleju@0 115 xp = x + s*dx; up = u + s*du; rp = r + s*Adx;
nikcleju@0 116 fu1p = xp - up; fu2p = -xp - up; fep = 1/2*(rp'*rp - epsilon^2);
nikcleju@0 117 fp = sum(up) - (1/tau)*(sum(log(-fu1p)) + sum(log(-fu2p)) + log(-fep));
nikcleju@0 118 flin = f + alpha*s*(gradf'*[dx; du]);
nikcleju@0 119 suffdec = (fp <= flin);
nikcleju@0 120 s = beta*s;
nikcleju@0 121 backiter = backiter + 1;
nikcleju@0 122 if (backiter > 32)
nikcleju@0 123 disp('Stuck on backtracking line search, returning previous iterate. (See Section 4 of notes for more information.)');
nikcleju@0 124 xp = x; up = u;
nikcleju@0 125 return
nikcleju@0 126 end
nikcleju@0 127 end
nikcleju@0 128
nikcleju@0 129 % set up for next iteration
nikcleju@0 130 x = xp; u = up; r = rp;
nikcleju@0 131 fu1 = fu1p; fu2 = fu2p; fe = fep; f = fp;
nikcleju@0 132
nikcleju@0 133 lambda2 = -(gradf'*[dx; du]);
nikcleju@0 134 stepsize = s*norm([dx; du]);
nikcleju@0 135 niter = niter + 1;
nikcleju@0 136 done = (lambda2/2 < newtontol) | (niter >= newtonmaxiter);
nikcleju@0 137
nikcleju@0 138 disp(sprintf('Newton iter = %d, Functional = %8.3f, Newton decrement = %8.3f, Stepsize = %8.3e', ...
nikcleju@0 139 niter, f, lambda2/2, stepsize));
nikcleju@0 140 if (largescale)
nikcleju@0 141 disp(sprintf(' CG Res = %8.3e, CG Iter = %d', cgres, cgiter));
nikcleju@0 142 else
nikcleju@0 143 disp(sprintf(' H11p condition number = %8.3e', hcond));
nikcleju@0 144 end
nikcleju@0 145
nikcleju@0 146 end
nikcleju@0 147
nikcleju@0 148
nikcleju@0 149
nikcleju@0 150