src/norms.rs

branch
dev
changeset 59
9226980e45a7
parent 33
75d65fa74eba
child 60
848ecc05becf
--- a/src/norms.rs	Sat Dec 14 09:31:27 2024 -0500
+++ b/src/norms.rs	Tue Dec 31 08:30:02 2024 -0500
@@ -3,18 +3,31 @@
 */
 
 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)]
+/// Helper structure to convert a [`NormExponent`] into a [`Mapping`]
+pub struct NormMapping<F : Float, E : NormExponent>{
+    pub(crate) exponent : E,
+    _phantoms : PhantomData<F>
+}
+
 /// 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 + Send + Sync + 'static {
+    /// Return the norm as a mappin
+    fn as_mapping<F : Float>(self) -> NormMapping<F, Self> {
+        NormMapping{ exponent : self, _phantoms : PhantomData }
+    }
+}
 
 /// Exponent type for the 1-[`Norm`].
 #[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)]
@@ -37,6 +50,15 @@
 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)]
+pub struct PairNorm<A, B, J>(pub A, pub B, pub J);
+
+impl<A, B, J> NormExponent for PairNorm<A, B, J>
+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
@@ -154,3 +176,29 @@
     }
 }
 
+impl<F : Float, E : Norm<F, L2>> Norm<F, L21> for Vec<E> {
+    fn norm(&self, _l21 : L21) -> F {
+        self.iter().map(|e| e.norm(L2)).sum()
+    }
+}
+
+impl<F : Float, E : Dist<F, L2>> Dist<F, L21> for Vec<E> {
+    fn dist(&self, other : &Self, _l21 : L21) -> F {
+        self.iter().zip(other.iter()).map(|(e, g)| e.dist(g, L2)).sum()
+    }
+}
+
+impl<E, F, Domain> Mapping<Domain> for NormMapping<F, E>
+where
+    F : Float,
+    E : NormExponent,
+    Domain : Space + Norm<F, E>,
+{
+    type Codomain = F;
+
+    #[inline]
+    fn apply<I : Instance<Domain>>(&self, x : I) -> F {
+        x.eval(|r| r.norm(self.exponent))
+    }
+}
+

mercurial