annotate BP/l1qc.py @ 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
nikcleju@0 2 import numpy as np
nikcleju@0 3 import scipy.linalg
nikcleju@0 4 import math
nikcleju@0 5
nikcleju@0 6
nikcleju@0 7 #function [x, res, iter] = cgsolve(A, b, tol, maxiter, verbose)
nikcleju@0 8 def cgsolve(A, b, tol, maxiter, verbose=1):
nikcleju@0 9 # Solve a symmetric positive definite system Ax = b via conjugate gradients.
nikcleju@0 10 #
nikcleju@0 11 # Usage: [x, res, iter] = cgsolve(A, b, tol, maxiter, verbose)
nikcleju@0 12 #
nikcleju@0 13 # A - Either an NxN matrix, or a function handle.
nikcleju@0 14 #
nikcleju@0 15 # b - N vector
nikcleju@0 16 #
nikcleju@0 17 # tol - Desired precision. Algorithm terminates when
nikcleju@0 18 # norm(Ax-b)/norm(b) < tol .
nikcleju@0 19 #
nikcleju@0 20 # maxiter - Maximum number of iterations.
nikcleju@0 21 #
nikcleju@0 22 # verbose - If 0, do not print out progress messages.
nikcleju@0 23 # If and integer greater than 0, print out progress every 'verbose' iters.
nikcleju@0 24 #
nikcleju@0 25 # Written by: Justin Romberg, Caltech
nikcleju@0 26 # Email: jrom@acm.caltech.edu
nikcleju@0 27 # Created: October 2005
nikcleju@0 28 #
nikcleju@0 29
nikcleju@0 30 #---------------------
nikcleju@0 31 # Original Matab code:
nikcleju@0 32 #
nikcleju@0 33 #if (nargin < 5), verbose = 1; end
nikcleju@0 34 #
nikcleju@0 35 #implicit = isa(A,'function_handle');
nikcleju@0 36 #
nikcleju@0 37 #x = zeros(length(b),1);
nikcleju@0 38 #r = b;
nikcleju@0 39 #d = r;
nikcleju@0 40 #delta = r'*r;
nikcleju@0 41 #delta0 = b'*b;
nikcleju@0 42 #numiter = 0;
nikcleju@0 43 #bestx = x;
nikcleju@0 44 #bestres = sqrt(delta/delta0);
nikcleju@0 45 #while ((numiter < maxiter) && (delta > tol^2*delta0))
nikcleju@0 46 #
nikcleju@0 47 # # q = A*d
nikcleju@0 48 # if (implicit), q = A(d); else q = A*d; end
nikcleju@0 49 #
nikcleju@0 50 # alpha = delta/(d'*q);
nikcleju@0 51 # x = x + alpha*d;
nikcleju@0 52 #
nikcleju@0 53 # if (mod(numiter+1,50) == 0)
nikcleju@0 54 # # r = b - Aux*x
nikcleju@0 55 # if (implicit), r = b - A(x); else r = b - A*x; end
nikcleju@0 56 # else
nikcleju@0 57 # r = r - alpha*q;
nikcleju@0 58 # end
nikcleju@0 59 #
nikcleju@0 60 # deltaold = delta;
nikcleju@0 61 # delta = r'*r;
nikcleju@0 62 # beta = delta/deltaold;
nikcleju@0 63 # d = r + beta*d;
nikcleju@0 64 # numiter = numiter + 1;
nikcleju@0 65 # if (sqrt(delta/delta0) < bestres)
nikcleju@0 66 # bestx = x;
nikcleju@0 67 # bestres = sqrt(delta/delta0);
nikcleju@0 68 # end
nikcleju@0 69 #
nikcleju@0 70 # if ((verbose) && (mod(numiter,verbose)==0))
nikcleju@0 71 # disp(sprintf('cg: Iter = #d, Best residual = #8.3e, Current residual = #8.3e', ...
nikcleju@0 72 # numiter, bestres, sqrt(delta/delta0)));
nikcleju@0 73 # end
nikcleju@0 74 #
nikcleju@0 75 #end
nikcleju@0 76 #
nikcleju@0 77 #if (verbose)
nikcleju@0 78 # disp(sprintf('cg: Iterations = #d, best residual = #14.8e', numiter, bestres));
nikcleju@0 79 #end
nikcleju@0 80 #x = bestx;
nikcleju@0 81 #res = bestres;
nikcleju@0 82 #iter = numiter;
nikcleju@0 83
nikcleju@0 84 # End of original Matab code
nikcleju@0 85 #----------------------------
nikcleju@0 86
nikcleju@0 87 #if (nargin < 5), verbose = 1; end
nikcleju@0 88 # Optional argument
nikcleju@0 89
nikcleju@0 90 #implicit = isa(A,'function_handle');
nikcleju@0 91 if hasattr(A, '__call__'):
nikcleju@0 92 implicit = True
nikcleju@0 93 else:
nikcleju@0 94 implicit = False
nikcleju@0 95
nikcleju@0 96 x = np.zeros(b.size)
nikcleju@0 97 r = b.copy()
nikcleju@0 98 d = r.copy()
nikcleju@0 99 delta = np.vdot(r,r)
nikcleju@0 100 delta0 = np.vdot(b,b)
nikcleju@0 101 numiter = 0
nikcleju@0 102 bestx = x.copy()
nikcleju@0 103 bestres = math.sqrt(delta/delta0)
nikcleju@0 104 while (numiter < maxiter) and (delta > tol**2*delta0):
nikcleju@0 105
nikcleju@0 106 # q = A*d
nikcleju@0 107 #if (implicit), q = A(d); else q = A*d; end
nikcleju@0 108 if implicit:
nikcleju@0 109 q = A(d)
nikcleju@0 110 else:
nikcleju@0 111 q = np.dot(A,d)
nikcleju@0 112
nikcleju@0 113 alpha = delta/np.vdot(d,q)
nikcleju@0 114 x = x + alpha*d
nikcleju@0 115
nikcleju@0 116 if divmod(numiter+1,50)[1] == 0:
nikcleju@0 117 # r = b - Aux*x
nikcleju@0 118 #if (implicit), r = b - A(x); else r = b - A*x; end
nikcleju@0 119 if implicit:
nikcleju@0 120 r = b - A(x)
nikcleju@0 121 else:
nikcleju@0 122 r = b - np.dot(A,x)
nikcleju@0 123 else:
nikcleju@0 124 r = r - alpha*q
nikcleju@0 125 #end
nikcleju@0 126
nikcleju@0 127 deltaold = delta;
nikcleju@0 128 delta = np.vdot(r,r)
nikcleju@0 129 beta = delta/deltaold;
nikcleju@0 130 d = r + beta*d
nikcleju@0 131 numiter = numiter + 1
nikcleju@0 132 if (math.sqrt(delta/delta0) < bestres):
nikcleju@0 133 bestx = x.copy()
nikcleju@0 134 bestres = math.sqrt(delta/delta0)
nikcleju@0 135 #end
nikcleju@0 136
nikcleju@0 137 if ((verbose) and (divmod(numiter,verbose)[1]==0)):
nikcleju@0 138 #disp(sprintf('cg: Iter = #d, Best residual = #8.3e, Current residual = #8.3e', ...
nikcleju@0 139 # numiter, bestres, sqrt(delta/delta0)));
nikcleju@0 140 print 'cg: Iter = ',numiter,', Best residual = ',bestres,', Current residual = ',math.sqrt(delta/delta0)
nikcleju@0 141 #end
nikcleju@0 142
nikcleju@0 143 #end
nikcleju@0 144
nikcleju@0 145 if (verbose):
nikcleju@0 146 #disp(sprintf('cg: Iterations = #d, best residual = #14.8e', numiter, bestres));
nikcleju@0 147 print 'cg: Iterations = ',numiter,', best residual = ',bestres
nikcleju@0 148 #end
nikcleju@0 149 x = bestx.copy()
nikcleju@0 150 res = bestres
nikcleju@0 151 iter = numiter
nikcleju@0 152
nikcleju@0 153 return x,res,iter
nikcleju@0 154
nikcleju@0 155
nikcleju@0 156
nikcleju@0 157 #function [xp, up, niter] = l1qc_newton(x0, u0, A, At, b, epsilon, tau, newtontol, newtonmaxiter, cgtol, cgmaxiter)
nikcleju@0 158 def l1qc_newton(x0, u0, A, At, b, epsilon, tau, newtontol, newtonmaxiter, cgtol, cgmaxiter):
nikcleju@0 159 # Newton algorithm for log-barrier subproblems for l1 minimization
nikcleju@0 160 # with quadratic constraints.
nikcleju@0 161 #
nikcleju@0 162 # Usage:
nikcleju@0 163 # [xp,up,niter] = l1qc_newton(x0, u0, A, At, b, epsilon, tau,
nikcleju@0 164 # newtontol, newtonmaxiter, cgtol, cgmaxiter)
nikcleju@0 165 #
nikcleju@0 166 # x0,u0 - starting points
nikcleju@0 167 #
nikcleju@0 168 # A - Either a handle to a function that takes a N vector and returns a K
nikcleju@0 169 # vector , or a KxN matrix. If A is a function handle, the algorithm
nikcleju@0 170 # operates in "largescale" mode, solving the Newton systems via the
nikcleju@0 171 # Conjugate Gradients algorithm.
nikcleju@0 172 #
nikcleju@0 173 # At - Handle to a function that takes a K vector and returns an N vector.
nikcleju@0 174 # If A is a KxN matrix, At is ignored.
nikcleju@0 175 #
nikcleju@0 176 # b - Kx1 vector of observations.
nikcleju@0 177 #
nikcleju@0 178 # epsilon - scalar, constraint relaxation parameter
nikcleju@0 179 #
nikcleju@0 180 # tau - Log barrier parameter.
nikcleju@0 181 #
nikcleju@0 182 # newtontol - Terminate when the Newton decrement is <= newtontol.
nikcleju@0 183 # Default = 1e-3.
nikcleju@0 184 #
nikcleju@0 185 # newtonmaxiter - Maximum number of iterations.
nikcleju@0 186 # Default = 50.
nikcleju@0 187 #
nikcleju@0 188 # cgtol - Tolerance for Conjugate Gradients; ignored if A is a matrix.
nikcleju@0 189 # Default = 1e-8.
nikcleju@0 190 #
nikcleju@0 191 # cgmaxiter - Maximum number of iterations for Conjugate Gradients; ignored
nikcleju@0 192 # if A is a matrix.
nikcleju@0 193 # Default = 200.
nikcleju@0 194 #
nikcleju@0 195 # Written by: Justin Romberg, Caltech
nikcleju@0 196 # Email: jrom@acm.caltech.edu
nikcleju@0 197 # Created: October 2005
nikcleju@0 198 #
nikcleju@0 199
nikcleju@0 200 #---------------------
nikcleju@0 201 # Original Matab code:
nikcleju@0 202
nikcleju@0 203 ## check if the matrix A is implicit or explicit
nikcleju@0 204 #largescale = isa(A,'function_handle');
nikcleju@0 205 #
nikcleju@0 206 ## line search parameters
nikcleju@0 207 #alpha = 0.01;
nikcleju@0 208 #beta = 0.5;
nikcleju@0 209 #
nikcleju@0 210 #if (~largescale), AtA = A'*A; end
nikcleju@0 211 #
nikcleju@0 212 ## initial point
nikcleju@0 213 #x = x0;
nikcleju@0 214 #u = u0;
nikcleju@0 215 #if (largescale), r = A(x) - b; else r = A*x - b; end
nikcleju@0 216 #fu1 = x - u;
nikcleju@0 217 #fu2 = -x - u;
nikcleju@0 218 #fe = 1/2*(r'*r - epsilon^2);
nikcleju@0 219 #f = sum(u) - (1/tau)*(sum(log(-fu1)) + sum(log(-fu2)) + log(-fe));
nikcleju@0 220 #
nikcleju@0 221 #niter = 0;
nikcleju@0 222 #done = 0;
nikcleju@0 223 #while (~done)
nikcleju@0 224 #
nikcleju@0 225 # if (largescale), atr = At(r); else atr = A'*r; end
nikcleju@0 226 #
nikcleju@0 227 # ntgz = 1./fu1 - 1./fu2 + 1/fe*atr;
nikcleju@0 228 # ntgu = -tau - 1./fu1 - 1./fu2;
nikcleju@0 229 # gradf = -(1/tau)*[ntgz; ntgu];
nikcleju@0 230 #
nikcleju@0 231 # sig11 = 1./fu1.^2 + 1./fu2.^2;
nikcleju@0 232 # sig12 = -1./fu1.^2 + 1./fu2.^2;
nikcleju@0 233 # sigx = sig11 - sig12.^2./sig11;
nikcleju@0 234 #
nikcleju@0 235 # w1p = ntgz - sig12./sig11.*ntgu;
nikcleju@0 236 # if (largescale)
nikcleju@0 237 # h11pfun = @(z) sigx.*z - (1/fe)*At(A(z)) + 1/fe^2*(atr'*z)*atr;
nikcleju@0 238 # [dx, cgres, cgiter] = cgsolve(h11pfun, w1p, cgtol, cgmaxiter, 0);
nikcleju@0 239 # if (cgres > 1/2)
nikcleju@0 240 # disp('Cannot solve system. Returning previous iterate. (See Section 4 of notes for more information.)');
nikcleju@0 241 # xp = x; up = u;
nikcleju@0 242 # return
nikcleju@0 243 # end
nikcleju@0 244 # Adx = A(dx);
nikcleju@0 245 # else
nikcleju@0 246 # H11p = diag(sigx) - (1/fe)*AtA + (1/fe)^2*atr*atr';
nikcleju@0 247 # opts.POSDEF = true; opts.SYM = true;
nikcleju@0 248 # [dx,hcond] = linsolve(H11p, w1p, opts);
nikcleju@0 249 # if (hcond < 1e-14)
nikcleju@0 250 # disp('Matrix ill-conditioned. Returning previous iterate. (See Section 4 of notes for more information.)');
nikcleju@0 251 # xp = x; up = u;
nikcleju@0 252 # return
nikcleju@0 253 # end
nikcleju@0 254 # Adx = A*dx;
nikcleju@0 255 # end
nikcleju@0 256 # du = (1./sig11).*ntgu - (sig12./sig11).*dx;
nikcleju@0 257 #
nikcleju@0 258 # # minimum step size that stays in the interior
nikcleju@0 259 # ifu1 = find((dx-du) > 0); ifu2 = find((-dx-du) > 0);
nikcleju@0 260 # aqe = Adx'*Adx; bqe = 2*r'*Adx; cqe = r'*r - epsilon^2;
nikcleju@0 261 # smax = min(1,min([...
nikcleju@0 262 # -fu1(ifu1)./(dx(ifu1)-du(ifu1)); -fu2(ifu2)./(-dx(ifu2)-du(ifu2)); ...
nikcleju@0 263 # (-bqe+sqrt(bqe^2-4*aqe*cqe))/(2*aqe)
nikcleju@0 264 # ]));
nikcleju@0 265 # s = (0.99)*smax;
nikcleju@0 266 #
nikcleju@0 267 # # backtracking line search
nikcleju@0 268 # suffdec = 0;
nikcleju@0 269 # backiter = 0;
nikcleju@0 270 # while (~suffdec)
nikcleju@0 271 # xp = x + s*dx; up = u + s*du; rp = r + s*Adx;
nikcleju@0 272 # fu1p = xp - up; fu2p = -xp - up; fep = 1/2*(rp'*rp - epsilon^2);
nikcleju@0 273 # fp = sum(up) - (1/tau)*(sum(log(-fu1p)) + sum(log(-fu2p)) + log(-fep));
nikcleju@0 274 # flin = f + alpha*s*(gradf'*[dx; du]);
nikcleju@0 275 # suffdec = (fp <= flin);
nikcleju@0 276 # s = beta*s;
nikcleju@0 277 # backiter = backiter + 1;
nikcleju@0 278 # if (backiter > 32)
nikcleju@0 279 # disp('Stuck on backtracking line search, returning previous iterate. (See Section 4 of notes for more information.)');
nikcleju@0 280 # xp = x; up = u;
nikcleju@0 281 # return
nikcleju@0 282 # end
nikcleju@0 283 # end
nikcleju@0 284 #
nikcleju@0 285 # # set up for next iteration
nikcleju@0 286 # x = xp; u = up; r = rp;
nikcleju@0 287 # fu1 = fu1p; fu2 = fu2p; fe = fep; f = fp;
nikcleju@0 288 #
nikcleju@0 289 # lambda2 = -(gradf'*[dx; du]);
nikcleju@0 290 # stepsize = s*norm([dx; du]);
nikcleju@0 291 # niter = niter + 1;
nikcleju@0 292 # done = (lambda2/2 < newtontol) | (niter >= newtonmaxiter);
nikcleju@0 293 #
nikcleju@0 294 # disp(sprintf('Newton iter = #d, Functional = #8.3f, Newton decrement = #8.3f, Stepsize = #8.3e', ...
nikcleju@0 295 # niter, f, lambda2/2, stepsize));
nikcleju@0 296 # if (largescale)
nikcleju@0 297 # disp(sprintf(' CG Res = #8.3e, CG Iter = #d', cgres, cgiter));
nikcleju@0 298 # else
nikcleju@0 299 # disp(sprintf(' H11p condition number = #8.3e', hcond));
nikcleju@0 300 # end
nikcleju@0 301 #
nikcleju@0 302 #end
nikcleju@0 303
nikcleju@0 304 # End of original Matab code
nikcleju@0 305 #----------------------------
nikcleju@0 306
nikcleju@0 307 # check if the matrix A is implicit or explicit
nikcleju@0 308 #largescale = isa(A,'function_handle');
nikcleju@0 309 if hasattr(A, '__call__'):
nikcleju@0 310 largescale = True
nikcleju@0 311 else:
nikcleju@0 312 largescale = False
nikcleju@0 313
nikcleju@0 314 # line search parameters
nikcleju@0 315 alpha = 0.01
nikcleju@0 316 beta = 0.5
nikcleju@0 317
nikcleju@0 318 #if (~largescale), AtA = A'*A; end
nikcleju@0 319 if not largescale:
nikcleju@0 320 AtA = np.dot(A.T,A)
nikcleju@0 321
nikcleju@0 322 # initial point
nikcleju@0 323 x = x0.copy()
nikcleju@0 324 u = u0.copy()
nikcleju@0 325 #if (largescale), r = A(x) - b; else r = A*x - b; end
nikcleju@0 326 if largescale:
nikcleju@0 327 r = A(x) - b
nikcleju@0 328 else:
nikcleju@0 329 r = np.dot(A,x) - b
nikcleju@0 330
nikcleju@0 331 fu1 = x - u
nikcleju@0 332 fu2 = -x - u
nikcleju@0 333 fe = 1/2*(np.vdot(r,r) - epsilon**2)
nikcleju@0 334 f = u.sum() - (1/tau)*(np.log(-fu1).sum() + np.log(-fu2).sum() + math.log(-fe))
nikcleju@0 335
nikcleju@0 336 niter = 0
nikcleju@0 337 done = 0
nikcleju@0 338 while not done:
nikcleju@0 339
nikcleju@0 340 #if (largescale), atr = At(r); else atr = A'*r; end
nikcleju@0 341 if largescale:
nikcleju@0 342 atr = At(r)
nikcleju@0 343 else:
nikcleju@0 344 atr = np.dot(A.T,r)
nikcleju@0 345
nikcleju@0 346 #ntgz = 1./fu1 - 1./fu2 + 1/fe*atr;
nikcleju@0 347 ntgz = 1.0/fu1 - 1.0/fu2 + 1.0/fe*atr
nikcleju@0 348 #ntgu = -tau - 1./fu1 - 1./fu2;
nikcleju@0 349 ntgu = -tau - 1.0/fu1 - 1.0/fu2
nikcleju@0 350 #gradf = -(1/tau)*[ntgz; ntgu];
nikcleju@0 351 gradf = -(1.0/tau)*np.concatenate((ntgz, ntgu),0)
nikcleju@0 352
nikcleju@0 353 #sig11 = 1./fu1.^2 + 1./fu2.^2;
nikcleju@0 354 sig11 = 1.0/(fu1**2) + 1.0/(fu2**2)
nikcleju@0 355 #sig12 = -1./fu1.^2 + 1./fu2.^2;
nikcleju@0 356 sig12 = -1.0/(fu1**2) + 1.0/(fu2**2)
nikcleju@0 357 #sigx = sig11 - sig12.^2./sig11;
nikcleju@0 358 sigx = sig11 - (sig12**2)/sig11
nikcleju@0 359
nikcleju@0 360 #w1p = ntgz - sig12./sig11.*ntgu;
nikcleju@0 361 w1p = ntgz - sig12/sig11*ntgu
nikcleju@0 362 if largescale:
nikcleju@0 363 #h11pfun = @(z) sigx.*z - (1/fe)*At(A(z)) + 1/fe^2*(atr'*z)*atr;
nikcleju@0 364 h11pfun = lambda z: sigx*z - (1.0/fe)*At(A(z)) + 1.0/(fe**2)*np.dot(np.dot(atr.T,z),atr)
nikcleju@0 365 dx,cgres,cgiter = cgsolve(h11pfun, w1p, cgtol, cgmaxiter, 0)
nikcleju@0 366 if (cgres > 1/2):
nikcleju@0 367 print 'Cannot solve system. Returning previous iterate. (See Section 4 of notes for more information.)'
nikcleju@0 368 xp = x.copy()
nikcleju@0 369 up = u.copy()
nikcleju@0 370 return xp,up,niter
nikcleju@0 371 #end
nikcleju@0 372 Adx = A(dx)
nikcleju@0 373 else:
nikcleju@0 374 #H11p = diag(sigx) - (1/fe)*AtA + (1/fe)^2*atr*atr';
nikcleju@0 375 H11p = np.diag(sigx) - (1/fe)*AtA + (1/fe)**2*np.dot(atr,atr.T)
nikcleju@0 376 #opts.POSDEF = true; opts.SYM = true;
nikcleju@0 377 #[dx,hcond] = linsolve(H11p, w1p, opts);
nikcleju@0 378 #if (hcond < 1e-14)
nikcleju@0 379 # disp('Matrix ill-conditioned. Returning previous iterate. (See Section 4 of notes for more information.)');
nikcleju@0 380 # xp = x; up = u;
nikcleju@0 381 # return
nikcleju@0 382 #end
nikcleju@0 383 try:
nikcleju@0 384 dx = scipy.linalg.solve(H11p, w1p, sym_pos=True)
nikcleju@0 385 hcond = 1.0/scipy.linalg.cond(H11p)
nikcleju@0 386 except scipy.linalg.LinAlgError:
nikcleju@0 387 print 'Matrix ill-conditioned. Returning previous iterate. (See Section 4 of notes for more information.)'
nikcleju@0 388 xp = x.copy()
nikcleju@0 389 up = u.copy()
nikcleju@0 390 return xp,up,niter
nikcleju@0 391 if hcond < 1e-14:
nikcleju@0 392 print 'Matrix ill-conditioned. Returning previous iterate. (See Section 4 of notes for more information.)'
nikcleju@0 393 xp = x.copy()
nikcleju@0 394 up = u.copy()
nikcleju@0 395 return xp,up,niter
nikcleju@0 396
nikcleju@0 397 #Adx = A*dx;
nikcleju@0 398 Adx = np.dot(A,dx)
nikcleju@0 399 #end
nikcleju@0 400 #du = (1./sig11).*ntgu - (sig12./sig11).*dx;
nikcleju@0 401 du = (1.0/sig11)*ntgu - (sig12/sig11)*dx;
nikcleju@0 402
nikcleju@0 403 # minimum step size that stays in the interior
nikcleju@0 404 #ifu1 = find((dx-du) > 0); ifu2 = find((-dx-du) > 0);
nikcleju@0 405 ifu1 = np.nonzero((dx-du)>0)
nikcleju@0 406 ifu2 = np.nonzero((-dx-du)>0)
nikcleju@0 407 #aqe = Adx'*Adx; bqe = 2*r'*Adx; cqe = r'*r - epsilon^2;
nikcleju@0 408 aqe = np.dot(Adx.T,Adx)
nikcleju@0 409 bqe = 2*np.dot(r.T,Adx)
nikcleju@0 410 cqe = np.vdot(r,r) - epsilon**2
nikcleju@0 411 #smax = min(1,min([...
nikcleju@0 412 # -fu1(ifu1)./(dx(ifu1)-du(ifu1)); -fu2(ifu2)./(-dx(ifu2)-du(ifu2)); ...
nikcleju@0 413 # (-bqe+sqrt(bqe^2-4*aqe*cqe))/(2*aqe)
nikcleju@0 414 # ]));
nikcleju@0 415 smax = min(1,np.concatenate((-fu1[ifu1]/(dx[ifu1]-du[ifu1]) , -fu2[ifu2]/(-dx[ifu2]-du[ifu2]) , (-bqe + math.sqrt(bqe**2-4*aqe*cqe))/(2*aqe)),0).min())
nikcleju@0 416
nikcleju@0 417 s = (0.99)*smax
nikcleju@0 418
nikcleju@0 419 # backtracking line search
nikcleju@0 420 suffdec = 0
nikcleju@0 421 backiter = 0
nikcleju@0 422 while not suffdec:
nikcleju@0 423 #xp = x + s*dx; up = u + s*du; rp = r + s*Adx;
nikcleju@0 424 xp = x + s*dx
nikcleju@0 425 up = u + s*du
nikcleju@0 426 rp = r + s*Adx
nikcleju@0 427 #fu1p = xp - up; fu2p = -xp - up; fep = 1/2*(rp'*rp - epsilon^2);
nikcleju@0 428 fu1p = xp - up
nikcleju@0 429 fu2p = -xp - up
nikcleju@0 430 fep = 0.5*(np.vdot(r,r) - epsilon**2)
nikcleju@0 431 #fp = sum(up) - (1/tau)*(sum(log(-fu1p)) + sum(log(-fu2p)) + log(-fep));
nikcleju@0 432 fp = up.sum() - (1.0/tau)*(np.log(-fu1p).sum() + np.log(-fu2p).sum() + log(-fep))
nikcleju@0 433 #flin = f + alpha*s*(gradf'*[dx; du]);
nikcleju@0 434 flin = f + alpha*s*np.dot(gradf.T , np.concatenate((dx,du),0))
nikcleju@0 435 #suffdec = (fp <= flin);
nikcleju@0 436 if fp <= flin:
nikcleju@0 437 suffdec = True
nikcleju@0 438 else:
nikcleju@0 439 suffdec = False
nikcleju@0 440
nikcleju@0 441 s = beta*s
nikcleju@0 442 backiter = backiter + 1
nikcleju@0 443 if (backiter > 32):
nikcleju@0 444 print 'Stuck on backtracking line search, returning previous iterate. (See Section 4 of notes for more information.)'
nikcleju@0 445 xp = x.copy()
nikcleju@0 446 up = u.copy()
nikcleju@0 447 return xp,up,niter
nikcleju@0 448 #end
nikcleju@0 449 #end
nikcleju@0 450
nikcleju@0 451 # set up for next iteration
nikcleju@0 452 #x = xp; u = up; r = rp;
nikcleju@0 453 x = xp.copy()
nikcleju@0 454 u = up.copy()
nikcleju@0 455 r = rp.copy()
nikcleju@0 456 #fu1 = fu1p; fu2 = fu2p; fe = fep; f = fp;
nikcleju@0 457 fu1 = fu1p.copy()
nikcleju@0 458 fu2 = fu2p.copy()
nikcleju@0 459 fe = fep
nikcleju@0 460 f = fp
nikcleju@0 461
nikcleju@0 462 #lambda2 = -(gradf'*[dx; du]);
nikcleju@0 463 lambda2 = -np.dot(gradf , np.concatenate((dx,du),0))
nikcleju@0 464 #stepsize = s*norm([dx; du]);
nikcleju@0 465 stepsize = s * np.linalg.norm(np.concatenate((dx,du),0))
nikcleju@0 466 niter = niter + 1
nikcleju@0 467 #done = (lambda2/2 < newtontol) | (niter >= newtonmaxiter);
nikcleju@0 468 if lambda2/2.0 < newtontol or niter >= newtonmaxiter:
nikcleju@0 469 done = 1
nikcleju@0 470 else:
nikcleju@0 471 done = 0
nikcleju@0 472
nikcleju@0 473 #disp(sprintf('Newton iter = #d, Functional = #8.3f, Newton decrement = #8.3f, Stepsize = #8.3e', ...
nikcleju@0 474 print 'Newton iter = ',niter,', Functional = ',f,', Newton decrement = ',lambda2/2.0,', Stepsize = ',stepsize
nikcleju@0 475
nikcleju@0 476 if largescale:
nikcleju@0 477 print ' CG Res = ',cgres,', CG Iter = ',cgiter
nikcleju@0 478 else:
nikcleju@0 479 print ' H11p condition number = ',hcond
nikcleju@0 480 #end
nikcleju@0 481
nikcleju@0 482 #end
nikcleju@0 483 return xp,up,niter
nikcleju@0 484
nikcleju@0 485 #function xp = l1qc_logbarrier(x0, A, At, b, epsilon, lbtol, mu, cgtol, cgmaxiter)
nikcleju@0 486 def l1qc_logbarrier(x0, A, At, b, epsilon, lbtol=1e-3, mu=10, cgtol=1e-8, cgmaxiter=200):
nikcleju@0 487 # Solve quadratically constrained l1 minimization:
nikcleju@0 488 # min ||x||_1 s.t. ||Ax - b||_2 <= \epsilon
nikcleju@0 489 #
nikcleju@0 490 # Reformulate as the second-order cone program
nikcleju@0 491 # min_{x,u} sum(u) s.t. x - u <= 0,
nikcleju@0 492 # -x - u <= 0,
nikcleju@0 493 # 1/2(||Ax-b||^2 - \epsilon^2) <= 0
nikcleju@0 494 # and use a log barrier algorithm.
nikcleju@0 495 #
nikcleju@0 496 # Usage: xp = l1qc_logbarrier(x0, A, At, b, epsilon, lbtol, mu, cgtol, cgmaxiter)
nikcleju@0 497 #
nikcleju@0 498 # x0 - Nx1 vector, initial point.
nikcleju@0 499 #
nikcleju@0 500 # A - Either a handle to a function that takes a N vector and returns a K
nikcleju@0 501 # vector , or a KxN matrix. If A is a function handle, the algorithm
nikcleju@0 502 # operates in "largescale" mode, solving the Newton systems via the
nikcleju@0 503 # Conjugate Gradients algorithm.
nikcleju@0 504 #
nikcleju@0 505 # At - Handle to a function that takes a K vector and returns an N vector.
nikcleju@0 506 # If A is a KxN matrix, At is ignored.
nikcleju@0 507 #
nikcleju@0 508 # b - Kx1 vector of observations.
nikcleju@0 509 #
nikcleju@0 510 # epsilon - scalar, constraint relaxation parameter
nikcleju@0 511 #
nikcleju@0 512 # lbtol - The log barrier algorithm terminates when the duality gap <= lbtol.
nikcleju@0 513 # Also, the number of log barrier iterations is completely
nikcleju@0 514 # determined by lbtol.
nikcleju@0 515 # Default = 1e-3.
nikcleju@0 516 #
nikcleju@0 517 # mu - Factor by which to increase the barrier constant at each iteration.
nikcleju@0 518 # Default = 10.
nikcleju@0 519 #
nikcleju@0 520 # cgtol - Tolerance for Conjugate Gradients; ignored if A is a matrix.
nikcleju@0 521 # Default = 1e-8.
nikcleju@0 522 #
nikcleju@0 523 # cgmaxiter - Maximum number of iterations for Conjugate Gradients; ignored
nikcleju@0 524 # if A is a matrix.
nikcleju@0 525 # Default = 200.
nikcleju@0 526 #
nikcleju@0 527 # Written by: Justin Romberg, Caltech
nikcleju@0 528 # Email: jrom@acm.caltech.edu
nikcleju@0 529 # Created: October 2005
nikcleju@0 530 #
nikcleju@0 531
nikcleju@0 532 #---------------------
nikcleju@0 533 # Original Matab code:
nikcleju@0 534
nikcleju@0 535 #largescale = isa(A,'function_handle');
nikcleju@0 536 #
nikcleju@0 537 #if (nargin < 6), lbtol = 1e-3; end
nikcleju@0 538 #if (nargin < 7), mu = 10; end
nikcleju@0 539 #if (nargin < 8), cgtol = 1e-8; end
nikcleju@0 540 #if (nargin < 9), cgmaxiter = 200; end
nikcleju@0 541 #
nikcleju@0 542 #newtontol = lbtol;
nikcleju@0 543 #newtonmaxiter = 50;
nikcleju@0 544 #
nikcleju@0 545 #N = length(x0);
nikcleju@0 546 #
nikcleju@0 547 ## starting point --- make sure that it is feasible
nikcleju@0 548 #if (largescale)
nikcleju@0 549 # if (norm(A(x0)-b) > epsilon)
nikcleju@0 550 # disp('Starting point infeasible; using x0 = At*inv(AAt)*y.');
nikcleju@0 551 # AAt = @(z) A(At(z));
nikcleju@0 552 # w = cgsolve(AAt, b, cgtol, cgmaxiter, 0);
nikcleju@0 553 # if (cgres > 1/2)
nikcleju@0 554 # disp('A*At is ill-conditioned: cannot find starting point');
nikcleju@0 555 # xp = x0;
nikcleju@0 556 # return;
nikcleju@0 557 # end
nikcleju@0 558 # x0 = At(w);
nikcleju@0 559 # end
nikcleju@0 560 #else
nikcleju@0 561 # if (norm(A*x0-b) > epsilon)
nikcleju@0 562 # disp('Starting point infeasible; using x0 = At*inv(AAt)*y.');
nikcleju@0 563 # opts.POSDEF = true; opts.SYM = true;
nikcleju@0 564 # [w, hcond] = linsolve(A*A', b, opts);
nikcleju@0 565 # if (hcond < 1e-14)
nikcleju@0 566 # disp('A*At is ill-conditioned: cannot find starting point');
nikcleju@0 567 # xp = x0;
nikcleju@0 568 # return;
nikcleju@0 569 # end
nikcleju@0 570 # x0 = A'*w;
nikcleju@0 571 # end
nikcleju@0 572 #end
nikcleju@0 573 #x = x0;
nikcleju@0 574 #u = (0.95)*abs(x0) + (0.10)*max(abs(x0));
nikcleju@0 575 #
nikcleju@0 576 #disp(sprintf('Original l1 norm = #.3f, original functional = #.3f', sum(abs(x0)), sum(u)));
nikcleju@0 577 #
nikcleju@0 578 ## choose initial value of tau so that the duality gap after the first
nikcleju@0 579 ## step will be about the origial norm
nikcleju@0 580 #tau = max((2*N+1)/sum(abs(x0)), 1);
nikcleju@0 581 #
nikcleju@0 582 #lbiter = ceil((log(2*N+1)-log(lbtol)-log(tau))/log(mu));
nikcleju@0 583 #disp(sprintf('Number of log barrier iterations = #d\n', lbiter));
nikcleju@0 584 #
nikcleju@0 585 #totaliter = 0;
nikcleju@0 586 #
nikcleju@0 587 ## Added by Nic
nikcleju@0 588 #if lbiter == 0
nikcleju@0 589 # xp = zeros(size(x0));
nikcleju@0 590 #end
nikcleju@0 591 #
nikcleju@0 592 #for ii = 1:lbiter
nikcleju@0 593 #
nikcleju@0 594 # [xp, up, ntiter] = l1qc_newton(x, u, A, At, b, epsilon, tau, newtontol, newtonmaxiter, cgtol, cgmaxiter);
nikcleju@0 595 # totaliter = totaliter + ntiter;
nikcleju@0 596 #
nikcleju@0 597 # disp(sprintf('\nLog barrier iter = #d, l1 = #.3f, functional = #8.3f, tau = #8.3e, total newton iter = #d\n', ...
nikcleju@0 598 # ii, sum(abs(xp)), sum(up), tau, totaliter));
nikcleju@0 599 #
nikcleju@0 600 # x = xp;
nikcleju@0 601 # u = up;
nikcleju@0 602 #
nikcleju@0 603 # tau = mu*tau;
nikcleju@0 604 #
nikcleju@0 605 #end
nikcleju@0 606 #
nikcleju@0 607 # End of original Matab code
nikcleju@0 608 #----------------------------
nikcleju@0 609
nikcleju@0 610 #largescale = isa(A,'function_handle');
nikcleju@0 611 if hasattr(A, '__call__'):
nikcleju@0 612 largescale = True
nikcleju@0 613 else:
nikcleju@0 614 largescale = False
nikcleju@0 615
nikcleju@0 616 # if (nargin < 6), lbtol = 1e-3; end
nikcleju@0 617 # if (nargin < 7), mu = 10; end
nikcleju@0 618 # if (nargin < 8), cgtol = 1e-8; end
nikcleju@0 619 # if (nargin < 9), cgmaxiter = 200; end
nikcleju@0 620 # Nic: added them as optional parameteres
nikcleju@0 621
nikcleju@0 622 newtontol = lbtol
nikcleju@0 623 newtonmaxiter = 50
nikcleju@0 624
nikcleju@0 625 #N = length(x0);
nikcleju@0 626 N = x0.size()
nikcleju@0 627
nikcleju@0 628 # starting point --- make sure that it is feasible
nikcleju@0 629 if largescale:
nikcleju@0 630 if np.linalg.norm(A(x0) - b) > epsilon:
nikcleju@0 631 print 'Starting point infeasible; using x0 = At*inv(AAt)*y.'
nikcleju@0 632 #AAt = @(z) A(At(z));
nikcleju@0 633 AAt = lambda z: A(At(z))
nikcleju@0 634 # TODO: implement cgsolve
nikcleju@0 635 w,cgres,cgiter = cgsolve(AAt, b, cgtol, cgmaxiter, 0)
nikcleju@0 636 if (cgres > 1/2):
nikcleju@0 637 print 'A*At is ill-conditioned: cannot find starting point'
nikcleju@0 638 xp = x0.copy()
nikcleju@0 639 return xp
nikcleju@0 640 #end
nikcleju@0 641 x0 = At(w)
nikcleju@0 642 #end
nikcleju@0 643 else:
nikcleju@0 644 if np.linalg.norm( np.dot(A,x0) - b ) > epsilon:
nikcleju@0 645 print 'Starting point infeasible; using x0 = At*inv(AAt)*y.'
nikcleju@0 646 #opts.POSDEF = true; opts.SYM = true;
nikcleju@0 647 #[w, hcond] = linsolve(A*A', b, opts);
nikcleju@0 648 #if (hcond < 1e-14)
nikcleju@0 649 # disp('A*At is ill-conditioned: cannot find starting point');
nikcleju@0 650 # xp = x0;
nikcleju@0 651 # return;
nikcleju@0 652 #end
nikcleju@0 653 try:
nikcleju@0 654 w = scipy.linalg.solve(np.dot(A,A.T), b, sym_pos=True)
nikcleju@0 655 hcond = 1.0/scipy.linalg.cond(np.dot(A,A.T))
nikcleju@0 656 except scipy.linalg.LinAlgError:
nikcleju@0 657 print 'A*At is ill-conditioned: cannot find starting point'
nikcleju@0 658 xp = x0.copy()
nikcleju@0 659 return xp
nikcleju@0 660 if hcond < 1e-14:
nikcleju@0 661 print 'A*At is ill-conditioned: cannot find starting point'
nikcleju@0 662 xp = x0.copy()
nikcleju@0 663 return xp
nikcleju@0 664 #x0 = A'*w;
nikcleju@0 665 x0 = np.dot(A.T, w)
nikcleju@0 666 #end
nikcleju@0 667 #end
nikcleju@0 668 x = x0.copy()
nikcleju@0 669 u = (0.95)*np.abs(x0) + (0.10)*np.abs(x0).max()
nikcleju@0 670
nikcleju@0 671 #disp(sprintf('Original l1 norm = #.3f, original functional = #.3f', sum(abs(x0)), sum(u)));
nikcleju@0 672 print 'Original l1 norm = ',np.abs(x0).sum(),'original functional = ',u.sum()
nikcleju@0 673
nikcleju@0 674 # choose initial value of tau so that the duality gap after the first
nikcleju@0 675 # step will be about the origial norm
nikcleju@0 676 tau = max(((2*N+1)/np.abs(x0).sum()), 1)
nikcleju@0 677
nikcleju@0 678 lbiter = math.ceil((math.log(2*N+1)-math.log(lbtol)-math.log(tau))/math.log(mu))
nikcleju@0 679 #disp(sprintf('Number of log barrier iterations = #d\n', lbiter));
nikcleju@0 680 print 'Number of log barrier iterations = ',lbiter
nikcleju@0 681
nikcleju@0 682 totaliter = 0
nikcleju@0 683
nikcleju@0 684 # Added by Nic, to fix some crashing
nikcleju@0 685 if lbiter == 0:
nikcleju@0 686 xp = np.zeros(x0.size)
nikcleju@0 687 #end
nikcleju@0 688
nikcleju@0 689 #for ii = 1:lbiter
nikcleju@0 690 for ii in np.arange(lbiter):
nikcleju@0 691
nikcleju@0 692 xp,up,ntiter = l1qc_newton(x, u, A, At, b, epsilon, tau, newtontol, newtonmaxiter, cgtol, cgmaxiter)
nikcleju@0 693 totaliter = totaliter + ntiter
nikcleju@0 694
nikcleju@0 695 #disp(sprintf('\nLog barrier iter = #d, l1 = #.3f, functional = #8.3f, tau = #8.3e, total newton iter = #d\n', ...
nikcleju@0 696 # ii, sum(abs(xp)), sum(up), tau, totaliter));
nikcleju@0 697 print 'Log barrier iter = ',ii,', l1 = ',np.abs(xp).sum(),', functional = ',up.sum(),', tau = ',tau,', total newton iter = ',totaliter
nikcleju@0 698 x = xp.copy()
nikcleju@0 699 u = up.copy()
nikcleju@0 700
nikcleju@0 701 tau = mu*tau
nikcleju@0 702
nikcleju@0 703 #end
nikcleju@0 704 return xp
nikcleju@0 705