src/sliding_fb.rs

changeset 98
b9818eb24b47
parent 93
8f1e57821d76
--- a/src/sliding_fb.rs	Fri Aug 14 10:38:27 2026 -0500
+++ b/src/sliding_fb.rs	Fri Oct 02 12:03:25 2026 -0500
@@ -1006,7 +1006,7 @@
     Dat::DerivativeDomain:
         DifferentiableMapping<U, Codomain = F> + ClosedMul<F> + MinMaxMapping<U, F>,
     //for<'a> Dat::Differential<'a>: Lipschitz<&'a P, FloatType = F>,
-    DiscreteMeasure<U, F>: SpikeMerging<F>,
+    DiscreteMeasure<U, F>: SpikeMerging<F> + Norm<Radon, F>,
     Reg: SlidingRegTerm<U, F>,
     P: TransportProxPenalty<U, Dat::DerivativeDomain, Reg, F> + StepLengthBound<F, Dat>,
     Plot: Plotter<P::ReturnMapping, Dat::DerivativeDomain, DiscreteMeasure<U, F>>,
@@ -1038,19 +1038,23 @@
     let mut ε = tolerance.initial();
 
     // Statistics
-    let full_stats = |μ: &DiscreteMeasure<U, F>, ε, stats| IterInfo {
-        value: f.apply(μ) + reg.apply(μ),
-        n_spikes: μ.len(),
-        ε,
-        // postprocessing: config.insertion.postprocessing.then(|| μ.clone()),
-        ..stats
-    };
+    let full_stats =
+        |μ: &DiscreteMeasure<U, F>, v: &mut Dat::DerivativeDomain, ε, stats| IterInfo {
+            value: f.apply(μ) + reg.apply(μ),
+            n_spikes: μ.len(),
+            discrepancy: Some(τ * reg.discrepancy(v, 1.0, ε / τ, μ, &config.insertion)),
+            μ_norm: μ.norm(Radon),
+            ε,
+            // postprocessing: config.insertion.postprocessing.then(|| μ.clone()),
+            ..stats
+        };
     let mut stats = IterInfo::new();
 
+    // Construct initial smooth part of surrogate model
+    let mut v = f.differential(&μ);
+
     // Run the algorithm
-    for state in iterator.iter_init(|| full_stats(&μ, ε, stats.clone())) {
-        let mut v = f.differential(&μ);
-
+    for state in iterator.iter_init(|| full_stats(&μ, &mut v, ε, stats.clone())) {
         // Calculate initial transport
         prox_penalty.initial_transport(
             &mut γ,
@@ -1164,10 +1168,18 @@
         let iter = state.iteration();
         stats.this_iters += 1;
 
+        // Update smooth part of surrogate model
+        v = f.differential(&μ);
+
         // Give statistics if requested
         state.if_verbose(|| {
-            plotter.plot_spikes(iter, None, Some(&τv̆), &μ);
-            full_stats(&μ, ε, std::mem::replace(&mut stats, IterInfo::new()))
+            plotter.plot_spikes(iter, None, Some(&v), &μ);
+            full_stats(
+                &μ,
+                &mut v,
+                ε,
+                std::mem::replace(&mut stats, IterInfo::new()),
+            )
         });
 
         // Update main tolerance for next iteration
@@ -1198,7 +1210,7 @@
     Dat::DerivativeDomain:
         DifferentiableMapping<U, Codomain = F> + ClosedMul<F> + MinMaxMapping<U, F>,
     //for<'a> Dat::Differential<'a>: Lipschitz<&'a P, FloatType = F>,
-    DiscreteMeasure<U, F>: SpikeMerging<F>,
+    DiscreteMeasure<U, F>: SpikeMerging<F> + Norm<Radon, F>,
     Reg: SlidingRegTerm<U, F>,
     P: TransportProxPenalty<U, Dat::DerivativeDomain, Reg, F> + StepLengthBound<F, Dat>,
     Plot: Plotter<P::ReturnMapping, Dat::DerivativeDomain, DiscreteMeasure<U, F>>,

mercurial