Repository: OpenMined/PySyft

Issue:
Implement the Unfold function for IntTensor on the CPU
As a Data Scientist using PySyft's IntTensor type, I want to leverage a wide range of methods which use our new Unity backend. For this ticket to be complete, the unfold() should be added to our IntTensor class with the appropriate functionality, returning a new tensor.

If you want to take it to the next level, boost it implementing the operation on the GPU: Search for an issue titled like this but with "on the GPU" on the title!
                       HLSL (GPU language) tutorial here: [Direct Compute Programming Guide](https://github.com/OpenMined/OpenMined/blob/master/tutorials/DirectCompute_Programming_Guide.md)

Note, it is possible that when you look in the code you'll find that parts of this issue were completed on the backend while implementing another issue. This is normal as features do not live in isolation. If this is the case, just take it as a convenience that someone already built that part and press on!

### Every Reference You Might Need for this Issue:

- For a reference on the operation this performs check out [PyTorch](http://pytorch.org/docs/master/tensors.html)'s documentation.
- For a reference on how to program in Unity, check out [this basic tutorial](https://unity3d.com/learn/tutorials/projects/roll-ball-tutorial)
- For a reference on how to write HLSL code, check out [this basic tutorial](http://kylehalladay.com/blog/tutorial/2014/06/27/Compute-Shaders-Are-Nifty.html)
- For a complete tutorial on how to add functions to FloatTensor (step by step guide) see [this Google Document](https://docs.google.com/document/d/1WRd7gGLFN0Awtf86AICYIHtg3gfFWLBa5wYTthsB3i0/edit)
- For a reference on how other functions like this have been implemented check out the functions in [this notebook](https://github.com/OpenMined/OpenMined/blob/master/notebooks/Syft%20Tensor%20Example%20Notebook.ipynb) as well as the corresponding files that made it possible ([SyftController](https://github.com/OpenMined/OpenMined/blob/master/UnityProject/Assets/OpenMined/Network/Controllers/SyftController.cs), [FloatTensor.Ops](https://github.com/OpenMined/OpenMined/blob/master/UnityProject/Assets/OpenMined/Syft/Tensor/FloatTensor.Ops.cs), [FloatTensorShaders](https://github.com/OpenMined/OpenMined/blob/master/UnityProject/Assets/OpenMined/Syft/Tensor/Ops/Shaders/FloatTensorShaders.compute), [TensorOpsShaders](https://github.com/OpenMined/OpenMined/blob/master/UnityProject/Assets/OpenMined/Syft/Tensor/Ops/Shaders/TensorOpsShaders.compute), [FloatTensorTest](https://github.com/OpenMined/OpenMined/blob/master/UnityProject/Assets/OpenMined.Tests/Editor/FloatTensor/FloatTensorTest.cs) and [FloatTensorGpuTest](https://github.com/OpenMined/OpenMined/blob/master/UnityProject/Assets/OpenMined.Tests/Editor/FloatTensor/FloatTensorGpuTest.cs)).
- And of course, please consider our [Contributor Guidelines](https://github.com/OpenMined/Docs/blob/master/contributing/guidelines.md) for all contributions.

### Acceptance Criteria:

- [ ] comment below that you're picking up this project
- [ ] an example in a notebook in our [tests folder](https://github.com/OpenMined/OpenMined/tree/master/notebooks/tests) showing how to use the functionality from PySyft
- [ ] an integration test in PySyft demonstrating the correct CPU operation implemented over an IntTensor while connected to a Unity backend
- [ ] a Unit Test in OpenMined/OpenMined demonstrating the correct operation on a FloatTensor
- [ ] [inline](http://pytorch.org/docs/master/tensors.html) documentation in the python code. For inspiration on inline documentation, please check out PyTorch's documentation for this operator.
- [ ] Link your Pull Request back to this Issue so that it gets closed appropriately when the PR is merged.
Implement the Unfold function for IntTensor on the CPU
As a Data Scientist using PySyft's IntTensor type, I want to leverage a wide range of methods which use our new Unity backend. For this ticket to be complete, the unfold() should be added to our IntTensor class with the appropriate functionality, returning a new tensor.

If you want to take it to the next level, boost it implementing the operation on the GPU: Search for an issue titled like this but with "on the GPU" on the title!
                       HLSL (GPU language) tutorial here: [Direct Compute Programming Guide](https://github.com/OpenMined/OpenMined/blob/master/tutorials/DirectCompute_Programming_Guide.md)

Note, it is possible that when you look in the code you'll find that parts of this issue were completed on the backend while implementing another issue. This is normal as features do not live in isolation. If this is the case, just take it as a convenience that someone already built that part and press on!

### Every Reference You Might Need for this Issue:

- For a reference on the operation this performs check out [PyTorch](http://pytorch.org/docs/master/tensors.html)'s documentation.
- For a reference on how to program in Unity, check out [this basic tutorial](https://unity3d.com/learn/tutorials/projects/roll-ball-tutorial)
- For a reference on how to write HLSL code, check out [this basic tutorial](http://kylehalladay.com/blog/tutorial/2014/06/27/Compute-Shaders-Are-Nifty.html)
- For a complete tutorial on how to add functions to FloatTensor (step by step guide) see [this Google Document](https://docs.google.com/document/d/1WRd7gGLFN0Awtf86AICYIHtg3gfFWLBa5wYTthsB3i0/edit)
- For a reference on how other functions like this have been implemented check out the functions in [this notebook](https://github.com/OpenMined/OpenMined/blob/master/notebooks/Syft%20Tensor%20Example%20Notebook.ipynb) as well as the corresponding files that made it possible ([SyftController](https://github.com/OpenMined/OpenMined/blob/master/UnityProject/Assets/OpenMined/Network/Controllers/SyftController.cs), [FloatTensor.Ops](https://github.com/OpenMined/OpenMined/blob/master/UnityProject/Assets/OpenMined/Syft/Tensor/FloatTensor.Ops.cs), [FloatTensorShaders](https://github.com/OpenMined/OpenMined/blob/master/UnityProject/Assets/OpenMined/Syft/Tensor/Ops/Shaders/FloatTensorShaders.compute), [TensorOpsShaders](https://github.com/OpenMined/OpenMined/blob/master/UnityProject/Assets/OpenMined/Syft/Tensor/Ops/Shaders/TensorOpsShaders.compute), [FloatTensorTest](https://github.com/OpenMined/OpenMined/blob/master/UnityProject/Assets/OpenMined.Tests/Editor/FloatTensor/FloatTensorTest.cs) and [FloatTensorGpuTest](https://github.com/OpenMined/OpenMined/blob/master/UnityProject/Assets/OpenMined.Tests/Editor/FloatTensor/FloatTensorGpuTest.cs)).
- And of course, please consider our [Contributor Guidelines](https://github.com/OpenMined/Docs/blob/master/contributing/guidelines.md) for all contributions.

### Acceptance Criteria:

- [ ] comment below that you're picking up this project
- [ ] an example in a notebook in our [tests folder](https://github.com/OpenMined/OpenMined/tree/master/notebooks/tests) showing how to use the functionality from PySyft
- [ ] an integration test in PySyft demonstrating the correct CPU operation implemented over an IntTensor while connected to a Unity backend
- [ ] a Unit Test in OpenMined/OpenMined demonstrating the correct operation on a FloatTensor
- [ ] [inline](http://pytorch.org/docs/master/tensors.html) documentation in the python code. For inspiration on inline documentation, please check out PyTorch's documentation for this operator.
- [ ] Link your Pull Request back to this Issue so that it gets closed appropriately when the PR is merged.


Discussion:
I am taking up this one.
I am taking up this one.

Resolving patch:
diff --git a/syft/tensor/int_tensor.py b/syft/tensor/int_tensor.py
--- a/syft/tensor/int_tensor.py
+++ b/syft/tensor/int_tensor.py
@@ -404,3 +404,19 @@ def view_(self, *args):
         assert type(new_dim[0]) == int
         self.params_func("view_", new_dim, return_response=False)
         return self
+
+    def unfold(self, dim, size, step):
+        """
+        Returns a tensor which contains all slices of size `size` from `self` tensor in the dimension `dim`.
+        
+        Parameters:
+            dim (int) – dimension in which unfolding happens
+            size (int) – the size of each slice that is unfolded
+            step (int) – the step between each slice
+        ----------
+        Returns
+        -------
+        IntTensor
+            Output Tensor
+        """
+        return self.params_func("unfold", [dim, size, step], return_response=True)


Test patch:
diff --git a/tests/test_inttensor.py b/tests/test_inttensor.py
--- a/tests/test_inttensor.py
+++ b/tests/test_inttensor.py
@@ -41,3 +41,22 @@ def test_view():
     a.view_(4, -1, 2)
     c_v_ground = IntTensor(np.array([[[9, 3], [1, 0]], [[6, 8], [6, 6]], [[1, 6], [8, 6]], [[5, 0], [2, 0]]]))
     assert(a.equal(c_v_ground))
+
+def test_unfold():
+    a = IntTensor(np.array([[-1, 2, 3, 5], [0, 4, 6, 7], [10, 3, 2, -5]], dtype=np.int32))
+
+    # Test1
+    expected_a = IntTensor(np.array([[[-1, 2, 3, 5], [0, 4, 6, 7]], [[0, 4, 6, 7], [10, 3, 2, -5]]], dtype=np.int32))
+    actual_a = a.unfold(0, 2, 1)
+    assert(actual_a.equal(expected_a))
+
+    # Test2
+    expected_a = IntTensor(np.array([[[-1, 2, 3], [0, 4, 6], [10, 3, 2]],
+        [[2, 3, 5], [4, 6, 7], [3, 2, -5]]], dtype=np.int32))
+    actual_a = a.unfold(1, 3, 1)
+    assert(actual_a.equal(expected_a))
+
+    # Test3
+    expected_a = IntTensor(np.array([[[-1, 2], [0, 4], [10, 3]], [[3, 5], [6, 7], [2, -5]]], dtype=np.int32))
+    actual_a = a.unfold(1, 2, 2)
+    assert(actual_a.equal(expected_a))