Repository: OpenMined/PySyft

Issue:
Serialize / Deserialize FixedPrecisionTensors
**Is your feature request related to a problem? Please describe.**

I want to be able to serialize/deserialize FixedPrecisionTensors.

Tests should be implemented.


Discussion:

Resolving patch:
diff --git a/syft/frameworks/torch/tensors/interpreters/precision.py b/syft/frameworks/torch/tensors/interpreters/precision.py
--- a/syft/frameworks/torch/tensors/interpreters/precision.py
+++ b/syft/frameworks/torch/tensors/interpreters/precision.py
@@ -1,5 +1,7 @@
-import syft
 import torch
+
+import syft
+from syft.workers import AbstractWorker
 from syft.frameworks.torch.tensors.interpreters.abstract import AbstractTensor
 from syft.frameworks.torch.overload_torch import overloaded
 
@@ -515,3 +517,60 @@ def get(self):
     def share(self, *owners, field=None, crypto_provider=None):
         self.child = self.child.share(*owners, field=field, crypto_provider=crypto_provider)
         return self
+
+    @staticmethod
+    def simplify(tensor: "FixedPrecisionTensor") -> tuple:
+        """Takes the attributes of a FixedPrecisionTensor and saves them in a tuple.
+
+        Args:
+            tensor: a FixedPrecisionTensor.
+
+        Returns:
+            tuple: a tuple holding the unique attributes of the fixed precision tensor.
+        """
+        chain = None
+        if hasattr(tensor, "child"):
+            chain = syft.serde._simplify(tensor.child)
+
+        return (
+            syft.serde._simplify(tensor.id),
+            tensor.field,
+            tensor.base,
+            tensor.precision_fractional,
+            tensor.kappa,
+            syft.serde._simplify(tensor.tags),
+            syft.serde._simplify(tensor.description),
+            chain,
+        )
+
+    @staticmethod
+    def detail(worker: AbstractWorker, tensor_tuple: tuple) -> "FixedPrecisionTensor":
+        """
+            This function reconstructs a FixedPrecisionTensor given it's attributes in form of a tuple.
+            Args:
+                worker: the worker doing the deserialization
+                tensor_tuple: a tuple holding the attributes of the FixedPrecisionTensor
+            Returns:
+                FixedPrecisionTensor: a FixedPrecisionTensor
+            Examples:
+                shared_tensor = detail(data)
+            """
+
+        tensor_id, field, base, precision_fractional, kappa, tags, description, chain = tensor_tuple
+
+        tensor = FixedPrecisionTensor(
+            owner=worker,
+            id=syft.serde._detail(worker, tensor_id),
+            field=field,
+            base=base,
+            precision_fractional=precision_fractional,
+            kappa=kappa,
+            tags=syft.serde._detail(worker, tags),
+            description=syft.serde._detail(worker, description),
+        )
+
+        if chain is not None:
+            chain = syft.serde._detail(worker, chain)
+            tensor.child = chain
+
+        return tensor
diff --git a/syft/serde/serde.py b/syft/serde/serde.py
--- a/syft/serde/serde.py
+++ b/syft/serde/serde.py
@@ -56,6 +56,7 @@
 
 
 from syft.frameworks.torch.tensors.decorators import LoggingTensor
+from syft.frameworks.torch.tensors.interpreters import FixedPrecisionTensor
 from syft.frameworks.torch.tensors.interpreters import AdditiveSharingTensor
 from syft.frameworks.torch.tensors.interpreters import MultiPointerTensor
 from syft.frameworks.torch import pointers
@@ -72,6 +73,7 @@
 # If a object implements its own simplify and detail functions it should be stored in this list
 OBJ_SIMPLIFIER_AND_DETAILERS = [
     AdditiveSharingTensor,
+    FixedPrecisionTensor,
     LoggingTensor,
     MultiPointerTensor,
     Plan,


Test patch:
diff --git a/test/test_serde.py b/test/test_serde.py
--- a/test/test_serde.py
+++ b/test/test_serde.py
@@ -606,6 +606,26 @@ def test_additive_sharing_tensor_serde(compress, workers):
     )
 
 
+@pytest.mark.parametrize("compress", [True, False])
+def test_fixed_precision_tensor_serde(compress, workers):
+    alice, bob, james = workers["alice"], workers["bob"], workers["james"]
+
+    x = (
+        torch.tensor([[3.1, 4.3]])
+        .fix_prec(base=12, precision_fractional=5)
+        .share(alice, bob, crypto_provider=james)
+    )
+
+    serialized_x = serde.serialize(x)
+    deserialied_x = serde.deserialize(serialized_x)
+
+    assert x.id == deserialied_x.child.id
+    assert x.child.field == deserialied_x.child.field
+    assert x.child.kappa == deserialied_x.child.kappa
+    assert x.child.precision_fractional == deserialied_x.child.precision_fractional
+    assert x.child.base == deserialied_x.child.base
+
+
 def test_serde_object_wrapper_int():
     obj = 4
     obj_wrapper = pointers.ObjectWrapper(obj, id=100)