src/sliding_fb.rs

branch
dev
changeset 44
03251c546744
parent 41
b6bdb6cb4d44
child 45
5200e7090e06
--- a/src/sliding_fb.rs	Thu Jan 23 23:39:40 2025 +0100
+++ b/src/sliding_fb.rs	Fri Jan 31 18:00:17 2025 -0500
@@ -22,7 +22,7 @@
 use crate::forward_model::{
     ForwardModel,
     AdjointProductBoundedBy,
-    LipschitzValues,
+    BoundedCurvature,
 };
 //use crate::tolerance::Tolerance;
 use crate::plot::{
@@ -99,6 +99,7 @@
 /// Internal type of adaptive transport step length calculation
 pub(crate) enum TransportStepLength<F : Float, G : Fn(F, F) -> F> {
     /// Fixed, known step length
+    #[allow(dead_code)]
     Fixed(F),
     /// Adaptive step length, only wrt. maximum transport.
     /// Content of `l` depends on use case, while `g` calculates the step length from `l`.
@@ -158,16 +159,16 @@
                 ρ.x = δ.x - v.differential(&δ.x) * (ρ.α.signum() * θτ);
             }
         },
-        AdaptiveMax{ l : ℓ_v, ref mut max_transport, g : ref calculate_θ } => {
+        AdaptiveMax{ l : ℓ_F, ref mut max_transport, g : ref calculate_θ } => {
             *max_transport = max_transport.max(γ1.norm(Radon));
-            let θτ = τ * calculate_θ(ℓ_v, *max_transport);
+            let θτ = τ * calculate_θ(ℓ_F, *max_transport);
             for (δ, ρ) in izip!(μ.iter_spikes(), γ1.iter_spikes_mut()) {
                 ρ.x = δ.x - v.differential(&δ.x) * (ρ.α.signum() * θτ);
             }
         },
-        FullyAdaptive{ l : ref mut adaptive_ℓ_v, ref mut max_transport, g : ref calculate_θ } => {
+        FullyAdaptive{ l : ref mut adaptive_ℓ_F, ref mut max_transport, g : ref calculate_θ } => {
             *max_transport = max_transport.max(γ1.norm(Radon));
-            let mut θ = calculate_θ(*adaptive_ℓ_v, *max_transport);
+            let mut θ = calculate_θ(*adaptive_ℓ_F, *max_transport);
             // Do two runs through the spikes to update θ, breaking if first run did not cause
             // a change.
             for _i in 0..=1 {
@@ -179,9 +180,9 @@
                     let n = g.norm2();
                     if n >= F::EPSILON {
                         // Estimate Lipschitz factor of ∇v
-                        let this_ℓ_v = (dv_x - v.differential(&ρ.x)).norm2() / n;
-                        *adaptive_ℓ_v = adaptive_ℓ_v.max(this_ℓ_v);
-                        θ = calculate_θ(*adaptive_ℓ_v, *max_transport);
+                        let this_ℓ_F = (dv_x - v.differential(&ρ.x)).norm2() / n;
+                        *adaptive_ℓ_F = adaptive_ℓ_F.max(this_ℓ_F);
+                        θ = calculate_θ(*adaptive_ℓ_F, *max_transport);
                         changes = true
                     }
                 }
@@ -274,10 +275,9 @@
     F : Float + ToNalgebraRealField,
     I : AlgIteratorFactory<IterInfo<F, N>>,
     A : ForwardModel<RNDM<F, N>, F>
-        + AdjointProductBoundedBy<RNDM<F, N>, P, FloatType=F>,
-        //+ TransportLipschitz<L2Squared, FloatType=F>,
+        + AdjointProductBoundedBy<RNDM<F, N>, P, FloatType=F>
+        + BoundedCurvature<FloatType=F>,
     for<'b> &'b A::Observable : std::ops::Neg<Output=A::Observable> + Instance<A::Observable>,
-    for<'b> A::Preadjoint<'b> : LipschitzValues<FloatType=F>,
     A::PreadjointCodomain : DifferentiableRealMapping<F, N>,
     RNDM<F, N> : SpikeMerging<F>,
     Reg : SlidingRegTerm<F, N>,
@@ -301,12 +301,19 @@
     //let ℓ = opA.transport.lipschitz_factor(L2Squared) * max_transport;
     let ℓ = 0.0;
     let τ = config.τ0 / opA.adjoint_product_bound(prox_penalty).unwrap();
-    let calculate_θ = |ℓ_v, _| config.transport.θ0 / (τ*(ℓ + ℓ_v));
-    let mut θ_or_adaptive = match opA.preadjoint().value_diff_unit_lipschitz_factor() {
-        // We only estimate w (the uniform Lipschitz for of v), if we also estimate ℓ_v
-        // (the uniform Lipschitz factor of ∇v).
-        // We assume that the residual is decreasing.
-        Some(ℓ_v0) => TransportStepLength::Fixed(calculate_θ(ℓ_v0 * b.norm2(), 0.0)),
+    let (maybe_ℓ_v0, maybe_transport_lip) = opA.curvature_bound_components();
+    let transport_lip = maybe_transport_lip.unwrap();
+    let calculate_θ = |ℓ_v, max_transport| {
+        let ℓ_F = ℓ_v + transport_lip * max_transport;
+        config.transport.θ0 / (τ*(ℓ + ℓ_F))
+    };
+    let mut θ_or_adaptive = match maybe_ℓ_v0 {
+        //Some(ℓ_v0) => TransportStepLength::Fixed(calculate_θ(ℓ_v0 * b.norm2(), 0.0)),
+        Some(ℓ_v0) => TransportStepLength::AdaptiveMax {
+            l: ℓ_v0 * b.norm2(), // TODO: could estimate computing the real reesidual
+            max_transport : 0.0,
+            g : calculate_θ
+        },
         None => TransportStepLength::FullyAdaptive {
             l : 10.0 * F::EPSILON, // Start with something very small to estimate differentials
             max_transport : 0.0,

mercurial