Repository: OpenMined/PySyft

Issue:
Add support of torch.dot for additive shared tensor
torch.dot(x, y) currently fails, we should add a support for it, doing smthg like `(x * y).sum()`

Example of code to make run:
```python
import sys
import syft as sy
from syft.workers import WebsocketClientWorker
import torch

hook = sy.TorchHook(torch)

bob = sy.VirtualWorker(hook, id="bob")
alice = sy.VirtualWorker(hook, id="alice")
charlie = sy.VirtualWorker(hook, id="charlie")

print("Created clients")

data1 = torch.tensor([1,2,3,4,5])
d1r = data1.share(alice, bob, charlie)

print("Shared first tensor")

data2 = torch.tensor([3,3,3,3,3])
d2r = data2.share(alice, bob, charlie)

print("Shared second tensor")

res = (d1r * d2r).sum()
print(res.get())

plaintext_res = torch.dot(data1, data2)
print(plaintext_res)
```


Discussion:

Resolving patch:
diff --git a/syft/frameworks/torch/tensors/interpreters/additive_shared.py b/syft/frameworks/torch/tensors/interpreters/additive_shared.py
--- a/syft/frameworks/torch/tensors/interpreters/additive_shared.py
+++ b/syft/frameworks/torch/tensors/interpreters/additive_shared.py
@@ -563,6 +563,12 @@ def sum(self, *args, **kwargs):
 
         module.sum = sum
 
+        def dot(self, other):
+            """Overload torch.dot(x, y)"""
+            return self.mul(other).sum()
+
+        module.dot = dot
+
         def mean(self, *args, **kwargs):
             """Overload torch.mean(x)"""
             # We cannot directly use mean on Long tensors
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
@@ -393,6 +393,11 @@ def addmm(bias, input_tensor, weight):
 
         module.addmm = addmm
 
+        def dot(self, other):
+            return self.__mul__(other).sum()
+
+        module.dot = dot
+
         def conv2d(
             input,
             weight,


Test patch:
diff --git a/test/torch/tensors/test_additive_shared.py b/test/torch/tensors/test_additive_shared.py
--- a/test/torch/tensors/test_additive_shared.py
+++ b/test/torch/tensors/test_additive_shared.py
@@ -622,6 +622,16 @@ def test_torch_mean(workers):
     assert (s_keepdim == torch.tensor([[1.75], [6.75]])).all()
 
 
+def test_torch_dot(workers):
+    torch.manual_seed(121)  # Truncation might not always work so we set the random seed
+    alice, bob, james = workers["alice"], workers["bob"], workers["james"]
+
+    x = torch.tensor([1.0, 2.0, 3.0, 4.0, 5.0]).fix_prec().share(alice, bob, crypto_provider=james)
+    y = torch.tensor([3.0, 3.0, 3.0, 3.0, 3.0]).fix_prec().share(alice, bob, crypto_provider=james)
+
+    assert torch.dot(x, y).get().float_prec() == 45
+
+
 def test_unbind(workers):
     alice, bob, james = workers["alice"], workers["bob"], workers["james"]
 
diff --git a/test/torch/tensors/test_precision.py b/test/torch/tensors/test_precision.py
--- a/test/torch/tensors/test_precision.py
+++ b/test/torch/tensors/test_precision.py
@@ -272,6 +272,15 @@ def test_torch_addmm():
     assert (fp_result.float_precision() == torch.tensor([[10.0, 8.0]])).all()
 
 
+def test_torch_dot(workers):
+    alice, bob, james = workers["alice"], workers["bob"], workers["james"]
+
+    x = torch.tensor([1.0, 2.0, 3.0, 4.0, 5.0]).fix_prec()
+    y = torch.tensor([3.0, 3.0, 3.0, 3.0, 3.0]).fix_prec()
+
+    assert torch.dot(x, y).float_prec() == 45
+
+
 def test_torch_conv2d(workers):
     bob, alice, james = (workers["bob"], workers["alice"], workers["james"])
     im = torch.Tensor(
diff --git a/test/workers/test_websocket_worker.py b/test/workers/test_websocket_worker.py
--- a/test/workers/test_websocket_worker.py
+++ b/test/workers/test_websocket_worker.py
@@ -114,7 +114,7 @@ def test_list_objects_remote(hook, start_proc):
     kwargs = {"id": "fed", "host": "localhost", "port": 8765, "hook": hook}
     process_remote_fed1 = start_proc(WebsocketServerWorker, **kwargs)
 
-    time.sleep(0.1)
+    time.sleep(0.5)
 
     kwargs = {"id": "fed", "host": "localhost", "port": 8765, "hook": hook}
     local_worker = WebsocketClientWorker(**kwargs)
@@ -145,7 +145,7 @@ def test_objects_count_remote(hook, start_proc):
     kwargs = {"id": "fed", "host": "localhost", "port": 8764, "hook": hook}
     process_remote_worker = start_proc(WebsocketServerWorker, **kwargs)
 
-    time.sleep(0.1)
+    time.sleep(0.5)
 
     kwargs = {"id": "fed", "host": "localhost", "port": 8764, "hook": hook}
     local_worker = WebsocketClientWorker(**kwargs)
@@ -176,7 +176,7 @@ def test_connect_close(hook, start_proc):
     kwargs = {"id": "fed", "host": "localhost", "port": 8763, "hook": hook}
     process_remote_worker = start_proc(WebsocketServerWorker, **kwargs)
 
-    time.sleep(0.1)
+    time.sleep(0.5)
 
     kwargs = {"id": "fed", "host": "localhost", "port": 8763, "hook": hook}
     local_worker = WebsocketClientWorker(**kwargs)
@@ -211,7 +211,7 @@ def test_websocket_worker_multiple_output_response(hook, start_proc):
     kwargs = {"id": "socket_multiple_output", "host": "localhost", "port": 8768, "hook": hook}
     process_remote_worker = start_proc(WebsocketServerWorker, **kwargs)
 
-    time.sleep(0.1)
+    time.sleep(0.5)
     x = torch.tensor([1.0, 3, 2])
 
     local_worker = WebsocketClientWorker(**kwargs)