Source code for mitiq.benchmarks.quantum_volume_circuits

# 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 creating circuits of the form used in quantum
volume experiments as defined in

Useful overview of quantum volume experiments:

Cirq implementation of quantum volume circuits:

from typing import Optional, Sequence, Tuple

from cirq import decompose as cirq_decompose
from cirq.circuits import Circuit
from cirq.contrib.quantum_volume import (
from cirq.value import big_endian_int_to_bits
from numpy import random

from mitiq import QPROGRAM, Bitstring
from mitiq.interface import convert_from_mitiq

[docs]def generate_quantum_volume_circuit( num_qubits: int, depth: int, decompose: bool = False, seed: Optional[int] = None, return_type: Optional[str] = None, ) -> Tuple[QPROGRAM, Sequence[Bitstring]]: """Generate a quantum volume circuit with the given number of qubits and depth. The generated circuit consists of `depth` layers of random qubit permutations followed by random two-qubit gates that are sampled from the Haar measure on SU(4). Args: num_qubits: The number of qubits in the generated circuit. depth: The number of layers in the generated circuit. decompose: Recursively decomposes the randomly sampled (numerical) unitary matrix gates into simpler gates. seed: Seed for generating random circuit. 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 quantum volume circuit acting on ``num_qubits`` qubits. A list of the heavy bitstrings for the returned circuit. """ random_state = random.RandomState(seed) circuit = generate_model_circuit( num_qubits, depth, random_state=random_state ) heavy_bitstrings = compute_heavy_bitstrings(circuit, num_qubits) if decompose: # Decompose random unitary gates into simpler gates. circuit = Circuit(cirq_decompose(circuit)) return_type = "cirq" if not return_type else return_type return convert_from_mitiq(circuit, return_type), heavy_bitstrings
[docs]def compute_heavy_bitstrings( circuit: Circuit, num_qubits: int, ) -> Sequence[Bitstring]: """Classically compute the heavy bitstrings of the provided circuit. The heavy bitstrings are defined as the output bit-strings that have a greater than median probability of being generated. Args: circuit: The circuit to classically simulate. Returns: A list containing the heavy bitstrings. """ heavy_vals = compute_heavy_set(circuit) # Convert base-10 ints to Bitstrings. heavy_bitstrings = [ big_endian_int_to_bits(val, bit_count=num_qubits) for val in heavy_vals ] return heavy_bitstrings