Mercurial > hg > pycsalgos
changeset 9:f31d5484a573
Added SL0
author | nikcleju |
---|---|
date | Sat, 05 Nov 2011 21:13:06 +0000 |
parents | 64fbc37c8c06 |
children | edb5a287e0bb |
files | pyCSalgos/SL0/SL0.py pyCSalgos/SL0/__init__.py |
diffstat | 1 files changed, 202 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pyCSalgos/SL0/SL0.py Sat Nov 05 21:13:06 2011 +0000 @@ -0,0 +1,202 @@ +# -*- coding: utf-8 -*- +""" +Created on Sat Nov 05 18:39:54 2011 + +@author: Nic +""" + +import numpy as np + +#function s=SL0(A, x, sigma_min, sigma_decrease_factor, mu_0, L, A_pinv, true_s) +def SL0(A, x, sigma_min, sigma_decrease_factor=0.5, mu_0=2, L=3, A_pinv=None, true_s=None): + # + # SL0(A, x, sigma_min, sigma_decrease_factor, mu_0, L, A_pinv, true_s) + # + # Returns the sparsest vector s which satisfies underdetermined system of + # linear equations A*s=x, using Smoothed L0 (SL0) algorithm. Note that + # the matrix A should be a 'wide' matrix (more columns than rows). The + # number of the rows of matrix A should be equal to the length of the + # column vector x. + # + # The first 3 arguments should necessarily be provided by the user. The + # other parameters have defult values calculated within the function, or + # may be provided by the user. + # + # Sequence of Sigma (sigma_min and sigma_decrease_factor): + # This is a decreasing geometric sequence of positive numbers: + # - The first element of the sequence of sigma is calculated + # automatically. The last element is given by 'sigma_min', and the + # change factor for decreasing sigma is given by 'sigma_decrease_factor'. + # - The default value of 'sigma_decrease_factor' is 0.5. Larger value + # gives better results for less sparse sources, but it uses more steps + # on sigma to reach sigma_min, and hence it requires higher + # computational cost. + # - There is no default value for 'sigma_min', and it should be + # provided by the user (depending on his/her estimated source noise + # level, or his/her desired accuracy). By `noise' we mean here the + # noise in the sources, that is, the energy of the inactive elements of + # 's'. For example, by the noiseless case, we mean the inactive + # elements of 's' are exactly equal to zero. As a rule of tumb, for the + # noisy case, sigma_min should be about 2 to 4 times of the standard + # deviation of this noise. For the noiseless case, smaller 'sigma_min' + # results in better estimation of the sparsest solution, and hence its + # value is determined by the desired accuracy. + # + # mu_0: + # The value of mu_0 scales the sequence of mu. For each vlue of + # sigma, the value of mu is chosen via mu=mu_0*sigma^2. Note that this + # value effects Convergence. + # The default value is mu_0=2 (see the paper). + # + # L: + # number of iterations of the internal (steepest ascent) loop. The + # default value is L=3. + # + # A_pinv: + # is the pseudo-inverse of matrix A defined by A_pinv=A'*inv(A*A'). + # If it is not provided, it will be calculated within the function. If + # you use this function for solving x(t)=A s(t) for different values of + # 't', it would be a good idea to calculate A_pinv outside the function + # to prevent its re-calculation for each 't'. + # + # true_s: + # is the true value of the sparse solution. This argument is for + # simulation purposes. If it is provided by the user, then the function + # will calculate the SNR of the estimation for each value of sigma and + # it provides a progress report. + # + # Authors: Massoud Babaie-Zadeh and Hossein Mohimani + # Version: 1.4 + # Last modified: 4 April 2010. + # + # + # Web-page: + # ------------------ + # http://ee.sharif.ir/~SLzero + # + # Code History: + #-------------- + # Version 2.0: 4 April 2010 + # Doing a few small modifications that enable the code to work also + # for complex numbers (not only for real numbers). + # + # Version 1.3: 13 Sep 2008 + # Just a few modifications in the comments + # + # Version 1.2: Adding some more comments in the help section + # + # Version 1.1: 4 August 2008 + # - Using MATLAB's pseudo inverse function to generalize for the case + # the matrix A is not full-rank. + # + # Version 1.0 (first official version): 4 July 2008. + # + # First non-official version and algorithm development: Summer 2006 + #--------------------- + # Original Matab code: + # + #if nargin < 4 + # sigma_decrease_factor = 0.5; + # A_pinv = pinv(A); + # mu_0 = 2; + # L = 3; + # ShowProgress = logical(0); + #elseif nargin == 4 + # A_pinv = pinv(A); + # mu_0 = 2; + # L = 3; + # ShowProgress = logical(0); + #elseif nargin == 5 + # A_pinv = pinv(A); + # L = 3; + # ShowProgress = logical(0); + #elseif nargin == 6 + # A_pinv = pinv(A); + # ShowProgress = logical(0); + #elseif nargin == 7 + # ShowProgress = logical(0); + #elseif nargin == 8 + # ShowProgress = logical(1); + #else + # error('Error in calling SL0 function'); + #end + # + # + ## Initialization + ##s = A\x; + #s = A_pinv*x; + #sigma = 2*max(abs(s)); + # + ## Main Loop + #while sigma>sigma_min + # for i=1:L + # delta = OurDelta(s,sigma); + # s = s - mu_0*delta; + # s = s - A_pinv*(A*s-x); # Projection + # end + # + # if ShowProgress + # fprintf(' sigma=#f, SNR=#f\n',sigma,estimate_SNR(s,true_s)) + # end + # + # sigma = sigma * sigma_decrease_factor; + #end + # + # + ##################################################################### + #function delta=OurDelta(s,sigma) + # + #delta = s.*exp(-abs(s).^2/sigma^2); + # + ##################################################################### + #function SNR=estimate_SNR(estim_s,true_s) + # + #err = true_s - estim_s; + #SNR = 10*log10(sum(abs(true_s).^2)/sum(abs(err).^2)); + + # End of original Matab code + #---------------------------- + + if A_pinv is None: + A_pinv = np.linalg.pinv(A) + + if true_s is not None: + ShowProgress = True + else: + ShowProgress = False + + # Initialization + #s = A\x; + s = np.dot(A_pinv,x) + sigma = 2.0*np.abs(s).max() + + # Main Loop + while sigma>sigma_min: + for i in np.arange(L): + delta = OurDelta(s,sigma) + s = s - mu_0*delta + s = s - np.dot(A_pinv,(np.dot(A,s)-x)) # Projection + + if ShowProgress: + #fprintf(' sigma=#f, SNR=#f\n',sigma,estimate_SNR(s,true_s)) + string = ' sigma=%f, SNR=%f\n' % sigma,estimate_SNR(s,true_s) + print string + + sigma = sigma * sigma_decrease_factor + + return s + + +#################################################################### +#function delta=OurDelta(s,sigma) +def OurDelta(s,sigma): + + return s * np.exp( (-np.abs(s)**2) / sigma**2) + +#################################################################### +#function SNR=estimate_SNR(estim_s,true_s) +def estimate_SNR(estim_s, true_s): + + err = true_s - estim_s + return 10*np.log10((true_s**2).sum()/(err**2).sum()) +