mirror of https://github.com/Qiskit/qiskit.git
301 lines
11 KiB
Python
301 lines
11 KiB
Python
# This code is part of Qiskit.
|
|
#
|
|
# (C) Copyright IBM 2017, 2019.
|
|
#
|
|
# This code is licensed under the Apache License, Version 2.0. You may
|
|
# obtain a copy of this license in the LICENSE.txt file in the root directory
|
|
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
|
|
#
|
|
# Any modifications or derivative works of this code must retain this
|
|
# copyright notice, and modified files need to carry a notice indicating
|
|
# that they have been altered from the originals.
|
|
|
|
"""Test the MergeAdjacentBarriers pass"""
|
|
|
|
import random
|
|
import unittest
|
|
|
|
from qiskit.transpiler.passes import MergeAdjacentBarriers
|
|
from qiskit.converters import circuit_to_dag
|
|
from qiskit import QuantumRegister, QuantumCircuit
|
|
from test import QiskitTestCase # pylint: disable=wrong-import-order
|
|
|
|
|
|
class TestMergeAdjacentBarriers(QiskitTestCase):
|
|
"""Test the MergeAdjacentBarriers pass"""
|
|
|
|
def test_two_identical_barriers(self):
|
|
"""Merges two barriers that are identical into one
|
|
░ ░ ░
|
|
q_0: |0>─░──░─ -> q_0: |0>─░─
|
|
░ ░ ░
|
|
"""
|
|
qr = QuantumRegister(1, "q")
|
|
|
|
circuit = QuantumCircuit(qr)
|
|
circuit.barrier(qr)
|
|
circuit.barrier(qr)
|
|
|
|
expected = QuantumCircuit(qr)
|
|
expected.barrier(qr)
|
|
|
|
pass_ = MergeAdjacentBarriers()
|
|
result = pass_.run(circuit_to_dag(circuit))
|
|
|
|
self.assertEqual(result, circuit_to_dag(expected))
|
|
|
|
def test_numerous_identical_barriers(self):
|
|
"""Merges 5 identical barriers in a row into one
|
|
░ ░ ░ ░ ░ ░ ░
|
|
q_0: |0>─░──░──░──░──░──░─ -> q_0: |0>─░─
|
|
░ ░ ░ ░ ░ ░ ░
|
|
"""
|
|
qr = QuantumRegister(1, "q")
|
|
|
|
circuit = QuantumCircuit(qr)
|
|
circuit.barrier(qr)
|
|
circuit.barrier(qr)
|
|
circuit.barrier(qr)
|
|
circuit.barrier(qr)
|
|
circuit.barrier(qr)
|
|
circuit.barrier(qr)
|
|
|
|
expected = QuantumCircuit(qr)
|
|
expected.barrier(qr)
|
|
|
|
expected = QuantumCircuit(qr)
|
|
expected.barrier(qr)
|
|
|
|
pass_ = MergeAdjacentBarriers()
|
|
result = pass_.run(circuit_to_dag(circuit))
|
|
|
|
self.assertEqual(result, circuit_to_dag(expected))
|
|
|
|
def test_barriers_of_different_sizes(self):
|
|
"""Test two barriers of different sizes are merged into one
|
|
░ ░ ░
|
|
q_0: |0>─░──░─ q_0: |0>─░─
|
|
░ ░ -> ░
|
|
q_1: |0>────░─ q_1: |0>─░─
|
|
░ ░
|
|
"""
|
|
qr = QuantumRegister(2, "q")
|
|
|
|
circuit = QuantumCircuit(qr)
|
|
circuit.barrier(qr[0])
|
|
circuit.barrier(qr)
|
|
|
|
expected = QuantumCircuit(qr)
|
|
expected.barrier(qr)
|
|
|
|
pass_ = MergeAdjacentBarriers()
|
|
result = pass_.run(circuit_to_dag(circuit))
|
|
|
|
self.assertEqual(result, circuit_to_dag(expected))
|
|
|
|
def test_not_overlapping_barriers(self):
|
|
"""Test two barriers with no overlap are not merged
|
|
(NB in these pictures they look like 1 barrier but they are
|
|
actually 2 distinct barriers, this is just how the text
|
|
drawer draws them)
|
|
░ ░
|
|
q_0: |0>─░─ q_0: |0>─░─
|
|
░ -> ░
|
|
q_1: |0>─░─ q_1: |0>─░─
|
|
░ ░
|
|
"""
|
|
qr = QuantumRegister(2, "q")
|
|
|
|
circuit = QuantumCircuit(qr)
|
|
circuit.barrier(qr[0])
|
|
circuit.barrier(qr[1])
|
|
|
|
expected = QuantumCircuit(qr)
|
|
expected.barrier(qr[0])
|
|
expected.barrier(qr[1])
|
|
|
|
pass_ = MergeAdjacentBarriers()
|
|
result = pass_.run(circuit_to_dag(circuit))
|
|
|
|
self.assertEqual(result, circuit_to_dag(expected))
|
|
|
|
def test_barriers_with_obstacle_before(self):
|
|
"""Test with an obstacle before the larger barrier
|
|
░ ░ ░
|
|
q_0: |0>──░───░─ q_0: |0>──────░─
|
|
┌───┐ ░ -> ┌───┐ ░
|
|
q_1: |0>┤ H ├─░─ q_1: |0>┤ H ├─░─
|
|
└───┘ ░ └───┘ ░
|
|
"""
|
|
qr = QuantumRegister(2, "q")
|
|
|
|
circuit = QuantumCircuit(qr)
|
|
circuit.barrier(qr[0])
|
|
circuit.h(qr[1])
|
|
circuit.barrier(qr)
|
|
|
|
expected = QuantumCircuit(qr)
|
|
expected.h(qr[1])
|
|
expected.barrier(qr)
|
|
|
|
pass_ = MergeAdjacentBarriers()
|
|
result = pass_.run(circuit_to_dag(circuit))
|
|
|
|
self.assertEqual(result, circuit_to_dag(expected))
|
|
|
|
def test_barriers_with_obstacle_after(self):
|
|
"""Test with an obstacle after the larger barrier
|
|
░ ░ ░
|
|
q_0: |0>─░───░── q_0: |0>─░──────
|
|
░ ┌───┐ -> ░ ┌───┐
|
|
q_1: |0>─░─┤ H ├ q_1: |0>─░─┤ H ├
|
|
░ └───┘ ░ └───┘
|
|
"""
|
|
qr = QuantumRegister(2, "q")
|
|
|
|
circuit = QuantumCircuit(qr)
|
|
circuit.barrier(qr)
|
|
circuit.barrier(qr[0])
|
|
circuit.h(qr[1])
|
|
|
|
expected = QuantumCircuit(qr)
|
|
expected.barrier(qr)
|
|
expected.h(qr[1])
|
|
|
|
pass_ = MergeAdjacentBarriers()
|
|
result = pass_.run(circuit_to_dag(circuit))
|
|
|
|
self.assertEqual(result, circuit_to_dag(expected))
|
|
|
|
def test_barriers_with_blocking_obstacle(self):
|
|
"""Test that barriers don't merge if there is an obstacle that
|
|
is blocking
|
|
░ ┌───┐ ░ ░ ┌───┐ ░
|
|
q_0: |0>─░─┤ H ├─░─ -> q_0: |0>─░─┤ H ├─░─
|
|
░ └───┘ ░ ░ └───┘ ░
|
|
"""
|
|
qr = QuantumRegister(1, "q")
|
|
|
|
circuit = QuantumCircuit(qr)
|
|
circuit.barrier(qr)
|
|
circuit.h(qr)
|
|
circuit.barrier(qr)
|
|
|
|
expected = QuantumCircuit(qr)
|
|
expected.barrier(qr)
|
|
expected.h(qr)
|
|
expected.barrier(qr)
|
|
|
|
pass_ = MergeAdjacentBarriers()
|
|
result = pass_.run(circuit_to_dag(circuit))
|
|
|
|
self.assertEqual(result, circuit_to_dag(expected))
|
|
|
|
def test_barriers_with_blocking_obstacle_long(self):
|
|
"""Test that barriers don't merge if there is an obstacle that
|
|
is blocking
|
|
░ ┌───┐ ░ ░ ┌───┐ ░
|
|
q_0: |0>─░─┤ H ├─░─ q_0: |0>─░─┤ H ├─░─
|
|
░ └───┘ ░ -> ░ └───┘ ░
|
|
q_1: |0>─────────░─ q_1: |0>─────────░─
|
|
░ ░
|
|
"""
|
|
qr = QuantumRegister(2, "q")
|
|
|
|
circuit = QuantumCircuit(qr)
|
|
circuit.barrier(qr[0])
|
|
circuit.h(qr[0])
|
|
circuit.barrier(qr)
|
|
|
|
expected = QuantumCircuit(qr)
|
|
expected.barrier(qr[0])
|
|
expected.h(qr[0])
|
|
expected.barrier(qr)
|
|
|
|
pass_ = MergeAdjacentBarriers()
|
|
result = pass_.run(circuit_to_dag(circuit))
|
|
|
|
self.assertEqual(result, circuit_to_dag(expected))
|
|
|
|
def test_barriers_with_blocking_obstacle_narrow(self):
|
|
"""Test that barriers don't merge if there is an obstacle that
|
|
is blocking
|
|
░ ┌───┐ ░ ░ ┌───┐ ░
|
|
q_0: |0>─░─┤ H ├─░─ q_0: |0>─░─┤ H ├─░─
|
|
░ └───┘ ░ -> ░ └───┘ ░
|
|
q_1: |0>─░───────░─ q_1: |0>─░───────░─
|
|
░ ░ ░ ░
|
|
"""
|
|
qr = QuantumRegister(2, "q")
|
|
|
|
circuit = QuantumCircuit(qr)
|
|
circuit.barrier(qr)
|
|
circuit.h(qr[0])
|
|
circuit.barrier(qr)
|
|
|
|
expected = QuantumCircuit(qr)
|
|
expected.barrier(qr)
|
|
expected.h(qr[0])
|
|
expected.barrier(qr)
|
|
|
|
pass_ = MergeAdjacentBarriers()
|
|
result = pass_.run(circuit_to_dag(circuit))
|
|
|
|
self.assertEqual(result, circuit_to_dag(expected))
|
|
|
|
def test_barriers_with_blocking_obstacle_twoQ(self):
|
|
"""Test that barriers don't merge if there is an obstacle that
|
|
is blocking
|
|
|
|
░ ░ ░ ░
|
|
q_0: |0>─░───────░─ q_0: |0>─░───────░─
|
|
░ ░ ░ ░
|
|
q_1: |0>─░───■───── -> q_1: |0>─░───■─────
|
|
░ ┌─┴─┐ ░ ░ ┌─┴─┐ ░
|
|
q_2: |0>───┤ X ├─░─ q_2: |0>───┤ X ├─░─
|
|
└───┘ ░ └───┘ ░
|
|
|
|
"""
|
|
qr = QuantumRegister(3, "q")
|
|
|
|
circuit = QuantumCircuit(qr)
|
|
circuit.barrier(0, 1)
|
|
circuit.cx(1, 2)
|
|
circuit.barrier(0, 2)
|
|
|
|
expected = QuantumCircuit(qr)
|
|
expected.barrier(0, 1)
|
|
expected.cx(1, 2)
|
|
expected.barrier(0, 2)
|
|
|
|
pass_ = MergeAdjacentBarriers()
|
|
result = pass_.run(circuit_to_dag(circuit))
|
|
|
|
self.assertEqual(result, circuit_to_dag(expected))
|
|
|
|
def test_output_deterministic(self):
|
|
"""Test that the output barriers have a deterministic ordering (independent of
|
|
PYTHONHASHSEED). This is important to guarantee that any subsequent topological iterations
|
|
through the circuit are also deterministic; it's in general not possible for all transpiler
|
|
passes to produce identical outputs across all valid topological orderings, especially if
|
|
those passes have some stochastic element."""
|
|
order = list(range(20))
|
|
random.Random(2023_02_10).shuffle(order)
|
|
circuit = QuantumCircuit(20)
|
|
circuit.barrier([5, 2, 3])
|
|
circuit.barrier([7, 11, 14, 2, 4])
|
|
circuit.barrier(order)
|
|
|
|
# All the barriers should get merged together.
|
|
expected = QuantumCircuit(20)
|
|
expected.barrier(range(20))
|
|
|
|
output = MergeAdjacentBarriers()(circuit)
|
|
self.assertEqual(expected, output)
|
|
# This assertion is that the ordering of the arguments in the barrier is fixed.
|
|
self.assertEqual(list(output.data[0].qubits), list(output.qubits))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|