src/fb.rs

changeset 98
b9818eb24b47
parent 93
8f1e57821d76
--- a/src/fb.rs	Fri Aug 14 10:38:27 2026 -0500
+++ b/src/fb.rs	Fri Oct 02 12:03:25 2026 -0500
@@ -79,17 +79,19 @@
 
 use crate::domain::{AdmissibleDomain, FullSpace};
 use crate::measures::merging::SpikeMerging;
-use crate::measures::DiscreteMeasure;
+use crate::measures::{DiscreteMeasure, Radon};
 use crate::plot::Plotter;
 pub use crate::prox_penalty::{InsertionConfig, ProxPenalty, StepLengthBound};
 use crate::regularisation::RegTerm;
 use crate::types::*;
+use alg_tools::bounds::MinMaxMapping;
 use alg_tools::error::DynResult;
 use alg_tools::instance::Instance;
 use alg_tools::iterate::AlgIteratorFactory;
 use alg_tools::linops::Space;
 use alg_tools::mapping::DifferentiableMapping;
 use alg_tools::nalgebra_support::ToNalgebraRealField;
+use alg_tools::norms::Norm;
 use colored::Colorize;
 use measures::DeltaMeasure;
 use numeric_literals::replace_float_literals;
@@ -168,9 +170,9 @@
     U: Space + Clone,
     F: Float + ToNalgebraRealField,
     I: AlgIteratorFactory<IterInfo<F>>,
-    DiscreteMeasure<U, F>: SpikeMerging<F>,
+    DiscreteMeasure<U, F>: SpikeMerging<F> + Norm<Radon, F>,
     Dat: DifferentiableMapping<DiscreteMeasure<U, F>, Codomain = F>,
-    Dat::DerivativeDomain: ClosedMul<F>,
+    Dat::DerivativeDomain: ClosedMul<F> + MinMaxMapping<U, F>,
     Reg: RegTerm<U, F>,
     P: ProxPenalty<U, Dat::DerivativeDomain, Reg, F> + StepLengthBound<F, Dat>,
     Plot: Plotter<P::ReturnMapping, Dat::DerivativeDomain, DiscreteMeasure<U, F>>,
@@ -187,23 +189,26 @@
     let mut μ = μ0.unwrap_or_else(|| DiscreteMeasure::new());
 
     // Statistics
-    let full_stats = |μ: &DiscreteMeasure<U, F>, ε, stats| IterInfo {
-        value: f.apply(μ) + reg.apply(μ),
-        n_spikes: μ.len(),
-        ε,
-        //postprocessing: config.postprocessing.then(|| μ.clone()),
-        ..stats
-    };
+    let full_stats =
+        |μ: &DiscreteMeasure<U, F>, τv: &mut Dat::DerivativeDomain, ε, stats| IterInfo {
+            value: f.apply(μ) + reg.apply(μ),
+            n_spikes: μ.len(),
+            μ_norm: μ.norm(Radon),
+            ε,
+            discrepancy: Some(reg.discrepancy(τv, τ, ε, μ, config)),
+            //postprocessing: config.postprocessing.then(|| μ.clone()),
+            ..stats
+        };
     let mut stats = IterInfo::new();
 
+    // Calculate smooth part of surrogate model.
+    let mut τv = f.differential(&μ) * τ;
+
     // Run the algorithm
-    for state in iterator.iter_init(|| full_stats(&μ, ε, stats.clone())) {
+    for state in iterator.iter_init(|| full_stats(&μ, &mut τv, ε, stats.clone())) {
         let maybe_μ_base = config.if_merge_now_check(&state, || μ.clone());
         let μ_base_len = μ.len();
 
-        // Calculate smooth part of surrogate model.
-        let mut τv = f.differential(&μ) * τ;
-
         // Do spike insertiona nd finite-dimensional weight optimisation
         prox_penalty.insert_and_reweigh(&mut μ, &mut τv, τ, ε, config, &reg, &state, &mut stats)?;
 
@@ -256,10 +261,18 @@
         let iter = state.iteration();
         stats.this_iters += 1;
 
+        // Calculate smooth part of surrogate model.
+        τv = f.differential(&μ) * τ;
+
         // Give statistics if needed
         state.if_verbose(|| {
             plotter.plot_spikes(iter, None, Some(&τv), &μ);
-            full_stats(&μ, ε, std::mem::replace(&mut stats, IterInfo::new()))
+            full_stats(
+                &μ,
+                &mut τv,
+                ε,
+                std::mem::replace(&mut stats, IterInfo::new()),
+            )
         });
 
         // Update main tolerance for next iteration
@@ -284,9 +297,9 @@
     U: Space + Clone,
     F: Float + ToNalgebraRealField,
     I: AlgIteratorFactory<IterInfo<F>>,
-    DiscreteMeasure<U, F>: SpikeMerging<F>,
+    DiscreteMeasure<U, F>: SpikeMerging<F> + Norm<Radon, F>,
     Dat: DifferentiableMapping<DiscreteMeasure<U, F>, Codomain = F>,
-    Dat::DerivativeDomain: ClosedMul<F>,
+    Dat::DerivativeDomain: ClosedMul<F> + MinMaxMapping<U, F>,
     Reg: RegTerm<U, F>,
     P: ProxPenalty<U, Dat::DerivativeDomain, Reg, F> + StepLengthBound<F, Dat>,
     Plot: Plotter<P::ReturnMapping, Dat::DerivativeDomain, DiscreteMeasure<U, F>>,
@@ -330,7 +343,7 @@
     I: AlgIteratorFactory<IterInfo<F>>,
     DiscreteMeasure<U, F>: SpikeMerging<F>,
     Dat: DifferentiableMapping<DiscreteMeasure<U, F>, Codomain = F>,
-    Dat::DerivativeDomain: ClosedMul<F>,
+    Dat::DerivativeDomain: ClosedMul<F> + MinMaxMapping<U, F>,
     Reg: RegTerm<U, F>,
     P: ProxPenalty<U, Dat::DerivativeDomain, Reg, F> + StepLengthBound<F, Dat>,
     Plot: Plotter<P::ReturnMapping, Dat::DerivativeDomain, DiscreteMeasure<U, F>>,
@@ -350,17 +363,21 @@
     let mut warned_merging = false;
 
     // Statistics
-    let full_stats = |ν: &DiscreteMeasure<U, F>, ε, stats| IterInfo {
+    let full_stats = |ν: &DiscreteMeasure<U, F>,
+                      maybe_τv: Option<&mut Dat::DerivativeDomain>,
+                      ε,
+                      stats| IterInfo {
         value: f.apply(ν) + reg.apply(ν),
         n_spikes: ν.len(),
         ε,
+        discrepancy: maybe_τv.map(|τv| reg.discrepancy(τv, τ, ε, ν, config)),
         // postprocessing: config.postprocessing.then(|| ν.clone()),
         ..stats
     };
     let mut stats = IterInfo::new();
 
     // Run the algorithm
-    for state in iterator.iter_init(|| full_stats(&μ, ε, stats.clone())) {
+    for state in iterator.iter_init(|| full_stats(&μ, None, ε, stats.clone())) {
         let μ_base_len = μ.len();
         // Calculate smooth part of surrogate model.
         let mut τv = f.differential(&μ) * τ;
@@ -410,7 +427,12 @@
         // Give statistics if needed
         state.if_verbose(|| {
             plotter.plot_spikes(iter, None, Some(&τv), &μ_prev);
-            full_stats(&μ_prev, ε, std::mem::replace(&mut stats, IterInfo::new()))
+            full_stats(
+                &μ_prev,
+                Some(&mut τv),
+                ε,
+                std::mem::replace(&mut stats, IterInfo::new()),
+            )
         });
 
         // Update main tolerance for next iteration

mercurial