Skip to content

Commit

Permalink
Fix global phase in inverse of UCGate (#8508) (#8536)
Browse files Browse the repository at this point in the history
* Defines the inverse of the global phase

The inverse of UCGate is defined by simply inverting the existing decomposition, but the inverse of the global phase was missing.

* Tests the UCGate.inverse() function

* Lint

* Seed for building the matrices

* Replace `unitary_simulator` by using `qiskit.quantum_info.Operator`.

Co-authored-by: Julien Gacon <gaconju@gmail.com>

* Import `Operator` class

* Release notes

* Lint

* Test the phase of isometry decomposition

* Removes the `prelude` from the release notes file

* Replaces `matrix_equal` with `np.allclose`

Co-authored-by: Julien Gacon <gaconju@gmail.com>
(cherry picked from commit 82c85d8)

Co-authored-by: Israel F. Araujo <israelferrazaraujo@hotmail.com>
Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Aug 17, 2022
1 parent 5a3738d commit 1d5dce6
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 4 deletions.
3 changes: 3 additions & 0 deletions qiskit/extensions/quantum_initializer/uc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -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 <https://github.com/Qiskit/qiskit-terra/issues/4687>` for more
details.
5 changes: 2 additions & 3 deletions test/python/circuit/test_isometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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),
Expand Down
18 changes: 17 additions & 1 deletion test/python/circuit/test_uc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]])
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down

0 comments on commit 1d5dce6

Please sign in to comment.