Source code for mitiq.benchmarks.randomized_benchmarking

# Copyright (C) 2020 Unitary Fund
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

"""Functions for generating randomized benchmarking circuits."""
from typing import List, Optional, cast

import numpy as np

from cirq.experiments.qubit_characterizations import (
    _single_qubit_cliffords,
    _random_single_q_clifford,
    _random_two_q_clifford,
    _gate_seq_to_mats,
    _two_qubit_clifford_matrices,
)
from cirq import LineQubit
from mitiq import QPROGRAM
from mitiq.interface import convert_from_mitiq


[docs]def generate_rb_circuits( n_qubits: int, num_cliffords: int, trials: int = 1, return_type: Optional[str] = None, ) -> List[QPROGRAM]: """Returns a list of randomized benchmarking circuits, i.e. circuits that are equivalent to the identity. Args: n_qubits: The number of qubits. Can be either 1 or 2. num_cliffords: The number of Clifford group elements in the random circuits. This is proportional to the depth per circuit. trials: The number of random circuits at each num_cfd. return_type: String which specifies the type of the returned circuits. See the keys of ``mitiq.SUPPORTED_PROGRAM_TYPES`` for options. If ``None``, the returned circuits have type ``cirq.Circuit``. Returns: A list of randomized benchmarking circuits. """ if n_qubits not in (1, 2): raise ValueError( "Only generates RB circuits on one or two " f"qubits not {n_qubits}." ) qubits = LineQubit.range(n_qubits) cliffords = _single_qubit_cliffords() if n_qubits == 1: c1 = cliffords.c1_in_xy cfd_mat_1q = cast( np.ndarray, [_gate_seq_to_mats(gates) for gates in c1] ) circuits = [ _random_single_q_clifford(qubits[0], num_cliffords, c1, cfd_mat_1q) for _ in range(trials) ] else: cfd_matrices = _two_qubit_clifford_matrices( qubits[0], qubits[1], cliffords, ) circuits = [ _random_two_q_clifford( qubits[0], qubits[1], num_cliffords, cfd_matrices, cliffords, ) for _ in range(trials) ] return_type = "cirq" if not return_type else return_type return [convert_from_mitiq(circuit, return_type) for circuit in circuits]