Skip to content

Commit 56f32f0

Browse files
committed
Added Log1 proximal
1 parent 45e2f22 commit 56f32f0

File tree

3 files changed

+73
-2
lines changed

3 files changed

+73
-2
lines changed

docs/source/api/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ Non-Convex
8989
ETP
9090
Geman
9191
Log
92+
Log1
9293
QuadraticEnvelopeCard
9394
QuadraticEnvelopeCardIndicator
9495
SCAD

pyproximal/proximal/Log.py

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,75 @@ def prox(self, x, tau):
9696
r = np.vstack((np.zeros_like(c), (b[idx] + c) / (2 * self.gamma)))
9797
val = tau * self.elementwise(r) + (r - np.abs(x[idx])) ** 2 / 2
9898
idx_minima = np.argmin(val, axis=0)
99-
out[idx] = r[idx_minima, range(r.shape[1])]
99+
out[idx] = r[idx_minima, list(range(r.shape[1]))]
100100
out *= np.sign(x)
101101
return out
102+
103+
class Log1(ProxOperator):
104+
r"""Logarithmic penalty.
105+
106+
The logarithmic penalty (Log) is defined as
107+
108+
.. math::
109+
110+
\mathrm{Log}_{\sigma,\delta}(\mathbf{x}) = \sum_i \log(|x_i| + \delta)
111+
112+
where :math:`{\sigma>0}`, :math:`{\gamma>0}`.
113+
114+
Parameters
115+
----------
116+
sigma : :obj:`float`
117+
Regularization parameter.
118+
delta : :obj:`float`, optional
119+
Regularization parameter. Default is 1e-10.
120+
121+
Notes
122+
-----
123+
The logarithmic penalty gives rise to a log-thresholding that is
124+
a smooth alternative falling in between the hard and soft thresholding.
125+
126+
The proximal operator is defined as [1]_:
127+
128+
.. math::
129+
130+
\prox_{\tau \sigma log}(\mathbf{x}) =
131+
\begin{cases}
132+
0.5 (x_i - \delta + \sqrt{(x_i+\delta)^2-2\tau \sigma}), & x_i - g_i < -x_0 \\
133+
0, & -x_0 \leq x_i - g_i x_0 \\
134+
0.5 (x_i + \delta - \sqrt{(x_i-\delta)^2-2\tau \sigma}), & x_i - g_i > x_0\\
135+
\end{cases}
136+
137+
where :math:`x_0=\sqrt{2 \tau \sigma} - \delta`.
138+
139+
.. [1] Malioutov, D., and Aravkin, A. "Iterative log thresholding",
140+
Arxiv, 2013.
141+
142+
"""
143+
144+
def __init__(self, sigma, delta=1e-10):
145+
super().__init__(None, False)
146+
if delta < 0:
147+
raise ValueError('Variable "delta" must be positive.')
148+
self.sigma = sigma
149+
self.delta = delta
150+
151+
def __call__(self, x):
152+
return np.sum(self.elementwise(x))
153+
154+
def elementwise(self, x):
155+
return np.log(np.abs(x) + self.delta)
156+
157+
@_check_tau
158+
def prox(self, x, tau):
159+
tau1 = self.sigma * tau
160+
thresh = np.sqrt(2*tau1) - self.delta
161+
x1 = np.zeros_like(x, dtype=x.dtype)
162+
if np.iscomplexobj(x):
163+
x1[np.abs(x) > thresh] = 0.5 * np.exp(1j * np.angle(x[np.abs(x) > thresh])) * \
164+
(np.abs(x[np.abs(x) > thresh]) - self.delta +
165+
np.sqrt(np.abs(x[np.abs(x) > thresh] + self.delta) ** 2 - 2 * tau1))
166+
else:
167+
x1[x > thresh] = 0.5 * (x[x > thresh] - self.delta + np.sqrt(np.abs(x[x > thresh] + self.delta) ** 2 - 2 * tau1))
168+
x1[x < -thresh] = 0.5 * (x[x < -thresh] + self.delta - np.sqrt(np.abs(x[x < -thresh] - self.delta) ** 2 - 2 * tau1))
169+
return x1
170+

pyproximal/proximal/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
VStack Stack of proximal operators
2929
SCAD Smoothly clipped absolute deviation
3030
Log Logarithmic
31+
Log1 Another form of logarithmic
3132
ETP Exponential-type penalty
3233
Geman Geman penalty
3334
QuadraticEnvelopeCard The quadratic envelope of the cardinality function
@@ -67,6 +68,6 @@
6768
'Euclidean', 'EuclideanBall', 'L0', 'L0Ball', 'L1', 'L1Ball', 'L2',
6869
'L2Convolve', 'L21', 'L21_plus_L1', 'Huber', 'TV', 'Nuclear',
6970
'NuclearBall', 'Orthogonal', 'VStack', 'Nonlinear', 'SCAD',
70-
'Log', 'ETP', 'Geman', 'QuadraticEnvelopeCard', 'SingularValuePenalty',
71+
'Log', 'Log1', 'ETP', 'Geman', 'QuadraticEnvelopeCard', 'SingularValuePenalty',
7172
'QuadraticEnvelopeCardIndicator', 'QuadraticEnvelopeRankL2',
7273
'Hankel']

0 commit comments

Comments
 (0)