diff -r 9e5b9fc81c52 -r 411c6be29fe5 src/norms.rs --- a/src/norms.rs Mon Apr 28 08:26:04 2025 -0500 +++ b/src/norms.rs Mon Apr 28 09:08:45 2025 -0500 @@ -2,79 +2,85 @@ Norms, projections, etc. */ +use crate::euclidean::*; +use crate::mapping::{Instance, Mapping, Space}; +use crate::types::*; use serde::Serialize; use std::marker::PhantomData; -use crate::types::*; -use crate::euclidean::*; -use crate::mapping::{Mapping, Space, Instance}; // // Abstract norms // -#[derive(Copy,Clone,Debug)] +#[derive(Copy, Clone, Debug)] /// Helper structure to convert a [`NormExponent`] into a [`Mapping`] -pub struct NormMapping{ - pub(crate) exponent : E, - _phantoms : PhantomData +pub struct NormMapping { + pub(crate) exponent: E, + _phantoms: PhantomData, } /// An exponent for norms. /// // Just a collection of desirable attributes for a marker type -pub trait NormExponent : Copy + Send + Sync + 'static { +pub trait NormExponent: Copy { /// Return the norm as a mappin - fn as_mapping(self) -> NormMapping { - NormMapping{ exponent : self, _phantoms : PhantomData } + fn as_mapping(self) -> NormMapping { + NormMapping { + exponent: self, + _phantoms: PhantomData, + } } } /// Exponent type for the 1-[`Norm`]. -#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] +#[derive(Copy, Debug, Clone, Serialize, Eq, PartialEq)] pub struct L1; impl NormExponent for L1 {} /// Exponent type for the 2-[`Norm`]. -#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] +#[derive(Copy, Debug, Clone, Serialize, Eq, PartialEq)] pub struct L2; impl NormExponent for L2 {} /// Exponent type for the ∞-[`Norm`]. -#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] +#[derive(Copy, Debug, Clone, Serialize, Eq, PartialEq)] pub struct Linfinity; impl NormExponent for Linfinity {} /// Exponent type for 2,1-[`Norm`]. /// (1-norm over a domain Ω, 2-norm of a vector at each point of the domain.) -#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] +#[derive(Copy, Debug, Clone, Serialize, Eq, PartialEq)] pub struct L21; impl NormExponent for L21 {} /// Norms for pairs (a, b). ‖(a,b)‖ = ‖(‖a‖_A, ‖b‖_B)‖_J /// For use with [`crate::direct_product::Pair`] -#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] +#[derive(Copy, Debug, Clone, Serialize, Eq, PartialEq)] pub struct PairNorm(pub A, pub B, pub J); impl NormExponent for PairNorm -where A : NormExponent, B : NormExponent, J : NormExponent {} - +where + A: NormExponent, + B: NormExponent, + J: NormExponent, +{ +} /// A Huber/Moreau–Yosida smoothed [`L1`] norm. (Not a norm itself.) /// /// The parameter γ of this type is the smoothing factor. Zero means no smoothing, and higher /// values more smoothing. Behaviour with γ < 0 is undefined. -#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] -pub struct HuberL1(pub F); -impl NormExponent for HuberL1 {} +#[derive(Copy, Debug, Clone, Serialize, Eq, PartialEq)] +pub struct HuberL1(pub F); +impl NormExponent for HuberL1 {} /// A Huber/Moreau–Yosida smoothed [`L21`] norm. (Not a norm itself.) /// /// The parameter γ of this type is the smoothing factor. Zero means no smoothing, and higher /// values more smoothing. Behaviour with γ < 0 is undefined. -#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)] -pub struct HuberL21(pub F); -impl NormExponent for HuberL21 {} - +#[derive(Copy, Debug, Clone, Serialize, Eq, PartialEq)] +pub struct HuberL21(pub F); +impl NormExponent for HuberL21 {} /// A normed space (type) with exponent or other type `Exponent` for the norm. /// @@ -86,27 +92,27 @@ /// /// println!("{}, {} {}", x.norm(L1), x.norm(L2), x.norm(Linfinity)) /// ``` -pub trait Norm { +pub trait Norm { /// Calculate the norm. - fn norm(&self, _p : Exponent) -> F; + fn norm(&self, _p: Exponent) -> F; } /// Indicates that the `Self`-[`Norm`] is dominated by the `Exponent`-`Norm` on the space /// `Elem` with the corresponding field `F`. -pub trait Dominated { +pub trait Dominated { /// Indicates the factor $c$ for the inequality $‖x‖ ≤ C ‖x‖_p$. - fn norm_factor(&self, p : Exponent) -> F; + fn norm_factor(&self, p: Exponent) -> F; /// Given a norm-value $‖x‖_p$, calculates $C‖x‖_p$ such that $‖x‖ ≤ C‖x‖_p$ #[inline] - fn from_norm(&self, p_norm : F, p : Exponent) -> F { + fn from_norm(&self, p_norm: F, p: Exponent) -> F { p_norm * self.norm_factor(p) } } /// Trait for distances with respect to a norm. -pub trait Dist : Norm + Space { +pub trait Dist: Norm + Space { /// Calculate the distance - fn dist>(&self, other : I, _p : Exponent) -> F; + fn dist>(&self, other: I, _p: Exponent) -> F; } /// Trait for Euclidean projections to the `Exponent`-[`Norm`]-ball. @@ -119,16 +125,18 @@ /// /// println!("{:?}, {:?}", x.proj_ball(1.0, L2), x.proj_ball(0.5, Linfinity)); /// ``` -pub trait Projection : Norm + Sized -where F : Float { +pub trait Projection: Norm + Sized +where + F: Float, +{ /// Projection of `self` to the `q`-norm-ball of radius ρ. - fn proj_ball(mut self, ρ : F, q : Exponent) -> Self { + fn proj_ball(mut self, ρ: F, q: Exponent) -> Self { self.proj_ball_mut(ρ, q); self } /// In-place projection of `self` to the `q`-norm-ball of radius ρ. - fn proj_ball_mut(&mut self, ρ : F, q : Exponent); + fn proj_ball_mut(&mut self, ρ: F, q: Exponent); } /*impl> Norm for E { @@ -138,25 +146,29 @@ fn dist(&self, other : &Self, _p : L2) -> F { self.dist2(other) } }*/ -impl + Norm> Projection for E { +impl + Norm> Projection for E { #[inline] - fn proj_ball(self, ρ : F, _p : L2) -> Self { self.proj_ball2(ρ) } + fn proj_ball(self, ρ: F, _p: L2) -> Self { + self.proj_ball2(ρ) + } #[inline] - fn proj_ball_mut(&mut self, ρ : F, _p : L2) { self.proj_ball2_mut(ρ) } + fn proj_ball_mut(&mut self, ρ: F, _p: L2) { + self.proj_ball2_mut(ρ) + } } -impl HuberL1 { - fn apply(self, xnsq : F) -> F { +impl HuberL1 { + fn apply(self, xnsq: F) -> F { let HuberL1(γ) = self; let xn = xnsq.sqrt(); if γ == F::ZERO { xn } else { if xn > γ { - xn-γ / F::TWO - } else if xn<(-γ) { - -xn-γ / F::TWO + xn - γ / F::TWO + } else if xn < (-γ) { + -xn - γ / F::TWO } else { xnsq / (F::TWO * γ) } @@ -164,14 +176,14 @@ } } -impl> Norm> for E { - fn norm(&self, huber : HuberL1) -> F { +impl> Norm> for E { + fn norm(&self, huber: HuberL1) -> F { huber.apply(self.norm2_squared()) } } -impl> Dist> for E { - fn dist>(&self, other : I, huber : HuberL1) -> F { +impl> Dist> for E { + fn dist>(&self, other: I, huber: HuberL1) -> F { huber.apply(self.dist2_squared(other)) } } @@ -190,20 +202,20 @@ impl Mapping for NormMapping where - F : Float, - E : NormExponent, - Domain : Space + Norm, + F: Float, + E: NormExponent, + Domain: Space + Norm, { type Codomain = F; #[inline] - fn apply>(&self, x : I) -> F { + fn apply>(&self, x: I) -> F { x.eval(|r| r.norm(self.exponent)) } } -pub trait Normed : Space + Norm { - type NormExp : NormExponent; +pub trait Normed: Space + Norm { + type NormExp: NormExponent; fn norm_exponent(&self) -> Self::NormExp; @@ -217,30 +229,28 @@ fn is_zero(&self) -> bool; } -pub trait HasDual : Normed { - type DualSpace : Normed; +pub trait HasDual: Normed { + type DualSpace: Normed; } /// Automatically implemented trait for reflexive spaces -pub trait Reflexive : HasDual +pub trait Reflexive: HasDual where - Self::DualSpace : HasDual -{ } + Self::DualSpace: HasDual, +{ +} -impl> Reflexive for X -where - X::DualSpace : HasDual -{ } +impl> Reflexive for X where X::DualSpace: HasDual {} -pub trait HasDualExponent : NormExponent { - type DualExp : NormExponent; +pub trait HasDualExponent: NormExponent { + type DualExp: NormExponent; fn dual_exponent(&self) -> Self::DualExp; } impl HasDualExponent for L2 { type DualExp = L2; - + #[inline] fn dual_exponent(&self) -> Self::DualExp { L2 @@ -249,17 +259,16 @@ impl HasDualExponent for L1 { type DualExp = Linfinity; - + #[inline] fn dual_exponent(&self) -> Self::DualExp { Linfinity } } - impl HasDualExponent for Linfinity { type DualExp = L1; - + #[inline] fn dual_exponent(&self) -> Self::DualExp { L1 @@ -271,49 +280,50 @@ ($exponent : ty) => { impl Norm> for D where - F : Float, - D : Norm, - C : Constant, + F: Float, + D: Norm, + C: Constant, { - fn norm(&self, e : Weighted<$exponent, C>) -> F { + fn norm(&self, e: Weighted<$exponent, C>) -> F { let v = e.weight.value(); assert!(v > F::ZERO); v * self.norm(e.base_fn) } } - impl NormExponent for Weighted<$exponent, C> {} + impl NormExponent for Weighted<$exponent, C> {} - impl HasDualExponent for Weighted<$exponent, C> - where $exponent : HasDualExponent { + impl HasDualExponent for Weighted<$exponent, C> + where + $exponent: HasDualExponent, + { type DualExp = Weighted<<$exponent as HasDualExponent>::DualExp, C::Type>; fn dual_exponent(&self) -> Self::DualExp { Weighted { - weight : C::Type::ONE / self.weight.value(), - base_fn : self.base_fn.dual_exponent() + weight: C::Type::ONE / self.weight.value(), + base_fn: self.base_fn.dual_exponent(), } } } - impl Projection> for T + impl Projection> for T where - T : Projection, - F : Float, - C : Constant, + T: Projection, + F: Float, + C: Constant, { - fn proj_ball(self, ρ : F, q : Weighted<$exponent , C>) -> Self { + fn proj_ball(self, ρ: F, q: Weighted<$exponent, C>) -> Self { self.proj_ball(ρ / q.weight.value(), q.base_fn) } - fn proj_ball_mut(&mut self, ρ : F, q : Weighted<$exponent , C>) { + fn proj_ball_mut(&mut self, ρ: F, q: Weighted<$exponent, C>) { self.proj_ball_mut(ρ / q.weight.value(), q.base_fn) } } - } + }; } //impl_weighted_norm!(L1); //impl_weighted_norm!(L2); //impl_weighted_norm!(Linfinity); -