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@15
|
58
|
nikcleju@15
|
59
|
nikcleju@15
|
60 ####################################################################
|
nikcleju@15
|
61 #function delta=OurDelta(s,sigma)
|
nikcleju@15
|
62 def OurDelta(s,sigma):
|
nikcleju@15
|
63
|
nikcleju@15
|
64 return s * np.exp( (-np.abs(s)**2) / sigma**2)
|
nikcleju@15
|
65
|
nikcleju@15
|
66 ####################################################################
|
nikcleju@15
|
67 #function SNR=estimate_SNR(estim_s,true_s)
|
nikcleju@15
|
68 def estimate_SNR(estim_s, true_s):
|
nikcleju@15
|
69
|
nikcleju@15
|
70 err = true_s - estim_s
|
nikcleju@15
|
71 return 10*np.log10((true_s**2).sum()/(err**2).sum())
|
nikcleju@15
|
72
|