diff -r 2e4517b55442 -r 9e5b9fc81c52 src/mapping.rs --- 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 { - type Codomain : Space; +pub trait Mapping { + type Codomain: Space; /// Compute the value of `self` at `x`. - fn apply>(&self, x : I) -> Self::Codomain; + fn apply>(&self, x: I) -> Self::Codomain; #[inline] /// Form the composition `self ∘ other` - fn compose>(self, other : T) - -> Composition + fn compose>(self, other: T) -> Composition 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( - self, other : T, norm : E - ) -> Composition + fn compose_with_norm(self, other: T, norm: E) -> Composition where - Self : Sized, - X : Space, - T : Mapping, - E : NormExponent, - Domain : Norm, - F : Num + Self: Sized, + X: Space, + T: Mapping, + E: NormExponent, + Domain: Norm, + 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(self, a : C) -> Weighted + fn weigh(self, a: C) -> Weighted where - Self : Sized, - C : Constant, - Self::Codomain : ClosedMul, + Self: Sized, + C: Constant, + Self::Codomain: ClosedMul, { - Weighted { weight : a, base_fn : self } + Weighted { + weight: a, + base_fn: self, + } } } /// Automatically implemented shorthand for referring to [`Mapping`]s from [`Loc`] to `F`. -pub trait RealMapping -: Mapping, Codomain = F> {} +pub trait RealMapping: Mapping, Codomain = F> {} -impl RealMapping for T -where T : Mapping, Codomain = F> {} +impl RealMapping for T where T: Mapping, Codomain = F> {} /// A helper trait alias for referring to [`Mapping`]s from [`Loc`] to [`Loc`]. -pub trait RealVectorField -: Mapping, Codomain = Loc> {} +pub trait RealVectorField: + Mapping, Codomain = Loc> +{ +} -impl RealVectorField for T -where T : Mapping, Codomain = Loc> {} +impl RealVectorField for T where + T: Mapping, Codomain = Loc> +{ +} /// A differentiable mapping from `Domain` to [`Mapping::Codomain`], with differentials /// `Differential`. /// /// This is automatically implemented when [`DifferentiableImpl`] is. -pub trait DifferentiableMapping : Mapping { - type DerivativeDomain : Space; - type Differential<'b> : Mapping where Self : 'b; +pub trait DifferentiableMapping: Mapping { + type DerivativeDomain: Space; + type Differential<'b>: Mapping + where + Self: 'b; /// Calculate differential at `x` - fn differential>(&self, x : I) -> Self::DerivativeDomain; + fn differential>(&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`] to `F`. -pub trait DifferentiableRealMapping -: DifferentiableMapping, Codomain = F, DerivativeDomain = Loc> {} +pub trait DifferentiableRealMapping: + DifferentiableMapping, Codomain = F, DerivativeDomain = Loc> +{ +} -impl DifferentiableRealMapping for T -where T : DifferentiableMapping, Codomain = F, DerivativeDomain = Loc> {} +impl DifferentiableRealMapping for T where + T: DifferentiableMapping, Codomain = F, DerivativeDomain = Loc> +{ +} /// Helper trait for implementing [`DifferentiableMapping`] -pub trait DifferentiableImpl : Sized { - type Derivative : Space; +pub trait DifferentiableImpl: Sized { + type Derivative: Space; /// Compute the differential of `self` at `x`, consuming the input. - fn differential_impl>(&self, x : I) -> Self::Derivative; + fn differential_impl>(&self, x: I) -> Self::Derivative; } impl DifferentiableMapping for T where - Domain : Space, - T : Clone + Mapping + DifferentiableImpl + Domain: Space, + T: Clone + Mapping + DifferentiableImpl, { 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>(&self, x : I) -> Self::DerivativeDomain { + fn differential>(&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 +pub struct Differential<'a, X, G: Clone> { + g: Cow<'a, G>, + _space: PhantomData, } -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 for Differential<'a, X, G> where - X : Space, - G : Clone + DifferentiableMapping + X: Space, + G: Clone + DifferentiableMapping, { type Codomain = G::DerivativeDomain; #[inline] - fn apply>(&self, x : I) -> Self::Codomain { + fn apply>(&self, x: I) -> Self::Codomain { (*self.g).differential(x) } } /// Container for flattening [`Loc`]`` codomain of a [`Mapping`] to `F`. pub struct FlattenedCodomain { - g : G, - _phantoms : PhantomData<(X, F)> + g: G, + _phantoms: PhantomData<(X, F)>, } -impl Mapping for FlattenedCodomain +impl Mapping for FlattenedCodomain where - X : Space, - G: Mapping> + X: Space, + G: Mapping>, { type Codomain = F; #[inline] - fn apply>(&self, x : I) -> Self::Codomain { + fn apply>(&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`]`` to `F`. -pub trait FlattenCodomain : Mapping> + Sized { +pub trait FlattenCodomain: Mapping> + Sized { /// Flatten the codomain from [`Loc`]`` to `F`. fn flatten_codomain(self) -> FlattenedCodomain { - FlattenedCodomain{ g : self, _phantoms : PhantomData } + FlattenedCodomain { + g: self, + _phantoms: PhantomData, + } } } -impl>> FlattenCodomain for G {} +impl>> FlattenCodomain for G {} /// Container for dimensional slicing [`Loc`]`` 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 for SlicedCodomain<'a, X, F, G, N> +impl<'a, X, F, G, const N: usize> Mapping for SlicedCodomain<'a, X, F, G, N> where - X : Space, - F : Copy + Space, - G : Mapping> + Clone, + X: Space, + F: Copy + Space, + G: Mapping> + Clone, { type Codomain = F; #[inline] - fn apply>(&self, x : I) -> Self::Codomain { - let tmp : [F; N] = (*self.g).apply(x).into(); + fn apply>(&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`]`` to `F`. -pub trait SliceCodomain - : Mapping> + Clone + Sized +pub trait SliceCodomain: + Mapping> + Clone + Sized { /// Flatten the codomain from [`Loc`]`` 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`]`` 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> + Clone, const N : usize> -SliceCodomain -for G {} - +impl> + Clone, const N: usize> + SliceCodomain for G +{ +} /// The composition S ∘ T. `E` is for storing a `NormExponent` for the intermediate space. pub struct Composition { - pub outer : S, - pub inner : T, - pub intermediate_norm_exponent : E + pub outer: S, + pub inner: T, + pub intermediate_norm_exponent: E, } impl Mapping for Composition where - X : Space, - T : Mapping, - S : Mapping + X: Space, + T: Mapping, + S: Mapping, { type Codomain = S::Codomain; #[inline] - fn apply>(&self, x : I) -> Self::Codomain { + fn apply>(&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 { + /// 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; +}