Source code for mitiq.benchmarks.rotated_randomized_benchmarking

# Copyright (C) Unitary Fund
#
# This source code is licensed under the GPL license (v3) found in the
# LICENSE file in the root directory of this source tree.

"""Functions for generating rotated randomized benchmarking circuits."""

from typing import List, Optional, cast

import cirq
import numpy as np

from mitiq import QPROGRAM
from mitiq.benchmarks import generate_rb_circuits
from mitiq.interface import convert_from_mitiq


[docs] def generate_rotated_rb_circuits( n_qubits: int, num_cliffords: int, theta: Optional[float] = None, trials: int = 1, return_type: Optional[str] = None, seed: Optional[int] = None, ) -> List[QPROGRAM]: r""" Generates a list of "rotated" randomized benchmarking circuits. This benchmarking method enables testing QEM techniques in more general scenarios, closer to real-world applications in which expectation values can take arbitrary values. Rotated randomized bencmarking circuits are randomized benchmarking circuits with an :math:`R_z(\theta)` rotation inserted in the middle, such that: .. math:: C(\theta) = G_n \dots G_{n/2 +1} R_z(\theta)G_{n/2} \dots G_2 G_1 where :math:`G_j` are Clifford elements or Clifford gates. For most values of the seed, the probability of the zero state is a sinusoidal function of :math:`\theta`. For some values of the seed the probability of the zero state is 1 for all :math:`\theta`. Since (up to factors of 2) we have :math:`R_z(\theta) =cos(\theta) I + i \ sin(\theta) Z`, the rotated Clifford circuit :math:`C(\theta)` can be written as a linear combination of just two Clifford circuits, and therefore it is still easy to classically simulate. 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. theta: The rotation angle about the :math:`Z` axis. trials: The number of random circuits to return. 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``. seed: A seed for generating radomzed benchmarking circuits. Returns: A list of rotated randomized benchmarking circuits. """ circuits = cast( List[cirq.Circuit], generate_rb_circuits(n_qubits, num_cliffords, trials, seed=seed), ) if theta is None: theta = 2 * np.pi * np.random.rand() for circ in circuits: qubits = list(circ.all_qubits()) circ.insert(len(circ) // 2, cirq.Rz(rads=theta).on(qubits[0])) return_type = "cirq" if not return_type else return_type return [convert_from_mitiq(circuit, return_type) for circuit in circuits]