Fix Hoare optimizer failure for successive gates of three (#7278)

* Record deleted gates in  _multigate_optto

* Move come code from _multigate_opt to a subroutine

* Create a release note for the bug fix

* Rename max_idx to from_idx and update comments

* Remove reference to private function in release note

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
Jintao YU 2021-11-27 02:40:02 +08:00 committed by GitHub
parent 8dbb7183c6
commit 605283d67e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 26 deletions

View File

@ -232,23 +232,24 @@ class HoareOptimizer(TransformationPass):
self._add_postconditions(gate, ctrl_ones, trgtqb, trgtvar)
def _target_successive_seq(self, qubit):
"""gates are target successive if they have the same set of target
qubits and follow each other immediately on these target qubits
(consider sequences of length 2 for now)
def _remove_successive_identity(self, dag, qubit, from_idx=None):
"""remove gates that have the same set of target qubits, follow each
other immediately on these target qubits, and combine to the
identity (consider sequences of length 2 for now)
Args:
dag (DAGCircuit): the directed acyclic graph to run on.
qubit (Qubit): qubit cache to inspect
Returns:
list(list(DAGOpNode or DAGOutNode)): list of target successive gate sequences for
this qubit's cache
from_idx (int): only gates whose indexes in the cache are larger
than this value can be removed
"""
seqs = []
for i in range(len(self.gatecache[qubit]) - 1):
i = 0
while i < len(self.gatecache[qubit]) - 1:
append = True
node1 = self.gatecache[qubit][i]
node2 = self.gatecache[qubit][i + 1]
trgtqb1 = self._seperate_ctrl_trgt(node1)[2]
trgtqb2 = self._seperate_ctrl_trgt(node2)[2]
i += 1
if trgtqb1 != trgtqb2:
continue
@ -260,10 +261,14 @@ class HoareOptimizer(TransformationPass):
except (IndexError, ValueError):
continue
if append:
seqs.append([node1, node2])
return seqs
seq = [node1, node2]
if append and self._is_identity(seq) and self._seq_as_one(seq):
i += 1
for node in seq:
dag.remove_op_node(node)
if from_idx is None or self.gatecache[qubit].index(node) > from_idx:
for qbt in node.qargs:
self.gatecache[qbt].remove(node)
def _is_identity(self, sequence):
"""determine whether the sequence of gates combines to the identity
@ -334,19 +339,7 @@ class HoareOptimizer(TransformationPass):
return
# try to optimize this qubit's pipeline
for seq in self._target_successive_seq(qubit):
if self._is_identity(seq) and self._seq_as_one(seq):
for node in seq:
dag.remove_op_node(node)
# if recursive call, gate will be removed further down
if max_idx is None:
for qbt in node.qargs:
self.gatecache[qbt].remove(node)
else:
if self.gatecache[qubit].index(node) > max_idx:
for qbt in node.qargs:
self.gatecache[qbt].remove(node)
self._remove_successive_identity(dag, qubit, max_idx)
if len(self.gatecache[qubit]) < self.size and max_idx is None:
# unless in a rec call, we are done if the cache isn't full
return

View File

@ -0,0 +1,5 @@
---
fixes:
- |
Fixed a bug in the Hoare optimizer transpilation pass where it could attempt to remove a gate twice if it could be separately combined with both its predecessor and its successor to form the identity.
Refer to `#7271 <https://github.com/Qiskit/qiskit-terra/issues/7271>`__ for more details.

View File

@ -175,6 +175,26 @@ class TestHoareOptimizer(QiskitTestCase):
self.assertEqual(result, circuit_to_dag(expected))
def test_successive_identity_removal(self):
"""Should remove a successive pair of H gates applying
on the same qubit.
"""
circuit = QuantumCircuit(1)
circuit.h(0)
circuit.h(0)
circuit.h(0)
expected = QuantumCircuit(1)
expected.h(0)
stv = Statevector.from_label("0" * circuit.num_qubits)
self.assertEqual(stv & circuit, stv & expected)
pass_ = HoareOptimizer(size=4)
result = pass_.run(circuit_to_dag(circuit))
self.assertEqual(result, circuit_to_dag(expected))
def test_targetsuccessive_identity_removal(self):
"""Should remove pair of controlled target successive
which are the inverse of each other, if they can be