Source code for qiskit_experiments.library.randomized_benchmarking.clifford_synthesis

# This code is part of Qiskit.
#
# (C) Copyright IBM 2023.
#
# 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.
"""
Clifford synthesis plugins for randomized benchmarking
"""
from __future__ import annotations

from typing import Sequence

from qiskit.circuit import QuantumCircuit, Operation
from qiskit.circuit.equivalence_library import SessionEquivalenceLibrary as sel
from qiskit.exceptions import QiskitError
from qiskit.passmanager.flow_controllers import ConditionalController
from qiskit.synthesis.clifford import synth_clifford_full
from qiskit.transpiler import PassManager, CouplingMap, Layout, Target
from qiskit.transpiler.passes import (
    SabreSwap,
    LayoutTransformation,
    BasisTranslator,
    CheckGateDirection,
    GateDirection,
    Optimize1qGatesDecomposition,
)
from qiskit.transpiler.passes.synthesis.plugin import HighLevelSynthesisPlugin


[docs] class RBDefaultCliffordSynthesis(HighLevelSynthesisPlugin): """Default Clifford synthesis plugin for randomized benchmarking."""
[docs] def run( self, high_level_object: Operation, coupling_map: CouplingMap | None = None, target: Target | None = None, qubits: Sequence | None = None, **options, ) -> QuantumCircuit: """Run synthesis for the given Clifford. Args: high_level_object: The operation to synthesize to a :class:`~qiskit.circuit.QuantumCircuit` object. coupling_map: The reduced coupling map of the backend. For example, if physical qubits [5, 6, 7] to be benchmarked is connected as 5 - 7 - 6 linearly, the reduced coupling map is 0 - 2 - 1. target: A target representing the target backend, which will be ignored in this plugin. qubits: List of physical qubits over which the operation is defined, which will be ignored in this plugin. options: Additional method-specific optional kwargs, which must include ``basis_gates``, basis gates to be used for the synthesis. Returns: The quantum circuit representation of the Operation when successful, and ``None`` otherwise. Raises: QiskitError: If basis_gates is not supplied. """ # synthesize cliffords circ = synth_clifford_full(high_level_object) # post processing to comply with basis gates and coupling map if coupling_map is None: # Sabre does not work with coupling_map=None return circ basis_gates = options.get("basis_gates", None) if basis_gates is None: raise QiskitError("basis_gates are required to run this synthesis plugin") basis_gates = list(basis_gates) # Run Sabre routing and undo the layout change # assuming Sabre routing does not change the initial layout. # And then decompose swap gates, fix 2q-gate direction and optimize 1q gates initial_layout = Layout.generate_trivial_layout(*circ.qubits) undo_layout_change = LayoutTransformation( coupling_map=coupling_map, from_layout="final_layout", to_layout=initial_layout ) def _direction_condition(property_set): return not property_set["is_direction_mapped"] pm = PassManager( [ SabreSwap(coupling_map), undo_layout_change, BasisTranslator(sel, basis_gates), CheckGateDirection(coupling_map), ConditionalController(GateDirection(coupling_map), condition=_direction_condition), Optimize1qGatesDecomposition(basis=basis_gates), ] ) return pm.run(circ)