More Serialize / Deserialize / Debug derives draft dev

Mon, 06 Jan 2025 20:29:25 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Mon, 06 Jan 2025 20:29:25 -0500
branch
dev
changeset 86
d5b0e496b72f
parent 76
99ad55974e62

More Serialize / Deserialize / Debug derives

Cargo.toml file | annotate | diff | comparison | revisions
src/bisection_tree/aggregator.rs file | annotate | diff | comparison | revisions
src/bisection_tree/bt.rs file | annotate | diff | comparison | revisions
src/bisection_tree/btfn.rs file | annotate | diff | comparison | revisions
src/bisection_tree/either.rs file | annotate | diff | comparison | revisions
src/bisection_tree/refine.rs file | annotate | diff | comparison | revisions
src/bisection_tree/support.rs file | annotate | diff | comparison | revisions
src/convex.rs file | annotate | diff | comparison | revisions
src/discrete_gradient.rs file | annotate | diff | comparison | revisions
src/fe_model/p2_local_model.rs file | annotate | diff | comparison | revisions
src/loc.rs file | annotate | diff | comparison | revisions
src/norms.rs file | annotate | diff | comparison | revisions
src/operator_arithmetic.rs file | annotate | diff | comparison | revisions
src/sets.rs file | annotate | diff | comparison | revisions
src/sets/cube.rs file | annotate | diff | comparison | revisions
src/types.rs file | annotate | diff | comparison | revisions
--- a/Cargo.toml	Mon Dec 30 15:46:28 2024 -0500
+++ b/Cargo.toml	Mon Jan 06 20:29:25 2025 -0500
@@ -12,7 +12,7 @@
 categories = ["mathematics", "data-structures"]
 
 [dependencies]
-serde = { version = "1.0", features = ["derive"] }
+serde = { version = "1.0", features = ["derive", "rc"] }
 csv = "~1.3.1"
 nalgebra = "~0.33.0"
 num-traits = { version = "~0.2.14", features = ["std"] }
--- a/src/bisection_tree/aggregator.rs	Mon Dec 30 15:46:28 2024 -0500
+++ b/src/bisection_tree/aggregator.rs	Mon Jan 06 20:29:25 2025 -0500
@@ -2,6 +2,7 @@
 Aggregation / summarisation of information in branches of bisection trees.
 */
 
+use serde::{Serialize, Deserialize};
 use crate::types::*;
 use crate::sets::Set;
 use crate::instance::Instance;
@@ -33,7 +34,7 @@
 }
 
 /// An [`Aggregator`] that doesn't aggregate anything.
-#[derive(Clone,Debug)]
+#[derive(Clone,Debug,Serialize,Deserialize)]
 pub struct NullAggregator;
 
 impl Aggregator for NullAggregator {
@@ -47,7 +48,7 @@
 }
 
 /// Upper and lower bounds on an `F`-valued function.
-#[derive(Copy,Clone,Debug)]
+#[derive(Copy,Clone,Debug,Serialize,Deserialize)]
 pub struct Bounds<F>(
     /// Lower bound
     pub F,
--- a/src/bisection_tree/bt.rs	Mon Dec 30 15:46:28 2024 -0500
+++ b/src/bisection_tree/bt.rs	Mon Jan 06 20:29:25 2025 -0500
@@ -43,7 +43,13 @@
 /// Node of a [`BT`] bisection tree.
 ///
 /// For the type and const parameteres, see the [module level documentation][super].
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(bound(
+    serialize = "NodeOption<F, D, A, N, P> : Serialize,
+                 A : Serialize,",
+    deserialize = "NodeOption<F, D, A, N, P> : for<'a> Deserialize<'a>,
+                   A : for<'a> Deserialize<'a>,"
+))]
 pub struct Node<F : Num, D, A : Aggregator, const N : usize, const P : usize> {
     /// The data or branches under the node.
     pub(super) data : NodeOption<F, D, A, N, P>,
@@ -54,7 +60,13 @@
 /// Branching information of a [`Node`] of a [`BT`] bisection tree into `P` subnodes.
 ///
 /// For the type and const parameters, see the [module level documentation][super].
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(bound(
+    serialize = "[Node<F, D, A, N, P>; P] : Serialize,
+                 Loc<F, N> : Serialize,",
+    deserialize = "[Node<F, D, A, N, P>; P] : for<'a> Deserialize<'a>,
+                   Loc<F, N> : for<'a> Deserialize<'a>,"
+))]
 pub(super) struct Branches<F : Num, D, A : Aggregator, const N : usize, const P : usize> {
     /// Point for subdivision of the (unstored) [`Cube`] corresponding to the node.
     pub(super) branch_at : Loc<F, N>,
@@ -198,6 +210,7 @@
 }
 
 /// An iterator over the $P=2^N$ subcubes of a [`Cube`] subdivided at a point `d`.
+#[derive(Debug, Clone)]
 pub(super) struct SubcubeIter<'b, F : Float, const N : usize, const P : usize> {
     domain : &'b Cube<F, N>,
     branch_at : Loc<F, N>,
@@ -637,7 +650,15 @@
 /// It should be accessed via the [`BTImpl`] trait to hide the `const P : usize` parameter until
 /// const generics are flexible enough to fix `P=pow(2, N)` and thus also get rid of
 /// the `BTNodeLookup : BTNode<F, D, A, N>` trait bound.
-#[derive(Clone,Debug)]
+#[derive(Clone,Debug,Serialize,Deserialize)]
+#[serde(bound(
+    serialize = "Cube<F, N> : Serialize,
+                 M : Serialize,
+                 <BTNodeLookup as BTNode<F, D, A, N>>::Node : Serialize,",
+    deserialize = "Cube<F, N> : for<'a> Deserialize<'a>,
+                   M : for<'a> Deserialize<'a>,
+                   <BTNodeLookup as BTNode<F, D, A, N>>::Node : for<'a> Deserialize<'a>,"
+))]
 pub struct BT<
     M : Depth,
     F : Float,
--- a/src/bisection_tree/btfn.rs	Mon Dec 30 15:46:28 2024 -0500
+++ b/src/bisection_tree/btfn.rs	Mon Jan 06 20:29:25 2025 -0500
@@ -1,5 +1,6 @@
 
 use numeric_literals::replace_float_literals;
+use serde::{Serialize, Deserialize};
 use std::iter::Sum;
 use std::marker::PhantomData;
 use std::sync::Arc;
@@ -30,7 +31,7 @@
 /// Identifiers of the components ([`SupportGenerator::Id`], usually `usize`) are stored stored
 /// in a [bisection tree][BTImpl], when one is provided as `bt`. However `bt` may also be `()`
 /// for a [`PreBTFN`] that is only useful for vector space operations with a full [`BTFN`].
-#[derive(Clone,Debug)]
+#[derive(Clone,Debug,Serialize,Deserialize)]
 pub struct BTFN<
     F : Float,
     G : SupportGenerator<F, N>,
@@ -39,6 +40,7 @@
 > /*where G::SupportType : LocalAnalysis<F, A, N>*/ {
     bt : BT,
     generator : Arc<G>,
+    #[serde(skip)]
     _phantoms : PhantomData<F>,
 }
 
@@ -587,14 +589,17 @@
 }
 
 /// Helper type to use [`P2Refiner`] for maximisation.
+#[derive(Debug, Clone, Serialize, Deserialize)]
 struct RefineMax;
 
 /// Helper type to use [`P2Refiner`] for minimisation.
+#[derive(Debug, Clone, Serialize, Deserialize)]
 struct RefineMin;
 
 /// A bisection tree [`Refiner`] for maximising or minimising a [`BTFN`].
 ///
 /// The type parameter `T` should be either [`RefineMax`] or [`RefineMin`].
+#[derive(Debug, Clone, Serialize, Deserialize)]
 struct P2Refiner<F : Float, T> {
     /// The maximum / minimum should be above / below this threshold.
     /// If the threshold cannot be satisfied, the refiner will return `None`.
@@ -733,6 +738,7 @@
 /// The type parameter `T` should be either [`RefineMax`] for upper bound or [`RefineMin`]
 /// for lower bound.
 
+#[derive(Debug, Clone, Serialize, Deserialize)]
 struct BoundRefiner<F : Float, T> {
     /// The upper/lower bound to check for
     bound : F,
--- a/src/bisection_tree/either.rs	Mon Dec 30 15:46:28 2024 -0500
+++ b/src/bisection_tree/either.rs	Mon Jan 06 20:29:25 2025 -0500
@@ -1,6 +1,7 @@
 
 use std::iter::Chain;
 use std::sync::Arc;
+use serde::{Serialize, Deserialize};
 
 use crate::types::*;
 use crate::mapping::{
@@ -20,7 +21,7 @@
 /// A structure for storing two [`SupportGenerator`]s summed/chain together.
 ///
 /// This is needed to work with sums of different types of [`Support`]s.
-#[derive(Debug,Clone)]
+#[derive(Debug,Clone,Serialize,Deserialize)]
 pub struct BothGenerators<A, B>(
     pub(super) Arc<A>,
     pub(super) Arc<B>,
@@ -29,7 +30,7 @@
 /// A structure for a [`Support`] that can be either `A` or `B`.
 ///
 /// This is needed to work with sums of different types of [`Support`]s.
-#[derive(Debug,Clone)]
+#[derive(Debug,Clone,Serialize,Deserialize)]
 pub enum EitherSupport<A, B> {
     Left(A),
     Right(B),
--- a/src/bisection_tree/refine.rs	Mon Dec 30 15:46:28 2024 -0500
+++ b/src/bisection_tree/refine.rs	Mon Jan 06 20:29:25 2025 -0500
@@ -3,6 +3,7 @@
 use std::cmp::{PartialOrd, Ord, Ordering, Ordering::*, max};
 use std::marker::PhantomData;
 use std::sync::{Arc, Mutex, MutexGuard, Condvar};
+use serde::{Serialize, Deserialize};
 use crate::types::*;
 use crate::nanleast::NaNLeast;
 use crate::sets::Cube;
@@ -35,12 +36,20 @@
 /// An [`AggregatorSorting`] for [`Bounds`], using the upper/lower bound as the upper/lower key.
 ///
 /// See [`LowerBoundSorting`] for the opposite ordering.
-pub struct UpperBoundSorting<F : Float>(PhantomData<F>);
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct UpperBoundSorting<F : Float>(
+    #[serde(skip)]
+    PhantomData<F>
+);
 
 /// An [`AggregatorSorting`] for [`Bounds`], using the upper/lower bound as the lower/upper key.
 ///
 /// See [`UpperBoundSorting`] for the opposite ordering.
-pub struct LowerBoundSorting<F : Float>(PhantomData<F>);
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct LowerBoundSorting<F : Float>(
+    #[serde(skip)]
+    PhantomData<F>
+);
 
 impl<F : Float> AggregatorSorting for UpperBoundSorting<F> {
     type Agg = Bounds<F>;
@@ -136,6 +145,7 @@
 }
 
 /// Structure for tracking the refinement process in a [`BinaryHeap`].
+#[derive(Debug)]
 struct RefinementInfo<'a, F, D, A, S, RResult, const N : usize, const P : usize>
 where F : Float,
       D : 'static,
@@ -228,6 +238,7 @@
 /// This is a container for a [`BinaryHeap`] of [`RefinementInfo`]s together with tracking of
 /// the greatest lower bound of the [`Aggregator`]s of the [`Node`]s therein accroding to
 /// chosen [`AggregatorSorting`].
+#[derive(Debug)]
 struct HeapContainer<'a, F, D, A, S, RResult, const N : usize, const P : usize>
 where F : Float,
       D : 'static + Copy,
--- a/src/bisection_tree/support.rs	Mon Dec 30 15:46:28 2024 -0500
+++ b/src/bisection_tree/support.rs	Mon Jan 06 20:29:25 2025 -0500
@@ -2,7 +2,7 @@
 /*!
 Traits for representing the support of a [`Mapping`], and analysing the mapping on a [`Cube`].
 */
-use serde::Serialize;
+use serde::{Serialize, Deserialize};
 use std::ops::{MulAssign,DivAssign,Neg};
 use crate::types::{Float, Num};
 use crate::maputil::map2;
@@ -103,7 +103,13 @@
 impl<F : Float, T : GlobalAnalysis<F, Bounds<F>>> Bounded<F> for T { }
 
 /// Shift of [`Support`] and [`Mapping`]; output of [`Support::shift`].
-#[derive(Copy,Clone,Debug,Serialize)] // Serialize! but not implemented by Loc.
+#[derive(Copy,Clone,Debug,Serialize,Deserialize)]
+#[serde(bound(
+    serialize = "Loc<F, N> : Serialize,
+                 T : Serialize,",
+    deserialize = "Loc<F, N> : for<'a> Deserialize<'a>,
+                   T : for<'a> Deserialize<'a>",
+))]
 pub struct Shift<T, F, const N : usize> {
     shift : Loc<F, N>,
     base_fn : T,
--- a/src/convex.rs	Mon Dec 30 15:46:28 2024 -0500
+++ b/src/convex.rs	Mon Jan 06 20:29:25 2025 -0500
@@ -3,6 +3,7 @@
 */
 
 use std::marker::PhantomData;
+use serde::{Serialize, Deserialize};
 use crate::types::*;
 use crate::mapping::{Mapping, Space};
 use crate::linops::IdOp;
@@ -68,6 +69,7 @@
 }
 
 
+#[derive(Serialize,Deserialize,Debug,Clone)]
 pub struct NormConstraint<F : Float, E : NormExponent> {
     radius : F,
     norm : NormMapping<F, E>,
@@ -160,6 +162,7 @@
     }
 }
 
+#[derive(Serialize,Deserialize,Debug,Clone)]
 pub struct NormProjection<F : Float, E : NormExponent> {
     radius : F,
     exponent : E,
@@ -194,7 +197,11 @@
 
 
 /// The zero mapping
-pub struct Zero<Domain : Space, F : Num>(PhantomData<(Domain, F)>);
+#[derive(Serialize,Deserialize,Debug,Clone)]
+pub struct Zero<Domain : Space, F : Num>(
+    #[serde(skip)]
+    PhantomData<(Domain, F)>
+);
 
 impl<Domain : Space, F : Num> Zero<Domain, F> {
     pub fn new() -> Self {
@@ -247,7 +254,11 @@
 
 
 /// The zero indicator
-pub struct ZeroIndicator<Domain : Space, F : Num>(PhantomData<(Domain, F)>);
+#[derive(Serialize,Deserialize,Debug,Clone)]
+pub struct ZeroIndicator<Domain : Space, F : Num>(
+    #[serde(skip)]
+    PhantomData<(Domain, F)>
+);
 
 impl<Domain : Space, F : Num> ZeroIndicator<Domain, F> {
     pub fn new() -> Self {
--- a/src/discrete_gradient.rs	Mon Dec 30 15:46:28 2024 -0500
+++ b/src/discrete_gradient.rs	Mon Jan 06 20:29:25 2025 -0500
@@ -2,6 +2,7 @@
 Simple disrete gradient operators
  */
 use numeric_literals::replace_float_literals;
+use serde::{Serialize, Deserialize};
 use nalgebra::{
     DVector, Matrix, U1, Storage, StorageMut, Dyn
 };
@@ -10,23 +11,32 @@
 use crate::linops::{Mapping, Linear, BoundedLinear, Adjointable, GEMV};
 use crate::norms::{Norm, L2};
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
 /// Forward differences with Neumann boundary conditions
 pub struct ForwardNeumann;
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
 /// Forward differences with Dirichlet boundary conditions
 pub struct ForwardDirichlet;
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
 /// Backward differences with Dirichlet boundary conditions
 pub struct BackwardDirichlet;
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
 /// Backward differences with Neumann boundary conditions
 pub struct BackwardNeumann;
 
 /// Finite differences gradient
+#[derive(Clone, Debug, Serialize, Deserialize)]
+#[serde(bound(
+    serialize = "[usize; N] : Serialize,
+                 B : Serialize,
+                 F : Serialize,",
+    deserialize = "[usize; N] : for<'a> Deserialize<'a>,
+                   B : for<'a> Deserialize<'a>,
+                   F : for<'a> Deserialize<'a>,"
+))]
 pub struct Grad<
     F : Float + nalgebra::RealField,
     B : Discretisation<F>,
--- a/src/fe_model/p2_local_model.rs	Mon Dec 30 15:46:28 2024 -0500
+++ b/src/fe_model/p2_local_model.rs	Mon Jan 06 20:29:25 2025 -0500
@@ -2,6 +2,7 @@
 Second order polynomical (P2) models on real intervals and planar 2D simplices.
 */
 
+use serde::{Serialize, Deserialize};
 use crate::types::*;
 use crate::loc::Loc;
 use crate::sets::{Set,NPolygon,SpannedHalfspace};
@@ -16,6 +17,11 @@
 ///
 /// The type parameter `D` indicates the number of nodes. (Rust's const generics do not currently
 /// allow its automatic calculation from `N`.)
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[serde(bound(
+    serialize = "[Loc<F, N>; D] : Serialize",
+    deserialize = "[Loc<F, N>; D] : for<'a> Deserialize<'a>",
+))]
 pub struct Simplex<F : Float, const N : usize, const D : usize>(pub [Loc<F, N>; D]);
 /// A two-dimensional planar simplex
 pub type PlanarSimplex<F> = Simplex<F, 2, 3>;
@@ -119,6 +125,15 @@
 }
 
 /// A local second order polynomical model of dimension `N` with `E` edges
+#[derive(Serialize, Deserialize, Debug, Clone)]
+#[serde(bound(
+    serialize = "F : Serialize,
+                 Loc<F, N> : Serialize,
+                 Loc<F, E> : Serialize",
+    deserialize = "F : for<'a> Deserialize<'a>,
+                   Loc<F, N> : for<'a> Deserialize<'a>,
+                   Loc<F, E> : for<'a> Deserialize<'a>",
+))]
 pub struct P2LocalModel<F : Num, const N : usize, const E : usize/*, const V : usize, const Q : usize*/> {
     a0 : F,
     a1 : Loc<F, N>,
--- a/src/loc.rs	Mon Dec 30 15:46:28 2024 -0500
+++ b/src/loc.rs	Mon Jan 06 20:29:25 2025 -0500
@@ -13,14 +13,18 @@
 use crate::linops::{AXPY, Mapping, Linear};
 use crate::instance::{Instance, BasicDecomposition};
 use crate::mapping::Space;
-use serde::ser::{Serialize, Serializer, SerializeSeq};
+use serde::{Serialize, Deserialize};
 
 
 /// A container type for (short) `N`-dimensional vectors of element type `F`.
 ///
 /// Supports basic operations of an [`Euclidean`] space, several [`Norm`]s, and
 /// fused [`AXPY`] operations, among others.
-#[derive(Copy,Clone,Debug,PartialEq,Eq)]
+#[derive(Copy,Clone,Debug,PartialEq,Eq,Serialize,Deserialize)]
+#[serde(bound(
+    serialize = "[F; N] : Serialize",
+    deserialize = "[F; N] : for<'a> Deserialize<'a>"
+))]
 pub struct Loc<F, const N : usize>(
     /// An array of the elements of the vector
     pub [F; N]
@@ -39,23 +43,6 @@
     }
 }
 
-// Need to manually implement as [F; N] serialisation is provided only for some N.
-impl<F, const N : usize> Serialize for Loc<F, N>
-where
-    F: Serialize,
-{
-    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    where
-        S: Serializer,
-    {
-        let mut seq = serializer.serialize_seq(Some(N))?;
-        for e in self.iter() {
-            seq.serialize_element(e)?;
-        }
-        seq.end()
-    }
-}
-
 impl<F, const N : usize> Loc<F, N> {
     /// Creates a new `Loc` vector from an array.
     #[inline]
--- a/src/norms.rs	Mon Dec 30 15:46:28 2024 -0500
+++ b/src/norms.rs	Mon Jan 06 20:29:25 2025 -0500
@@ -2,7 +2,7 @@
 Norms, projections, etc.
 */
 
-use serde::Serialize;
+use serde::{Serialize, Deserialize};
 use std::marker::PhantomData;
 use crate::types::*;
 use crate::euclidean::*;
@@ -12,10 +12,11 @@
 // Abstract norms
 //
 
-#[derive(Copy,Clone,Debug)]
+#[derive(Copy,Clone,Debug, Serialize, Deserialize)]
 /// Helper structure to convert a [`NormExponent`] into a [`Mapping`]
 pub struct NormMapping<F : Float, E : NormExponent>{
     pub(crate) exponent : E,
+    #[serde(skip)]
     _phantoms : PhantomData<F>
 }
 
@@ -30,29 +31,29 @@
 }
 
 /// Exponent type for the 1-[`Norm`].
-#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)]
+#[derive(Copy,Debug,Clone,Serialize,Deserialize,Eq,PartialEq)]
 pub struct L1;
 impl NormExponent for L1 {}
 
 /// Exponent type for the 2-[`Norm`].
-#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)]
+#[derive(Copy,Debug,Clone,Serialize,Deserialize,Eq,PartialEq)]
 pub struct L2;
 impl NormExponent for L2 {}
 
 /// Exponent type for the ∞-[`Norm`].
-#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)]
+#[derive(Copy,Debug,Clone,Serialize,Deserialize,Eq,PartialEq)]
 pub struct Linfinity;
 impl NormExponent for Linfinity {}
 
 /// Exponent type for 2,1-[`Norm`].
 /// (1-norm over a domain Ω, 2-norm of a vector at each point of the domain.)
-#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)]
+#[derive(Copy,Debug,Clone,Serialize,Deserialize,Eq,PartialEq)]
 pub struct L21;
 impl NormExponent for L21 {}
 
 /// Norms for pairs (a, b). ‖(a,b)‖ = ‖(‖a‖_A, ‖b‖_B)‖_J
 /// For use with [`crate::direct_product::Pair`]
-#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)]
+#[derive(Copy,Debug,Clone,Serialize,Deserialize,Eq,PartialEq)]
 pub struct PairNorm<A, B, J>(pub A, pub B, pub J);
 
 impl<A, B, J> NormExponent for PairNorm<A, B, J>
@@ -63,7 +64,7 @@
 ///
 /// The parameter γ of this type is the smoothing factor. Zero means no smoothing, and higher
 /// values more smoothing. Behaviour with γ < 0 is undefined.
-#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)]
+#[derive(Copy,Debug,Clone,Serialize,Deserialize,Eq,PartialEq)]
 pub struct HuberL1<F : Float>(pub F);
 impl<F : Float> NormExponent for HuberL1<F> {}
 
@@ -71,7 +72,7 @@
 ///
 /// The parameter γ of this type is the smoothing factor. Zero means no smoothing, and higher
 /// values more smoothing. Behaviour with γ < 0 is undefined.
-#[derive(Copy,Debug,Clone,Serialize,Eq,PartialEq)]
+#[derive(Copy,Debug,Clone,Serialize,Deserialize,Eq,PartialEq)]
 pub struct HuberL21<F : Float>(pub F);
 impl<F : Float> NormExponent for HuberL21<F> {}
 
--- a/src/operator_arithmetic.rs	Mon Dec 30 15:46:28 2024 -0500
+++ b/src/operator_arithmetic.rs	Mon Jan 06 20:29:25 2025 -0500
@@ -2,7 +2,7 @@
 Arithmetic of [`Mapping`]s.
  */
 
-use serde::Serialize;
+use serde::{Serialize, Deserialize};
 use crate::types::*;
 use crate::instance::{Space, Instance};
 use crate::mapping::{Mapping, DifferentiableImpl, DifferentiableMapping};
@@ -22,7 +22,7 @@
 }
 
 /// Weighting of a [`Mapping`] by scalar multiplication.
-#[derive(Copy,Clone,Debug,Serialize)]
+#[derive(Copy,Clone,Debug,Serialize,Deserialize)]
 pub struct Weighted<T, C : Constant> {
     /// The weight
     pub weight : C,
@@ -73,7 +73,7 @@
 }
 
 /// A sum of [`Mapping`]s.
-#[derive(Serialize, Debug, Clone)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
 pub struct MappingSum<M>(Vec<M>);
 
 impl< M> MappingSum<M> {
--- a/src/sets.rs	Mon Dec 30 15:46:28 2024 -0500
+++ b/src/sets.rs	Mon Jan 06 20:29:25 2025 -0500
@@ -7,7 +7,7 @@
 use crate::loc::Loc;
 use crate::euclidean::Euclidean;
 use crate::instance::{Space, Instance};
-use serde::Serialize;
+use serde::{Serialize, Deserialize};
 
 pub mod cube;
 pub use cube::Cube;
@@ -62,7 +62,7 @@
 ///
 /// The halfspace is $H = \\{ t v + a \mid a^⊤ v = 0 \\}$, where $v$ is the orthogonal
 /// vector and $t$ the offset.
-#[derive(Clone,Copy,Debug,Serialize,Eq,PartialEq)]
+#[derive(Clone,Copy,Debug,Serialize,Deserialize,Eq,PartialEq)]
 pub struct Halfspace<A, F> where A : Euclidean<F>, F : Float {
     pub orthogonal : A,
     pub offset : F,
@@ -116,7 +116,11 @@
 }
 
 /// Polygons defined by `N` `Halfspace`s.
-#[derive(Clone,Copy,Debug,Eq,PartialEq)]
+#[derive(Clone,Copy,Debug,Eq,PartialEq,Serialize,Deserialize)]
+#[serde(bound(
+    serialize = "[Halfspace<A,F>; N] : Serialize",
+    deserialize = "[Halfspace<A,F>; N] : for<'a> Deserialize<'a>"
+))]
 pub struct NPolygon<A, F, const N : usize>(pub [Halfspace<A,F>; N])
 where A : Euclidean<F>, F : Float;
 
--- a/src/sets/cube.rs	Mon Dec 30 15:46:28 2024 -0500
+++ b/src/sets/cube.rs	Mon Jan 06 20:29:25 2025 -0500
@@ -16,7 +16,7 @@
 ```
 */
 
-use serde::ser::{Serialize, Serializer, SerializeTupleStruct};
+use serde::{Serialize, Deserialize};
 use crate::types::*;
 use crate::loc::Loc;
 use crate::sets::SetOrd;
@@ -30,25 +30,14 @@
 
 /// A multi-dimensional cube $∏_{i=1}^N [a_i, b_i)$ with the starting and ending points
 /// along $a_i$ and $b_i$ along each dimension of type `U`.
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-pub struct Cube<U : Num, const N : usize>(pub(super) [[U; 2]; N]);
-
-// Need to manually implement as [F; N] serialisation is provided only for some N.
-impl<F : Num + Serialize, const N : usize> Serialize for Cube<F, N>
-where
-    F: Serialize,
-{
-    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
-    where
-        S: Serializer,
-    {
-        let mut ts = serializer.serialize_tuple_struct("Cube", N)?;
-        for e in self.0.iter() {
-            ts.serialize_field(e)?;
-        }
-        ts.end()
-    }
-}
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
+#[serde(bound(
+    serialize = "[[U; 2]; N] : Serialize",
+    deserialize = "[[U; 2]; N] : for<'a> Deserialize<'a>",
+))]
+pub struct Cube<U : Num, const N : usize>(
+    pub(super) [[U; 2]; N]
+);
 
 impl<A : Num, const N : usize> FixedLength<N> for Cube<A,N> {
     type Iter = std::array::IntoIter<[A; 2], N>;
--- a/src/types.rs	Mon Dec 30 15:46:28 2024 -0500
+++ b/src/types.rs	Mon Jan 06 20:29:25 2025 -0500
@@ -60,7 +60,8 @@
 /// Trait for general numeric types
 pub trait Num : 'static + Copy + Sync + Send + num::Num + num_traits::NumAssign
                  + std::iter::Sum + std::iter::Product
-                 + std::fmt::Debug + std::fmt::Display + serde::Serialize
+                 + std::fmt::Debug + std::fmt::Display
+                 + serde::Serialize
                  + CastFrom<u8>   + CastFrom<u16> + CastFrom<u32> + CastFrom<u64>
                  + CastFrom<u128> + CastFrom<usize>
                  + CastFrom<i8>   + CastFrom<i16> + CastFrom<i32> + CastFrom<i64>

mercurial