Repository: mars-project/mars

Issue:
[BUG] `cdist(x, y)` creates tensor with wrong nsplits
<!--
Thank you for your contribution!

Please review https://github.com/mars-project/mars/blob/master/CONTRIBUTING.rst before opening an issue.
-->

**Describe the bug**

`cdist(x, y)` creates tensor with wrong nsplits.

**To Reproduce**

```
In [1]: import mars.tensor as mt                                                

In [2]: a = mt.random.rand(10, 8, chunk_size=(4, 8))                            

In [3]: b = mt.random.rand(8, 8, chunk_size=(5, 8))                             

In [4]: from mars.tensor.spatial.distance import cdist                          

In [5]: c = cdist(a, b)                                                         
In [6]: c.tiles().nsplits                                                       
Out[6]: ((4, 4, 2), (8,)) . # should be ((4, 4, 2), (5, 3))
```




Discussion:

Resolving patch:
diff --git a/mars/tensor/spatial/distance/cdist.py b/mars/tensor/spatial/distance/cdist.py
--- a/mars/tensor/spatial/distance/cdist.py
+++ b/mars/tensor/spatial/distance/cdist.py
@@ -146,7 +146,7 @@ def _tile_chunks(cls, op, xa, xb, w, v, vi):
         return new_op.new_tensors(op.inputs, shape=out_tensor.shape,
                                   order=out_tensor.order,
                                   chunks=out_chunks,
-                                  nsplits=(xa.nsplits[0], xb.nsplits[1]))
+                                  nsplits=(xa.nsplits[0], xb.nsplits[0]))
 
     @classmethod
     def tile(cls, op):


Test patch:
diff --git a/mars/lib/sparse/tests/test_sparse.py b/mars/lib/sparse/tests/test_sparse.py
--- a/mars/lib/sparse/tests/test_sparse.py
+++ b/mars/lib/sparse/tests/test_sparse.py
@@ -50,14 +50,7 @@ def testSparseCreation(self):
         self.assertArrayEqual(v.toarray(), self.v1_data)
         self.assertArrayEqual(v, self.v1_data)
 
-    def _nan_equal(self, a, b):
-        try:
-            np.testing.assert_equal(a, b)
-        except AssertionError:
-            return False
-        return True
-
-    def assertArrayEqual(self, a, b):
+    def assertArrayEqual(self, a, b, almost=False):
         if issparse(a):
             a = a.toarray()
         else:
@@ -66,7 +59,10 @@ def assertArrayEqual(self, a, b):
             b = b.toarray()
         else:
             b = np.asarray(b)
-        return self.assertTrue(self._nan_equal(a, b))
+        if not almost:
+            np.testing.assert_array_equal(a, b)
+        else:
+            np.testing.assert_almost_equal(a, b)
 
     def testSparseAdd(self):
         s1 = SparseNDArray(self.s1)
@@ -268,8 +264,8 @@ def testSparseDot(self):
         self.assertArrayEqual(mls.dot(s2, v1), self.s2.dot(self.v1_data))
         self.assertArrayEqual(mls.dot(v2, s1), self.v2_data.dot(self.s1.A))
         self.assertArrayEqual(mls.dot(v2, s2), self.v2_data.dot(self.s2.A))
-        self.assertArrayEqual(mls.dot(v1, v1), self.v1_data.dot(self.v1_data))
-        self.assertArrayEqual(mls.dot(v2, v2), self.v2_data.dot(self.v2_data))
+        self.assertArrayEqual(mls.dot(v1, v1), self.v1_data.dot(self.v1_data), almost=True)
+        self.assertArrayEqual(mls.dot(v2, v2), self.v2_data.dot(self.v2_data), almost=True)
 
         self.assertArrayEqual(mls.dot(v2, s1, sparse=False), self.v2_data.dot(self.s1.A))
         self.assertArrayEqual(mls.dot(v1, v1, sparse=False), self.v1_data.dot(self.v1_data))
diff --git a/mars/tensor/spatial/distance/tests/test_distance.py b/mars/tensor/spatial/distance/tests/test_distance.py
--- a/mars/tensor/spatial/distance/tests/test_distance.py
+++ b/mars/tensor/spatial/distance/tests/test_distance.py
@@ -97,6 +97,8 @@ def testCdist(self):
 
         dist = dist.tiles()
         self.assertEqual(len(dist.chunks), (100 // 15 + 1) * (90 // 16 + 1))
+        self.assertEqual(dist.nsplits, (get_tiled(a).nsplits[0],
+                                        get_tiled(b).nsplits[0]))
         for c in dist.chunks:
             ta = get_tiled(a)
             tb = get_tiled(b)