--- a/src/types.rs Tue Aug 01 10:25:09 2023 +0300 +++ b/src/types.rs Mon Feb 17 13:54:53 2025 -0500 @@ -4,7 +4,6 @@ use colored::ColoredString; use serde::{Serialize, Deserialize}; -use clap::ValueEnum; use alg_tools::iterate::LogRepr; use alg_tools::euclidean::Euclidean; use alg_tools::norms::{Norm, L1}; @@ -13,7 +12,7 @@ pub use alg_tools::loc::Loc; pub use alg_tools::sets::Cube; -use crate::measures::DiscreteMeasure; +// use crate::measures::DiscreteMeasure; /// [`Float`] with extra display and string conversion traits such that [`clap`] doesn't choke up. pub trait ClapFloat : Float @@ -27,31 +26,74 @@ pub struct IterInfo<F : Float, const N : usize> { /// Function value pub value : F, - /// Number of speaks + /// Number of spikes pub n_spikes : usize, /// Number of iterations this statistic covers pub this_iters : usize, + /// Number of spikes inserted since last IterInfo statistic + pub inserted : usize, /// Number of spikes removed by merging since last IterInfo statistic pub merged : usize, /// Number of spikes removed by pruning since last IterInfo statistic pub pruned : usize, /// Number of inner iterations since last IterInfo statistic pub inner_iters : usize, + /// Tuple of (transported mass, source mass) + pub untransported_fraction : Option<(F, F)>, + /// Tuple of (|destination mass - untransported_mass|, transported mass) + pub transport_error : Option<(F, F)>, /// Current tolerance pub ε : F, - /// Solve fin.dim problem for this measure to get the optimal `value`. - pub postprocessing : Option<DiscreteMeasure<Loc<F, N>, F>>, + // /// Solve fin.dim problem for this measure to get the optimal `value`. + // pub postprocessing : Option<RNDM<F, N>>, } +impl<F : Float, const N : usize> IterInfo<F, N> { + /// Initialise statistics with zeros. `ε` and `value` are unspecified. + pub fn new() -> Self { + IterInfo { + value : F::NAN, + n_spikes : 0, + this_iters : 0, + merged : 0, + inserted : 0, + pruned : 0, + inner_iters : 0, + ε : F::NAN, + // postprocessing : None, + untransported_fraction : None, + transport_error : None, + } + } +} + +#[replace_float_literals(F::cast_from(literal))] impl<F, const N : usize> LogRepr for IterInfo<F, N> where F : LogRepr + Float { fn logrepr(&self) -> ColoredString { - format!("{}\t| N = {}, ε = {:.8}, inner_iters_mean = {}, merged+pruned_mean = {}+{}", + format!("{}\t| N = {}, ε = {:.8}, 𝔼inner_it = {}, 𝔼ins/mer/pru = {}/{}/{}{}{}", self.value.logrepr(), self.n_spikes, self.ε, - self.inner_iters as float / self.this_iters as float, - self.merged as float / self.this_iters as float, - self.pruned as float / self.this_iters as float, + self.inner_iters as float / self.this_iters.max(1) as float, + self.inserted as float / self.this_iters.max(1) as float, + self.merged as float / self.this_iters.max(1) as float, + self.pruned as float / self.this_iters.max(1) as float, + match self.untransported_fraction { + None => format!(""), + Some((a, b)) => if b > 0.0 { + format!(", untransported {:.2}%", 100.0*a/b) + } else { + format!("") + } + }, + match self.transport_error { + None => format!(""), + Some((a, b)) => if b > 0.0 { + format!(", transport error {:.2}%", 100.0*a/b) + } else { + format!("") + } + } ).as_str().into() } } @@ -78,7 +120,7 @@ } /// Data term type -#[derive(Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug, ValueEnum)] +#[derive(Clone, Copy, PartialEq, Serialize, Deserialize, Debug)] pub enum DataTerm { /// $\\|z\\|\_2^2/2$ L2Squared, @@ -95,3 +137,24 @@ } } } + +/// Type for indicating norm-2-squared data fidelity or transport cost. +#[derive(Clone, Copy, Serialize, Deserialize)] +pub struct L2Squared; + +/// Trait for indicating that `Self` is Lipschitz with respect to the (semi)norm `D`. +pub trait Lipschitz<M> { + /// The type of floats + type FloatType : Float; + + /// Returns the Lipschitz factor of `self` with respect to the (semi)norm `D`. + fn lipschitz_factor(&self, seminorm : M) -> Option<Self::FloatType>; +} + +/// Trait for norm-bounded functions. +pub trait NormBounded<M> { + type FloatType : Float; + + /// Returns a bound on the values of this function object in the `M`-norm. + fn norm_bound(&self, m : M) -> Self::FloatType; +}