Repository: Qiskit/qiskit — pull request #10126 (python)
Title: fix 1q matrix bug in Quantum Shannon Decomposer

<!--\r\n⚠️ If you do not respect this template, your pull request will be closed.\r\n⚠️ Your pull request title should be short detailed and understandable for all.\r\n⚠️ Also, please add a release note file using reno if the change needs to be\r\n  documented in the release notes.\r\n⚠️ If your pull request fixes an open issue, please link to the issue.\r\n\r\n- [x] I have added the tests to cover my changes.\r\n- [x] I have updated the documentation accordingly.\r\n- [x] I have read the CONTRIBUTING document.\r\n-->\r\n\r\n### Summary\r\nFixes #10036\r\n\r\n\r\n### Details and comments\r\n\r\n\r\n

Resolved issues:
title: Quantum shannon decomposition failing for some inputs
body: ### Environment\r\n\r\n- **Qiskit Terra version**: 0.42.1\r\n- **Python version**: 3.10.8\r\n\r\n\r\n\r\n### What is happening?\r\n\r\nqs_decomposition in [qsd.py](https://github.com/Qiskit/qiskit-terra/blob/main/qiskit/quantum_info/synthesis/qsd.py) throws an error for some examples, seemingly due to a bug in the code\r\n\r\n### How can we reproduce the issue?\r\n\r\n```\r\nfrom qiskit.quantum_info.synthesis.qsd import qs_decomposition\r\nqs_decomposition(np.array([[0,1],[1,0]]))\r\n```\r\nOutput:\r\n```\r\nTraceback (most recent call last):\r\n  Cell In[14], line 3\r\n    qs_decomposition(np.array([[0,1],[1,0]]))\r\n  File /opt/conda/lib/python3.10/site-packages/qiskit/quantum_info/synthesis/qsd.py:122 in qs_decomposition\r\n    return _apply_a2(circ)\r\n  File /opt/conda/lib/python3.10/site-packages/qiskit/quantum_info/synthesis/qsd.py:253 in _apply_a2\r\n    qc3 = two_qubit_decompose.two_qubit_cnot_decompose(mat2)\r\nUnboundLocalError: local variable 'mat2' referenced before assignment\r\n \r\nUse %tb to get the full traceback.\r\n```\r\nAlternatively,\r\n```\r\nqs_decomposition(qiskit.quantum_info.random_unitary(4).to_matrix())\r\n```\r\nGiving the same error\r\n\r\n### What should happen?\r\n\r\nWe should still be able to produce a decomposed circuit from these examples\r\n\r\n### Any suggestions?\r\n\r\nThis seems to occur when line 233 of qsd.py in the function ‘_apply_a2()’ does not transpile to include any of the ‘qsd2q’ gate type for an instance.\r\n\r\nTo fix this add something such as the following before the loop on line 242:\r\n```\r\nif not ind2q:\r\n    return ccirc\r\n```\r\nAdditionally should add a test for this kind of case to the [test](https://github.com/Qiskit/qiskit-terra/blob/main/test/python/quantum_info/test_synthesis.py) 

Hints:

Fix patch:
diff --git a/qiskit/quantum_info/synthesis/qsd.py b/qiskit/quantum_info/synthesis/qsd.py\nindex 87aae51cabad..82694e45ab22 100644\n--- a/qiskit/quantum_info/synthesis/qsd.py\n+++ b/qiskit/quantum_info/synthesis/qsd.py\n@@ -81,7 +81,7 @@ def qs_decomposition(\n         circ = decomposer_1q(mat)\n     elif dim == 4:\n         if decomposer_2q is None:\n-            if opt_a2:\n+            if opt_a2 and _depth > 0:\n                 from qiskit.extensions.unitary import UnitaryGate  # pylint: disable=cyclic-import\n \n                 def decomp_2q(mat):\n@@ -118,7 +118,7 @@ def decomp_2q(mat):\n         right_circ = _demultiplex(u1, u2, opt_a1=opt_a1, opt_a2=opt_a2, _depth=_depth)\n         circ.append(right_circ.to_instruction(), qr)\n \n-    if opt_a2 and _depth == 0:\n+    if opt_a2 and _depth == 0 and dim > 4:\n         return _apply_a2(circ)\n     return circ\n \n@@ -236,6 +236,8 @@ def _apply_a2(circ):\n     for i, instruction in enumerate(ccirc.data):\n         if instruction.operation.name == "qsd2q":\n             ind2q.append(i)\n+    if not ind2q:\n+        return ccirc\n     # rolling over diagonals\n     ind2 = None  # lint\n     for ind1, ind2 in zip(ind2q[0:-1:], ind2q[1::]):\ndiff --git a/releasenotes/notes/fix-1q-matrix-bug-in-quantum-shannon-decomposer-c99ce6509f03715b.yaml b/releasenotes/notes/fix-1q-matrix-bug-in-quantum-shannon-decomposer-c99ce6509f03715b.yaml\nnew file mode 100644\nindex 000000000000..d68d20c89e24\n--- /dev/null\n+++ b/releasenotes/notes/fix-1q-matrix-bug-in-quantum-shannon-decomposer-c99ce6509f03715b.yaml\n@@ -0,0 +1,7 @@\n+---\n+fixes:\n+  - |\n+    When :func:`~qiskit.quantum_info.synthesis.qs_decomposition`, which does quantum Shannon\n+    decomposition, was called on trivial numeric unitaries that do not benefit from this\n+    decomposition, an unexpected error was raised. With this fix, such unitaries are detected and\n+    the equivalent circuit is returned without performing Shannon decomposition.\n

Test patch:
diff --git a/test/python/quantum_info/test_synthesis.py b/test/python/quantum_info/test_synthesis.py\nindex 58074995c7a1..19ec8b8139e9 100644\n--- a/test/python/quantum_info/test_synthesis.py\n+++ b/test/python/quantum_info/test_synthesis.py\n@@ -1530,7 +1530,7 @@ def test_hermitian(self, nqubits):\n             expected_cx = self._qsd_l2_cx_count(nqubits) - self._qsd_l2_a1_mod(nqubits)\n             self.assertLessEqual(ccirc.count_ops().get("cx"), expected_cx)\n \n-    @data(*list(range(3, 6)))\n+    @data(*list(range(1, 6)))\n     def test_opt_a1a2(self, nqubits):\n         """Test decomposition with both optimization a1 and a2 from shende2006"""\n         dim = 2**nqubits\n@@ -1538,9 +1538,15 @@ def test_opt_a1a2(self, nqubits):\n         circ = self.qsd(umat, opt_a1=True, opt_a2=True)\n         ccirc = transpile(circ, basis_gates=["u", "cx"], optimization_level=0)\n         self.assertTrue(Operator(umat) == Operator(ccirc))\n-        self.assertEqual(\n-            ccirc.count_ops().get("cx"), (23 / 48) * 4**nqubits - (3 / 2) * 2**nqubits + 4 / 3\n-        )\n+        if nqubits > 2:\n+            self.assertEqual(\n+                ccirc.count_ops().get("cx"),\n+                (23 / 48) * 4**nqubits - (3 / 2) * 2**nqubits + 4 / 3,\n+            )\n+        elif nqubits == 1:\n+            self.assertEqual(ccirc.count_ops().get("cx", 0), 0)\n+        elif nqubits == 2:\n+            self.assertLessEqual(ccirc.count_ops().get("cx", 0), 3)\n \n \n class TestTwoQubitDecomposeUpToDiagonal(QiskitTestCase):\n