src/measures/discrete.rs

branch
dev
changeset 35
b087e3eab191
parent 34
efa60bc4f743
child 37
c5d8bd1a7728
--- a/src/measures/discrete.rs	Thu Aug 29 00:00:00 2024 -0500
+++ b/src/measures/discrete.rs	Tue Dec 31 09:25:45 2024 -0500
@@ -11,9 +11,11 @@
 
 use alg_tools::norms::Norm;
 use alg_tools::tabledump::TableDump;
-use alg_tools::linops::{Apply, Linear};
+use alg_tools::linops::{Mapping, Linear};
 use alg_tools::iter::{MapF,Mappable};
 use alg_tools::nalgebra_support::ToNalgebraRealField;
+use alg_tools::collection::Collection;
+use alg_tools::instance::{Instance, Decomposition, MyCow, EitherDecomp, Space};
 
 use crate::types::*;
 use super::base::*;
@@ -29,6 +31,8 @@
     pub(super) spikes : Vec<DeltaMeasure<Domain, F>>,
 }
 
+pub type RNDM<F, const N : usize> = DiscreteMeasure<Loc<F, N>, F>;
+
 /// Iterator over the [`DeltaMeasure`] spikes of a [`DiscreteMeasure`].
 pub type SpikeIter<'a, Domain, F> = std::slice::Iter<'a, DeltaMeasure<Domain, F>>;
 
@@ -109,6 +113,13 @@
         self.spikes.iter_mut().zip(iter).for_each(|(δ, α)| δ.set_mass(α));
     }
 
+    /// Update the locations of all the spikes to those produced by an iterator.
+    #[inline]
+    pub fn set_locations<'a, I : Iterator<Item=&'a Domain>>(&mut self, iter : I) 
+    where Domain : 'static + Clone {
+        self.spikes.iter_mut().zip(iter.cloned()).for_each(|(δ, α)| δ.set_location(α));
+    }
+
     // /// Map the masses of all the spikes using a function and an iterator
     // #[inline]
     // pub fn zipmap_masses<
@@ -190,7 +201,7 @@
 
 impl<Domain, F : Num> IntoIterator for DiscreteMeasure<Domain, F> {
     type Item =  DeltaMeasure<Domain, F>;
-    type IntoIter =  <Vec<DeltaMeasure<Domain, F>> as IntoIterator>::IntoIter;
+    type IntoIter = std::vec::IntoIter<DeltaMeasure<Domain, F>>;
 
     #[inline]
     fn into_iter(self) -> Self::IntoIter {
@@ -198,6 +209,60 @@
     }
 }
 
+impl<'a, Domain, F : Num> IntoIterator for &'a DiscreteMeasure<Domain, F> {
+    type Item =  &'a DeltaMeasure<Domain, F>;
+    type IntoIter =  SpikeIter<'a, Domain, F>;
+
+    #[inline]
+    fn into_iter(self) -> Self::IntoIter {
+        self.spikes.iter()
+    }
+}
+
+impl<Domain, F : Num> Sum<DeltaMeasure<Domain, F>> for DiscreteMeasure<Domain, F>  {
+    // Required method
+    fn sum<I>(iter: I) -> Self
+    where
+        I : Iterator<Item = DeltaMeasure<Domain, F>>
+    {
+        Self::from_iter(iter)
+    }
+}
+
+impl<'a, Domain : Clone, F : Num> Sum<&'a DeltaMeasure<Domain, F>>
+    for DiscreteMeasure<Domain, F>
+{
+    // Required method
+    fn sum<I>(iter: I) -> Self
+    where
+        I : Iterator<Item = &'a DeltaMeasure<Domain, F>>
+    {
+        Self::from_iter(iter.cloned())
+    }
+}
+
+impl<Domain, F : Num> Sum<DiscreteMeasure<Domain, F>> for DiscreteMeasure<Domain, F>  {
+    // Required method
+    fn sum<I>(iter: I) -> Self
+    where
+        I : Iterator<Item = DiscreteMeasure<Domain, F>>
+    {
+        Self::from_iter(iter.map(|μ| μ.into_iter()).flatten())
+    }
+}
+
+impl<'a, Domain : Clone, F : Num> Sum<&'a DiscreteMeasure<Domain, F>>
+    for DiscreteMeasure<Domain, F>
+{
+    // Required method
+    fn sum<I>(iter: I) -> Self
+    where
+        I : Iterator<Item = &'a DiscreteMeasure<Domain, F>>
+    {
+        Self::from_iter(iter.map(|μ| μ.iter_spikes()).flatten().cloned())
+    }
+}
+
 impl<Domain : Clone, F : Float> DiscreteMeasure<Domain, F> {
     /// Computes `μ1 ← θ * μ1 - ζ * μ2`, pruning entries where both `μ1` (`self`) and `μ2` have
     // zero weight. `μ2` will contain copy of pruned original `μ1` without arithmetic performed.
@@ -312,6 +377,45 @@
     }
 }
 
+impl<Domain, F : Num> From<Vec<DeltaMeasure<Domain, F>>>
+for DiscreteMeasure<Domain, F> {
+    #[inline]
+    fn from(spikes : Vec<DeltaMeasure<Domain, F>>) -> Self {
+        DiscreteMeasure{ spikes }
+    }
+}
+
+impl<'a, Domain, F : Num, D> From<&'a [D]>
+for DiscreteMeasure<Domain, F>
+where &'a D : Into<DeltaMeasure<Domain, F>> {
+    #[inline]
+    fn from(list : &'a [D]) -> Self {
+        list.into_iter().map(|d| d.into()).collect()
+    }
+}
+
+
+impl<Domain, F : Num> From<DeltaMeasure<Domain, F>>
+for DiscreteMeasure<Domain, F> {
+    #[inline]
+    fn from(δ : DeltaMeasure<Domain, F>) -> Self {
+        DiscreteMeasure{
+            spikes : vec!(δ)
+        }
+    }
+}
+
+impl<'a, Domain : Clone, F : Num> From<&'a DeltaMeasure<Domain, F>>
+for DiscreteMeasure<Domain, F> {
+    #[inline]
+    fn from(δ : &'a DeltaMeasure<Domain, F>) -> Self {
+        DiscreteMeasure{
+            spikes : vec!(δ.clone())
+        }
+    }
+}
+
+
 impl<Domain, F : Num, D : Into<DeltaMeasure<Domain, F>>> FromIterator<D>
 for DiscreteMeasure<Domain, F> {
     #[inline]
@@ -371,19 +475,28 @@
     }
 }
 
-impl<Domain, G, F : Num, Y : Sum + Mul<F, Output=Y>> Apply<G> for DiscreteMeasure<Domain, F>
-where G: for<'a> Apply<&'a Domain, Output = Y> {
-    type Output = Y;
+impl<Domain, G, F : Num> Mapping<G> for DiscreteMeasure<Domain, F>
+where
+    Domain : Space,
+    G::Codomain : Sum + Mul<F, Output=G::Codomain>,
+    G : Mapping<Domain, Codomain=F> + Clone + Space,
+    for<'b> &'b Domain : Instance<Domain>,
+{
+    type Codomain = G::Codomain;
+
     #[inline]
-    fn apply(&self, g : G) -> Y {
-        self.spikes.iter().map(|m| g.apply(&m.x) * m.α).sum()
+    fn apply<I : Instance<G>>(&self, g : I) -> Self::Codomain {
+        g.eval(|g| self.spikes.iter().map(|m| g.apply(&m.x) * m.α).sum())
     }
 }
 
-impl<Domain, G, F : Num, Y : Sum + Mul<F, Output=Y>> Linear<G> for DiscreteMeasure<Domain, F>
-where G : for<'a> Apply<&'a Domain, Output = Y> {
-    type Codomain = Y;
-}
+impl<Domain, G, F : Num> Linear<G> for DiscreteMeasure<Domain, F>
+where
+    Domain : Space,
+    G::Codomain : Sum + Mul<F, Output=G::Codomain>,
+    G : Mapping<Domain, Codomain=F> + Clone + Space,
+    for<'b> &'b Domain : Instance<Domain>,
+{ }
 
 
 /// Helper trait for constructing arithmetic operations for combinations
@@ -391,6 +504,7 @@
 trait Lift<F : Num, Domain> {
     type Producer : Iterator<Item=DeltaMeasure<Domain, F>>;
 
+    #[allow(dead_code)]
     /// Lifts `self` into a [`DiscreteMeasure`].
     fn lift(self) -> DiscreteMeasure<Domain, F>;
 
@@ -687,3 +801,217 @@
 
 make_discrete_scalarop_lhs!(Mul, mul; f32 f64 i8 i16 i32 i64 isize u8 u16 u32 u64 usize);
 make_discrete_scalarop_lhs!(Div, div; f32 f64 i8 i16 i32 i64 isize u8 u16 u32 u64 usize);
+
+impl<F : Num, Domain> Collection for DiscreteMeasure<Domain, F> {
+    type Element = DeltaMeasure<Domain, F>;
+    type RefsIter<'a> = std::slice::Iter<'a, Self::Element> where Self : 'a;
+
+    #[inline]
+    fn iter_refs(&self) -> Self::RefsIter<'_> {
+        self.iter_spikes()
+    }
+}
+
+impl<Domain : Clone, F : Num> Space for DiscreteMeasure<Domain, F> {
+    type Decomp = MeasureDecomp;
+}
+
+pub type SpikeSlice<'b, Domain, F> = &'b [DeltaMeasure<Domain, F>];
+
+pub type EitherSlice<'b, Domain, F> = EitherDecomp<
+    Vec<DeltaMeasure<Domain, F>>,
+    SpikeSlice<'b, Domain, F>
+>;
+
+impl<F : Num, Domain : Clone> Decomposition<DiscreteMeasure<Domain, F>> for MeasureDecomp {
+    type Decomposition<'b> = EitherSlice<'b, Domain, F> where DiscreteMeasure<Domain, F> : 'b;
+    type Reference<'b> = SpikeSlice<'b, Domain, F> where DiscreteMeasure<Domain, F> : 'b;
+
+    /// Left the lightweight reference type into a full decomposition type.
+    fn lift<'b>(r : Self::Reference<'b>) -> Self::Decomposition<'b> {
+        EitherDecomp::Borrowed(r)
+    }
+}
+
+impl<F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp>
+for DiscreteMeasure<Domain, F>
+{
+    fn decompose<'b>(self)
+        -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b>
+    where Self : 'b, DiscreteMeasure<Domain, F> : 'b {
+        EitherDecomp::Owned(self.spikes)
+    }
+  
+    fn ref_instance(&self)
+        -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_>
+    {
+        self.spikes.as_slice()
+    }
+
+    fn cow<'b>(self) -> MyCow<'b, DiscreteMeasure<Domain, F>> where Self : 'b {
+        MyCow::Owned(self)
+    }
+
+    fn own(self) -> DiscreteMeasure<Domain, F> {
+        self
+    }
+}
+
+impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp>
+for &'a DiscreteMeasure<Domain, F>
+{
+    fn decompose<'b>(self)
+        -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b>
+    where Self : 'b, DiscreteMeasure<Domain, F> : 'b {
+        EitherDecomp::Borrowed(self.spikes.as_slice())
+    }
+  
+    fn ref_instance(&self)
+        -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_>
+    {
+        self.spikes.as_slice()
+    }
+
+    fn cow<'b>(self) -> MyCow<'b, DiscreteMeasure<Domain, F>> where Self : 'b {
+        MyCow::Borrowed(self)
+    }
+
+    fn own(self) -> DiscreteMeasure<Domain, F> {
+        self.clone()
+    }
+}
+
+impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp>
+for EitherSlice<'a, Domain, F>
+{
+    fn decompose<'b>(self)
+        -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b>
+    where Self : 'b, DiscreteMeasure<Domain, F> : 'b {
+        self
+    }
+  
+    fn ref_instance(&self)
+        -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_>
+    {
+        match self {
+            EitherDecomp::Owned(v) => v.as_slice(),
+            EitherDecomp::Borrowed(s) => s,
+        }
+    }
+
+    fn own(self) -> DiscreteMeasure<Domain, F> {
+        match self {
+            EitherDecomp::Owned(v) => v.into(),
+            EitherDecomp::Borrowed(s) => s.into(),
+        }
+    }
+}
+
+impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp>
+for &'a EitherSlice<'a, Domain, F>
+{
+    fn decompose<'b>(self)
+        -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b>
+    where Self : 'b, DiscreteMeasure<Domain, F> : 'b {
+        match self {
+            EitherDecomp::Owned(v) => EitherDecomp::Borrowed(v.as_slice()),
+            EitherDecomp::Borrowed(s) => EitherDecomp::Borrowed(s),
+        }
+    }
+  
+    fn ref_instance(&self)
+        -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_>
+    {
+        match self {
+            EitherDecomp::Owned(v) => v.as_slice(),
+            EitherDecomp::Borrowed(s) => s,
+        }
+    }
+
+    fn own(self) -> DiscreteMeasure<Domain, F> {
+        match self {
+            EitherDecomp::Owned(v) => v.as_slice(),
+            EitherDecomp::Borrowed(s) => s
+        }.into()
+    }
+}
+
+impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp>
+for SpikeSlice<'a, Domain, F>
+{
+    fn decompose<'b>(self)
+        -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b>
+    where Self : 'b, DiscreteMeasure<Domain, F> : 'b {
+        EitherDecomp::Borrowed(self)
+    }
+  
+    fn ref_instance(&self)
+        -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_>
+    {
+        self
+    }
+
+    fn own(self) -> DiscreteMeasure<Domain, F> {
+        self.into()
+    }
+}
+
+impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp>
+for &'a SpikeSlice<'a, Domain, F>
+{
+    fn decompose<'b>(self)
+        -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b>
+    where Self : 'b, DiscreteMeasure<Domain, F> : 'b {
+        EitherDecomp::Borrowed(*self)
+    }
+  
+    fn ref_instance(&self)
+        -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_>
+    {
+        *self
+    }
+
+    fn own(self) -> DiscreteMeasure<Domain, F> {
+        (*self).into()
+    }
+}
+
+impl<F : Num, Domain : Clone > Instance<DiscreteMeasure<Domain, F>, MeasureDecomp>
+for DeltaMeasure<Domain, F>
+{
+    fn decompose<'b>(self)
+        -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b>
+    where Self : 'b, DiscreteMeasure<Domain, F> : 'b {
+        EitherDecomp::Owned(vec![self])
+    }
+  
+    fn ref_instance(&self)
+        -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_>
+    {
+        std::slice::from_ref(self)
+    }
+
+    fn own(self) -> DiscreteMeasure<Domain, F> {
+        self.into()
+    }
+}
+
+impl<'a, F : Num, Domain : Clone> Instance<DiscreteMeasure<Domain, F>, MeasureDecomp>
+for &'a DeltaMeasure<Domain, F>
+{
+    fn decompose<'b>(self)
+        -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Decomposition<'b>
+    where Self : 'b, DiscreteMeasure<Domain, F> : 'b {
+        EitherDecomp::Borrowed(std::slice::from_ref(self))
+    }
+  
+    fn ref_instance(&self)
+        -> <MeasureDecomp as Decomposition<DiscreteMeasure<Domain, F>>>::Reference<'_>
+    {
+        std::slice::from_ref(*self)
+    }
+
+    fn own(self) -> DiscreteMeasure<Domain, F> {
+        self.into()
+    }
+}

mercurial