annotate pyCSalgos/SL0/SL0_approx.py @ 60:a7082bb22644

Modified structure:should keep in this repo only the bare solvers. Anything related to Analysis should be moved to ABS repository. Renamed RecomTST to TST, renamed lots of functions, removed Analysis.py and algos.py.
author Nic Cleju <nikcleju@gmail.com>
date Fri, 09 Mar 2012 16:25:31 +0200
parents afcfd4d1d548
children ee10ffb60428
rev   line source
nikcleju@15 1 # -*- coding: utf-8 -*-
nikcleju@15 2 """
nikcleju@15 3 Created on Sat Nov 05 21:29:09 2011
nikcleju@15 4
nikcleju@15 5 @author: Nic
nikcleju@15 6 """
nikcleju@15 7
nikcleju@15 8 # -*- coding: utf-8 -*-
nikcleju@15 9 """
nikcleju@15 10 Created on Sat Nov 05 18:39:54 2011
nikcleju@15 11
nikcleju@15 12 @author: Nic
nikcleju@15 13 """
nikcleju@15 14
nikcleju@15 15 import numpy as np
nikcleju@15 16
nikcleju@15 17 #function s=SL0(A, x, sigma_min, sigma_decrease_factor, mu_0, L, A_pinv, true_s)
nikcleju@15 18 def SL0_approx(A, x, eps, sigma_min, sigma_decrease_factor=0.5, mu_0=2, L=3, A_pinv=None, true_s=None):
nikcleju@15 19
nikcleju@15 20 if A_pinv is None:
nikcleju@15 21 A_pinv = np.linalg.pinv(A)
nikcleju@15 22
nikcleju@15 23 if true_s is not None:
nikcleju@15 24 ShowProgress = True
nikcleju@15 25 else:
nikcleju@15 26 ShowProgress = False
nikcleju@15 27
nikcleju@15 28 # Initialization
nikcleju@15 29 #s = A\x;
nikcleju@15 30 s = np.dot(A_pinv,x)
nikcleju@15 31 sigma = 2.0 * np.abs(s).max()
nikcleju@15 32
nikcleju@15 33 # Main Loop
nikcleju@15 34 while sigma>sigma_min:
nikcleju@15 35 for i in np.arange(L):
nikcleju@15 36 delta = OurDelta(s,sigma)
nikcleju@15 37 s = s - mu_0*delta
nikcleju@15 38 # At this point, s no longer exactly satisfies x = A*s
nikcleju@15 39 # The original SL0 algorithm projects s onto {s | x = As} with
nikcleju@15 40 # s = s - np.dot(A_pinv,(np.dot(A,s)-x)) # Projection
nikcleju@15 41 # We want to project s onto {s | |x-As| < eps}
nikcleju@15 42 # We move onto the direction -A_pinv*(A*s-x), but only with a
nikcleju@15 43 # smaller step:
nikcleju@15 44 direction = np.dot(A_pinv,(np.dot(A,s)-x))
nikcleju@15 45 if (np.linalg.norm(np.dot(A,direction)) >= eps):
nikcleju@15 46 s = s - (1.0 - eps/np.linalg.norm(np.dot(A,direction))) * direction
nikcleju@15 47
nikcleju@15 48 #assert(np.linalg.norm(x - np.dot(A,s)) < eps + 1e-6)
nikcleju@15 49
nikcleju@15 50 if ShowProgress:
nikcleju@15 51 #fprintf(' sigma=#f, SNR=#f\n',sigma,estimate_SNR(s,true_s))
nikcleju@15 52 string = ' sigma=%f, SNR=%f\n' % sigma,estimate_SNR(s,true_s)
nikcleju@15 53 print string
nikcleju@15 54
nikcleju@15 55 sigma = sigma * sigma_decrease_factor
nikcleju@15 56
nikcleju@15 57 return s
nikcleju@37 58
nikcleju@37 59 # Direct approximate analysis-based version of SL0
nikcleju@37 60 # Solves argimn_gamma ||gamma||_0 such that ||x - Aeps*gamma|| < eps AND ||Aexact*gamma|| = 0
nikcleju@37 61 # Basically instead of having a single A, we now have one Aeps which is up to eps error
nikcleju@37 62 # and an Axeact which requires exact orthogonality
nikcleju@37 63 # It is assumed that the rows of Aexact are orthogonal to the rows of Aeps
nikcleju@37 64 def SL0_approx_analysis(Aeps, Aexact, x, eps, sigma_min, sigma_decrease_factor=0.5, mu_0=2, L=3, Aeps_pinv=None, Aexact_pinv=None, true_s=None):
nikcleju@15 65
nikcleju@37 66 if Aeps_pinv is None:
nikcleju@37 67 Aeps_pinv = np.linalg.pinv(Aeps)
nikcleju@37 68 if Aexact_pinv is None:
nikcleju@37 69 Aexact_pinv = np.linalg.pinv(Aexact)
nikcleju@37 70
nikcleju@37 71 if true_s is not None:
nikcleju@37 72 ShowProgress = True
nikcleju@37 73 else:
nikcleju@37 74 ShowProgress = False
nikcleju@15 75
nikcleju@37 76 # Initialization
nikcleju@37 77 #s = A\x;
nikcleju@37 78 s = np.dot(Aeps_pinv,x)
nikcleju@37 79 sigma = 2.0 * np.abs(s).max()
nikcleju@37 80
nikcleju@37 81 # Main Loop
nikcleju@37 82 while sigma>sigma_min:
nikcleju@37 83 for i in np.arange(L):
nikcleju@37 84 delta = OurDelta(s,sigma)
nikcleju@37 85 s = s - mu_0*delta
nikcleju@37 86 # At this point, s no longer exactly satisfies x = A*s
nikcleju@37 87 # The original SL0 algorithm projects s onto {s | x = As} with
nikcleju@37 88 # s = s - np.dot(A_pinv,(np.dot(A,s)-x)) # Projection
nikcleju@37 89 #
nikcleju@37 90 # We want to project s onto {s | |x-AEPS*s|<eps AND |Aexact*s|=0}
nikcleju@37 91 # First: make s orthogonal to Aexact (|Aexact*s|=0)
nikcleju@37 92 # Second: move onto the direction -A_pinv*(A*s-x), but only with a smaller step:
nikcleju@37 93 # This separation assumes that the rows of Aexact are orthogonal to the rows of Aeps
nikcleju@37 94 #
nikcleju@37 95 # 1. Make s orthogonal to Aexact:
nikcleju@37 96 # s = s - Aexact_pinv * Aexact * s
nikcleju@37 97 s = s - np.dot(Aexact_pinv,(np.dot(Aexact,s)))
nikcleju@37 98 # 2. Move onto the direction -A_pinv*(A*s-x), but only with a smaller step:
nikcleju@37 99 direction = np.dot(Aeps_pinv,(np.dot(Aeps,s)-x))
nikcleju@37 100 if (np.linalg.norm(np.dot(Aeps,direction)) >= eps):
nikcleju@37 101 s = s - (1.0 - eps/np.linalg.norm(np.dot(Aeps,direction))) * direction
nikcleju@37 102
nikcleju@37 103 #assert(np.linalg.norm(x - np.dot(A,s)) < eps + 1e-6)
nikcleju@37 104
nikcleju@37 105 if ShowProgress:
nikcleju@37 106 #fprintf(' sigma=#f, SNR=#f\n',sigma,estimate_SNR(s,true_s))
nikcleju@37 107 string = ' sigma=%f, SNR=%f\n' % sigma,estimate_SNR(s,true_s)
nikcleju@37 108 print string
nikcleju@37 109
nikcleju@37 110 sigma = sigma * sigma_decrease_factor
nikcleju@37 111
nikcleju@37 112 return s
nikcleju@37 113
nikcleju@37 114
nikcleju@15 115 ####################################################################
nikcleju@15 116 #function delta=OurDelta(s,sigma)
nikcleju@15 117 def OurDelta(s,sigma):
nikcleju@15 118
nikcleju@15 119 return s * np.exp( (-np.abs(s)**2) / sigma**2)
nikcleju@15 120
nikcleju@15 121 ####################################################################
nikcleju@15 122 #function SNR=estimate_SNR(estim_s,true_s)
nikcleju@15 123 def estimate_SNR(estim_s, true_s):
nikcleju@15 124
nikcleju@15 125 err = true_s - estim_s
nikcleju@15 126 return 10*np.log10((true_s**2).sum()/(err**2).sum())
nikcleju@15 127