forked from epnev/SPGL1_python_port
-
Notifications
You must be signed in to change notification settings - Fork 0
/
oneProjector.py
executable file
·113 lines (87 loc) · 2.41 KB
/
oneProjector.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import numpy as np
# THIS NEEDS TO BE REDONE IN C AND COMPILED FOR CYTHON
# ALL OF THIS CODE IS CURRENTLY GROTESQUELY INEFFICIENT
# I'LL SPEED IT UP AND RELEASE THAT PROMPTLY - DRR
def oneProjectorMex_I(b,tau):
n = np.size(b)
x = np.zeros(n)
bNorm = np.linalg.norm(b,1)
if (tau >= bNorm):
return b.copy()
if (tau < np.spacing(1) ):
return x.copy()
idx = np.argsort(b)[::-1]
b = b[idx]
alphaPrev = 0.
csb = np.cumsum(b) - tau
alpha = np.zeros(n+1)
alpha[1:] = csb / (np.arange(n)+1.0)
alphaindex = np.where(alpha[1:] >= b)
if alphaindex[0].any():
alphaPrev = alpha[alphaindex[0][0]]
else:
alphaPrev = alpha[-1]
x[idx] = b - alphaPrev
x[x<0]=0
return x
# THIS NEEDS TO BE REDONE IN C AND COMPILED FOR CYTHON
def oneProjectorMex_D(b,d,tau):
n = np.size(b)
x = np.zeros(n)
if (tau >= np.linalg.norm(d*b,1)):
return b.copy()
if (tau < np.spacing(1)):
return x.copy()
idx = np.argsort(b / d)[::-1]
b = b[idx]
d = d[idx]
csdb = np.cumsum(d*b)
csd2 = np.cumsum(d*d)
alpha1 = (csdb-tau)/csd2
alpha2 = b/d
ggg = np.where(alpha1>=alpha2)
if(np.size(ggg[0])==0):
i=n
else:
i=ggg[0][0]
if(i>0):
soft = alpha1[i-1]
x[idx[0:i]] = b[0:i] - d[0:i] * max(0,soft);
else:
soft = 0
return x
# THIS NEEDS TO BE REDONE IN C AND COMPILED FOR CYTHON
def oneProjectorMex(b,d,tau=-1):
if tau==-1:
tau = d
d = 1
if np.isscalar(d):
return oneProjectorMex_I(b,tau/abs(d))
else:
return oneProjectorMex_D(b,d,tau)
# THIS NEEDS TO BE REDONE IN C AND COMPILED FOR CYTHON
def oneProjector(b,d=[],tau=-1):
if tau==-1:
if not d:
print('ERROR: oneProjector requires at least two input parameters')
return
tau = d
d = []
#print d
#if not d:
# d=1
if not np.isscalar(d) and np.size(b) != np.size(d):
print('ERROR: oneProjector: Vectors b and d must have the same length')
return
if np.isscalar(d) and d == 0:
return b.copy()
s = np.sign(b)
b = abs(b)
if np.isscalar(d):
x = oneProjectorMex(b,tau/d);
else:
d = abs(d)
idx = np.where(d > np.spacing(1))
x = b.copy()
x[idx] = oneProjectorMex(b[idx],d[idx],tau)
return x*s