We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Remove conjugate in Cholesky decomposition which effects performance heavily
<!--
Thank you for your contribution!

Please review https://github.com/mars-project/mars/blob/master/CONTRIBUTING.rst before opening an issue.
-->

In the tile of Cholesky decomposition, we do a conjugate after transpose which is unnecessary and effect performance heavily.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mars/tensor/linalg/cholesky.py`
Content:
```
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 # Copyright 1999-2018 Alibaba Group Holding Ltd.
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 #      http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 
17 import numpy as np
18 from numpy.linalg import LinAlgError
19 
20 from ...serialize import KeyField, BoolField
21 from ... import opcodes as OperandDef
22 from ..operands import TensorHasInput, TensorOperandMixin
23 from ..datasource import tensor as astensor
24 from ..core import TensorOrder
25 from ..array_utils import as_same_device, device
26 
27 
28 def _H(chunk):
29     from ..base.transpose import TensorTranspose
30     from ..arithmetic.conj import TensorConj
31 
32     trans_op = TensorTranspose(dtype=chunk.dtype)
33     c = trans_op.new_chunk([chunk], shape=chunk.shape[::-1], index=chunk.index[::-1])
34     conj_op = TensorConj(dtype=c.dtype)
35     return conj_op.new_chunk([c], shape=c.shape, index=c.index)
36 
37 
38 class TensorCholesky(TensorHasInput, TensorOperandMixin):
39     _op_type_ = OperandDef.CHOLESKY
40 
41     _input = KeyField('input')
42     _lower = BoolField('lower')
43 
44     def __init__(self, lower=None, dtype=None, **kw):
45         super(TensorCholesky, self).__init__(_lower=lower, _dtype=dtype, **kw)
46 
47     @property
48     def lower(self):
49         return self._lower
50 
51     def _set_inputs(self, inputs):
52         super(TensorCholesky, self)._set_inputs(inputs)
53         self._input = self._inputs[0]
54 
55     def __call__(self, a):
56         return self.new_tensor([a], a.shape, order=TensorOrder.C_ORDER)
57 
58     @classmethod
59     def tile(cls, op):
60         from ..datasource.zeros import TensorZeros
61         from ..arithmetic.subtract import TensorSubtract
62         from ..arithmetic.utils import tree_add
63         from .dot import TensorDot
64         from .solve_triangular import TensorSolveTriangular
65 
66         tensor = op.outputs[0]
67         in_tensor = op.input
68         if in_tensor.nsplits[0] != in_tensor.nsplits[1]:
69             # all chunks on diagonal should be square
70             nsplits = in_tensor.nsplits[0]
71             in_tensor = in_tensor.rechunk([nsplits, nsplits]).single_tiles()
72 
73         lower_chunks, upper_chunks = {}, {}
74         for i in range(in_tensor.chunk_shape[0]):
75             for j in range(in_tensor.chunk_shape[1]):
76                 if i < j:
77                     lower_chunk = TensorZeros(dtype=tensor.dtype).new_chunk(
78                         None, shape=(in_tensor.nsplits[0][i], in_tensor.nsplits[1][j]),
79                         index=(i, j), order=tensor.order)
80                     upper_chunk = TensorZeros(dtype=tensor.dtype).new_chunk(
81                         None, shape=(in_tensor.nsplits[1][j], in_tensor.nsplits[0][i]),
82                         index=(j, i), order=tensor.order)
83                     lower_chunks[lower_chunk.index] = lower_chunk
84                     upper_chunks[upper_chunk.index] = upper_chunk
85                 elif i == j:
86                     target = in_tensor.cix[i, j]
87                     if i > 0:
88                         prev_chunks = []
89                         for p in range(i):
90                             a, b = lower_chunks[i, p], upper_chunks[p, j]
91                             prev_chunk = TensorDot(dtype=tensor.dtype).new_chunk(
92                                 [a, b], shape=(a.shape[0], b.shape[1]), order=tensor.order)
93                             prev_chunks.append(prev_chunk)
94                         if len(prev_chunks) == 1:
95                             s = prev_chunks[0]
96                         else:
97                             s = tree_add(prev_chunks[0].dtype, prev_chunks,
98                                          None, prev_chunks[0].shape)
99                         target = TensorSubtract(dtype=tensor.dtype, lhs=target, rhs=s).new_chunk(
100                             [target, s], shape=target.shape, order=tensor.order)
101                     lower_chunk = TensorCholesky(lower=True, dtype=tensor.dtype).new_chunk(
102                         [target], shape=target.shape, index=(i, j), order=tensor.order)
103                     upper_chunk = _H(lower_chunk)
104                     lower_chunks[lower_chunk.index] = lower_chunk
105                     upper_chunks[upper_chunk.index] = upper_chunk
106                 else:
107                     target = in_tensor.cix[j, i]
108                     if j > 0:
109                         prev_chunks = []
110                         for p in range(j):
111                             a, b = lower_chunks[j, p], upper_chunks[p, i]
112                             prev_chunk = TensorDot(dtype=tensor.dtype).new_chunk(
113                                 [a, b], shape=(a.shape[0], b.shape[1]), order=tensor.order)
114                             prev_chunks.append(prev_chunk)
115                         if len(prev_chunks) == 1:
116                             s = prev_chunks[0]
117                         else:
118                             s = tree_add(prev_chunks[0].dtype, prev_chunks,
119                                          None, prev_chunks[0].shape)
120                         target = TensorSubtract(dtype=tensor.dtype, lhs=target, rhs=s).new_chunk(
121                             [target, s], shape=target.shape, order=tensor.order)
122                     upper_chunk = TensorSolveTriangular(lower=True, dtype=tensor.dtype).new_chunk(
123                         [lower_chunks[j, j], target], shape=target.shape,
124                         index=(j, i), order=tensor.order)
125                     lower_chunk = _H(upper_chunk)
126                     lower_chunks[lower_chunk.index] = lower_chunk
127                     upper_chunks[upper_chunk.index] = upper_chunk
128 
129         new_op = op.copy()
130         if op.lower:
131             return new_op.new_tensors(op.inputs, tensor.shape, order=tensor.order,
132                                       chunks=list(lower_chunks.values()), nsplits=in_tensor.nsplits)
133         else:
134             return new_op.new_tensors(op.inputs, tensor.shape, order=tensor.order,
135                                       chunks=list(upper_chunks.values()), nsplits=in_tensor.nsplits)
136 
137     @classmethod
138     def execute(cls, ctx, op):
139         chunk = op.outputs[0]
140         (a,), device_id, xp = as_same_device(
141             [ctx[c.key] for c in op.inputs], device=op.device, ret_extra=True)
142 
143         with device(device_id):
144             if xp is np:
145                 try:
146                     import scipy.linalg
147 
148                     ctx[chunk.key] = scipy.linalg.cholesky(a, lower=op.lower)
149                     return
150                 except ImportError:  # pragma: no cover
151                     pass
152 
153             r = xp.linalg.cholesky(a)
154             if not chunk.op.lower:
155                 r = r.T.conj()
156 
157             ctx[chunk.key] = r
158 
159 
160 def cholesky(a, lower=False):
161     """
162     Cholesky decomposition.
163 
164     Return the Cholesky decomposition, `L * L.H`, of the square matrix `a`,
165     where `L` is lower-triangular and .H is the conjugate transpose operator
166     (which is the ordinary transpose if `a` is real-valued).  `a` must be
167     Hermitian (symmetric if real-valued) and positive-definite.  Only `L` is
168     actually returned.
169 
170     Parameters
171     ----------
172     a : (..., M, M) array_like
173         Hermitian (symmetric if all elements are real), positive-definite
174         input matrix.
175     lower : bool
176         Whether to compute the upper or lower triangular Cholesky
177         factorization.  Default is upper-triangular.
178 
179     Returns
180     -------
181     L : (..., M, M) array_like
182         Upper or lower-triangular Cholesky factor of `a`.
183 
184     Raises
185     ------
186     LinAlgError
187        If the decomposition fails, for example, if `a` is not
188        positive-definite.
189 
190     Notes
191     -----
192 
193     Broadcasting rules apply, see the `mt.linalg` documentation for
194     details.
195 
196     The Cholesky decomposition is often used as a fast way of solving
197 
198     .. math:: A \\mathbf{x} = \\mathbf{b}
199 
200     (when `A` is both Hermitian/symmetric and positive-definite).
201 
202     First, we solve for :math:`\\mathbf{y}` in
203 
204     .. math:: L \\mathbf{y} = \\mathbf{b},
205 
206     and then for :math:`\\mathbf{x}` in
207 
208     .. math:: L.H \\mathbf{x} = \\mathbf{y}.
209 
210     Examples
211     --------
212     >>> import mars.tensor as mt
213 
214     >>> A = mt.array([[1,-2j],[2j,5]])
215     >>> A.execute()
216     array([[ 1.+0.j,  0.-2.j],
217            [ 0.+2.j,  5.+0.j]])
218     >>> L = mt.linalg.cholesky(A, lower=True)
219     >>> L.execute()
220     array([[ 1.+0.j,  0.+0.j],
221            [ 0.+2.j,  1.+0.j]])
222     >>> mt.dot(L, L.T.conj()).execute() # verify that L * L.H = A
223     array([[ 1.+0.j,  0.-2.j],
224            [ 0.+2.j,  5.+0.j]])
225     >>> A = [[1,-2j],[2j,5]] # what happens if A is only array_like?
226     >>> mt.linalg.cholesky(A, lower=True).execute()
227     array([[ 1.+0.j,  0.+0.j],
228            [ 0.+2.j,  1.+0.j]])
229 
230     """
231     a = astensor(a)
232 
233     if a.ndim != 2:
234         raise LinAlgError('{0}-dimensional array given. '
235                           'Tensor must be two-dimensional'.format(a.ndim))
236     if a.shape[0] != a.shape[1]:
237         raise LinAlgError('Input must be square')
238 
239     cho = np.linalg.cholesky(np.array([[1, 2], [2, 5]], dtype=a.dtype))
240 
241     op = TensorCholesky(lower=lower, dtype=cho.dtype)
242     return op(a)
243
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mars/tensor/linalg/cholesky.py b/mars/tensor/linalg/cholesky.py
--- a/mars/tensor/linalg/cholesky.py
+++ b/mars/tensor/linalg/cholesky.py
@@ -25,16 +25,6 @@
 from ..array_utils import as_same_device, device
 
 
-def _H(chunk):
-    from ..base.transpose import TensorTranspose
-    from ..arithmetic.conj import TensorConj
-
-    trans_op = TensorTranspose(dtype=chunk.dtype)
-    c = trans_op.new_chunk([chunk], shape=chunk.shape[::-1], index=chunk.index[::-1])
-    conj_op = TensorConj(dtype=c.dtype)
-    return conj_op.new_chunk([c], shape=c.shape, index=c.index)
-
-
 class TensorCholesky(TensorHasInput, TensorOperandMixin):
     _op_type_ = OperandDef.CHOLESKY
 
@@ -60,6 +50,8 @@
         from ..datasource.zeros import TensorZeros
         from ..arithmetic.subtract import TensorSubtract
         from ..arithmetic.utils import tree_add
+        from ..base import TensorTranspose
+        from ..utils import reverse_order
         from .dot import TensorDot
         from .solve_triangular import TensorSolveTriangular
 
@@ -100,7 +92,9 @@
                             [target, s], shape=target.shape, order=tensor.order)
                     lower_chunk = TensorCholesky(lower=True, dtype=tensor.dtype).new_chunk(
                         [target], shape=target.shape, index=(i, j), order=tensor.order)
-                    upper_chunk = _H(lower_chunk)
+                    upper_chunk = TensorTranspose(dtype=lower_chunk.dtype).new_chunk(
+                        [lower_chunk], shape=lower_chunk.shape[::-1],
+                        index=lower_chunk.index[::-1], order=reverse_order(lower_chunk.order))
                     lower_chunks[lower_chunk.index] = lower_chunk
                     upper_chunks[upper_chunk.index] = upper_chunk
                 else:
@@ -122,7 +116,9 @@
                     upper_chunk = TensorSolveTriangular(lower=True, dtype=tensor.dtype).new_chunk(
                         [lower_chunks[j, j], target], shape=target.shape,
                         index=(j, i), order=tensor.order)
-                    lower_chunk = _H(upper_chunk)
+                    lower_chunk = TensorTranspose(dtype=upper_chunk.dtype).new_chunk(
+                        [upper_chunk], shape=upper_chunk.shape[::-1],
+                        index=upper_chunk.index[::-1], order=reverse_order(upper_chunk.order))
                     lower_chunks[lower_chunk.index] = lower_chunk
                     upper_chunks[upper_chunk.index] = upper_chunk

{"golden_diff": "diff --git a/mars/tensor/linalg/cholesky.py b/mars/tensor/linalg/cholesky.py\n--- a/mars/tensor/linalg/cholesky.py\n+++ b/mars/tensor/linalg/cholesky.py\n@@ -25,16 +25,6 @@\n from ..array_utils import as_same_device, device\n \n \n-def _H(chunk):\n-    from ..base.transpose import TensorTranspose\n-    from ..arithmetic.conj import TensorConj\n-\n-    trans_op = TensorTranspose(dtype=chunk.dtype)\n-    c = trans_op.new_chunk([chunk], shape=chunk.shape[::-1], index=chunk.index[::-1])\n-    conj_op = TensorConj(dtype=c.dtype)\n-    return conj_op.new_chunk([c], shape=c.shape, index=c.index)\n-\n-\n class TensorCholesky(TensorHasInput, TensorOperandMixin):\n     _op_type_ = OperandDef.CHOLESKY\n \n@@ -60,6 +50,8 @@\n         from ..datasource.zeros import TensorZeros\n         from ..arithmetic.subtract import TensorSubtract\n         from ..arithmetic.utils import tree_add\n+        from ..base import TensorTranspose\n+        from ..utils import reverse_order\n         from .dot import TensorDot\n         from .solve_triangular import TensorSolveTriangular\n \n@@ -100,7 +92,9 @@\n                             [target, s], shape=target.shape, order=tensor.order)\n                     lower_chunk = TensorCholesky(lower=True, dtype=tensor.dtype).new_chunk(\n                         [target], shape=target.shape, index=(i, j), order=tensor.order)\n-                    upper_chunk = _H(lower_chunk)\n+                    upper_chunk = TensorTranspose(dtype=lower_chunk.dtype).new_chunk(\n+                        [lower_chunk], shape=lower_chunk.shape[::-1],\n+                        index=lower_chunk.index[::-1], order=reverse_order(lower_chunk.order))\n                     lower_chunks[lower_chunk.index] = lower_chunk\n                     upper_chunks[upper_chunk.index] = upper_chunk\n                 else:\n@@ -122,7 +116,9 @@\n                     upper_chunk = TensorSolveTriangular(lower=True, dtype=tensor.dtype).new_chunk(\n                         [lower_chunks[j, j], target], shape=target.shape,\n                         index=(j, i), order=tensor.order)\n-                    lower_chunk = _H(upper_chunk)\n+                    lower_chunk = TensorTranspose(dtype=upper_chunk.dtype).new_chunk(\n+                        [upper_chunk], shape=upper_chunk.shape[::-1],\n+                        index=upper_chunk.index[::-1], order=reverse_order(upper_chunk.order))\n                     lower_chunks[lower_chunk.index] = lower_chunk\n                     upper_chunks[upper_chunk.index] = upper_chunk\n", "issue": "Remove conjugate in Cholesky decomposition which effects performance heavily\n<!--\r\nThank you for your contribution!\r\n\r\nPlease review https://github.com/mars-project/mars/blob/master/CONTRIBUTING.rst before opening an issue.\r\n-->\r\n\r\nIn the tile of Cholesky decomposition, we do a conjugate after transpose which is unnecessary and effect performance heavily.\r\n\n", "before_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright 1999-2018 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport numpy as np\nfrom numpy.linalg import LinAlgError\n\nfrom ...serialize import KeyField, BoolField\nfrom ... import opcodes as OperandDef\nfrom ..operands import TensorHasInput, TensorOperandMixin\nfrom ..datasource import tensor as astensor\nfrom ..core import TensorOrder\nfrom ..array_utils import as_same_device, device\n\n\ndef _H(chunk):\n    from ..base.transpose import TensorTranspose\n    from ..arithmetic.conj import TensorConj\n\n    trans_op = TensorTranspose(dtype=chunk.dtype)\n    c = trans_op.new_chunk([chunk], shape=chunk.shape[::-1], index=chunk.index[::-1])\n    conj_op = TensorConj(dtype=c.dtype)\n    return conj_op.new_chunk([c], shape=c.shape, index=c.index)\n\n\nclass TensorCholesky(TensorHasInput, TensorOperandMixin):\n    _op_type_ = OperandDef.CHOLESKY\n\n    _input = KeyField('input')\n    _lower = BoolField('lower')\n\n    def __init__(self, lower=None, dtype=None, **kw):\n        super(TensorCholesky, self).__init__(_lower=lower, _dtype=dtype, **kw)\n\n    @property\n    def lower(self):\n        return self._lower\n\n    def _set_inputs(self, inputs):\n        super(TensorCholesky, self)._set_inputs(inputs)\n        self._input = self._inputs[0]\n\n    def __call__(self, a):\n        return self.new_tensor([a], a.shape, order=TensorOrder.C_ORDER)\n\n    @classmethod\n    def tile(cls, op):\n        from ..datasource.zeros import TensorZeros\n        from ..arithmetic.subtract import TensorSubtract\n        from ..arithmetic.utils import tree_add\n        from .dot import TensorDot\n        from .solve_triangular import TensorSolveTriangular\n\n        tensor = op.outputs[0]\n        in_tensor = op.input\n        if in_tensor.nsplits[0] != in_tensor.nsplits[1]:\n            # all chunks on diagonal should be square\n            nsplits = in_tensor.nsplits[0]\n            in_tensor = in_tensor.rechunk([nsplits, nsplits]).single_tiles()\n\n        lower_chunks, upper_chunks = {}, {}\n        for i in range(in_tensor.chunk_shape[0]):\n            for j in range(in_tensor.chunk_shape[1]):\n                if i < j:\n                    lower_chunk = TensorZeros(dtype=tensor.dtype).new_chunk(\n                        None, shape=(in_tensor.nsplits[0][i], in_tensor.nsplits[1][j]),\n                        index=(i, j), order=tensor.order)\n                    upper_chunk = TensorZeros(dtype=tensor.dtype).new_chunk(\n                        None, shape=(in_tensor.nsplits[1][j], in_tensor.nsplits[0][i]),\n                        index=(j, i), order=tensor.order)\n                    lower_chunks[lower_chunk.index] = lower_chunk\n                    upper_chunks[upper_chunk.index] = upper_chunk\n                elif i == j:\n                    target = in_tensor.cix[i, j]\n                    if i > 0:\n                        prev_chunks = []\n                        for p in range(i):\n                            a, b = lower_chunks[i, p], upper_chunks[p, j]\n                            prev_chunk = TensorDot(dtype=tensor.dtype).new_chunk(\n                                [a, b], shape=(a.shape[0], b.shape[1]), order=tensor.order)\n                            prev_chunks.append(prev_chunk)\n                        if len(prev_chunks) == 1:\n                            s = prev_chunks[0]\n                        else:\n                            s = tree_add(prev_chunks[0].dtype, prev_chunks,\n                                         None, prev_chunks[0].shape)\n                        target = TensorSubtract(dtype=tensor.dtype, lhs=target, rhs=s).new_chunk(\n                            [target, s], shape=target.shape, order=tensor.order)\n                    lower_chunk = TensorCholesky(lower=True, dtype=tensor.dtype).new_chunk(\n                        [target], shape=target.shape, index=(i, j), order=tensor.order)\n                    upper_chunk = _H(lower_chunk)\n                    lower_chunks[lower_chunk.index] = lower_chunk\n                    upper_chunks[upper_chunk.index] = upper_chunk\n                else:\n                    target = in_tensor.cix[j, i]\n                    if j > 0:\n                        prev_chunks = []\n                        for p in range(j):\n                            a, b = lower_chunks[j, p], upper_chunks[p, i]\n                            prev_chunk = TensorDot(dtype=tensor.dtype).new_chunk(\n                                [a, b], shape=(a.shape[0], b.shape[1]), order=tensor.order)\n                            prev_chunks.append(prev_chunk)\n                        if len(prev_chunks) == 1:\n                            s = prev_chunks[0]\n                        else:\n                            s = tree_add(prev_chunks[0].dtype, prev_chunks,\n                                         None, prev_chunks[0].shape)\n                        target = TensorSubtract(dtype=tensor.dtype, lhs=target, rhs=s).new_chunk(\n                            [target, s], shape=target.shape, order=tensor.order)\n                    upper_chunk = TensorSolveTriangular(lower=True, dtype=tensor.dtype).new_chunk(\n                        [lower_chunks[j, j], target], shape=target.shape,\n                        index=(j, i), order=tensor.order)\n                    lower_chunk = _H(upper_chunk)\n                    lower_chunks[lower_chunk.index] = lower_chunk\n                    upper_chunks[upper_chunk.index] = upper_chunk\n\n        new_op = op.copy()\n        if op.lower:\n            return new_op.new_tensors(op.inputs, tensor.shape, order=tensor.order,\n                                      chunks=list(lower_chunks.values()), nsplits=in_tensor.nsplits)\n        else:\n            return new_op.new_tensors(op.inputs, tensor.shape, order=tensor.order,\n                                      chunks=list(upper_chunks.values()), nsplits=in_tensor.nsplits)\n\n    @classmethod\n    def execute(cls, ctx, op):\n        chunk = op.outputs[0]\n        (a,), device_id, xp = as_same_device(\n            [ctx[c.key] for c in op.inputs], device=op.device, ret_extra=True)\n\n        with device(device_id):\n            if xp is np:\n                try:\n                    import scipy.linalg\n\n                    ctx[chunk.key] = scipy.linalg.cholesky(a, lower=op.lower)\n                    return\n                except ImportError:  # pragma: no cover\n                    pass\n\n            r = xp.linalg.cholesky(a)\n            if not chunk.op.lower:\n                r = r.T.conj()\n\n            ctx[chunk.key] = r\n\n\ndef cholesky(a, lower=False):\n    \"\"\"\n    Cholesky decomposition.\n\n    Return the Cholesky decomposition, `L * L.H`, of the square matrix `a`,\n    where `L` is lower-triangular and .H is the conjugate transpose operator\n    (which is the ordinary transpose if `a` is real-valued).  `a` must be\n    Hermitian (symmetric if real-valued) and positive-definite.  Only `L` is\n    actually returned.\n\n    Parameters\n    ----------\n    a : (..., M, M) array_like\n        Hermitian (symmetric if all elements are real), positive-definite\n        input matrix.\n    lower : bool\n        Whether to compute the upper or lower triangular Cholesky\n        factorization.  Default is upper-triangular.\n\n    Returns\n    -------\n    L : (..., M, M) array_like\n        Upper or lower-triangular Cholesky factor of `a`.\n\n    Raises\n    ------\n    LinAlgError\n       If the decomposition fails, for example, if `a` is not\n       positive-definite.\n\n    Notes\n    -----\n\n    Broadcasting rules apply, see the `mt.linalg` documentation for\n    details.\n\n    The Cholesky decomposition is often used as a fast way of solving\n\n    .. math:: A \\\\mathbf{x} = \\\\mathbf{b}\n\n    (when `A` is both Hermitian/symmetric and positive-definite).\n\n    First, we solve for :math:`\\\\mathbf{y}` in\n\n    .. math:: L \\\\mathbf{y} = \\\\mathbf{b},\n\n    and then for :math:`\\\\mathbf{x}` in\n\n    .. math:: L.H \\\\mathbf{x} = \\\\mathbf{y}.\n\n    Examples\n    --------\n    >>> import mars.tensor as mt\n\n    >>> A = mt.array([[1,-2j],[2j,5]])\n    >>> A.execute()\n    array([[ 1.+0.j,  0.-2.j],\n           [ 0.+2.j,  5.+0.j]])\n    >>> L = mt.linalg.cholesky(A, lower=True)\n    >>> L.execute()\n    array([[ 1.+0.j,  0.+0.j],\n           [ 0.+2.j,  1.+0.j]])\n    >>> mt.dot(L, L.T.conj()).execute() # verify that L * L.H = A\n    array([[ 1.+0.j,  0.-2.j],\n           [ 0.+2.j,  5.+0.j]])\n    >>> A = [[1,-2j],[2j,5]] # what happens if A is only array_like?\n    >>> mt.linalg.cholesky(A, lower=True).execute()\n    array([[ 1.+0.j,  0.+0.j],\n           [ 0.+2.j,  1.+0.j]])\n\n    \"\"\"\n    a = astensor(a)\n\n    if a.ndim != 2:\n        raise LinAlgError('{0}-dimensional array given. '\n                          'Tensor must be two-dimensional'.format(a.ndim))\n    if a.shape[0] != a.shape[1]:\n        raise LinAlgError('Input must be square')\n\n    cho = np.linalg.cholesky(np.array([[1, 2], [2, 5]], dtype=a.dtype))\n\n    op = TensorCholesky(lower=lower, dtype=cho.dtype)\n    return op(a)\n", "path": "mars/tensor/linalg/cholesky.py"}], "after_files": [{"content": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n# Copyright 1999-2018 Alibaba Group Holding Ltd.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#      http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nimport numpy as np\nfrom numpy.linalg import LinAlgError\n\nfrom ...serialize import KeyField, BoolField\nfrom ... import opcodes as OperandDef\nfrom ..operands import TensorHasInput, TensorOperandMixin\nfrom ..datasource import tensor as astensor\nfrom ..core import TensorOrder\nfrom ..array_utils import as_same_device, device\n\n\nclass TensorCholesky(TensorHasInput, TensorOperandMixin):\n    _op_type_ = OperandDef.CHOLESKY\n\n    _input = KeyField('input')\n    _lower = BoolField('lower')\n\n    def __init__(self, lower=None, dtype=None, **kw):\n        super(TensorCholesky, self).__init__(_lower=lower, _dtype=dtype, **kw)\n\n    @property\n    def lower(self):\n        return self._lower\n\n    def _set_inputs(self, inputs):\n        super(TensorCholesky, self)._set_inputs(inputs)\n        self._input = self._inputs[0]\n\n    def __call__(self, a):\n        return self.new_tensor([a], a.shape, order=TensorOrder.C_ORDER)\n\n    @classmethod\n    def tile(cls, op):\n        from ..datasource.zeros import TensorZeros\n        from ..arithmetic.subtract import TensorSubtract\n        from ..arithmetic.utils import tree_add\n        from ..base import TensorTranspose\n        from ..utils import reverse_order\n        from .dot import TensorDot\n        from .solve_triangular import TensorSolveTriangular\n\n        tensor = op.outputs[0]\n        in_tensor = op.input\n        if in_tensor.nsplits[0] != in_tensor.nsplits[1]:\n            # all chunks on diagonal should be square\n            nsplits = in_tensor.nsplits[0]\n            in_tensor = in_tensor.rechunk([nsplits, nsplits]).single_tiles()\n\n        lower_chunks, upper_chunks = {}, {}\n        for i in range(in_tensor.chunk_shape[0]):\n            for j in range(in_tensor.chunk_shape[1]):\n                if i < j:\n                    lower_chunk = TensorZeros(dtype=tensor.dtype).new_chunk(\n                        None, shape=(in_tensor.nsplits[0][i], in_tensor.nsplits[1][j]),\n                        index=(i, j), order=tensor.order)\n                    upper_chunk = TensorZeros(dtype=tensor.dtype).new_chunk(\n                        None, shape=(in_tensor.nsplits[1][j], in_tensor.nsplits[0][i]),\n                        index=(j, i), order=tensor.order)\n                    lower_chunks[lower_chunk.index] = lower_chunk\n                    upper_chunks[upper_chunk.index] = upper_chunk\n                elif i == j:\n                    target = in_tensor.cix[i, j]\n                    if i > 0:\n                        prev_chunks = []\n                        for p in range(i):\n                            a, b = lower_chunks[i, p], upper_chunks[p, j]\n                            prev_chunk = TensorDot(dtype=tensor.dtype).new_chunk(\n                                [a, b], shape=(a.shape[0], b.shape[1]), order=tensor.order)\n                            prev_chunks.append(prev_chunk)\n                        if len(prev_chunks) == 1:\n                            s = prev_chunks[0]\n                        else:\n                            s = tree_add(prev_chunks[0].dtype, prev_chunks,\n                                         None, prev_chunks[0].shape)\n                        target = TensorSubtract(dtype=tensor.dtype, lhs=target, rhs=s).new_chunk(\n                            [target, s], shape=target.shape, order=tensor.order)\n                    lower_chunk = TensorCholesky(lower=True, dtype=tensor.dtype).new_chunk(\n                        [target], shape=target.shape, index=(i, j), order=tensor.order)\n                    upper_chunk = TensorTranspose(dtype=lower_chunk.dtype).new_chunk(\n                        [lower_chunk], shape=lower_chunk.shape[::-1],\n                        index=lower_chunk.index[::-1], order=reverse_order(lower_chunk.order))\n                    lower_chunks[lower_chunk.index] = lower_chunk\n                    upper_chunks[upper_chunk.index] = upper_chunk\n                else:\n                    target = in_tensor.cix[j, i]\n                    if j > 0:\n                        prev_chunks = []\n                        for p in range(j):\n                            a, b = lower_chunks[j, p], upper_chunks[p, i]\n                            prev_chunk = TensorDot(dtype=tensor.dtype).new_chunk(\n                                [a, b], shape=(a.shape[0], b.shape[1]), order=tensor.order)\n                            prev_chunks.append(prev_chunk)\n                        if len(prev_chunks) == 1:\n                            s = prev_chunks[0]\n                        else:\n                            s = tree_add(prev_chunks[0].dtype, prev_chunks,\n                                         None, prev_chunks[0].shape)\n                        target = TensorSubtract(dtype=tensor.dtype, lhs=target, rhs=s).new_chunk(\n                            [target, s], shape=target.shape, order=tensor.order)\n                    upper_chunk = TensorSolveTriangular(lower=True, dtype=tensor.dtype).new_chunk(\n                        [lower_chunks[j, j], target], shape=target.shape,\n                        index=(j, i), order=tensor.order)\n                    lower_chunk = TensorTranspose(dtype=upper_chunk.dtype).new_chunk(\n                        [upper_chunk], shape=upper_chunk.shape[::-1],\n                        index=upper_chunk.index[::-1], order=reverse_order(upper_chunk.order))\n                    lower_chunks[lower_chunk.index] = lower_chunk\n                    upper_chunks[upper_chunk.index] = upper_chunk\n\n        new_op = op.copy()\n        if op.lower:\n            return new_op.new_tensors(op.inputs, tensor.shape, order=tensor.order,\n                                      chunks=list(lower_chunks.values()), nsplits=in_tensor.nsplits)\n        else:\n            return new_op.new_tensors(op.inputs, tensor.shape, order=tensor.order,\n                                      chunks=list(upper_chunks.values()), nsplits=in_tensor.nsplits)\n\n    @classmethod\n    def execute(cls, ctx, op):\n        chunk = op.outputs[0]\n        (a,), device_id, xp = as_same_device(\n            [ctx[c.key] for c in op.inputs], device=op.device, ret_extra=True)\n\n        with device(device_id):\n            if xp is np:\n                try:\n                    import scipy.linalg\n\n                    ctx[chunk.key] = scipy.linalg.cholesky(a, lower=op.lower)\n                    return\n                except ImportError:  # pragma: no cover\n                    pass\n\n            r = xp.linalg.cholesky(a)\n            if not chunk.op.lower:\n                r = r.T.conj()\n\n            ctx[chunk.key] = r\n\n\ndef cholesky(a, lower=False):\n    \"\"\"\n    Cholesky decomposition.\n\n    Return the Cholesky decomposition, `L * L.H`, of the square matrix `a`,\n    where `L` is lower-triangular and .H is the conjugate transpose operator\n    (which is the ordinary transpose if `a` is real-valued).  `a` must be\n    Hermitian (symmetric if real-valued) and positive-definite.  Only `L` is\n    actually returned.\n\n    Parameters\n    ----------\n    a : (..., M, M) array_like\n        Hermitian (symmetric if all elements are real), positive-definite\n        input matrix.\n    lower : bool\n        Whether to compute the upper or lower triangular Cholesky\n        factorization.  Default is upper-triangular.\n\n    Returns\n    -------\n    L : (..., M, M) array_like\n        Upper or lower-triangular Cholesky factor of `a`.\n\n    Raises\n    ------\n    LinAlgError\n       If the decomposition fails, for example, if `a` is not\n       positive-definite.\n\n    Notes\n    -----\n\n    Broadcasting rules apply, see the `mt.linalg` documentation for\n    details.\n\n    The Cholesky decomposition is often used as a fast way of solving\n\n    .. math:: A \\\\mathbf{x} = \\\\mathbf{b}\n\n    (when `A` is both Hermitian/symmetric and positive-definite).\n\n    First, we solve for :math:`\\\\mathbf{y}` in\n\n    .. math:: L \\\\mathbf{y} = \\\\mathbf{b},\n\n    and then for :math:`\\\\mathbf{x}` in\n\n    .. math:: L.H \\\\mathbf{x} = \\\\mathbf{y}.\n\n    Examples\n    --------\n    >>> import mars.tensor as mt\n\n    >>> A = mt.array([[1,-2j],[2j,5]])\n    >>> A.execute()\n    array([[ 1.+0.j,  0.-2.j],\n           [ 0.+2.j,  5.+0.j]])\n    >>> L = mt.linalg.cholesky(A, lower=True)\n    >>> L.execute()\n    array([[ 1.+0.j,  0.+0.j],\n           [ 0.+2.j,  1.+0.j]])\n    >>> mt.dot(L, L.T.conj()).execute() # verify that L * L.H = A\n    array([[ 1.+0.j,  0.-2.j],\n           [ 0.+2.j,  5.+0.j]])\n    >>> A = [[1,-2j],[2j,5]] # what happens if A is only array_like?\n    >>> mt.linalg.cholesky(A, lower=True).execute()\n    array([[ 1.+0.j,  0.+0.j],\n           [ 0.+2.j,  1.+0.j]])\n\n    \"\"\"\n    a = astensor(a)\n\n    if a.ndim != 2:\n        raise LinAlgError('{0}-dimensional array given. '\n                          'Tensor must be two-dimensional'.format(a.ndim))\n    if a.shape[0] != a.shape[1]:\n        raise LinAlgError('Input must be square')\n\n    cho = np.linalg.cholesky(np.array([[1, 2], [2, 5]], dtype=a.dtype))\n\n    op = TensorCholesky(lower=lower, dtype=cho.dtype)\n    return op(a)\n", "path": "mars/tensor/linalg/cholesky.py"}]}