# HG changeset patch # User Tuomo Valkonen # Date 1708450457 18000 # Node ID 8aaa22fcd30268c7f031c0ec0e4420231d95b845 # Parent 2bee40c5e8349952943e39ea1089b645ca7df863# Parent d14c877e14b70dd4c1ddc9436e4095e84964ef20 merge default diff -r d14c877e14b7 -r 8aaa22fcd302 Cargo.lock --- a/Cargo.lock Tue Feb 20 12:33:16 2024 -0500 +++ b/Cargo.lock Tue Feb 20 12:34:17 2024 -0500 @@ -4,7 +4,7 @@ [[package]] name = "alg_tools" -version = "0.1.0" +version = "0.2.0-dev" dependencies = [ "colored", "cpu-time", diff -r d14c877e14b7 -r 8aaa22fcd302 Cargo.toml --- a/Cargo.toml Tue Feb 20 12:33:16 2024 -0500 +++ b/Cargo.toml Tue Feb 20 12:34:17 2024 -0500 @@ -1,6 +1,6 @@ [package] name = "alg_tools" -version = "0.1.0" +version = "0.2.0-dev" edition = "2021" rust-version = "1.67" authors = ["Tuomo Valkonen "] diff -r d14c877e14b7 -r 8aaa22fcd302 src/bisection_tree/btfn.rs --- a/src/bisection_tree/btfn.rs Tue Feb 20 12:33:16 2024 -0500 +++ b/src/bisection_tree/btfn.rs Tue Feb 20 12:34:17 2024 -0500 @@ -4,7 +4,7 @@ use std::marker::PhantomData; use std::sync::Arc; use crate::types::Float; -use crate::mapping::{Apply, Mapping}; +use crate::mapping::{Apply, Mapping, Differentiable}; //use crate::linops::{Apply, Linear}; use crate::sets::Set; use crate::sets::Cube; @@ -386,10 +386,8 @@ make_btfn_unaryop!(Neg, neg); - - // -// Mapping +// Apply, Mapping, Differentiate // impl<'a, F : Float, G, BT, V, const N : usize> Apply<&'a Loc> @@ -422,6 +420,42 @@ } } +impl<'a, F : Float, G, BT, V, const N : usize> Differentiable<&'a Loc> +for BTFN +where BT : BTImpl, + G : SupportGenerator, + G::SupportType : LocalAnalysis + Differentiable<&'a Loc, Output = V>, + V : Sum { + + type Output = V; + + fn differential(&self, x : &'a Loc) -> Self::Output { + self.bt.iter_at(x) + .map(|&d| self.generator.support_for(d).differential(x)) + .sum() + } +} + +impl Differentiable> +for BTFN +where BT : BTImpl, + G : SupportGenerator, + G::SupportType : LocalAnalysis + Differentiable, Output = V>, + V : Sum { + + type Output = V; + + fn differential(&self, x : Loc) -> Self::Output { + self.bt.iter_at(&x) + .map(|&d| self.generator.support_for(d).differential(x)) + .sum() + } +} + +// +// GlobalAnalysis +// + impl GlobalAnalysis for BTFN where BT : BTImpl, diff -r d14c877e14b7 -r 8aaa22fcd302 src/bisection_tree/either.rs --- a/src/bisection_tree/either.rs Tue Feb 20 12:33:16 2024 -0500 +++ b/src/bisection_tree/either.rs Tue Feb 20 12:34:17 2024 -0500 @@ -3,8 +3,8 @@ use std::sync::Arc; use crate::types::*; -use crate::mapping::Apply; -use crate::iter::{Mappable,MapF,MapZ}; +use crate::mapping::{Apply, Differentiable}; +use crate::iter::{Mappable, MapF, MapZ}; use crate::sets::Cube; use crate::loc::Loc; @@ -190,6 +190,19 @@ } } +impl Differentiable for EitherSupport +where S1 : Differentiable, + S2 : Differentiable { + type Output = F; + #[inline] + fn differential(&self, x : X) -> F { + match self { + EitherSupport::Left(ref a) => a.differential(x), + EitherSupport::Right(ref b) => b.differential(x), + } + } +} + macro_rules! make_either_scalarop_rhs { ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { impl diff -r d14c877e14b7 -r 8aaa22fcd302 src/bisection_tree/support.rs --- a/src/bisection_tree/support.rs Tue Feb 20 12:33:16 2024 -0500 +++ b/src/bisection_tree/support.rs Tue Feb 20 12:34:17 2024 -0500 @@ -6,7 +6,7 @@ use std::ops::{MulAssign,DivAssign,Neg}; use crate::types::{Float, Num}; use crate::maputil::map2; -use crate::mapping::Apply; +use crate::mapping::{Apply, Differentiable}; use crate::sets::Cube; use crate::loc::Loc; use super::aggregator::Bounds; @@ -145,6 +145,24 @@ } } +impl<'a, T, V, F : Float, const N : usize> Differentiable<&'a Loc> for Shift +where T : Differentiable, Output=V> { + type Output = V; + #[inline] + fn differential(&self, x : &'a Loc) -> Self::Output { + self.base_fn.differential(x - &self.shift) + } +} + +impl<'a, T, V, F : Float, const N : usize> Differentiable> for Shift +where T : Differentiable, Output=V> { + type Output = V; + #[inline] + fn differential(&self, x : Loc) -> Self::Output { + self.base_fn.differential(x - &self.shift) + } +} + impl<'a, T, F : Float, const N : usize> Support for Shift where T : Support { #[inline] @@ -232,6 +250,28 @@ } } +impl<'a, T, V, F : Float, C, const N : usize> Differentiable<&'a Loc> for Weighted +where T : for<'b> Differentiable<&'b Loc, Output=V>, + V : std::ops::Mul, + C : Constant { + type Output = V; + #[inline] + fn differential(&self, x : &'a Loc) -> Self::Output { + self.base_fn.differential(x) * self.weight.value() + } +} + +impl<'a, T, V, F : Float, C, const N : usize> Differentiable> for Weighted +where T : Differentiable, Output=V>, + V : std::ops::Mul, + C : Constant { + type Output = V; + #[inline] + fn differential(&self, x : Loc) -> Self::Output { + self.base_fn.differential(x) * self.weight.value() + } +} + impl<'a, T, F : Float, C, const N : usize> Support for Weighted where T : Support, C : Constant { diff -r d14c877e14b7 -r 8aaa22fcd302 src/iterate.rs --- a/src/iterate.rs Tue Feb 20 12:33:16 2024 -0500 +++ b/src/iterate.rs Tue Feb 20 12:34:17 2024 -0500 @@ -126,6 +126,9 @@ /// Returns the current iteration count. fn iteration(&self) -> usize; + + /// Indicates whether the iterator is quiet + fn is_quiet(&self) -> bool; } /// Result of a step of an [`AlgIterator`] @@ -467,6 +470,8 @@ verbose : bool, /// Whether results should be calculated. calc : bool, + /// Indicates whether the iteration is quiet + quiet : bool, } /// [`AlgIteratorFactory`] for [`BasicAlgIterator`] @@ -585,10 +590,11 @@ fn state(&self) -> BasicState { let iter = self.iter; let verbose = self.options.verbose_iter.is_verbose(iter); - BasicState{ + BasicState { iter : iter, verbose : verbose, calc : verbose, + quiet : self.options.quiet } } } @@ -605,7 +611,12 @@ #[inline] fn iteration(&self) -> usize { - return self.iter; + self.iter + } + + #[inline] + fn is_quiet(&self) -> bool { + self.quiet } } diff -r d14c877e14b7 -r 8aaa22fcd302 src/loc.rs --- a/src/loc.rs Tue Feb 20 12:33:16 2024 -0500 +++ b/src/loc.rs Tue Feb 20 12:34:17 2024 -0500 @@ -135,6 +135,14 @@ } } +impl Loc { + #[inline] + pub fn flatten1d(self) -> F { + let Loc([v]) = self; + v + } +} + impl From> for [F; N] { #[inline] fn from(other : Loc) -> [F; N] { @@ -237,6 +245,20 @@ make_binop!(Add, add, AddAssign, add_assign); make_binop!(Sub, sub, SubAssign, sub_assign); +impl std::iter::Sum for Loc { + fn sum>>(mut iter: I) -> Self { + match iter.next() { + None => Self::ORIGIN, + Some(mut v) => { + for w in iter { + v += w + } + v + } + } + } +} + macro_rules! make_scalarop_rhs { ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { impl $trait for Loc { diff -r d14c877e14b7 -r 8aaa22fcd302 src/mapping.rs --- a/src/mapping.rs Tue Feb 20 12:33:16 2024 -0500 +++ b/src/mapping.rs Tue Feb 20 12:34:17 2024 -0500 @@ -42,39 +42,59 @@ type Codomain = Codomain; } - -/// A helper trait alias for referring to [`Mapping`]s from [`Loc`] to `F` a [`Float`]. -pub trait RealMapping : Mapping, Codomain = F> {} +/// Automatically implemented shorthand for referring to [`Mapping`]s from [`Loc`] to `F`. +pub trait RealMapping +: Mapping, Codomain = F> {} impl RealMapping for T where T : Mapping, Codomain = F> {} +/// Automatically implemented shorthand for referring to differentiable [`Mapping`]s from +/// [`Loc`] to `F`. +pub trait DifferentiableRealMapping +: DifferentiableMapping, Codomain = F, Differential=Loc> {} + +impl DifferentiableRealMapping for T +where T : DifferentiableMapping, Codomain = F, Differential=Loc> {} + + +/// A helper trait alias for referring to [`Mapping`]s from [`Loc`] to [`Loc`]. +pub trait RealVectorField +: Mapping, Codomain = Loc> {} + +impl RealVectorField for T +where T : Mapping, Codomain = Loc> {} + /// Trait for calculation the differential of `Self` as a mathematical function on `X`. -pub trait Differentiate { +pub trait Differentiable : Sized { type Output; /// Compute the differential of `self` at `x`. fn differential(&self, x : X) -> Self::Output; } - /// A differentiable mapping from `Domain` to [`Mapping::Codomain`], with differentials /// `Differential`. /// /// This is automatically implemented when the relevant [`Differentiate`] are implemented. pub trait DifferentiableMapping : Mapping - + Differentiate - + for<'a> Differentiate<&'a Domain, Output=Self::Differential>{ + + Differentiable + + for<'a> Differentiable<&'a Domain, Output=Self::Differential> { type Differential; + + /// Form the differential mapping of `self`. + fn diff(self) -> Differential { + Differential{ g : self, _space : PhantomData } + } } impl DifferentiableMapping for T where T : Mapping - + Differentiate - + for<'a> Differentiate<&'a Domain, Output=Differential> { + + Differentiable + + for<'a> Differentiable<&'a Domain, Output=Differential> { type Differential = Differential; } @@ -103,7 +123,7 @@ } } -impl Differentiate for Sum +impl Differentiable for Sum where M : DifferentiableMapping, M :: Codomain : std::iter::Sum, M :: Differential : std::iter::Sum, @@ -115,3 +135,101 @@ self.components.iter().map(|c| c.differential(x)).sum() } } + +/// Container for the differential [`Mapping`] of a [`Differentiable`] mapping. +pub struct Differential> { + g : G, + _space : PhantomData +} + +impl> Apply for Differential { + type Output = G::Differential; + + #[inline] + fn apply(&self, x : X) -> G::Differential { + self.g.differential(x) + } +} + +impl<'a, X, G : DifferentiableMapping> Apply<&'a X> for Differential { + type Output = G::Differential; + + #[inline] + fn apply(&self, x : &'a X) -> G::Differential { + self.g.differential(x) + } +} + + +/// Container for flattening [`Loc`]`` codomain of a [`Mapping`] to `F`. +pub struct FlattenedCodomain>> { + g : G, + _phantoms : PhantomData<(X, F)> +} + +impl>> Apply for FlattenedCodomain { + type Output = F; + + #[inline] + fn apply(&self, x : X) -> Self::Output { + 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 { + /// Flatten the codomain from [`Loc`]`` to `F`. + fn flatten_codomain(self) -> FlattenedCodomain { + FlattenedCodomain{ g : self, _phantoms : PhantomData } + } +} + +impl>> FlattenCodomain for G {} + + +/// Container for dimensional slicing [`Loc`]`` codomain of a [`Mapping`] to `F`. +pub struct SlicedCodomain>, const N : usize> { + g : G, + slice : usize, + _phantoms : PhantomData<(X, F)> +} + +impl>, const N : usize> Apply +for SlicedCodomain { + type Output = F; + + #[inline] + fn apply(&self, x : X) -> Self::Output { + let tmp : [F; N] = self.g.apply(x).into(); + // Safety: `slice_codomain` below checks the range. + unsafe { *tmp.get_unchecked(self.slice) } + } +} + +impl<'a, X, F : Copy, G : Mapping>, const N : usize> Apply<&'a X> +for SlicedCodomain { + type Output = F; + + #[inline] + fn apply(&self, x : &'a X) -> Self::Output { + let tmp : [F; N] = self.g.apply(x).into(); + // Safety: `slice_codomain` below checks the range. + unsafe { *tmp.get_unchecked(self.slice) } + } +} + +/// An auto-trait for constructing a [`FlattenCodomain`] structure for +/// flattening the codomain of a [`Mapping`] from [`Loc`]`` to `F`. +pub trait SliceCodomain : Mapping> + Sized { + /// Flatten the codomain from [`Loc`]`` to `F`. + fn slice_codomain(self, slice : usize) -> SlicedCodomain { + assert!(slice < N); + SlicedCodomain{ g : self, slice, _phantoms : PhantomData } + } +} + +impl>, const N : usize> +SliceCodomain +for G {} + diff -r d14c877e14b7 -r 8aaa22fcd302 src/norms.rs --- a/src/norms.rs Tue Feb 20 12:33:16 2024 -0500 +++ b/src/norms.rs Tue Feb 20 12:34:17 2024 -0500 @@ -12,7 +12,7 @@ /// An exponent for norms. /// -// Just a collection of desirabl attributes for a marker type +// Just a collection of desirable attributes for a marker type pub trait NormExponent : Copy + Send + Sync + 'static {} diff -r d14c877e14b7 -r 8aaa22fcd302 src/types.rs --- a/src/types.rs Tue Feb 20 12:33:16 2024 -0500 +++ b/src/types.rs Tue Feb 20 12:34:17 2024 -0500 @@ -84,6 +84,7 @@ const SQRT_2 : Self; const INFINITY : Self; const NEG_INFINITY : Self; + const NAN : Self; const FRAC_2_SQRT_PI : Self; } @@ -133,6 +134,7 @@ const SQRT_2 : Self = std::f64::consts::SQRT_2; const INFINITY : Self = std::f64::INFINITY; const NEG_INFINITY : Self = std::f64::NEG_INFINITY; + const NAN : Self = std::f64::NAN; const FRAC_2_SQRT_PI : Self = std::f64::consts::FRAC_2_SQRT_PI; } @@ -150,6 +152,7 @@ const SQRT_2 : Self = std::f32::consts::SQRT_2; const INFINITY : Self = std::f32::INFINITY; const NEG_INFINITY : Self = std::f32::NEG_INFINITY; + const NAN : Self = std::f32::NAN; const FRAC_2_SQRT_PI : Self = std::f32::consts::FRAC_2_SQRT_PI; }