--- a/src/bisection_tree/support.rs Tue Feb 20 12:33:16 2024 -0500 +++ b/src/bisection_tree/support.rs Mon Feb 03 19:22:16 2025 -0500 @@ -1,35 +1,23 @@ /*! -Traits for representing the support of a [`Apply`], and analysing the mapping on a [`Cube`]. +Traits for representing the support of a [`Mapping`], and analysing the mapping on a [`Cube`]. */ use serde::Serialize; use std::ops::{MulAssign,DivAssign,Neg}; use crate::types::{Float, Num}; use crate::maputil::map2; -use crate::mapping::Apply; +use crate::mapping::{ + Instance, Mapping, DifferentiableImpl, DifferentiableMapping, Space +}; use crate::sets::Cube; use crate::loc::Loc; use super::aggregator::Bounds; use crate::norms::{Norm, L1, L2, Linfinity}; - -/// A trait for encoding constant [`Float`] values -pub trait Constant : Copy + Sync + Send + 'static + std::fmt::Debug + Into<Self::Type> { - /// The type of the value - type Type : Float; - /// Returns the value of the constant - fn value(&self) -> Self::Type; -} +pub use crate::operator_arithmetic::{Weighted, Constant}; -impl<F : Float> Constant for F { - type Type = F; - #[inline] - fn value(&self) -> F { *self } -} - - -/// A trait for working with the supports of [`Apply`]s. +/// A trait for working with the supports of [`Mapping`]s. /// -/// Apply is not a super-trait to allow more general use. +/// `Mapping` is not a super-trait to allow more general use. pub trait Support<F : Num, const N : usize> : Sized + Sync + Send + 'static { /// Return a cube containing the support of the function represented by `self`. /// @@ -62,15 +50,9 @@ fn shift(self, x : Loc<F, N>) -> Shift<Self, F, N> { Shift { shift : x, base_fn : self } } - - /// Multiply `self` by the scalar `a`. - #[inline] - fn weigh<C : Constant<Type=F>>(self, a : C) -> Weighted<Self, C> { - Weighted { weight : a, base_fn : self } - } } -/// Trait for globally analysing a property `A` of a [`Apply`]. +/// Trait for globally analysing a property `A` of a [`Mapping`]. /// /// Typically `A` is an [`Aggregator`][super::aggregator::Aggregator] such as /// [`Bounds`][super::aggregator::Bounds]. @@ -91,7 +73,7 @@ // } // } -/// Trait for locally analysing a property `A` of a [`Apply`] (implementing [`Support`]) +/// Trait for locally analysing a property `A` of a [`Mapping`] (implementing [`Support`]) /// within a [`Cube`]. /// /// Typically `A` is an [`Aggregator`][super::aggregator::Aggregator] such as @@ -105,10 +87,10 @@ fn local_analysis(&self, cube : &Cube<F, N>) -> A; } -/// Trait for determining the upper and lower bounds of an float-valued [`Apply`]. +/// Trait for determining the upper and lower bounds of an float-valued [`Mapping`]. /// /// This is a blanket-implemented alias for [`GlobalAnalysis`]`<F, Bounds<F>>` -/// [`Apply`] is not a supertrait to allow flexibility in the implementation of either +/// [`Mapping`] is not a supertrait to allow flexibility in the implementation of either /// reference or non-reference arguments. pub trait Bounded<F : Float> : GlobalAnalysis<F, Bounds<F>> { /// Return lower and upper bounds for the values of of `self`. @@ -120,28 +102,30 @@ impl<F : Float, T : GlobalAnalysis<F, Bounds<F>>> Bounded<F> for T { } -/// Shift of [`Support`] and [`Apply`]; output of [`Support::shift`]. +/// Shift of [`Support`] and [`Mapping`]; output of [`Support::shift`]. #[derive(Copy,Clone,Debug,Serialize)] // Serialize! but not implemented by Loc. pub struct Shift<T, F, const N : usize> { shift : Loc<F, N>, base_fn : T, } -impl<'a, T, V, F : Float, const N : usize> Apply<&'a Loc<F, N>> for Shift<T,F,N> -where T : Apply<Loc<F, N>, Output=V> { - type Output = V; +impl<'a, T, V : Space, F : Float, const N : usize> Mapping<Loc<F, N>> for Shift<T,F,N> +where T : Mapping<Loc<F, N>, Codomain=V> { + type Codomain = V; + #[inline] - fn apply(&self, x : &'a Loc<F, N>) -> Self::Output { - self.base_fn.apply(x - &self.shift) + fn apply<I : Instance<Loc<F, N>>>(&self, x : I) -> Self::Codomain { + self.base_fn.apply(x.own() - &self.shift) } } -impl<'a, T, V, F : Float, const N : usize> Apply<Loc<F, N>> for Shift<T,F,N> -where T : Apply<Loc<F, N>, Output=V> { - type Output = V; +impl<'a, T, V : Space, F : Float, const N : usize> DifferentiableImpl<Loc<F, N>> for Shift<T,F,N> +where T : DifferentiableMapping<Loc<F, N>, DerivativeDomain=V> { + type Derivative = V; + #[inline] - fn apply(&self, x : Loc<F, N>) -> Self::Output { - self.base_fn.apply(x - &self.shift) + fn differential_impl<I : Instance<Loc<F, N>>>(&self, x : I) -> Self::Derivative { + self.base_fn.differential(x.own() - &self.shift) } } @@ -200,38 +184,6 @@ impl_shift_norm!(L1 L2 Linfinity); -/// Weighting of a [`Support`] and [`Apply`] by scalar multiplication; -/// output of [`Support::weigh`]. -#[derive(Copy,Clone,Debug,Serialize)] -pub struct Weighted<T, C : Constant> { - /// The weight - pub weight : C, - /// The base [`Support`] or [`Apply`] being weighted. - pub base_fn : T, -} - -impl<'a, T, V, F : Float, C, const N : usize> Apply<&'a Loc<F, N>> for Weighted<T, C> -where T : for<'b> Apply<&'b Loc<F, N>, Output=V>, - V : std::ops::Mul<F,Output=V>, - C : Constant<Type=F> { - type Output = V; - #[inline] - fn apply(&self, x : &'a Loc<F, N>) -> Self::Output { - self.base_fn.apply(x) * self.weight.value() - } -} - -impl<'a, T, V, F : Float, C, const N : usize> Apply<Loc<F, N>> for Weighted<T, C> -where T : Apply<Loc<F, N>, Output=V>, - V : std::ops::Mul<F,Output=V>, - C : Constant<Type=F> { - type Output = V; - #[inline] - fn apply(&self, x : Loc<F, N>) -> Self::Output { - self.base_fn.apply(x) * self.weight.value() - } -} - impl<'a, T, F : Float, C, const N : usize> Support<F,N> for Weighted<T, C> where T : Support<F, N>, C : Constant<Type=F> { @@ -331,30 +283,21 @@ impl_weighted_norm!(L1 L2 Linfinity); -/// Normalisation of [`Support`] and [`Apply`] to L¹ norm 1. +/// Normalisation of [`Support`] and [`Mapping`] to L¹ norm 1. /// /// Currently only scalar-valued functions are supported. #[derive(Copy, Clone, Debug, Serialize, PartialEq)] pub struct Normalised<T>( - /// The base [`Support`] or [`Apply`]. + /// The base [`Support`] or [`Mapping`]. pub T ); -impl<'a, T, F : Float, const N : usize> Apply<&'a Loc<F, N>> for Normalised<T> -where T : Norm<F, L1> + for<'b> Apply<&'b Loc<F, N>, Output=F> { - type Output = F; +impl<'a, T, F : Float, const N : usize> Mapping<Loc<F, N>> for Normalised<T> +where T : Norm<F, L1> + Mapping<Loc<F,N>, Codomain=F> { + type Codomain = F; + #[inline] - fn apply(&self, x : &'a Loc<F, N>) -> Self::Output { - let w = self.0.norm(L1); - if w == F::ZERO { F::ZERO } else { self.0.apply(x) / w } - } -} - -impl<'a, T, F : Float, const N : usize> Apply<Loc<F, N>> for Normalised<T> -where T : Norm<F, L1> + Apply<Loc<F,N>, Output=F> { - type Output = F; - #[inline] - fn apply(&self, x : Loc<F, N>) -> Self::Output { + fn apply<I : Instance<Loc<F, N>>>(&self, x : I) -> Self::Codomain { let w = self.0.norm(L1); if w == F::ZERO { F::ZERO } else { self.0.apply(x) / w } } @@ -449,7 +392,7 @@ : MulAssign<F> + DivAssign<F> + Neg<Output=Self> + Clone + Sync + Send + 'static { /// The identification type type Id : 'static + Copy; - /// The type of the [`Support`] (often also a [`Apply`]). + /// The type of the [`Support`] (often also a [`Mapping`]). type SupportType : 'static + Support<F, N>; /// An iterator over all the [`Support`]s of the generator. type AllDataIter<'a> : Iterator<Item=(Self::Id, Self::SupportType)> where Self : 'a;