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
|