diff --git a/qiskit/extensions/quantum_initializer/uc.py b/qiskit/extensions/quantum_initializer/uc.py index 61618efb3563..d859ed4a96de 100644 --- a/qiskit/extensions/quantum_initializer/uc.py +++ b/qiskit/extensions/quantum_initializer/uc.py @@ -110,6 +110,9 @@ def inverse(self): definition = QuantumCircuit(*self.definition.qregs) for inst in reversed(self._definition): definition._append(inst.replace(operation=inst.operation.inverse())) + + definition.global_phase = -self.definition.global_phase + inverse_gate.definition = definition return inverse_gate diff --git a/releasenotes/notes/bugfix-ucgate-inverse-global_phase-c9655c13c22e5cf4.yaml b/releasenotes/notes/bugfix-ucgate-inverse-global_phase-c9655c13c22e5cf4.yaml new file mode 100644 index 000000000000..eae30452782b --- /dev/null +++ b/releasenotes/notes/bugfix-ucgate-inverse-global_phase-c9655c13c22e5cf4.yaml @@ -0,0 +1,9 @@ +--- +fixes: + - | + Fixes the :meth:`.UCGate.inverse` method which previously did not invert the + global phase. + - | + Fixes the global phase problem of the isometry decomposition. Refer to + `#4687 ` for more + details. diff --git a/test/python/circuit/test_isometry.py b/test/python/circuit/test_isometry.py index c411836da5fb..bffd9c69bac3 100644 --- a/test/python/circuit/test_isometry.py +++ b/test/python/circuit/test_isometry.py @@ -24,7 +24,6 @@ from qiskit import execute from qiskit.test import QiskitTestCase from qiskit.compiler import transpile -from qiskit.quantum_info.operators.predicates import matrix_equal from qiskit.quantum_info import Operator from qiskit.extensions.quantum_initializer.isometry import Isometry @@ -69,7 +68,7 @@ def test_isometry(self, iso): unitary = result.get_unitary(qc) iso_from_circuit = unitary[::, 0 : 2**num_q_input] iso_desired = iso - self.assertTrue(matrix_equal(iso_from_circuit, iso_desired, ignore_phase=True)) + self.assertTrue(np.allclose(iso_from_circuit, iso_desired)) @data( np.eye(2, 2), @@ -108,7 +107,7 @@ def test_isometry_tolerance(self, iso): result = execute(qc, simulator).result() unitary = result.get_unitary(qc) iso_from_circuit = unitary[::, 0 : 2**num_q_input] - self.assertTrue(matrix_equal(iso_from_circuit, iso, ignore_phase=True)) + self.assertTrue(np.allclose(iso_from_circuit, iso)) @data( np.eye(2, 2), diff --git a/test/python/circuit/test_uc.py b/test/python/circuit/test_uc.py index cedff9f4ac41..1f50b650623c 100644 --- a/test/python/circuit/test_uc.py +++ b/test/python/circuit/test_uc.py @@ -30,6 +30,7 @@ from qiskit.quantum_info.random import random_unitary from qiskit.compiler import transpile from qiskit.quantum_info.operators.predicates import matrix_equal +from qiskit.quantum_info import Operator _id = np.eye(2, 2) _not = np.matrix([[0, 1], [1, 0]]) @@ -71,7 +72,7 @@ def test_ucg(self, squs, up_to_diagonal): self.assertTrue(matrix_equal(unitary_desired, unitary, ignore_phase=True)) def test_global_phase_ucg(self): - """ "Test global phase of uniformly controlled gates""" + """Test global phase of uniformly controlled gates""" gates = [random_unitary(2).data for _ in range(2**2)] num_con = int(np.log2(len(gates))) q = QuantumRegister(num_con + 1) @@ -85,6 +86,21 @@ def test_global_phase_ucg(self): self.assertTrue(np.allclose(unitary_desired, unitary)) + def test_inverse_ucg(self): + """Test inverse function of uniformly controlled gates""" + gates = [random_unitary(2, seed=42 + s).data for s in range(2**2)] + num_con = int(np.log2(len(gates))) + q = QuantumRegister(num_con + 1) + qc = QuantumCircuit(q) + + qc.uc(gates, q[1:], q[0], up_to_diagonal=False) + qc.append(qc.inverse(), qc.qubits) + + unitary = Operator(qc).data + unitary_desired = np.identity(2**qc.num_qubits) + + self.assertTrue(np.allclose(unitary_desired, unitary)) + def _get_ucg_matrix(squs): return block_diag(*squs)