src/mapping.rs

branch
dev
changeset 99
9e5b9fc81c52
parent 75
e9f4550cfa18
child 102
aead46a19767
--- a/src/mapping.rs	Sun Apr 27 20:41:36 2025 -0500
+++ b/src/mapping.rs	Mon Apr 28 08:26:04 2025 -0500
@@ -2,84 +2,95 @@
 Traits for mathematical functions.
 */
 
-use std::marker::PhantomData;
-use std::borrow::Cow;
-use crate::types::{Num, Float, ClosedMul};
+pub use crate::instance::{BasicDecomposition, Decomposition, Instance, Space};
 use crate::loc::Loc;
-pub use crate::instance::{Instance, Decomposition, BasicDecomposition, Space};
 use crate::norms::{Norm, NormExponent};
-use crate::operator_arithmetic::{Weighted, Constant};
+use crate::operator_arithmetic::{Constant, Weighted};
+use crate::types::{ClosedMul, Float, Num};
+use std::borrow::Cow;
+use std::marker::PhantomData;
 
 /// A mapping from `Domain` to `Self::Codomain`.
-pub trait Mapping<Domain : Space> {
-    type Codomain : Space;
+pub trait Mapping<Domain: Space> {
+    type Codomain: Space;
 
     /// Compute the value of `self` at `x`.
-    fn apply<I : Instance<Domain>>(&self, x : I) -> Self::Codomain;
+    fn apply<I: Instance<Domain>>(&self, x: I) -> Self::Codomain;
 
     #[inline]
     /// Form the composition `self ∘ other`
-    fn compose<X : Space, T : Mapping<X, Codomain=Domain>>(self, other : T)
-        -> Composition<Self, T>
+    fn compose<X: Space, T: Mapping<X, Codomain = Domain>>(self, other: T) -> Composition<Self, T>
     where
-        Self : Sized
+        Self: Sized,
     {
-        Composition{ outer : self, inner : other, intermediate_norm_exponent : () }
+        Composition {
+            outer: self,
+            inner: other,
+            intermediate_norm_exponent: (),
+        }
     }
 
-
     #[inline]
     /// Form the composition `self ∘ other`, assigning a norm to the inermediate space
-    fn compose_with_norm<F, X, T, E>(
-        self, other : T, norm : E
-    )  -> Composition<Self, T, E>
+    fn compose_with_norm<F, X, T, E>(self, other: T, norm: E) -> Composition<Self, T, E>
     where
-        Self : Sized,
-        X : Space,
-        T : Mapping<X, Codomain=Domain>,
-        E : NormExponent,
-        Domain : Norm<F, E>,
-        F : Num
+        Self: Sized,
+        X: Space,
+        T: Mapping<X, Codomain = Domain>,
+        E: NormExponent,
+        Domain: Norm<F, E>,
+        F: Num,
     {
-        Composition{ outer : self, inner : other, intermediate_norm_exponent : norm }
+        Composition {
+            outer: self,
+            inner: other,
+            intermediate_norm_exponent: norm,
+        }
     }
 
     /// Multiply `self` by the scalar `a`.
     #[inline]
-    fn weigh<C>(self, a : C) -> Weighted<Self, C>
+    fn weigh<C>(self, a: C) -> Weighted<Self, C>
     where
-        Self : Sized,
-        C : Constant,
-        Self::Codomain : ClosedMul<C::Type>,
+        Self: Sized,
+        C: Constant,
+        Self::Codomain: ClosedMul<C::Type>,
     {
-        Weighted { weight : a, base_fn : self }
+        Weighted {
+            weight: a,
+            base_fn: self,
+        }
     }
 }
 
 /// Automatically implemented shorthand for referring to [`Mapping`]s from [`Loc<F, N>`] to `F`.
-pub trait RealMapping<F : Float, const N : usize>
-: Mapping<Loc<F, N>, Codomain = F> {}
+pub trait RealMapping<F: Float, const N: usize>: Mapping<Loc<F, N>, Codomain = F> {}
 
-impl<F : Float, T, const N : usize> RealMapping<F, N> for T
-where T : Mapping<Loc<F, N>, Codomain = F> {}
+impl<F: Float, T, const N: usize> RealMapping<F, N> for T where T: Mapping<Loc<F, N>, Codomain = F> {}
 
 /// A helper trait alias for referring to [`Mapping`]s from [`Loc<F, N>`] to [`Loc<F, M>`].
-pub trait RealVectorField<F : Float, const N : usize, const M : usize>
-: Mapping<Loc<F, N>, Codomain = Loc<F, M>> {}
+pub trait RealVectorField<F: Float, const N: usize, const M: usize>:
+    Mapping<Loc<F, N>, Codomain = Loc<F, M>>
+{
+}
 
-impl<F : Float, T, const N : usize, const M : usize> RealVectorField<F, N, M> for T
-where T : Mapping<Loc<F, N>, Codomain = Loc<F, M>> {}
+impl<F: Float, T, const N: usize, const M: usize> RealVectorField<F, N, M> for T where
+    T: Mapping<Loc<F, N>, Codomain = Loc<F, M>>
+{
+}
 
 /// A differentiable mapping from `Domain` to [`Mapping::Codomain`], with differentials
 /// `Differential`.
 ///
 /// This is automatically implemented when [`DifferentiableImpl`] is.
-pub trait DifferentiableMapping<Domain : Space> : Mapping<Domain> {
-    type DerivativeDomain : Space;
-    type Differential<'b> : Mapping<Domain, Codomain=Self::DerivativeDomain> where Self : 'b;
+pub trait DifferentiableMapping<Domain: Space>: Mapping<Domain> {
+    type DerivativeDomain: Space;
+    type Differential<'b>: Mapping<Domain, Codomain = Self::DerivativeDomain>
+    where
+        Self: 'b;
 
     /// Calculate differential at `x`
-    fn differential<I : Instance<Domain>>(&self, x : I) -> Self::DerivativeDomain;
+    fn differential<I: Instance<Domain>>(&self, x: I) -> Self::DerivativeDomain;
 
     /// Form the differential mapping of `self`.
     fn diff(self) -> Self::Differential<'static>;
@@ -90,50 +101,62 @@
 
 /// Automatically implemented shorthand for referring to differentiable [`Mapping`]s from
 /// [`Loc<F, N>`] to `F`.
-pub trait DifferentiableRealMapping<F : Float, const N : usize>
-: DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain = Loc<F, N>> {}
+pub trait DifferentiableRealMapping<F: Float, const N: usize>:
+    DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain = Loc<F, N>>
+{
+}
 
-impl<F : Float, T, const N : usize> DifferentiableRealMapping<F, N> for T
-where T : DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain = Loc<F, N>> {}
+impl<F: Float, T, const N: usize> DifferentiableRealMapping<F, N> for T where
+    T: DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain = Loc<F, N>>
+{
+}
 
 /// Helper trait for implementing [`DifferentiableMapping`]
-pub trait DifferentiableImpl<X : Space> : Sized {
-    type Derivative : Space;
+pub trait DifferentiableImpl<X: Space>: Sized {
+    type Derivative: Space;
 
     /// Compute the differential of `self` at `x`, consuming the input.
-    fn differential_impl<I : Instance<X>>(&self, x : I) -> Self::Derivative;
+    fn differential_impl<I: Instance<X>>(&self, x: I) -> Self::Derivative;
 }
 
 impl<T, Domain> DifferentiableMapping<Domain> for T
 where
-    Domain : Space,
-    T : Clone + Mapping<Domain> + DifferentiableImpl<Domain>
+    Domain: Space,
+    T: Clone + Mapping<Domain> + DifferentiableImpl<Domain>,
 {
     type DerivativeDomain = T::Derivative;
-    type Differential<'b> = Differential<'b, Domain, Self> where Self : 'b;
-    
+    type Differential<'b>
+        = Differential<'b, Domain, Self>
+    where
+        Self: 'b;
+
     #[inline]
-    fn differential<I : Instance<Domain>>(&self, x : I) -> Self::DerivativeDomain {
+    fn differential<I: Instance<Domain>>(&self, x: I) -> Self::DerivativeDomain {
         self.differential_impl(x)
     }
 
     fn diff(self) -> Differential<'static, Domain, Self> {
-        Differential{ g : Cow::Owned(self), _space : PhantomData }
+        Differential {
+            g: Cow::Owned(self),
+            _space: PhantomData,
+        }
     }
 
     fn diff_ref(&self) -> Differential<'_, Domain, Self> {
-        Differential{ g : Cow::Borrowed(self), _space : PhantomData }
+        Differential {
+            g: Cow::Borrowed(self),
+            _space: PhantomData,
+        }
     }
 }
 
-
 /// Container for the differential [`Mapping`] of a [`DifferentiableMapping`].
-pub struct Differential<'a, X, G : Clone> {
-    g : Cow<'a, G>,
-    _space : PhantomData<X>
+pub struct Differential<'a, X, G: Clone> {
+    g: Cow<'a, G>,
+    _space: PhantomData<X>,
 }
 
-impl<'a, X, G : Clone> Differential<'a, X, G> {
+impl<'a, X, G: Clone> Differential<'a, X, G> {
     pub fn base_fn(&self) -> &G {
         &self.g
     }
@@ -141,65 +164,68 @@
 
 impl<'a, X, G> Mapping<X> for Differential<'a, X, G>
 where
-    X : Space,
-    G : Clone + DifferentiableMapping<X>
+    X: Space,
+    G: Clone + DifferentiableMapping<X>,
 {
     type Codomain = G::DerivativeDomain;
 
     #[inline]
-    fn apply<I : Instance<X>>(&self, x : I) -> Self::Codomain {
+    fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain {
         (*self.g).differential(x)
     }
 }
 
 /// Container for flattening [`Loc`]`<F, 1>` codomain of a [`Mapping`] to `F`.
 pub struct FlattenedCodomain<X, F, G> {
-    g : G,
-    _phantoms : PhantomData<(X, F)>
+    g: G,
+    _phantoms: PhantomData<(X, F)>,
 }
 
-impl<F : Space, X, G> Mapping<X> for FlattenedCodomain<X, F, G>
+impl<F: Space, X, G> Mapping<X> for FlattenedCodomain<X, F, G>
 where
-    X : Space,
-    G: Mapping<X, Codomain=Loc<F, 1>>
+    X: Space,
+    G: Mapping<X, Codomain = Loc<F, 1>>,
 {
     type Codomain = F;
 
     #[inline]
-    fn apply<I : Instance<X>>(&self, x : I) -> Self::Codomain {
+    fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain {
         self.g.apply(x).flatten1d()
     }
 }
 
 /// An auto-trait for constructing a [`FlattenCodomain`] structure for
 /// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`.
-pub trait FlattenCodomain<X : Space, F> : Mapping<X, Codomain=Loc<F, 1>> + Sized {
+pub trait FlattenCodomain<X: Space, F>: Mapping<X, Codomain = Loc<F, 1>> + Sized {
     /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`.
     fn flatten_codomain(self) -> FlattenedCodomain<X, F, Self> {
-        FlattenedCodomain{ g : self, _phantoms : PhantomData }
+        FlattenedCodomain {
+            g: self,
+            _phantoms: PhantomData,
+        }
     }
 }
 
-impl<X : Space, F, G : Sized + Mapping<X, Codomain=Loc<F, 1>>> FlattenCodomain<X, F> for G {}
+impl<X: Space, F, G: Sized + Mapping<X, Codomain = Loc<F, 1>>> FlattenCodomain<X, F> for G {}
 
 /// Container for dimensional slicing [`Loc`]`<F, N>` codomain of a [`Mapping`] to `F`.
-pub struct SlicedCodomain<'a, X, F, G : Clone, const N : usize> {
-    g : Cow<'a, G>,
-    slice : usize,
-    _phantoms : PhantomData<(X, F)>
+pub struct SlicedCodomain<'a, X, F, G: Clone, const N: usize> {
+    g: Cow<'a, G>,
+    slice: usize,
+    _phantoms: PhantomData<(X, F)>,
 }
 
-impl<'a, X, F, G, const N : usize> Mapping<X> for SlicedCodomain<'a, X, F, G, N>
+impl<'a, X, F, G, const N: usize> Mapping<X> for SlicedCodomain<'a, X, F, G, N>
 where
-    X : Space,
-    F : Copy + Space,
-    G : Mapping<X, Codomain=Loc<F, N>> + Clone,
+    X: Space,
+    F: Copy + Space,
+    G: Mapping<X, Codomain = Loc<F, N>> + Clone,
 {
     type Codomain = F;
 
     #[inline]
-    fn apply<I : Instance<X>>(&self, x : I) -> Self::Codomain {
-        let tmp : [F; N] = (*self.g).apply(x).into();
+    fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain {
+        let tmp: [F; N] = (*self.g).apply(x).into();
         // Safety: `slice_codomain` below checks the range.
         unsafe { *tmp.get_unchecked(self.slice) }
     }
@@ -207,44 +233,64 @@
 
 /// An auto-trait for constructing a [`FlattenCodomain`] structure for
 /// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`.
-pub trait SliceCodomain<X : Space, F : Copy, const N : usize>
-    : Mapping<X, Codomain=Loc<F, N>> + Clone + Sized
+pub trait SliceCodomain<X: Space, F: Copy, const N: usize>:
+    Mapping<X, Codomain = Loc<F, N>> + Clone + Sized
 {
     /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`.
-    fn slice_codomain(self, slice : usize) -> SlicedCodomain<'static, X, F, Self, N> {
+    fn slice_codomain(self, slice: usize) -> SlicedCodomain<'static, X, F, Self, N> {
         assert!(slice < N);
-        SlicedCodomain{ g : Cow::Owned(self), slice, _phantoms : PhantomData }
+        SlicedCodomain {
+            g: Cow::Owned(self),
+            slice,
+            _phantoms: PhantomData,
+        }
     }
 
     /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`.
-    fn slice_codomain_ref(&self, slice : usize) -> SlicedCodomain<'_, X, F, Self, N> {
+    fn slice_codomain_ref(&self, slice: usize) -> SlicedCodomain<'_, X, F, Self, N> {
         assert!(slice < N);
-        SlicedCodomain{ g : Cow::Borrowed(self), slice, _phantoms : PhantomData }
+        SlicedCodomain {
+            g: Cow::Borrowed(self),
+            slice,
+            _phantoms: PhantomData,
+        }
     }
 }
 
-impl<X : Space, F : Copy, G : Sized + Mapping<X, Codomain=Loc<F, N>> + Clone, const N : usize>
-SliceCodomain<X, F, N>
-for G {}
-
+impl<X: Space, F: Copy, G: Sized + Mapping<X, Codomain = Loc<F, N>> + Clone, const N: usize>
+    SliceCodomain<X, F, N> for G
+{
+}
 
 /// The composition S ∘ T. `E` is for storing a `NormExponent` for the intermediate space.
 pub struct Composition<S, T, E = ()> {
-    pub outer : S,
-    pub inner : T,
-    pub intermediate_norm_exponent : E
+    pub outer: S,
+    pub inner: T,
+    pub intermediate_norm_exponent: E,
 }
 
 impl<S, T, X, E> Mapping<X> for Composition<S, T, E>
 where
-    X : Space,
-    T : Mapping<X>,
-    S : Mapping<T::Codomain>
+    X: Space,
+    T: Mapping<X>,
+    S: Mapping<T::Codomain>,
 {
     type Codomain = S::Codomain;
 
     #[inline]
-    fn apply<I : Instance<X>>(&self, x : I) -> Self::Codomain {
+    fn apply<I: Instance<X>>(&self, x: I) -> Self::Codomain {
         self.outer.apply(self.inner.apply(x))
     }
 }
+
+mod quadratic;
+pub use quadratic::Quadratic;
+
+/// 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>;
+}

mercurial