--- 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();