Source code for mitiq.benchmarks.mirror_qv_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 to create a Mirror Quantum Volume Benchmarking circuit
as defined in https://arxiv.org/abs/2303.02108."""
from typing import Optional, cast
import cirq
from mitiq import QPROGRAM
from mitiq.benchmarks.quantum_volume_circuits import (
generate_quantum_volume_circuit,
)
from mitiq.interface.conversions import convert_from_mitiq
[docs]
def generate_mirror_qv_circuit(
num_qubits: int,
depth: int,
decompose: bool = False,
seed: Optional[int] = None,
return_type: Optional[str] = None,
) -> QPROGRAM:
"""Generate a mirror quantum volume circuit with the given number of qubits
and depth as defined in :cite:`Amico_2023_arxiv`.
The generated circuit consists of a quantum volume circuit up to `depth/2`
layers followed by an inverse of the quantum volume portion up to `depth/2`
when `depth` is an even number.
When `depth` is odd, the layers will be changed to `depth+1`.
The ideal output bit-string is a string of zeroes.
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.
"""
if depth <= 0:
raise ValueError(
"{} is invalid for the generated circuit depth.", depth
)
if depth % 2 == 0:
first_half_depth = int(depth / 2)
else:
first_half_depth = int((depth + 1) / 2)
qv_circuit, _ = generate_quantum_volume_circuit(
num_qubits, first_half_depth, seed=seed, decompose=decompose
)
qv_circuit = cast(cirq.Circuit, qv_circuit)
mirror_qv_circuit = qv_circuit + cirq.inverse(qv_circuit)
if decompose:
# Decompose random unitary gates into simpler gates.
mirror_qv_circuit = cirq.Circuit(cirq.decompose(mirror_qv_circuit))
return_type = "cirq" if not return_type else return_type
return convert_from_mitiq(mirror_qv_circuit, return_type)