src/frank_wolfe.rs

changeset 2
7a953a87b6c1
parent 0
eb3c7813b67a
--- a/src/frank_wolfe.rs	Thu Dec 01 23:07:35 2022 +0200
+++ b/src/frank_wolfe.rs	Tue Nov 29 15:36:12 2022 +0200
@@ -52,10 +52,10 @@
 };
 use crate::forward_model::ForwardModel;
 #[allow(unused_imports)] // Used in documentation
-use crate::subproblem::{
-    quadratic_nonneg,
-    InnerSettings,
-    InnerMethod,
+use crate::subproblem::InnerSettings;
+use crate::weight_optim::{
+    prepare_optimise_weights,
+    optimise_weights_l2
 };
 use crate::tolerance::Tolerance;
 use crate::plot::{
@@ -104,75 +104,6 @@
     }
 }
 
-/// Helper struct for pre-initialising the finite-dimensional subproblems solver
-/// [`prepare_optimise_weights`].
-///
-/// The pre-initialisation is done by [`prepare_optimise_weights`].
-pub struct FindimData<F : Float> {
-    opAnorm_squared : F
-}
-
-/// Return a pre-initialisation struct for [`prepare_optimise_weights`].
-///
-/// The parameter `opA` is the forward operator $A$.
-pub fn prepare_optimise_weights<F, A, const N : usize>(opA : &A) -> FindimData<F>
-where F : Float + ToNalgebraRealField,
-      A : ForwardModel<Loc<F, N>, F> {
-    FindimData{
-        opAnorm_squared : opA.opnorm_bound().powi(2)
-    }
-}
-
-/// Solve the finite-dimensional weight optimisation problem for the 2-norm-squared data fidelity
-/// point source localisation problem.
-///
-/// That is, we minimise
-/// <div>$$
-///     μ ↦ \frac{1}{2}\|Aμ-b\|_w^2 + α\|μ\|_ℳ + δ_{≥ 0}(μ)
-/// $$</div>
-/// only with respect to the weights of $μ$.
-///
-/// The parameter `μ` is the discrete measure whose weights are to be optimised.
-/// The `opA` parameter is the forward operator $A$, while `b`$ and `α` are as in the
-/// objective above. The method parameter are set in `inner` (see [`InnerSettings`]), while
-/// `iterator` is used to iterate the steps of the method, and `plotter` may be used to
-/// save intermediate iteration states as images. The parameter `findim_data` should be
-/// prepared using [`prepare_optimise_weights`]:
-///
-/// Returns the number of iterations taken by the method configured in `inner`.
-pub fn optimise_weights<'a, F, A, I, const N : usize>(
-    μ : &mut DiscreteMeasure<Loc<F, N>, F>,
-    opA : &'a A,
-    b : &A::Observable,
-    α : F,
-    findim_data : &FindimData<F>,
-    inner : &InnerSettings<F>,
-    iterator : I
-) -> usize
-where F : Float + ToNalgebraRealField,
-      I : AlgIteratorFactory<F>,
-      A : ForwardModel<Loc<F, N>, F>
-{
-    // Form and solve finite-dimensional subproblem.
-    let (Ã, g̃) = opA.findim_quadratic_model(&μ, b);
-    let mut x = μ.masses_dvector();
-
-    // `inner_τ1` is based on an estimate of the operator norm of $A$ from ℳ(Ω) to
-    // ℝ^n. This estimate is a good one for the matrix norm from ℝ^m to ℝ^n when the
-    // former is equipped with the 1-norm. We need the 2-norm. To pass from 1-norm to
-    // 2-norm, we estimate
-    //      ‖A‖_{2,2} := sup_{‖x‖_2 ≤ 1} ‖Ax‖_2 ≤ sup_{‖x‖_1 ≤ C} ‖Ax‖_2
-    //                 = C sup_{‖x‖_1 ≤ 1} ‖Ax‖_2 = C ‖A‖_{1,2},
-    // where C = √m satisfies ‖x‖_1 ≤ C ‖x‖_2. Since we are intested in ‖A_*A‖, no
-    // square root is needed when we scale:
-    let inner_τ = inner.τ0 / (findim_data.opAnorm_squared * F::cast_from(μ.len()));
-    let iters = quadratic_nonneg(inner.method, &Ã, &g̃, α, &mut x, inner_τ, iterator);
-    // Update masses of μ based on solution of finite-dimensional subproblem.
-    μ.set_masses_dvector(&x);
-
-    iters
-}
-
 /// Solve point source localisation problem using a conditional gradient method
 /// for the 2-norm-squared data fidelity, i.e., the problem
 /// <div>$$
@@ -279,7 +210,7 @@
             }
         };
 
-        inner_iters += optimise_weights(&mut μ, opA, b, α, &findim_data, &config.inner, inner_it);
+        inner_iters += optimise_weights_l2(&mut μ, opA, b, α, &findim_data, &config.inner, inner_it);
    
         // Merge spikes and update residual for next step and `if_verbose` below.
         let n_before_merge = μ.len();

mercurial