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