Attempt to do more Serialize / Deserialize but run into csv problems draft dev

Mon, 06 Jan 2025 21:37:03 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Mon, 06 Jan 2025 21:37:03 -0500
branch
dev
changeset 38
0f59c0d02e13
parent 37
c5d8bd1a7728

Attempt to do more Serialize / Deserialize but run into csv problems

src/experiments.rs file | annotate | diff | comparison | revisions
src/forward_model/sensor_grid.rs file | annotate | diff | comparison | revisions
src/kernels/ball_indicator.rs file | annotate | diff | comparison | revisions
src/kernels/base.rs file | annotate | diff | comparison | revisions
src/kernels/gaussian.rs file | annotate | diff | comparison | revisions
src/kernels/hat.rs file | annotate | diff | comparison | revisions
src/kernels/hat_convolution.rs file | annotate | diff | comparison | revisions
src/kernels/linear.rs file | annotate | diff | comparison | revisions
src/kernels/mollifier.rs file | annotate | diff | comparison | revisions
src/measures/delta.rs file | annotate | diff | comparison | revisions
src/measures/discrete.rs file | annotate | diff | comparison | revisions
src/run.rs file | annotate | diff | comparison | revisions
--- a/src/experiments.rs	Thu Jan 23 23:35:28 2025 +0100
+++ b/src/experiments.rs	Mon Jan 06 21:37:03 2025 -0500
@@ -102,7 +102,13 @@
 ];
 
 /// The $\{0,1\}$-valued characteristic function of a ball as a [`Mapping`].
-#[derive(Debug,Copy,Clone,Serialize,PartialEq)]
+#[derive(Debug,Copy,Clone,Serialize,Deserialize,PartialEq)]
+#[serde(bound(
+    serialize = "F : Serialize,
+                 Loc<F, N> : Serialize",
+    deserialize = "F : for<'a> Deserialize<'a>,
+                   Loc<F, N> : for<'a> Deserialize<'a>",
+))]
 struct BallCharacteristic<F : Float, const N : usize> {
     pub center : Loc<F, N>,
     pub radius : F,
--- a/src/forward_model/sensor_grid.rs	Thu Jan 23 23:35:28 2025 +0100
+++ b/src/forward_model/sensor_grid.rs	Mon Jan 06 21:37:03 2025 -0500
@@ -9,6 +9,7 @@
 };
 use std::iter::Zip;
 use std::ops::RangeFrom;
+use serde::Serialize;
 
 pub use alg_tools::linops::*;
 use alg_tools::norms::{
@@ -407,6 +408,7 @@
       S : Sensor<F, N>,
       P : Spread<F, N>,
       Convolution<S, P> : Spread<F, N> + LocalAnalysis<F, BT::Agg, N>,
+      [F; N]: Serialize,
       /*ShiftedSensor<F, S, P, N> : LocalAnalysis<F, BT::Agg, N>,
       Weighted<ShiftedSensor<F, S, P, N>, F> : LocalAnalysis<F, BT::Agg, N>*/ {
     type Observable = DVector<F>;
@@ -429,6 +431,7 @@
       S : Sensor<F, N>,
       P : Spread<F, N>,
       Convolution<S, P> : Spread<F, N> + LocalAnalysis<F, BT::Agg, N>,
+      [F; N] : Serialize,
       /*ShiftedSensor<F, S, P, N> : LocalAnalysis<F, BT::Agg, N>,
       Weighted<ShiftedSensor<F, S, P, N>, F> : LocalAnalysis<F, BT::Agg, N>*/ {
 
--- a/src/kernels/ball_indicator.rs	Thu Jan 23 23:35:28 2025 +0100
+++ b/src/kernels/ball_indicator.rs	Mon Jan 06 21:37:03 2025 -0500
@@ -2,7 +2,7 @@
 //! Implementation of the indicator function of a ball with respect to various norms.
 use float_extras::f64::tgamma as gamma;
 use numeric_literals::replace_float_literals;
-use serde::Serialize;
+use serde::{Serialize, Deserialize};
 use alg_tools::types::*;
 use alg_tools::norms::*;
 use alg_tools::loc::Loc;
@@ -28,7 +28,7 @@
 
 /// Representation of the indicator of the ball $𝔹_q = \\{ x ∈ ℝ^N \mid \\|x\\|\_q ≤ r \\}$,
 /// where $q$ is the `Exponent`, and $r$ is the radius [`Constant`] `C`.
-#[derive(Copy,Clone,Serialize,Debug,Eq,PartialEq)]
+#[derive(Copy,Clone,Serialize,Deserialize,Debug,Eq,PartialEq)]
 pub struct BallIndicator<C : Constant, Exponent : NormExponent, const N : usize> {
     /// The radius of the ball.
     pub r : C,
--- a/src/kernels/base.rs	Thu Jan 23 23:35:28 2025 +0100
+++ b/src/kernels/base.rs	Mon Jan 06 21:37:03 2025 -0500
@@ -1,6 +1,6 @@
 
 //! Things for constructing new kernels from component kernels and traits for analysing them
-use serde::Serialize;
+use serde::{Serialize, Deserialize};
 use numeric_literals::replace_float_literals;
 
 use alg_tools::types::*;
@@ -296,7 +296,7 @@
 /// The kernels typically implement [`Support`]s and [`Mapping`].
 //
 /// Trait implementations have to be on a case-by-case basis.
-#[derive(Copy,Clone,Serialize,Debug,Eq,PartialEq)]
+#[derive(Copy,Clone,Serialize,Deserialize,Debug,Eq,PartialEq)]
 pub struct Convolution<A, B>(
     /// First kernel
     pub A,
--- a/src/kernels/gaussian.rs	Thu Jan 23 23:35:28 2025 +0100
+++ b/src/kernels/gaussian.rs	Mon Jan 06 21:37:03 2025 -0500
@@ -2,7 +2,7 @@
 
 use float_extras::f64::erf;
 use numeric_literals::replace_float_literals;
-use serde::Serialize;
+use serde::{Serialize, Deserialize};
 use alg_tools::types::*;
 use alg_tools::euclidean::Euclidean;
 use alg_tools::norms::*;
@@ -34,7 +34,7 @@
 ///
 /// This is the function $f(x) = C e^{-\\|x\\|\_2^2/(2σ^2)}$ for $x ∈ ℝ^N$
 /// with $C=1/(2πσ^2)^{N/2}$.
-#[derive(Copy,Clone,Debug,Serialize,Eq)]
+#[derive(Copy,Clone,Debug,Serialize,Deserialize,Eq)]
 pub struct Gaussian<S : Constant, const N : usize> {
     /// The variance $σ^2$.
     pub variance : S,
--- a/src/kernels/hat.rs	Thu Jan 23 23:35:28 2025 +0100
+++ b/src/kernels/hat.rs	Mon Jan 06 21:37:03 2025 -0500
@@ -1,7 +1,7 @@
 //! Implementation of the hat function
 
 use numeric_literals::replace_float_literals;
-use serde::Serialize;
+use serde::{Serialize, Deserialize};
 use alg_tools::types::*;
 use alg_tools::norms::*;
 use alg_tools::loc::Loc;
@@ -19,7 +19,7 @@
 use crate::types::Lipschitz;
 
 /// Representation of the hat function $f(x)=1-\\|x\\|\_1/ε$ of `width` $ε$ on $ℝ^N$.
-#[derive(Copy,Clone,Serialize,Debug,Eq,PartialEq)]
+#[derive(Copy,Clone,Serialize,Deserialize,Debug,Eq,PartialEq)]
 pub struct Hat<C : Constant, const N : usize> {
     /// The parameter $ε>0$.
     pub width : C,
--- a/src/kernels/hat_convolution.rs	Thu Jan 23 23:35:28 2025 +0100
+++ b/src/kernels/hat_convolution.rs	Mon Jan 06 21:37:03 2025 -0500
@@ -1,7 +1,7 @@
 //! Implementation of the convolution of two hat functions,
 //! and its convolution with a [`CubeIndicator`].
 use numeric_literals::replace_float_literals;
-use serde::Serialize;
+use serde::{Serialize, Deserialize};
 use alg_tools::types::*;
 use alg_tools::norms::*;
 use alg_tools::loc::Loc;
@@ -69,7 +69,7 @@
 // $$
 //     [∇f(x\_1, …, x\_n)]_j = \frac{4}{σ} (h\*h)'(x\_j/σ) \prod\_{j ≠ i} \frac{4}{σ} (h\*h)(x\_i/σ)
 // $$
-#[derive(Copy,Clone,Debug,Serialize,Eq)]
+#[derive(Copy,Clone,Debug,Serialize,Deserialize,Eq)]
 pub struct HatConv<S : Constant, const N : usize> {
     /// The parameter $σ$ of the kernel.
     pub radius : S,
--- a/src/kernels/linear.rs	Thu Jan 23 23:35:28 2025 +0100
+++ b/src/kernels/linear.rs	Mon Jan 06 21:37:03 2025 -0500
@@ -1,7 +1,7 @@
 //! Implementation of the linear function
 
 use numeric_literals::replace_float_literals;
-use serde::Serialize;
+use serde::{Serialize, Deserialize};
 use alg_tools::types::*;
 use alg_tools::norms::*;
 use alg_tools::loc::Loc;
@@ -18,7 +18,8 @@
 use alg_tools::euclidean::Euclidean;
 
 /// Representation of the hat function $f(x)=1-\\|x\\|\_1/ε$ of `width` $ε$ on $ℝ^N$.
-#[derive(Copy,Clone,Serialize,Debug,Eq,PartialEq)]
+#[derive(Copy,Clone,Serialize,Deserialize,Debug,Eq,PartialEq)]
+#[serde(bound = "Loc<F, N> : Serialize + for<'a> Deserialize<'a>")]
 pub struct Linear<F : Float, const N : usize> {
     /// The parameter $ε>0$.
     pub v : Loc<F, N>,
--- a/src/kernels/mollifier.rs	Thu Jan 23 23:35:28 2025 +0100
+++ b/src/kernels/mollifier.rs	Mon Jan 06 21:37:03 2025 -0500
@@ -4,7 +4,7 @@
 use rgsl::hypergeometric::hyperg_U;
 use float_extras::f64::tgamma as gamma;
 use numeric_literals::replace_float_literals;
-use serde::Serialize;
+use serde::{Serialize, Deserialize};
 use alg_tools::types::*;
 use alg_tools::euclidean::Euclidean;
 use alg_tools::norms::*;
@@ -29,7 +29,7 @@
 ///         0, & \text{otherwise}.
 ///     \end{cases}
 /// $$</div>
-#[derive(Copy,Clone,Serialize,Debug,Eq,PartialEq)]
+#[derive(Copy,Clone,Serialize,Deserialize,Debug,Eq,PartialEq)]
 pub struct Mollifier<C : Constant, const N : usize> {
     /// The parameter $ε$ of the mollifier.
     pub width : C,
--- a/src/measures/delta.rs	Thu Jan 23 23:35:28 2025 +0100
+++ b/src/measures/delta.rs	Mon Jan 06 21:37:03 2025 -0500
@@ -6,7 +6,7 @@
 use super::base::*;
 use crate::types::*;
 use std::ops::{Div, Mul, DivAssign, MulAssign, Neg};
-use serde::ser::{Serialize, Serializer, SerializeStruct};
+use serde::{Serialize, Deserialize};
 use alg_tools::norms::Norm;
 use alg_tools::linops::{Mapping, Linear};
 use alg_tools::instance::{Instance, Space};
@@ -15,7 +15,7 @@
 ///
 /// This is a single spike $\alpha \delta\_x$ for some location $x$ in `Domain` and
 /// a mass $\alpha$ in `F`.
-#[derive(Clone,Copy,Debug)]
+#[derive(Clone,Copy,Debug,Serialize,Deserialize)]
 pub struct DeltaMeasure<Domain, F : Num> {
     // This causes [`csv`] to crash.
     //#[serde(flatten)]
@@ -25,32 +25,6 @@
     pub α : F
 }
 
-const COORDINATE_NAMES : &'static [&'static str] = &[
-    "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7"
-];
-
-// Need to manually implement serialisation as [`csv`] writer fails on
-// structs with nested arrays as well as with #[serde(flatten)].
-impl<F : Num, const N : usize> Serialize for DeltaMeasure<Loc<F, N>, F>
-where
-    F: Serialize,
-{
-    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    where
-        S: Serializer,
-    {
-        assert!(N <= COORDINATE_NAMES.len());
-
-        let mut s = serializer.serialize_struct("DeltaMeasure", N+1)?;
-        for (i, e) in (0..).zip(self.x.iter()) {
-            s.serialize_field(COORDINATE_NAMES[i], e)?;
-        }
-        s.serialize_field("weight", &self.α)?;
-        s.end()
-    }
-}
-
-
 impl<Domain, F : Float> Measure<F> for DeltaMeasure<Domain, F> {
     type Domain = Domain;
 }
--- a/src/measures/discrete.rs	Thu Jan 23 23:35:28 2025 +0100
+++ b/src/measures/discrete.rs	Mon Jan 06 21:37:03 2025 -0500
@@ -6,7 +6,7 @@
     Index,IndexMut,
 };
 use std::iter::Sum;
-use serde::ser::{Serializer, Serialize, SerializeSeq};
+use serde::{Serialize, Deserialize};
 use nalgebra::DVector;
 
 use alg_tools::norms::Norm;
@@ -26,7 +26,7 @@
 /// This is the measure $μ = ∑_{k=1}^n α_k δ_{x_k}$, consisting of several
 /// [`DeltaMeasure`], i.e., “spikes” $α_k δ_{x_k}$ with weights $\alpha_k$ in `F` at locations
 /// $x_k$ in `Domain`.
-#[derive(Clone,Debug)]
+#[derive(Clone,Debug,Serialize,Deserialize)]
 pub struct DiscreteMeasure<Domain, F : Num> {
     pub(super) spikes : Vec<DeltaMeasure<Domain, F>>,
 }
@@ -456,25 +456,6 @@
     }
 }
 
-// Need to manually implement serialisation for DeltaMeasure<Loc<F, N>, F> [`csv`] writer fails on
-// structs with nested arrays as well as with #[serde(flatten)].
-// Then derive no longer works for DiscreteMeasure
-impl<F : Num, const N : usize> Serialize for DiscreteMeasure<Loc<F, N>, F>
-where
-    F: Serialize,
-{
-    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    where
-        S: Serializer,
-    {
-        let mut s = serializer.serialize_seq(Some(self.spikes.len()))?;
-        for δ in self.spikes.iter() {
-            s.serialize_element(δ)?;
-        }
-        s.end()
-    }
-}
-
 impl<Domain : PartialEq, F : Float> Measure<F> for DiscreteMeasure<Domain, F> {
     type Domain = Domain;
 }
--- a/src/run.rs	Thu Jan 23 23:35:28 2025 +0100
+++ b/src/run.rs	Mon Jan 06 21:37:03 2025 -0500
@@ -327,7 +327,7 @@
 // }
 
 /// Plotting level configuration
-#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, ValueEnum, Debug)]
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, ValueEnum, Debug)]
 pub enum PlotLevel {
     /// Plot nothing
     #[clap(name = "none")]
@@ -357,7 +357,7 @@
 >;
 
 /// This is a dirty workaround to rust-csv not supporting struct flattening etc.
-#[derive(Serialize)]
+#[derive(Serialize, Deserialize)]
 struct CSVLog<F> {
     iter : usize,
     cpu_time : f64,
@@ -372,7 +372,7 @@
 }
 
 /// Collected experiment statistics
-#[derive(Clone, Debug, Serialize)]
+#[derive(Clone, Debug, Serialize, Deserialize)]
 struct ExperimentStats<F : Float> {
     /// Signal-to-noise ratio in decibels
     ssnr : F,
@@ -398,7 +398,7 @@
     }
 }
 /// Collected algorithm statistics
-#[derive(Clone, Debug, Serialize)]
+#[derive(Clone, Debug, Serialize, Deserialize)]
 struct AlgorithmStats<F : Float> {
     /// Overall CPU time spent
     cpu_time : F,
@@ -416,10 +416,29 @@
 
 
 /// Struct for experiment configurations
-#[derive(Debug, Clone, Serialize)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[serde(bound(
+    serialize = "Cube<F, N> : Serialize,
+                 NoiseDistr : Serialize,
+                 [usize; N] : Serialize,
+                 RNDM<F, N> : Serialize,
+                 Regularisation<F> : Serialize,
+                 F : Serialize,
+                 S : Serialize,
+                 P : Serialize,
+                 K : Serialize",
+    deserialize = "Cube<F, N> : for<'a> Deserialize<'a>,
+                   NoiseDistr : for<'a> Deserialize<'a>,
+                   [usize; N] : for<'a> Deserialize<'a>,
+                   RNDM<F, N> : for<'a> Deserialize<'a>,
+                   Regularisation<F> : for<'a> Deserialize<'a>,
+                   F : for<'a> Deserialize<'a>,
+                   S : for<'a> Deserialize<'a>,
+                   P : for<'a> Deserialize<'a>,
+                   K : for<'a> Deserialize<'a>,",
+))]
 pub struct ExperimentV2<F, NoiseDistr, S, K, P, const N : usize>
 where F : Float,
-      [usize; N] : Serialize,
       NoiseDistr : Distribution<F>,
       S : Sensor<F, N>,
       P : Spread<F, N>,
@@ -452,7 +471,15 @@
     pub algorithm_defaults : HashMap<DefaultAlgorithm, AlgorithmConfig<F>>,
 }
 
-#[derive(Debug, Clone, Serialize)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[serde(bound(
+    serialize = "ExperimentV2<F, NoiseDistr, S, K, P, N> : Serialize,
+                 B : Serialize,
+                 F : Serialize",
+    deserialize = "ExperimentV2<F, NoiseDistr, S, K, P, N >: for<'a> Deserialize<'a>,
+                   B : for<'a> Deserialize<'a>,
+                   F : for<'a> Deserialize<'a>",
+))]
 pub struct ExperimentBiased<F, NoiseDistr, S, K, P, B, const N : usize>
 where F : Float,
       [usize; N] : Serialize,
@@ -541,6 +568,7 @@
 ) ->  DynError
 where
     PlotLookup : Plotting<N>,
+    DeltaMeasure<Loc<F, N>, F> : Serialize,
 {
     let mut logs = Vec::new();
 
@@ -647,6 +675,8 @@
     BTNodeLookup: BTNode<F, usize, Bounds<F>, N>,
     RNDM<F, N> : SpikeMerging<F>,
     NoiseDistr : Distribution<F> + Serialize + std::fmt::Debug,
+    [F; N] : Serialize,
+    [[F; 2]; N] : Serialize,
     // DefaultSG<F, S, P, N> : ForwardModel<RNDM<F, N>, F, PreadjointCodomain = PreadjointCodomain, Observable=DVector<F::MixedType>>,
     // PreadjointCodomain : Space + Bounded<F> + DifferentiableRealMapping<F, N>,
     // DefaultSeminormOp<F, K, N> : ProxPenalty<F, PreadjointCodomain, RadonRegTerm<F>, N>,
@@ -912,6 +942,8 @@
     RNDM<F, N> : SpikeMerging<F>,
     NoiseDistr : Distribution<F> + Serialize + std::fmt::Debug,
     B : Mapping<Loc<F, N>, Codomain = F> + Serialize + std::fmt::Debug,
+    [F; N] : Serialize,
+    [[F; 2]; N] : Serialize,
     // DefaultSG<F, S, P, N> : ForwardModel<RNDM<F, N>, F, PreadjointCodomain = PreadjointCodomain, Observable=DVector<F::MixedType>>,
     // PreadjointCodomain : Bounded<F> + DifferentiableRealMapping<F, N>,
     // DefaultSeminormOp<F, K, N> :  ProxPenalty<F, PreadjointCodomain, RadonRegTerm<F>, N>,
@@ -1169,18 +1201,21 @@
     b : &A::Observable,
     kernel_plot_width : F,
 ) -> DynError
-where F : Float + ToNalgebraRealField,
-      Sensor : RealMapping<F, N> + Support<F, N> + Clone,
-      Spread : RealMapping<F, N> + Support<F, N> + Clone,
-      Kernel : RealMapping<F, N> + Support<F, N>,
-      Convolution<Sensor, Spread> : DifferentiableRealMapping<F, N> + Support<F, N>,
-      𝒟 : DiscreteMeasureOp<Loc<F, N>, F>,
-      𝒟::Codomain : RealMapping<F, N>,
-      A : ForwardModel<RNDM<F, N>, F>,
-      for<'a> &'a A::Observable : Instance<A::Observable>,
-      A::PreadjointCodomain : DifferentiableRealMapping<F, N> + Bounded<F>,
-      PlotLookup : Plotting<N>,
-      Cube<F, N> : SetOrd {
+where
+    F : Float + ToNalgebraRealField,
+    Sensor : RealMapping<F, N> + Support<F, N> + Clone,
+    Spread : RealMapping<F, N> + Support<F, N> + Clone,
+    Kernel : RealMapping<F, N> + Support<F, N>,
+    Convolution<Sensor, Spread> : DifferentiableRealMapping<F, N> + Support<F, N>,
+    𝒟 : DiscreteMeasureOp<Loc<F, N>, F>,
+    𝒟::Codomain : RealMapping<F, N>,
+    A : ForwardModel<RNDM<F, N>, F>,
+    for<'a> &'a A::Observable : Instance<A::Observable>,
+    A::PreadjointCodomain : DifferentiableRealMapping<F, N> + Bounded<F>,
+    PlotLookup : Plotting<N>,
+    Cube<F, N> : SetOrd,
+    DeltaMeasure<Loc<F, N>, F> : Serialize,
+{
 
     if cli.plot < PlotLevel::Data {
         return Ok(())

mercurial