merge default dev

Tue, 20 Feb 2024 12:34:17 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Tue, 20 Feb 2024 12:34:17 -0500
branch
dev
changeset 38
8aaa22fcd302
parent 37
2bee40c5e834 (diff)
parent 25
d14c877e14b7 (current diff)
child 39
dd144a972722

merge default

src/iterate.rs file | annotate | diff | comparison | revisions
--- 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",
--- 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 <tuomov@iki.fi>"]
--- 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<F, N>>
@@ -422,6 +420,42 @@
     }
 }
 
+impl<'a, F : Float, G, BT, V, const N : usize> Differentiable<&'a Loc<F, N>>
+for BTFN<F, G, BT, N>
+where BT : BTImpl<F, N>,
+      G : SupportGenerator<F, N, Id=BT::Data>,
+      G::SupportType : LocalAnalysis<F, BT::Agg, N> + Differentiable<&'a Loc<F, N>, Output = V>,
+      V : Sum {
+
+    type Output = V;
+
+    fn differential(&self, x : &'a Loc<F, N>) -> Self::Output {
+        self.bt.iter_at(x)
+            .map(|&d| self.generator.support_for(d).differential(x))
+            .sum()
+    }
+}
+
+impl<F : Float, G, BT, V, const N : usize> Differentiable<Loc<F, N>>
+for BTFN<F, G, BT, N>
+where BT : BTImpl<F, N>,
+      G : SupportGenerator<F, N, Id=BT::Data>,
+      G::SupportType : LocalAnalysis<F, BT::Agg, N> + Differentiable<Loc<F, N>, Output = V>,
+      V : Sum {
+
+    type Output = V;
+
+    fn differential(&self, x : Loc<F, N>) -> Self::Output {
+        self.bt.iter_at(&x)
+            .map(|&d| self.generator.support_for(d).differential(x))
+            .sum()
+    }
+}
+
+//
+// GlobalAnalysis
+//
+
 impl<F : Float, G, BT, const N : usize> GlobalAnalysis<F, BT::Agg>
 for BTFN<F, G, BT, N>
 where BT : BTImpl<F, N>,
--- 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<F, S1, S2, X> Differentiable<X> for EitherSupport<S1, S2>
+where S1 : Differentiable<X, Output=F>,
+      S2 : Differentiable<X, Output=F> {
+    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<F : Float, G1, G2>
--- 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<F, N>> for Shift<T,F,N>
+where T : Differentiable<Loc<F, N>, Output=V> {
+    type Output = V;
+    #[inline]
+    fn differential(&self, x : &'a Loc<F, N>) -> Self::Output {
+        self.base_fn.differential(x - &self.shift)
+    }
+}
+
+impl<'a, T, V, F : Float, const N : usize> Differentiable<Loc<F, N>> for Shift<T,F,N>
+where T : Differentiable<Loc<F, N>, Output=V> {
+    type Output = V;
+    #[inline]
+    fn differential(&self, x : Loc<F, N>) -> Self::Output {
+        self.base_fn.differential(x - &self.shift)
+    }
+}
+
 impl<'a, T, F : Float, const N : usize> Support<F,N> for Shift<T,F,N>
 where T : Support<F, N> {
     #[inline]
@@ -232,6 +250,28 @@
     }
 }
 
+impl<'a, T, V, F : Float, C, const N : usize> Differentiable<&'a Loc<F, N>> for Weighted<T, C>
+where T : for<'b> Differentiable<&'b Loc<F, N>, Output=V>,
+      V : std::ops::Mul<F, Output=V>,
+      C : Constant<Type=F> {
+    type Output = V;
+    #[inline]
+    fn differential(&self, x : &'a Loc<F, N>) -> Self::Output {
+        self.base_fn.differential(x) * self.weight.value()
+    }
+}
+
+impl<'a, T, V, F : Float, C, const N : usize> Differentiable<Loc<F, N>> for Weighted<T, C>
+where T : Differentiable<Loc<F, N>, Output=V>,
+      V : std::ops::Mul<F, Output=V>,
+      C : Constant<Type=F> {
+    type Output = V;
+    #[inline]
+    fn differential(&self, x : Loc<F, N>) -> Self::Output {
+        self.base_fn.differential(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> {
--- 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
     }
 }
 
--- 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<F> Loc<F, 1> {
+    #[inline]
+    pub fn flatten1d(self) -> F {
+        let Loc([v]) = self;
+        v
+    }
+}
+
 impl<F, const N : usize> From<Loc<F, N>> for [F; N] {
     #[inline]
     fn from(other : Loc<F, N>) -> [F; N] {
@@ -237,6 +245,20 @@
 make_binop!(Add, add, AddAssign, add_assign);
 make_binop!(Sub, sub, SubAssign, sub_assign);
 
+impl<F : Float, const N : usize> std::iter::Sum for Loc<F, N> {
+    fn sum<I: Iterator<Item = Loc<F, N>>>(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<F : Num, const N : usize> $trait<F> for Loc<F, N> {
--- 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<F, N>`] to `F` a [`Float`].
-pub trait RealMapping<F : Float, const N : usize> : Mapping<Loc<F, N>, Codomain = F> {}
+/// 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> {}
 
 impl<F : Float, T, const N : usize> RealMapping<F, N> for T
 where T : Mapping<Loc<F, N>, Codomain = F> {}
 
+/// 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, Differential=Loc<F, N>> {}
+
+impl<F : Float, T, const N : usize> DifferentiableRealMapping<F, N> for T
+where T : DifferentiableMapping<Loc<F, N>, Codomain = F, Differential=Loc<F, N>> {}
+
+
+/// 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>> {}
+
+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>> {}
+
 
 /// Trait for calculation the differential of `Self` as a mathematical function on `X`.
-pub trait Differentiate<X> {
+pub trait Differentiable<X> : 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<Domain>
 : Mapping<Domain>
-  + Differentiate<Domain, Output=Self::Differential>
-  + for<'a> Differentiate<&'a Domain, Output=Self::Differential>{
+  + Differentiable<Domain, Output=Self::Differential>
+  + for<'a> Differentiable<&'a Domain, Output=Self::Differential> {
     type Differential;
+
+    /// Form the differential mapping of `self`.
+    fn diff(self) -> Differential<Domain, Self> {
+        Differential{ g : self, _space : PhantomData }
+    }
 }
 
 
 impl<Domain, Differential, T> DifferentiableMapping<Domain> for T
 where T : Mapping<Domain>
-          + Differentiate<Domain, Output=Differential>
-          + for<'a> Differentiate<&'a Domain, Output=Differential> {
+          + Differentiable<Domain, Output=Differential>
+          + for<'a> Differentiable<&'a Domain, Output=Differential> {
     type Differential = Differential;
 }
 
@@ -103,7 +123,7 @@
     }
 }
 
-impl<Domain, M> Differentiate<Domain> for Sum<Domain, M>
+impl<Domain, M> Differentiable<Domain> for Sum<Domain, M>
 where M : DifferentiableMapping<Domain>,
       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<X, G : DifferentiableMapping<X>> {
+    g : G,
+    _space : PhantomData<X>
+}
+
+impl<X, G : DifferentiableMapping<X>> Apply<X> for Differential<X, G> {
+    type Output = G::Differential;
+
+    #[inline]
+    fn apply(&self, x : X) -> G::Differential {
+        self.g.differential(x)
+    }
+}
+
+impl<'a, X, G : DifferentiableMapping<X>> Apply<&'a X> for Differential<X, G> {
+    type Output = G::Differential;
+
+    #[inline]
+    fn apply(&self, x : &'a X) -> G::Differential {
+        self.g.differential(x)
+    }
+}
+
+
+/// Container for flattening [`Loc`]`<F, 1>` codomain of a [`Mapping`] to `F`.
+pub struct FlattenedCodomain<X, F, G : Mapping<X, Codomain=Loc<F, 1>>> {
+    g : G,
+    _phantoms : PhantomData<(X, F)>
+}
+
+impl<X, F, G : Mapping<X, Codomain=Loc<F, 1>>> Apply<X> for FlattenedCodomain<X, F, G> {
+    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`]`<F, 1>` to `F`.
+pub trait FlattenCodomain<X, 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 }
+    }
+}
+
+impl<X, 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<X, F, G : Mapping<X, Codomain=Loc<F, N>>, const N : usize> {
+    g : G,
+    slice : usize,
+    _phantoms : PhantomData<(X, F)>
+}
+
+impl<X, F : Copy, G : Mapping<X, Codomain=Loc<F, N>>, const N : usize> Apply<X>
+for SlicedCodomain<X, F, G, N> {
+    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<X, Codomain=Loc<F, N>>, const N : usize> Apply<&'a X>
+for SlicedCodomain<X, F, G, N> {
+    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`]`<F, 1>` to `F`.
+pub trait SliceCodomain<X, F : Copy, const N : usize> : Mapping<X, Codomain=Loc<F, N>> + Sized {
+    /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`.
+    fn slice_codomain(self, slice : usize) -> SlicedCodomain<X, F, Self, N> {
+        assert!(slice < N);
+        SlicedCodomain{ g : self, slice, _phantoms : PhantomData }
+    }
+}
+
+impl<X, F : Copy, G : Sized + Mapping<X, Codomain=Loc<F, N>>, const N : usize>
+SliceCodomain<X, F, N>
+for G {}
+
--- 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 {}
 
 
--- 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;
 }
 

mercurial