We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Flaky Test when seed not used
The test `test_max_truncation_error` in `tensornetwork/backends/symmetric/decompositions_test.py` [link](https://github.com/google/TensorNetwork/blob/edf3f345640c64595b4ad1002bebf4a008988b3e/tensornetwork/backends/symmetric/decompositions_test.py#L90) almost always fails when the seed [here](https://github.com/google/TensorNetwork/blob/edf3f345640c64595b4ad1002bebf4a008988b3e/tensornetwork/backends/symmetric/decompositions_test.py#L91) is removed. This happens only for `[3-float64]` and `[4-complex128]` parameters. The test failed 500/500 times for me for both these parameters.

From the error message it seems `svals[mask][::-1]` is always empty whereas `S2.data` most often has an element of size 1(except when using the seed). Is this expected? Or is this indicative of a bug?

Please let me know if you need more details. I will be happy to raise a PR if you have any suggestions on how to fix it.

Test failure message:
```
>     np.testing.assert_allclose(S2.data, svals[mask][::-1])
E     AssertionError:
E     Not equal to tolerance rtol=1e-07, atol=0
E
E     (shapes (1,), (0,) mismatch)
E      x: array([1.])
E      y: array([], dtype=float64)

tensornetwork/backends/symmetric/decompositions_test.py:112: AssertionError
```

Environment:
```
Anaconda python 3.6
tensorflow==2.6.0
numpy==1.19.5
scipy==1.5.4
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `tensornetwork/backends/symmetric/decompositions.py`
Content:
```
1 # Copyright 2019 The TensorNetwork Authors
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #      http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """Tensor Decomposition Implementations."""
15 import numpy as np
16 import warnings
17 from typing import Optional, Any, Tuple
18 from tensornetwork.block_sparse.blocksparse_utils import (
19     _find_transposed_diagonal_sparse_blocks)
20 from tensornetwork.block_sparse.utils import get_real_dtype
21 from tensornetwork.block_sparse.sizetypes import SIZE_T
22 from tensornetwork.block_sparse.blocksparsetensor import (BlockSparseTensor,
23                                                           ChargeArray)
24 Tensor = Any
25 
26 
27 def svd(
28     bt,
29     tensor: BlockSparseTensor,
30     pivot_axis: int,
31     max_singular_values: Optional[int] = None,
32     max_truncation_error: Optional[float] = None,
33     relative: Optional[bool] = False) -> Tuple[Tensor, Tensor, Tensor, Tensor]:
34   """
35   Computes the singular value decomposition (SVD) of a tensor.
36   See tensornetwork.backends.tensorflow.decompositions for details.
37   """
38 
39   left_dims = tensor.shape[:pivot_axis]
40   right_dims = tensor.shape[pivot_axis:]
41 
42   matrix = bt.reshape(tensor, [np.prod(left_dims), np.prod(right_dims)])
43 
44   flat_charges = matrix._charges
45   flat_flows = matrix._flows
46   flat_order = matrix.flat_order
47   tr_partition = len(matrix._order[0])
48   blocks, charges, shapes = _find_transposed_diagonal_sparse_blocks(
49       flat_charges, flat_flows, tr_partition, flat_order)
50 
51   u_blocks = []
52   singvals = []
53   v_blocks = []
54   for n, b in enumerate(blocks):
55     out = np.linalg.svd(
56         np.reshape(matrix.data[b], shapes[:, n]),
57         full_matrices=False,
58         compute_uv=True)
59     u_blocks.append(out[0])
60     singvals.append(out[1])
61     v_blocks.append(out[2])
62 
63   orig_num_singvals = np.int64(np.sum([len(s) for s in singvals]))
64   orig_block_size = [len(s) for s in singvals]
65   discarded_singvals = np.zeros(0, dtype=get_real_dtype(tensor.dtype))
66   if (max_singular_values
67       is not None) and (max_singular_values >= orig_num_singvals):
68     max_singular_values = None
69 
70   if (max_truncation_error is not None) or (max_singular_values is not None):
71     max_D = np.max([len(s) for s in singvals]) if len(singvals) > 0 else 0
72 
73     #extend singvals of all blocks into a matrix by padding each block with 0
74     if len(singvals) > 0:
75       extended_singvals = np.stack([
76           np.append(s, np.zeros(max_D - len(s), dtype=s.dtype))
77           for s in singvals
78       ],
79                                    axis=1)
80     else:
81       extended_singvals = np.empty((0, 0), dtype=get_real_dtype(tensor.dtype))
82 
83     extended_flat_singvals = np.ravel(extended_singvals)
84     #sort singular values
85     inds = np.argsort(extended_flat_singvals, kind='stable')
86     discarded_inds = np.zeros(0, dtype=SIZE_T)
87     if inds.shape[0] > 0:
88       maxind = inds[-1]
89     else:
90       maxind = 0
91     if max_truncation_error is not None:
92       if relative and (len(singvals) > 0):
93         max_truncation_error = max_truncation_error * np.max(
94             [s[0] for s in singvals])
95 
96       kept_inds_mask = np.sqrt(
97           np.cumsum(np.square(
98               extended_flat_singvals[inds]))) > max_truncation_error
99       trunc_inds_mask = np.logical_not(kept_inds_mask)
100       discarded_inds = inds[trunc_inds_mask]
101       inds = inds[kept_inds_mask]
102     if max_singular_values is not None:
103       #if the original number of non-zero singular values
104       #is smaller than `max_singular_values` we need to reset
105       #`max_singular_values` (we were filling in 0.0 into singular
106       #value blocks to facilitate trunction steps, thus we could end up
107       #with more singular values than originally there).
108       if max_singular_values > orig_num_singvals:
109         max_singular_values = orig_num_singvals
110       if max_singular_values < len(inds):
111         discarded_inds = np.append(discarded_inds,
112                                    inds[:(-1) * max_singular_values])
113         inds = inds[(-1) * max_singular_values::]
114 
115     if len(inds) == 0:
116       #special case of truncation to 0 dimension;
117       warnings.warn("svd_decomposition truncated to 0 dimensions. "
118                     "Adjusting to `max_singular_values = 1`")
119       inds = np.asarray([maxind])
120 
121     if extended_singvals.shape[1] > 0:
122       #pylint: disable=no-member
123       keep = np.divmod(inds, extended_singvals.shape[1])
124       disc = np.divmod(discarded_inds, extended_singvals.shape[1])
125     else:
126       keep = (np.zeros(1, dtype=SIZE_T), np.zeros(1, dtype=SIZE_T))
127       disc = (np.zeros(0, dtype=SIZE_T), np.zeros(0, dtype=SIZE_T))
128     newsingvals = [
129         extended_singvals[keep[0][keep[1] == n], keep[1][keep[1] == n]][::-1]
130         for n in range(extended_singvals.shape[1])
131     ]
132     discsingvals = [
133         extended_singvals[disc[0][disc[1] == n], disc[1][disc[1] == n]][::-1]
134         for n in range(extended_singvals.shape[1])
135     ]
136     new_block_size = [len(s) for s in newsingvals]
137     discsingvals = [
138         d[:(orig_block_size[n] - new_block_size[n])]
139         for n, d in enumerate(discsingvals)
140     ]
141     singvals = newsingvals
142     discarded_singvals = discsingvals
143   if len(singvals) > 0:
144     left_singval_charge_labels = np.concatenate([
145         np.full(singvals[n].shape[0], fill_value=n, dtype=np.int16)
146         for n in range(len(singvals))
147     ])
148     all_singvals = np.concatenate(singvals)
149     #define the new charges on the two central bonds
150     left_charge_labels = np.concatenate([
151         np.full(len(singvals[n]), fill_value=n, dtype=np.int16)
152         for n in range(len(u_blocks))
153     ])
154     right_charge_labels = np.concatenate([
155         np.full(len(singvals[n]), fill_value=n, dtype=np.int16)
156         for n in range(len(v_blocks))
157     ])
158     all_ublocks = np.concatenate([
159         np.ravel(np.transpose(u_blocks[n][:, 0:len(singvals[n])]))
160         for n in range(len(u_blocks))
161     ])
162     all_vblocks = np.concatenate([
163         np.ravel(v_blocks[n][0:len(singvals[n]), :])
164         for n in range(len(v_blocks))
165     ])
166   else:
167     left_singval_charge_labels = np.empty(0, dtype=np.int16)
168     all_singvals = np.empty(0, dtype=get_real_dtype(tensor.dtype))
169     left_charge_labels = np.empty(0, dtype=np.int16)
170     right_charge_labels = np.empty(0, dtype=np.int16)
171     all_ublocks = np.empty(0, dtype=get_real_dtype(tensor.dtype))
172     all_vblocks = np.empty(0, dtype=get_real_dtype(tensor.dtype))
173 
174   if len(discarded_singvals) > 0:
175     tmp_labels = [
176         np.full(discarded_singvals[n].shape[0], fill_value=n, dtype=np.int16)
177         for n in range(len(discarded_singvals))
178     ]
179     left_discarded_singval_charge_labels = np.concatenate(tmp_labels)
180     all_discarded_singvals = np.concatenate(discarded_singvals)
181 
182   else:
183     left_discarded_singval_charge_labels = np.empty(0, dtype=np.int16)
184     all_discarded_singvals = np.empty(0, dtype=get_real_dtype(tensor.dtype))
185 
186 
187   left_singval_charge = charges[left_singval_charge_labels]
188   S = ChargeArray(all_singvals, [left_singval_charge], [False])
189 
190   left_discarded_singval_charge = charges[left_discarded_singval_charge_labels]
191   Sdisc = ChargeArray(all_discarded_singvals, [left_discarded_singval_charge],
192                       [False])
193 
194   new_left_charge = charges[left_charge_labels]
195   new_right_charge = charges[right_charge_labels]
196 
197   #get the indices of the new tensors U,S and V
198   charges_u = [new_left_charge] + [matrix._charges[o] for o in matrix._order[0]]
199   order_u = [[0]] + [list(np.arange(1, len(matrix._order[0]) + 1))]
200   flows_u = [True] + [matrix._flows[o] for o in matrix._order[0]]
201   charges_v = [new_right_charge
202               ] + [matrix._charges[o] for o in matrix._order[1]]
203   flows_v = [False] + [matrix._flows[o] for o in matrix._order[1]]
204   order_v = [[0]] + [list(np.arange(1, len(matrix._order[1]) + 1))]
205 
206   #We fill in data into the transposed U
207   U = BlockSparseTensor(
208       all_ublocks,
209       charges=charges_u,
210       flows=flows_u,
211       order=order_u,
212       check_consistency=False).transpose((1, 0))
213 
214   V = BlockSparseTensor(
215       all_vblocks,
216       charges=charges_v,
217       flows=flows_v,
218       order=order_v,
219       check_consistency=False)
220   left_shape = left_dims + (S.shape[0],)
221   right_shape = (S.shape[0],) + right_dims
222   return U.reshape(left_shape), S, V.reshape(right_shape), Sdisc
223 
224 
225 def qr(bt, tensor: BlockSparseTensor, pivot_axis: int) -> Tuple[Tensor, Tensor]:
226   """Computes the QR decomposition of a tensor.
227 
228   See tensornetwork.backends.tensorflow.decompositions for details.
229   """
230   left_dims = tensor.shape[:pivot_axis]
231   right_dims = tensor.shape[pivot_axis:]
232   tensor = bt.reshape(tensor, [np.prod(left_dims), np.prod(right_dims)])
233   q, r = bt.qr(tensor)
234   center_dim = q.shape[1]
235   q = bt.reshape(q, list(left_dims) + [center_dim])
236   r = bt.reshape(r, [center_dim] + list(right_dims))
237   return q, r
238 
239 
240 def rq(bt, tensor: BlockSparseTensor, pivot_axis: int) -> Tuple[Tensor, Tensor]:
241   """Computes the RQ (reversed QR) decomposition of a tensor.
242 
243   See tensornetwork.backends.tensorflow.decompositions for details.
244   """
245   left_dims = tensor.shape[:pivot_axis]
246   right_dims = tensor.shape[pivot_axis:]
247   tensor = bt.reshape(tensor, [np.prod(left_dims), np.prod(right_dims)])
248   q, r = bt.qr(bt.conj(bt.transpose(tensor, (1, 0))))
249   r, q = bt.conj(bt.transpose(r, (1, 0))), bt.conj(bt.transpose(
250       q, (1, 0)))  #M=r*q at this point
251   center_dim = r.shape[1]
252   r = bt.reshape(r, list(left_dims) + [center_dim])
253   q = bt.reshape(q, [center_dim] + list(right_dims))
254   return r, q
255
```
--- 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/tensornetwork/backends/symmetric/decompositions.py b/tensornetwork/backends/symmetric/decompositions.py
--- a/tensornetwork/backends/symmetric/decompositions.py
+++ b/tensornetwork/backends/symmetric/decompositions.py
@@ -84,10 +84,6 @@
     #sort singular values
     inds = np.argsort(extended_flat_singvals, kind='stable')
     discarded_inds = np.zeros(0, dtype=SIZE_T)
-    if inds.shape[0] > 0:
-      maxind = inds[-1]
-    else:
-      maxind = 0
     if max_truncation_error is not None:
       if relative and (len(singvals) > 0):
         max_truncation_error = max_truncation_error * np.max(
@@ -114,9 +110,7 @@
 
     if len(inds) == 0:
       #special case of truncation to 0 dimension;
-      warnings.warn("svd_decomposition truncated to 0 dimensions. "
-                    "Adjusting to `max_singular_values = 1`")
-      inds = np.asarray([maxind])
+      warnings.warn("svd_decomposition truncated to 0 dimensions.")
 
     if extended_singvals.shape[1] > 0:
       #pylint: disable=no-member

{"golden_diff": "diff --git a/tensornetwork/backends/symmetric/decompositions.py b/tensornetwork/backends/symmetric/decompositions.py\n--- a/tensornetwork/backends/symmetric/decompositions.py\n+++ b/tensornetwork/backends/symmetric/decompositions.py\n@@ -84,10 +84,6 @@\n     #sort singular values\n     inds = np.argsort(extended_flat_singvals, kind='stable')\n     discarded_inds = np.zeros(0, dtype=SIZE_T)\n-    if inds.shape[0] > 0:\n-      maxind = inds[-1]\n-    else:\n-      maxind = 0\n     if max_truncation_error is not None:\n       if relative and (len(singvals) > 0):\n         max_truncation_error = max_truncation_error * np.max(\n@@ -114,9 +110,7 @@\n \n     if len(inds) == 0:\n       #special case of truncation to 0 dimension;\n-      warnings.warn(\"svd_decomposition truncated to 0 dimensions. \"\n-                    \"Adjusting to `max_singular_values = 1`\")\n-      inds = np.asarray([maxind])\n+      warnings.warn(\"svd_decomposition truncated to 0 dimensions.\")\n \n     if extended_singvals.shape[1] > 0:\n       #pylint: disable=no-member\n", "issue": "Flaky Test when seed not used\nThe test `test_max_truncation_error` in `tensornetwork/backends/symmetric/decompositions_test.py` [link](https://github.com/google/TensorNetwork/blob/edf3f345640c64595b4ad1002bebf4a008988b3e/tensornetwork/backends/symmetric/decompositions_test.py#L90) almost always fails when the seed [here](https://github.com/google/TensorNetwork/blob/edf3f345640c64595b4ad1002bebf4a008988b3e/tensornetwork/backends/symmetric/decompositions_test.py#L91) is removed. This happens only for `[3-float64]` and `[4-complex128]` parameters. The test failed 500/500 times for me for both these parameters.\r\n\r\nFrom the error message it seems `svals[mask][::-1]` is always empty whereas `S2.data` most often has an element of size 1(except when using the seed). Is this expected? Or is this indicative of a bug?\r\n\r\nPlease let me know if you need more details. I will be happy to raise a PR if you have any suggestions on how to fix it.\r\n\r\nTest failure message:\r\n```\r\n>     np.testing.assert_allclose(S2.data, svals[mask][::-1])\r\nE     AssertionError:\r\nE     Not equal to tolerance rtol=1e-07, atol=0\r\nE\r\nE     (shapes (1,), (0,) mismatch)\r\nE      x: array([1.])\r\nE      y: array([], dtype=float64)\r\n\r\ntensornetwork/backends/symmetric/decompositions_test.py:112: AssertionError\r\n```\r\n\r\nEnvironment:\r\n```\r\nAnaconda python 3.6\r\ntensorflow==2.6.0\r\nnumpy==1.19.5\r\nscipy==1.5.4\r\n```\r\n\n", "before_files": [{"content": "# Copyright 2019 The TensorNetwork Authors\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\"\"\"Tensor Decomposition Implementations.\"\"\"\nimport numpy as np\nimport warnings\nfrom typing import Optional, Any, Tuple\nfrom tensornetwork.block_sparse.blocksparse_utils import (\n    _find_transposed_diagonal_sparse_blocks)\nfrom tensornetwork.block_sparse.utils import get_real_dtype\nfrom tensornetwork.block_sparse.sizetypes import SIZE_T\nfrom tensornetwork.block_sparse.blocksparsetensor import (BlockSparseTensor,\n                                                          ChargeArray)\nTensor = Any\n\n\ndef svd(\n    bt,\n    tensor: BlockSparseTensor,\n    pivot_axis: int,\n    max_singular_values: Optional[int] = None,\n    max_truncation_error: Optional[float] = None,\n    relative: Optional[bool] = False) -> Tuple[Tensor, Tensor, Tensor, Tensor]:\n  \"\"\"\n  Computes the singular value decomposition (SVD) of a tensor.\n  See tensornetwork.backends.tensorflow.decompositions for details.\n  \"\"\"\n\n  left_dims = tensor.shape[:pivot_axis]\n  right_dims = tensor.shape[pivot_axis:]\n\n  matrix = bt.reshape(tensor, [np.prod(left_dims), np.prod(right_dims)])\n\n  flat_charges = matrix._charges\n  flat_flows = matrix._flows\n  flat_order = matrix.flat_order\n  tr_partition = len(matrix._order[0])\n  blocks, charges, shapes = _find_transposed_diagonal_sparse_blocks(\n      flat_charges, flat_flows, tr_partition, flat_order)\n\n  u_blocks = []\n  singvals = []\n  v_blocks = []\n  for n, b in enumerate(blocks):\n    out = np.linalg.svd(\n        np.reshape(matrix.data[b], shapes[:, n]),\n        full_matrices=False,\n        compute_uv=True)\n    u_blocks.append(out[0])\n    singvals.append(out[1])\n    v_blocks.append(out[2])\n\n  orig_num_singvals = np.int64(np.sum([len(s) for s in singvals]))\n  orig_block_size = [len(s) for s in singvals]\n  discarded_singvals = np.zeros(0, dtype=get_real_dtype(tensor.dtype))\n  if (max_singular_values\n      is not None) and (max_singular_values >= orig_num_singvals):\n    max_singular_values = None\n\n  if (max_truncation_error is not None) or (max_singular_values is not None):\n    max_D = np.max([len(s) for s in singvals]) if len(singvals) > 0 else 0\n\n    #extend singvals of all blocks into a matrix by padding each block with 0\n    if len(singvals) > 0:\n      extended_singvals = np.stack([\n          np.append(s, np.zeros(max_D - len(s), dtype=s.dtype))\n          for s in singvals\n      ],\n                                   axis=1)\n    else:\n      extended_singvals = np.empty((0, 0), dtype=get_real_dtype(tensor.dtype))\n\n    extended_flat_singvals = np.ravel(extended_singvals)\n    #sort singular values\n    inds = np.argsort(extended_flat_singvals, kind='stable')\n    discarded_inds = np.zeros(0, dtype=SIZE_T)\n    if inds.shape[0] > 0:\n      maxind = inds[-1]\n    else:\n      maxind = 0\n    if max_truncation_error is not None:\n      if relative and (len(singvals) > 0):\n        max_truncation_error = max_truncation_error * np.max(\n            [s[0] for s in singvals])\n\n      kept_inds_mask = np.sqrt(\n          np.cumsum(np.square(\n              extended_flat_singvals[inds]))) > max_truncation_error\n      trunc_inds_mask = np.logical_not(kept_inds_mask)\n      discarded_inds = inds[trunc_inds_mask]\n      inds = inds[kept_inds_mask]\n    if max_singular_values is not None:\n      #if the original number of non-zero singular values\n      #is smaller than `max_singular_values` we need to reset\n      #`max_singular_values` (we were filling in 0.0 into singular\n      #value blocks to facilitate trunction steps, thus we could end up\n      #with more singular values than originally there).\n      if max_singular_values > orig_num_singvals:\n        max_singular_values = orig_num_singvals\n      if max_singular_values < len(inds):\n        discarded_inds = np.append(discarded_inds,\n                                   inds[:(-1) * max_singular_values])\n        inds = inds[(-1) * max_singular_values::]\n\n    if len(inds) == 0:\n      #special case of truncation to 0 dimension;\n      warnings.warn(\"svd_decomposition truncated to 0 dimensions. \"\n                    \"Adjusting to `max_singular_values = 1`\")\n      inds = np.asarray([maxind])\n\n    if extended_singvals.shape[1] > 0:\n      #pylint: disable=no-member\n      keep = np.divmod(inds, extended_singvals.shape[1])\n      disc = np.divmod(discarded_inds, extended_singvals.shape[1])\n    else:\n      keep = (np.zeros(1, dtype=SIZE_T), np.zeros(1, dtype=SIZE_T))\n      disc = (np.zeros(0, dtype=SIZE_T), np.zeros(0, dtype=SIZE_T))\n    newsingvals = [\n        extended_singvals[keep[0][keep[1] == n], keep[1][keep[1] == n]][::-1]\n        for n in range(extended_singvals.shape[1])\n    ]\n    discsingvals = [\n        extended_singvals[disc[0][disc[1] == n], disc[1][disc[1] == n]][::-1]\n        for n in range(extended_singvals.shape[1])\n    ]\n    new_block_size = [len(s) for s in newsingvals]\n    discsingvals = [\n        d[:(orig_block_size[n] - new_block_size[n])]\n        for n, d in enumerate(discsingvals)\n    ]\n    singvals = newsingvals\n    discarded_singvals = discsingvals\n  if len(singvals) > 0:\n    left_singval_charge_labels = np.concatenate([\n        np.full(singvals[n].shape[0], fill_value=n, dtype=np.int16)\n        for n in range(len(singvals))\n    ])\n    all_singvals = np.concatenate(singvals)\n    #define the new charges on the two central bonds\n    left_charge_labels = np.concatenate([\n        np.full(len(singvals[n]), fill_value=n, dtype=np.int16)\n        for n in range(len(u_blocks))\n    ])\n    right_charge_labels = np.concatenate([\n        np.full(len(singvals[n]), fill_value=n, dtype=np.int16)\n        for n in range(len(v_blocks))\n    ])\n    all_ublocks = np.concatenate([\n        np.ravel(np.transpose(u_blocks[n][:, 0:len(singvals[n])]))\n        for n in range(len(u_blocks))\n    ])\n    all_vblocks = np.concatenate([\n        np.ravel(v_blocks[n][0:len(singvals[n]), :])\n        for n in range(len(v_blocks))\n    ])\n  else:\n    left_singval_charge_labels = np.empty(0, dtype=np.int16)\n    all_singvals = np.empty(0, dtype=get_real_dtype(tensor.dtype))\n    left_charge_labels = np.empty(0, dtype=np.int16)\n    right_charge_labels = np.empty(0, dtype=np.int16)\n    all_ublocks = np.empty(0, dtype=get_real_dtype(tensor.dtype))\n    all_vblocks = np.empty(0, dtype=get_real_dtype(tensor.dtype))\n\n  if len(discarded_singvals) > 0:\n    tmp_labels = [\n        np.full(discarded_singvals[n].shape[0], fill_value=n, dtype=np.int16)\n        for n in range(len(discarded_singvals))\n    ]\n    left_discarded_singval_charge_labels = np.concatenate(tmp_labels)\n    all_discarded_singvals = np.concatenate(discarded_singvals)\n\n  else:\n    left_discarded_singval_charge_labels = np.empty(0, dtype=np.int16)\n    all_discarded_singvals = np.empty(0, dtype=get_real_dtype(tensor.dtype))\n\n\n  left_singval_charge = charges[left_singval_charge_labels]\n  S = ChargeArray(all_singvals, [left_singval_charge], [False])\n\n  left_discarded_singval_charge = charges[left_discarded_singval_charge_labels]\n  Sdisc = ChargeArray(all_discarded_singvals, [left_discarded_singval_charge],\n                      [False])\n\n  new_left_charge = charges[left_charge_labels]\n  new_right_charge = charges[right_charge_labels]\n\n  #get the indices of the new tensors U,S and V\n  charges_u = [new_left_charge] + [matrix._charges[o] for o in matrix._order[0]]\n  order_u = [[0]] + [list(np.arange(1, len(matrix._order[0]) + 1))]\n  flows_u = [True] + [matrix._flows[o] for o in matrix._order[0]]\n  charges_v = [new_right_charge\n              ] + [matrix._charges[o] for o in matrix._order[1]]\n  flows_v = [False] + [matrix._flows[o] for o in matrix._order[1]]\n  order_v = [[0]] + [list(np.arange(1, len(matrix._order[1]) + 1))]\n\n  #We fill in data into the transposed U\n  U = BlockSparseTensor(\n      all_ublocks,\n      charges=charges_u,\n      flows=flows_u,\n      order=order_u,\n      check_consistency=False).transpose((1, 0))\n\n  V = BlockSparseTensor(\n      all_vblocks,\n      charges=charges_v,\n      flows=flows_v,\n      order=order_v,\n      check_consistency=False)\n  left_shape = left_dims + (S.shape[0],)\n  right_shape = (S.shape[0],) + right_dims\n  return U.reshape(left_shape), S, V.reshape(right_shape), Sdisc\n\n\ndef qr(bt, tensor: BlockSparseTensor, pivot_axis: int) -> Tuple[Tensor, Tensor]:\n  \"\"\"Computes the QR decomposition of a tensor.\n\n  See tensornetwork.backends.tensorflow.decompositions for details.\n  \"\"\"\n  left_dims = tensor.shape[:pivot_axis]\n  right_dims = tensor.shape[pivot_axis:]\n  tensor = bt.reshape(tensor, [np.prod(left_dims), np.prod(right_dims)])\n  q, r = bt.qr(tensor)\n  center_dim = q.shape[1]\n  q = bt.reshape(q, list(left_dims) + [center_dim])\n  r = bt.reshape(r, [center_dim] + list(right_dims))\n  return q, r\n\n\ndef rq(bt, tensor: BlockSparseTensor, pivot_axis: int) -> Tuple[Tensor, Tensor]:\n  \"\"\"Computes the RQ (reversed QR) decomposition of a tensor.\n\n  See tensornetwork.backends.tensorflow.decompositions for details.\n  \"\"\"\n  left_dims = tensor.shape[:pivot_axis]\n  right_dims = tensor.shape[pivot_axis:]\n  tensor = bt.reshape(tensor, [np.prod(left_dims), np.prod(right_dims)])\n  q, r = bt.qr(bt.conj(bt.transpose(tensor, (1, 0))))\n  r, q = bt.conj(bt.transpose(r, (1, 0))), bt.conj(bt.transpose(\n      q, (1, 0)))  #M=r*q at this point\n  center_dim = r.shape[1]\n  r = bt.reshape(r, list(left_dims) + [center_dim])\n  q = bt.reshape(q, [center_dim] + list(right_dims))\n  return r, q\n", "path": "tensornetwork/backends/symmetric/decompositions.py"}], "after_files": [{"content": "# Copyright 2019 The TensorNetwork Authors\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\"\"\"Tensor Decomposition Implementations.\"\"\"\nimport numpy as np\nimport warnings\nfrom typing import Optional, Any, Tuple\nfrom tensornetwork.block_sparse.blocksparse_utils import (\n    _find_transposed_diagonal_sparse_blocks)\nfrom tensornetwork.block_sparse.utils import get_real_dtype\nfrom tensornetwork.block_sparse.sizetypes import SIZE_T\nfrom tensornetwork.block_sparse.blocksparsetensor import (BlockSparseTensor,\n                                                          ChargeArray)\nTensor = Any\n\n\ndef svd(\n    bt,\n    tensor: BlockSparseTensor,\n    pivot_axis: int,\n    max_singular_values: Optional[int] = None,\n    max_truncation_error: Optional[float] = None,\n    relative: Optional[bool] = False) -> Tuple[Tensor, Tensor, Tensor, Tensor]:\n  \"\"\"\n  Computes the singular value decomposition (SVD) of a tensor.\n  See tensornetwork.backends.tensorflow.decompositions for details.\n  \"\"\"\n\n  left_dims = tensor.shape[:pivot_axis]\n  right_dims = tensor.shape[pivot_axis:]\n\n  matrix = bt.reshape(tensor, [np.prod(left_dims), np.prod(right_dims)])\n\n  flat_charges = matrix._charges\n  flat_flows = matrix._flows\n  flat_order = matrix.flat_order\n  tr_partition = len(matrix._order[0])\n  blocks, charges, shapes = _find_transposed_diagonal_sparse_blocks(\n      flat_charges, flat_flows, tr_partition, flat_order)\n\n  u_blocks = []\n  singvals = []\n  v_blocks = []\n  for n, b in enumerate(blocks):\n    out = np.linalg.svd(\n        np.reshape(matrix.data[b], shapes[:, n]),\n        full_matrices=False,\n        compute_uv=True)\n    u_blocks.append(out[0])\n    singvals.append(out[1])\n    v_blocks.append(out[2])\n\n  orig_num_singvals = np.int64(np.sum([len(s) for s in singvals]))\n  orig_block_size = [len(s) for s in singvals]\n  discarded_singvals = np.zeros(0, dtype=get_real_dtype(tensor.dtype))\n  if (max_singular_values\n      is not None) and (max_singular_values >= orig_num_singvals):\n    max_singular_values = None\n\n  if (max_truncation_error is not None) or (max_singular_values is not None):\n    max_D = np.max([len(s) for s in singvals]) if len(singvals) > 0 else 0\n\n    #extend singvals of all blocks into a matrix by padding each block with 0\n    if len(singvals) > 0:\n      extended_singvals = np.stack([\n          np.append(s, np.zeros(max_D - len(s), dtype=s.dtype))\n          for s in singvals\n      ],\n                                   axis=1)\n    else:\n      extended_singvals = np.empty((0, 0), dtype=get_real_dtype(tensor.dtype))\n\n    extended_flat_singvals = np.ravel(extended_singvals)\n    #sort singular values\n    inds = np.argsort(extended_flat_singvals, kind='stable')\n    discarded_inds = np.zeros(0, dtype=SIZE_T)\n    if max_truncation_error is not None:\n      if relative and (len(singvals) > 0):\n        max_truncation_error = max_truncation_error * np.max(\n            [s[0] for s in singvals])\n\n      kept_inds_mask = np.sqrt(\n          np.cumsum(np.square(\n              extended_flat_singvals[inds]))) > max_truncation_error\n      trunc_inds_mask = np.logical_not(kept_inds_mask)\n      discarded_inds = inds[trunc_inds_mask]\n      inds = inds[kept_inds_mask]\n    if max_singular_values is not None:\n      #if the original number of non-zero singular values\n      #is smaller than `max_singular_values` we need to reset\n      #`max_singular_values` (we were filling in 0.0 into singular\n      #value blocks to facilitate trunction steps, thus we could end up\n      #with more singular values than originally there).\n      if max_singular_values > orig_num_singvals:\n        max_singular_values = orig_num_singvals\n      if max_singular_values < len(inds):\n        discarded_inds = np.append(discarded_inds,\n                                   inds[:(-1) * max_singular_values])\n        inds = inds[(-1) * max_singular_values::]\n\n    if len(inds) == 0:\n      #special case of truncation to 0 dimension;\n      warnings.warn(\"svd_decomposition truncated to 0 dimensions.\")\n\n    if extended_singvals.shape[1] > 0:\n      #pylint: disable=no-member\n      keep = np.divmod(inds, extended_singvals.shape[1])\n      disc = np.divmod(discarded_inds, extended_singvals.shape[1])\n    else:\n      keep = (np.zeros(1, dtype=SIZE_T), np.zeros(1, dtype=SIZE_T))\n      disc = (np.zeros(0, dtype=SIZE_T), np.zeros(0, dtype=SIZE_T))\n    newsingvals = [\n        extended_singvals[keep[0][keep[1] == n], keep[1][keep[1] == n]][::-1]\n        for n in range(extended_singvals.shape[1])\n    ]\n    discsingvals = [\n        extended_singvals[disc[0][disc[1] == n], disc[1][disc[1] == n]][::-1]\n        for n in range(extended_singvals.shape[1])\n    ]\n    new_block_size = [len(s) for s in newsingvals]\n    discsingvals = [\n        d[:(orig_block_size[n] - new_block_size[n])]\n        for n, d in enumerate(discsingvals)\n    ]\n    singvals = newsingvals\n    discarded_singvals = discsingvals\n  if len(singvals) > 0:\n    left_singval_charge_labels = np.concatenate([\n        np.full(singvals[n].shape[0], fill_value=n, dtype=np.int16)\n        for n in range(len(singvals))\n    ])\n    all_singvals = np.concatenate(singvals)\n    #define the new charges on the two central bonds\n    left_charge_labels = np.concatenate([\n        np.full(len(singvals[n]), fill_value=n, dtype=np.int16)\n        for n in range(len(u_blocks))\n    ])\n    right_charge_labels = np.concatenate([\n        np.full(len(singvals[n]), fill_value=n, dtype=np.int16)\n        for n in range(len(v_blocks))\n    ])\n    all_ublocks = np.concatenate([\n        np.ravel(np.transpose(u_blocks[n][:, 0:len(singvals[n])]))\n        for n in range(len(u_blocks))\n    ])\n    all_vblocks = np.concatenate([\n        np.ravel(v_blocks[n][0:len(singvals[n]), :])\n        for n in range(len(v_blocks))\n    ])\n  else:\n    left_singval_charge_labels = np.empty(0, dtype=np.int16)\n    all_singvals = np.empty(0, dtype=get_real_dtype(tensor.dtype))\n    left_charge_labels = np.empty(0, dtype=np.int16)\n    right_charge_labels = np.empty(0, dtype=np.int16)\n    all_ublocks = np.empty(0, dtype=get_real_dtype(tensor.dtype))\n    all_vblocks = np.empty(0, dtype=get_real_dtype(tensor.dtype))\n\n  if len(discarded_singvals) > 0:\n    tmp_labels = [\n        np.full(discarded_singvals[n].shape[0], fill_value=n, dtype=np.int16)\n        for n in range(len(discarded_singvals))\n    ]\n    left_discarded_singval_charge_labels = np.concatenate(tmp_labels)\n    all_discarded_singvals = np.concatenate(discarded_singvals)\n\n  else:\n    left_discarded_singval_charge_labels = np.empty(0, dtype=np.int16)\n    all_discarded_singvals = np.empty(0, dtype=get_real_dtype(tensor.dtype))\n\n\n  left_singval_charge = charges[left_singval_charge_labels]\n  S = ChargeArray(all_singvals, [left_singval_charge], [False])\n\n  left_discarded_singval_charge = charges[left_discarded_singval_charge_labels]\n  Sdisc = ChargeArray(all_discarded_singvals, [left_discarded_singval_charge],\n                      [False])\n\n  new_left_charge = charges[left_charge_labels]\n  new_right_charge = charges[right_charge_labels]\n\n  #get the indices of the new tensors U,S and V\n  charges_u = [new_left_charge] + [matrix._charges[o] for o in matrix._order[0]]\n  order_u = [[0]] + [list(np.arange(1, len(matrix._order[0]) + 1))]\n  flows_u = [True] + [matrix._flows[o] for o in matrix._order[0]]\n  charges_v = [new_right_charge\n              ] + [matrix._charges[o] for o in matrix._order[1]]\n  flows_v = [False] + [matrix._flows[o] for o in matrix._order[1]]\n  order_v = [[0]] + [list(np.arange(1, len(matrix._order[1]) + 1))]\n\n  #We fill in data into the transposed U\n  U = BlockSparseTensor(\n      all_ublocks,\n      charges=charges_u,\n      flows=flows_u,\n      order=order_u,\n      check_consistency=False).transpose((1, 0))\n\n  V = BlockSparseTensor(\n      all_vblocks,\n      charges=charges_v,\n      flows=flows_v,\n      order=order_v,\n      check_consistency=False)\n  left_shape = left_dims + (S.shape[0],)\n  right_shape = (S.shape[0],) + right_dims\n  return U.reshape(left_shape), S, V.reshape(right_shape), Sdisc\n\n\ndef qr(bt, tensor: BlockSparseTensor, pivot_axis: int) -> Tuple[Tensor, Tensor]:\n  \"\"\"Computes the QR decomposition of a tensor.\n\n  See tensornetwork.backends.tensorflow.decompositions for details.\n  \"\"\"\n  left_dims = tensor.shape[:pivot_axis]\n  right_dims = tensor.shape[pivot_axis:]\n  tensor = bt.reshape(tensor, [np.prod(left_dims), np.prod(right_dims)])\n  q, r = bt.qr(tensor)\n  center_dim = q.shape[1]\n  q = bt.reshape(q, list(left_dims) + [center_dim])\n  r = bt.reshape(r, [center_dim] + list(right_dims))\n  return q, r\n\n\ndef rq(bt, tensor: BlockSparseTensor, pivot_axis: int) -> Tuple[Tensor, Tensor]:\n  \"\"\"Computes the RQ (reversed QR) decomposition of a tensor.\n\n  See tensornetwork.backends.tensorflow.decompositions for details.\n  \"\"\"\n  left_dims = tensor.shape[:pivot_axis]\n  right_dims = tensor.shape[pivot_axis:]\n  tensor = bt.reshape(tensor, [np.prod(left_dims), np.prod(right_dims)])\n  q, r = bt.qr(bt.conj(bt.transpose(tensor, (1, 0))))\n  r, q = bt.conj(bt.transpose(r, (1, 0))), bt.conj(bt.transpose(\n      q, (1, 0)))  #M=r*q at this point\n  center_dim = r.shape[1]\n  r = bt.reshape(r, list(left_dims) + [center_dim])\n  q = bt.reshape(q, [center_dim] + list(right_dims))\n  return r, q\n", "path": "tensornetwork/backends/symmetric/decompositions.py"}]}