Skip to content

Commit caa6d02

Browse files
committed
To_positive_definite function erased
1 parent 150e73a commit caa6d02

File tree

6 files changed

+48
-61
lines changed

6 files changed

+48
-61
lines changed
61 Bytes
Binary file not shown.

docs/build/html/searchindex.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/insertion_mod.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
Global variables
77
----------------
8-
**known_curves** : list[:py:class:`src.classes.curves`]
8+
**known_curves** : list[:py:class:`src.classes.curve`]
99
List of member curves from the current iterate of the DGCG algorithm that
1010
have not yet been descended.
1111
**crossover_memory** : :py:class:`src.insertion_mod.ordered_list_of_lists`
@@ -322,15 +322,15 @@ def switch_at(curve1, curve2, idx):
322322
323323
Parameters
324324
----------
325-
curve1, curve2 : :py:class:`src.classes.curves`
325+
curve1, curve2 : :py:class:`src.classes.curve`
326326
Curve to crossover
327327
idx : int
328328
Time sample index where the crossover happens.
329329
330330
Returns
331331
-------
332-
new_curve_1 : :py:class:`src.classes.curves`
333-
new_curve_2 : :py:class:`src.classes.curves`
332+
new_curve_1 : :py:class:`src.classes.curve`
333+
new_curve_2 : :py:class:`src.classes.curve`
334334
"""
335335
midpoint = (curve1.spatial_points[idx] + curve2.spatial_points[idx])/2
336336
midpoint = midpoint.reshape(1, -1)
@@ -350,12 +350,12 @@ def crossover(curve1, curve2):
350350
351351
Parameters
352352
----------
353-
curve1, curve2 : :py:class:`src.classes.curves`
353+
curve1, curve2 : :py:class:`src.classes.curve`
354354
Curve to crossover.
355355
356356
Returns
357357
-------
358-
list[:py:class:`src.classes.curves`]
358+
list[:py:class:`src.classes.curve`]
359359
360360
Notes
361361
-----
@@ -391,7 +391,7 @@ def find_crossover(stationary_curves, energy_curves, w_t):
391391
392392
Parameters
393393
----------
394-
stationary_curves : list[:py:class:`src.classes.curves`]
394+
stationary_curves : list[:py:class:`src.classes.curve`]
395395
List of found stationary curves.
396396
energy_curves : numpy.array
397397
1-dimensional array of respective energies of the stationary curves.
@@ -400,7 +400,7 @@ def find_crossover(stationary_curves, energy_curves, w_t):
400400
401401
Returns
402402
-------
403-
:py:class:`src.classes.curves` or None
403+
:py:class:`src.classes.curve` or None
404404
If a crossover is found, returns it. If not, returns None.
405405
"""
406406
# From the known tabu curves, and the crossover_table, attempt to find

src/insertion_step.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def multistart_descent(current_measure):
7676
7777
Returns
7878
-------
79-
stationary_curves : list[:py:class:`src.classes.curves`]
79+
stationary_curves : list[:py:class:`src.classes.curve`]
8080
list of the found stationary points of the insertion step problem.
8181
energy_curves : numpy.ndarray
8282
respective energy of the found stationary_curves, sorted in ascending
@@ -226,11 +226,11 @@ def is_close_to_stationaries(new_curve, new_curve_energy,
226226
227227
Parameters
228228
----------
229-
new_curve : :py:class:`src.classes.curves`
229+
new_curve : :py:class:`src.classes.curve`
230230
Curve to check if it is close to the stationary set
231231
new_curve_energy : float
232232
Energy of the curve to check
233-
stationary_curves : list[:py:class:`src.classes.curves`]
233+
stationary_curves : list[:py:class:`src.classes.curve`]
234234
List of found stationary curves
235235
energy_curves : numpy.ndarray
236236
Energies of the found stationary curves sorted in ascendent order.
@@ -269,7 +269,7 @@ def gradient_descent(curve, w_t, max_iter=None, init_step=None,
269269
270270
Parameters
271271
----------
272-
curve : :py:class:`src.classes.curves`
272+
curve : :py:class:`src.classes.curve`
273273
Curve to be descended.
274274
w_t : :py:class:`src.classes.dual_variable`
275275
Dual variable associated to the current iterate.
@@ -285,7 +285,7 @@ def gradient_descent(curve, w_t, max_iter=None, init_step=None,
285285
286286
Returns
287287
-------
288-
:py:class:`src.classes.curves`
288+
:py:class:`src.classes.curve`
289289
290290
Notes
291291
-----

src/operators.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ def K_t_star(t, rho):
228228
The forward operator at time sample :math:`t` is a function that maps
229229
from the space of Radon measures :math:`\\mathcal{M}(\\Omega)` to the
230230
:math:`t`-th Hilbert space :math:`H_t`. The input measure of class
231-
:py:class:`src.classes.curves` is a dynamic measure, that once evaluated
231+
:py:class:`src.classes.curve` is a dynamic measure, that once evaluated
232232
at time :math:`t`, becomes a Radon Measure.
233233
234234
The formula that defines this function is the following Bochner integral

src/optimization.py

Lines changed: 33 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,27 @@
1616

1717

1818
def F(curve, w_t):
19-
""" The F(γ) operator, defined as F(γ) = W(γ)/L(γ).
19+
""" The F(γ) operator, minimization target in the insertion step.
2020
2121
Parameters
2222
----------
23-
curve : DGCG.classes.curve class
24-
w_t : DGCG.classes.dual_variable
23+
curve : :py:class:`src.classes.curve`
24+
Curve γ where the F operator is evaluated.
25+
w_t : :py:class:`src.classes.dual_variable`
26+
Dual variable that defines the F operator.
2527
2628
Returns
2729
-------
28-
double number.
30+
float
31+
2932
3033
Notes
3134
-----
32-
When solving the insertion step, this is the main energy to minimize.
35+
The F operator is defined via the dual variable as
36+
37+
.. math::
38+
F(\\gamma) = -\\frac{a_{\\gamma}}{T+1} \\sum_{t=0}^T w_t(\\gamma(t))
39+
3340
"""
3441
assert isinstance(curve, classes.curve) and \
3542
isinstance(w_t, classes.dual_variable)
@@ -41,19 +48,23 @@ def grad_F(curve, w_t):
4148
4249
Parameters
4350
----------
44-
curve : DGCG.classes.curve class
45-
w_t : DGCG.classes.dual_variable
51+
curve : :py:class:`src.classes.curve`
52+
Curve γ where the F operator is evaluated.
53+
w_t : :py:class:`src.classes.dual_variable`
54+
Dual variable that defines the F operator.
4655
4756
Returns
4857
-------
49-
double number.
58+
:py:class:`src.classes.curve`
5059
5160
Notes
5261
-----
53-
We use the gradient to minimize F(γ).
62+
The F operator is defined on the Hilbert space of curves, therefore the
63+
gradient should be a curve.
5464
"""
5565
assert isinstance(curve, classes.curve) and \
5666
isinstance(w_t, classes.dual_variable)
67+
# F = W/L
5768
L_gamma = curve.energy()
5869
W_gamma = -curve.integrate_against(w_t)
5970
# ∇L(γ) computation
@@ -68,15 +79,13 @@ def grad_F(curve, w_t):
6879
w_t_curve = lambda t: w_t.grad_eval(t, curve.eval_discrete(t)).reshape(2)
6980
T = config.T
7081
grad_W_gamma = -np.array([t_weigh[t]*w_t_curve(t) for t in range(T)])
71-
# grad_W_gamma = -np.array([config.time_weights[t] *
72-
# w_t.grad_eval(t, curve.eval_discrete(t)).reshape(2)
73-
# for t in range(config.T)])
7482
# (L(γ)∇W(γ)-W(γ)∇L(γ))/L(γ)²
7583
pos_gradient = (L_gamma*grad_W_gamma - W_gamma*grad_L_gamma)/L_gamma**2
7684
gradient_curve = classes.curve(pos_gradient)
7785
return gradient_curve
7886

79-
def after_optimization_sparsifier(current_measure, energy_curves=None):
87+
88+
def after_optimization_sparsifier(current_measure):
8089
""" Trims a sparse measure by merging atoms that are too close.
8190
8291
Given a measure composed of atoms, it will look for the atoms that are
@@ -85,10 +94,8 @@ def after_optimization_sparsifier(current_measure, energy_curves=None):
8594
8695
Parameters
8796
----------
88-
current_measure : DGCG.classes.measure class
89-
energy_curves : numpy.ndarray, optional
90-
vector indicating the energy of the curves of the measure. To
91-
accelerate the comparisons.
97+
current_measure : :py:class:`src.classes.measure`
98+
Target measure to trim.
9299
93100
Returns
94101
-------
@@ -97,9 +104,13 @@ def after_optimization_sparsifier(current_measure, energy_curves=None):
97104
Notes
98105
-----
99106
This method is required because the quadratic optimization step is realized
100-
by an interior point method. Therefore, it is likely to find minimums in
101-
between two identical items instead of selecting one and discarding the
102-
other.
107+
by an interior point method. Therefore, in the case that there are repeated
108+
(or very close to repeated) atoms in the current measure, the quadratic
109+
optimization step can give positive weights to both of them.
110+
111+
This is not desirable, since besides incrementing the computing power for
112+
the sliding step, we would prefer each atom numerically represented only
113+
once.
103114
"""
104115
output_measure = copy.deepcopy(current_measure)
105116
id1 = 0
@@ -140,6 +151,8 @@ def after_optimization_sparsifier(current_measure, energy_curves=None):
140151
return output_measure
141152

142153
def solve_quadratic_program(current_measure):
154+
"""
155+
"""
143156
assert isinstance(current_measure, classes.measure)
144157
# Build the quadratic system of step 5 and then use some generic python
145158
# solver to get a solution.
@@ -178,32 +191,6 @@ def solve_quadratic_program(current_measure):
178191
logger.status([1, 2, 2], coefficients)
179192
return curves_list, coefficients
180193

181-
def to_positive_semidefinite(Q):
182-
""" Takes a symmetric matrix and returns a positive semidefinite projection
183-
184-
Parameters
185-
----------
186-
Q : numpy.ndarray
187-
symmetric matrix
188-
189-
Returns
190-
-------
191-
numpy.ndarray, symmetric positive semidefinite matrix.
192-
"""
193-
min_eigval = 0
194-
eigval, eigvec = np.linalg.eigh(Q)
195-
if min(eigval) < min_eigval:
196-
# truncate
197-
print("Negative eigenvalues: ",
198-
[eig for eig in eigval if eig < min_eigval])
199-
eigval = np.maximum(eigval, min_eigval)
200-
# Recompute Q = VΣV^(-1)
201-
Q2 = np.linalg.solve(eigvec.T, np.diag(eigval)@eigvec.T).T
202-
print("PSD projection relative norm difference:",
203-
np.linalg.norm(Q-Q2)/np.linalg.norm(Q))
204-
return Q2
205-
return Q
206-
207194
def weight_optimization_step(current_measure):
208195
config.logger.status([1, 2, 1])
209196
# optimizes the coefficients for the current_measure

0 commit comments

Comments
 (0)