Mercurial > hg > pycsalgos
changeset 15:0d66a0aafb39
SL0_approx test working
author | nikcleju |
---|---|
date | Sat, 05 Nov 2011 22:10:06 +0000 |
parents | fc245ada9b0f |
children | a6ca929f49f1 |
files | matlab/SL0/SL0_approx.m pyCSalgos/SL0/SL0_approx.py tests/sl0approx_test.py |
diffstat | 3 files changed, 142 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/matlab/SL0/SL0_approx.m Sat Nov 05 22:06:11 2011 +0000 +++ b/matlab/SL0/SL0_approx.m Sat Nov 05 22:10:06 2011 +0000 @@ -113,11 +113,7 @@ % Initialization %s = A\x; s = A_pinv*x; -% Nic: -s = zeros(size(A,2),1); -s = randn(size(A,2),1); -sigma = 10; -%sigma = 2*max(abs(s)); +sigma = 2*max(abs(s)); % Main Loop while sigma>sigma_min
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pyCSalgos/SL0/SL0_approx.py Sat Nov 05 22:10:06 2011 +0000 @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +""" +Created on Sat Nov 05 21:29:09 2011 + +@author: Nic +""" + +# -*- 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_approx(A, x, eps, sigma_min, sigma_decrease_factor=0.5, mu_0=2, L=3, A_pinv=None, true_s=None): + + 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 + # At this point, s no longer exactly satisfies x = A*s + # The original SL0 algorithm projects s onto {s | x = As} with + # s = s - np.dot(A_pinv,(np.dot(A,s)-x)) # Projection + # We want to project s onto {s | |x-As| < eps} + # We move onto the direction -A_pinv*(A*s-x), but only with a + # smaller step: + direction = np.dot(A_pinv,(np.dot(A,s)-x)) + if (np.linalg.norm(np.dot(A,direction)) >= eps): + s = s - (1.0 - eps/np.linalg.norm(np.dot(A,direction))) * direction + + #assert(np.linalg.norm(x - np.dot(A,s)) < eps + 1e-6) + + 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()) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/sl0approx_test.py Sat Nov 05 22:10:06 2011 +0000 @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +""" +Created on Sat Nov 05 21:34:49 2011 + +@author: Nic +""" +import numpy as np +import numpy.linalg +import scipy.io +import unittest +from pyCSalgos.SL0.SL0_approx import SL0_approx + +class SL0results(unittest.TestCase): + def testResults(self): + mdict = scipy.io.loadmat('SL0approxtestdata.mat') + + # A = system matrix + # Y = matrix with measurements (on columns) + # sigmamin = vector with sigma_min + for A,Y,eps,sigmamin,Xr in zip(mdict['cellA'].squeeze(),mdict['cellY'].squeeze(),mdict['cellEps'].squeeze(),mdict['sigmamin'].squeeze(),mdict['cellXr'].squeeze()): + for i in np.arange(Y.shape[1]): + + # Fix numpy error "LapackError: Parameter a has non-native byte order in lapack_lite.dgesdd" + A = A.newbyteorder('=') + Y = Y.newbyteorder('=') + eps = eps.newbyteorder('=') + sigmamin = sigmamin.newbyteorder('=') + Xr = Xr.newbyteorder('=') + + xr = SL0_approx(A, Y[:,i], eps.squeeze()[i], sigmamin) + + # check if found solution is the same as the correct cslution + diff = numpy.linalg.norm(xr - Xr[:,i]) + self.assertTrue(diff < 1e-12) + # err1 = numpy.linalg.norm(Y[:,i] - np.dot(A,xr)) + # err2 = numpy.linalg.norm(Y[:,i] - np.dot(A,Xr[:,i])) + # norm1 = numpy.linalg.norm(xr,1) + # norm2 = numpy.linalg.norm(Xr[:,i],1) + # + # # Make a more robust condition: + # # OK; if solutions are close enough (diff < 1e-6) + # # or + # # ( + # # Python solution fulfills the constraint better (or up to 1e-6 worse) + # # and + # # Python solution has l1 norm no more than 1e-6 larger as the reference solution + # # (i.e. either norm1 < norm2 or norm1>norm2 not by more than 1e-6) + # # ) + # # + # # ERROR: else + # differr = err1 - err2 # intentionately no abs(), since err1` < err2 is good + # diffnorm = norm1 - norm2 # intentionately no abs(), since norm1 < norm2 is good + # if diff < 1e-6 or (differr < 1e-6 and (diffnorm < 1e-6)): + # isok = True + # else: + # isok = False + # self.assertTrue(isok) + + #diff = numpy.linalg.norm(xr - Xr[:,i]) + #if diff > 1e-6: + # self.assertTrue(diff < 1e-6) + + +if __name__ == "__main__": + #import cProfile + #cProfile.run('unittest.main()', 'profres') + unittest.main() + #suite = unittest.TestLoader().loadTestsFromTestCase(CompareResults) + #unittest.TextTestRunner(verbosity=2).run(suite)