Skip to content

Commit

Permalink
Adding pass to turn arbitrary circuit into Clifford circuit (#1887)
Browse files Browse the repository at this point in the history
Co-authored-by: joshuasn <53916441+joshuasn@users.noreply.github.com>
  • Loading branch information
SamFerracin and joshuasn authored Sep 5, 2024
1 parent a41738a commit e9f8524
Show file tree
Hide file tree
Showing 6 changed files with 199 additions and 1 deletion.
5 changes: 4 additions & 1 deletion qiskit_ibm_runtime/transpiler/passes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@
.. currentmodule:: qiskit_ibm_runtime.transpiler.passes
A collection of transpiler passes for IBM backends. Refer to
A collection of transpiler passes. Refer to
https://docs.quantum.ibm.com/guides/transpile to learn more about
transpilation and passes.
.. autosummary::
:toctree: ../stubs/
ConvertIdToDelay
ConvertISAToClifford
See :mod:`qiskit_ibm_runtime.transpiler.passes.scheduling` for a collection of scheduling passes.
"""
Expand All @@ -35,3 +36,5 @@
from .scheduling import ASAPScheduleAnalysis
from .scheduling import PadDynamicalDecoupling
from .scheduling import PadDelay

from .cliffordization import ConvertISAToClifford
15 changes: 15 additions & 0 deletions qiskit_ibm_runtime/transpiler/passes/cliffordization/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2022.
#
# 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.

"""Passes to transform a circuit into a Clifford circuit."""

from .convert_isa_to_clifford import ConvertISAToClifford
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2022.
#
# 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.

"""
Pass to convert the gates of an ISA circuit to Clifford gates.
"""

from random import choices
import numpy as np

from qiskit.circuit import Barrier, Measure
from qiskit.circuit.library import CXGate, CZGate, ECRGate, IGate, RZGate, SXGate, XGate
from qiskit.dagcircuit import DAGCircuit
from qiskit.transpiler.basepasses import TransformationPass

SUPPORTED_INSTRUCTIONS = (CXGate, CZGate, ECRGate, IGate, RZGate, SXGate, XGate, Barrier, Measure)
"""The set of instructions supported by the :class:`~.ConvertISAToClifford` pass."""


class ConvertISAToClifford(TransformationPass):
"""
Convert the gates of an ISA circuit to Clifford gates.
ISA circuits only contain Clifford gates from a restricted set or
:class:`qiskit.circuit.library.RZGate`\\s by arbitrary angles. To convert them to Clifford
circuits, this pass rounds the angle of every :class:`qiskit.circuit.library.RZGate` to the
closest multiple of `pi/2` (or to a random multiple of `pi/2` if the angle is unspecified),
while it skips every Clifford gate, measurement, and barrier.
.. code-block:: python
import numpy as np
from qiskit.circuit import QuantumCircuit, Parameter
from qiskit.transpiler import PassManager
from qiskit_ibm_runtime.transpiler.passes import ConvertISAToClifford
# An ISA circuit ending with a Z rotation by pi/3
qc = QuantumCircuit(2, 2)
qc.sx(0)
qc.rz(np.pi/2, 0)
qc.sx(0)
qc.barrier()
qc.cx(0, 1)
qc.rz(np.pi/3, 0) # non-Clifford Z rotation
qc.rz(Parameter("th"), 0) # Z rotation with unspecified angle
# Turn into a Clifford circuit
pm = PassManager([ConvertISAToClifford()])
clifford_qc = pm.run(qc)
Raises:
ValueError: If the given circuit contains unsupported operations, such as non-ISA gates.
"""

def run(self, dag: DAGCircuit) -> DAGCircuit:
for node in dag.op_nodes():
if not isinstance(node.op, SUPPORTED_INSTRUCTIONS):
raise ValueError(f"Operation ``{node.op.name}`` not supported.")

# Round the angle of `RZ`s to a multiple of pi/2 and skip the other instructions.
if isinstance(node.op, RZGate):
if isinstance(angle := node.op.params[0], float):
rem = angle % (np.pi / 2)
new_angle = angle - rem if rem < np.pi / 4 else angle + np.pi / 2 - rem
else:
# special handling of parametric gates
new_angle = choices([0, np.pi / 2, np.pi, 3 * np.pi / 2])[0]
dag.substitute_node(node, RZGate(new_angle), inplace=True)

return dag
1 change: 1 addition & 0 deletions release-notes/unreleased/1887.feat.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added ``ConvertISAToClifford`` transpilation pass to convert the gates of a circuit to Clifford gates.
11 changes: 11 additions & 0 deletions test/unit/transpiler/passes/cliffordization/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2024.
#
# 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.
87 changes: 87 additions & 0 deletions test/unit/transpiler/passes/cliffordization/test_to_clifford.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2024.
#
# 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 cliffordization pass."""

import numpy as np

from qiskit.circuit import QuantumCircuit
from qiskit.transpiler.passmanager import PassManager

from qiskit_ibm_runtime.transpiler.passes import ConvertISAToClifford

from .....ibm_test_case import IBMTestCase


class TestConvertISAToClifford(IBMTestCase):
"""Tests the ConvertISAToClifford pass."""

def test_clifford_isa_circuit(self):
"""Test the pass on a Clifford circuit with ISA gates."""
qc = QuantumCircuit(2, 2)
qc.id(0)
qc.sx(0)
qc.barrier()
qc.measure(0, 1)
qc.rz(0, 0)
qc.rz(np.pi / 2, 0)
qc.rz(np.pi, 0)
qc.rz(3 * np.pi / 2, 0)
qc.cx(0, 1)
qc.cz(0, 1)
qc.ecr(0, 1)

pm = PassManager([ConvertISAToClifford()])
transformed = pm.run(qc)

self.assertEqual(qc, transformed)

def test_error_clifford_non_isa_circuit(self):
"""Test that the pass errors when run on a Clifford circuit with non-ISA gates."""
qc = QuantumCircuit(2)
qc.id(0)
qc.sx(0)
qc.s(1)
qc.h(1)
qc.cx(0, 1)
qc.cz(0, 1)
qc.ecr(0, 1)

pm = PassManager([ConvertISAToClifford()])
with self.assertRaises(ValueError):
pm.run(qc)

def test_error_non_clifford_isa_circuit(self):
"""Test that the pass errors when run on a non-Clifford circuit with ISA gates."""
qc = QuantumCircuit(2)
qc.id(0)
qc.sx(0)
qc.rx(np.pi / 2 - 0.1, 0)
qc.cx(0, 1)
qc.cz(0, 1)
qc.ecr(0, 1)

pm = PassManager([ConvertISAToClifford()])
with self.assertRaises(ValueError):
pm.run(qc)

def test_error_reset(self):
"""Test that the pass errors when run on circuits with resets."""
qc = QuantumCircuit(2)
qc.x(1)
qc.barrier(0)
qc.reset(1)
qc.rx(np.pi / 2 - 0.1, 1)

pm = PassManager([ConvertISAToClifford()])
with self.assertRaises(ValueError):
pm.run(qc)

0 comments on commit e9f8524

Please sign in to comment.