Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GatesInBasis analysis pass #6832

Merged
merged 12 commits into from
Oct 13, 2021
2 changes: 2 additions & 0 deletions qiskit/transpiler/passes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
RemoveFinalMeasurements
DAGFixedPoint
FixedPoint
GatesInBasis
"""

# layout selection (placement)
Expand Down Expand Up @@ -210,3 +211,4 @@
from .utils import FixedPoint
from .utils import Error
from .utils import RemoveBarriers
from .utils import GatesInBasis
1 change: 1 addition & 0 deletions qiskit/transpiler/passes/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@
from .fixed_point import FixedPoint
from .error import Error
from .remove_barriers import RemoveBarriers
from .gates_basis import GatesInBasis
39 changes: 39 additions & 0 deletions qiskit/transpiler/passes/utils/gates_basis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2017, 2018.
#
# 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.

"""Check if a property reached a fixed point."""
mtreinish marked this conversation as resolved.
Show resolved Hide resolved

from qiskit.transpiler.basepasses import AnalysisPass


class GatesInBasis(AnalysisPass):
"""Check if a a dag is all in the basis"""
mtreinish marked this conversation as resolved.
Show resolved Hide resolved

def __init__(self, basis_gates):
"""FixedPoint initializer.
mtreinish marked this conversation as resolved.
Show resolved Hide resolved

Args:
basis_gates (list): The list of basis gate names to check
mtreinish marked this conversation as resolved.
Show resolved Hide resolved
"""
super().__init__()
self._basis_gates = set(basis_gates)

def run(self, dag):
"""Run the GatesInBasis pass on `dag`."""
gates_out_of_basis = False
gates = set(x.op.name for x in dag.gate_nodes())
for gate in gates:
if gate not in self._basis_gates:
gates_out_of_basis = True
break
mtreinish marked this conversation as resolved.
Show resolved Hide resolved

self.property_set["all_gates_in_basis"] = not gates_out_of_basis
27 changes: 27 additions & 0 deletions releasenotes/notes/gates-in-basis-pass-337f6637e61919db.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
features:
- |
A new analysis transpiler pass,
:class:`~qiskit.transpiler.passes.GatesInBasis`, was added to
:mod:`qiskit.transpiler.passes`. This pass is used to check if the
:class:`~qiskit.dagcircuit.DAGCircuit` being transpiled has all the gates
in the configured basis set or not. It will set the attribute
``"all_gates_in_basis"`` in the property set to ``True`` if all the gates
in the :class:`~qiskit.dagcircuit.DAGCircuit` are in the configured basis
set or ``False`` if they are not. For example::

from qiskit.circuit import QuantumCircuit
from qiskit.transpiler.passes import GatesInBasis

# Instatiate Pass
basis_gates = ["cx", "h"]
basis_check_pass = GatesInBasis(basis_gates)
# Build circuit
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
# Run pass on circuit
property_set = {}
basis_check_pass(circuit, property_set=property_set)
assert property_set["all_gates_in_basis"]
90 changes: 90 additions & 0 deletions test/python/transpiler/test_gates_in_basis_pass.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2021
#
# 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 GatesInBasis pass."""

from qiskit.circuit import QuantumCircuit
from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary
from qiskit.transpiler import PassManager
from qiskit.transpiler.passes import BasisTranslator
from qiskit.transpiler.passes import GatesInBasis
from qiskit.test import QiskitTestCase


class TestGatesInBasisPass(QiskitTestCase):
"""Tests for GatesInBasis pass."""

def test_all_gates_in_basis(self):
"""Test circuit with all gates in basis."""
basis_gates = ["cx", "h"]
property_set = {}
analysis_pass = GatesInBasis(basis_gates)
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
analysis_pass(circuit, property_set=property_set)
self.assertTrue(property_set["all_gates_in_basis"])

def test_all_gates_not_in_basis(self):
"""Test circuit with not all gates in basis."""
basis_gates = ["cx", "u"]
property_set = {}
analysis_pass = GatesInBasis(basis_gates)
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
analysis_pass(circuit, property_set=property_set)
self.assertFalse(property_set["all_gates_in_basis"])

def test_all_gates_in_basis_empty_circuit(self):
"""Test circuit with no gates."""
basis_gates = ["cx", "u"]
property_set = {}
analysis_pass = GatesInBasis(basis_gates)
circuit = QuantumCircuit(2)
analysis_pass(circuit, property_set=property_set)
self.assertTrue(property_set["all_gates_in_basis"])

def test_all_gates_in_basis_empty_basis(self):
"""Test circuit with gates and empty basis."""
basis_gates = []
property_set = {}
analysis_pass = GatesInBasis(basis_gates)
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
analysis_pass(circuit, property_set=property_set)
self.assertFalse(property_set["all_gates_in_basis"])

def test_all_gates_in_basis_after_translation(self):
"""Test circuit with gates in basis after conditional translation."""
basis_gates = ["cx", "u"]
property_set = {}
analysis_pass = GatesInBasis(basis_gates)
circuit = QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
analysis_pass(circuit, property_set=property_set)
self.assertFalse(property_set["all_gates_in_basis"])
pm = PassManager()
pm.append(analysis_pass)
pm.append(
BasisTranslator(SessionEquivalenceLibrary, basis_gates),
condition=lambda property_set: not property_set["all_gates_in_basis"],
)
pm.append(analysis_pass)
pm.run(circuit)
self.assertTrue(pm.property_set["all_gates_in_basis"])