--- 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>; +}