Source code for qiskit.circuit.random.utils

# -*- coding: utf-8 -*-

# This code is part of Qiskit.
#
# (C) Copyright IBM 2017.
#
# 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.

"""Utility functions for generating random circuits."""

import numpy as np

from qiskit.circuit import QuantumRegister, ClassicalRegister, QuantumCircuit
from qiskit.circuit import Reset
from qiskit.circuit.library.standard_gates import (IGate, U1Gate, U2Gate, U3Gate, XGate,
                                                   YGate, ZGate, HGate, SGate, SdgGate, TGate,
                                                   TdgGate, RXGate, RYGate, RZGate, CXGate,
                                                   CYGate, CZGate, CHGate, CRZGate, CU1Gate,
                                                   CU3Gate, SwapGate, RZZGate,
                                                   CCXGate, CSwapGate)
from qiskit.circuit.exceptions import CircuitError
from qiskit.util import deprecate_arguments


[docs]@deprecate_arguments({'n_qubits': 'num_qubits'}) def random_circuit(num_qubits, depth, max_operands=3, measure=False, conditional=False, reset=False, seed=None, *, n_qubits=None): # pylint:disable=unused-argument """Generate random circuit of arbitrary size and form. This function will generate a random circuit by randomly selecting gates from the set of standard gates in :mod:`qiskit.extensions`. For example: .. jupyter-execute:: from qiskit.circuit.random import random_circuit circ = random_circuit(2, 2, measure=True) circ.draw(output='mpl') Args: num_qubits (int): number of quantum wires depth (int): layers of operations (i.e. critical path length) max_operands (int): maximum operands of each gate (between 1 and 3) measure (bool): if True, measure all qubits at the end conditional (bool): if True, insert middle measurements and conditionals reset (bool): if True, insert middle resets seed (int): sets random seed (optional) n_qubits (int): deprecated, use num_qubits instead Returns: QuantumCircuit: constructed circuit Raises: CircuitError: when invalid options given """ if max_operands < 1 or max_operands > 3: raise CircuitError("max_operands must be between 1 and 3") one_q_ops = [IGate, U1Gate, U2Gate, U3Gate, XGate, YGate, ZGate, HGate, SGate, SdgGate, TGate, TdgGate, RXGate, RYGate, RZGate] one_param = [U1Gate, RXGate, RYGate, RZGate, RZZGate, CU1Gate, CRZGate] two_param = [U2Gate] three_param = [U3Gate, CU3Gate] two_q_ops = [CXGate, CYGate, CZGate, CHGate, CRZGate, CU1Gate, CU3Gate, SwapGate, RZZGate] three_q_ops = [CCXGate, CSwapGate] qr = QuantumRegister(num_qubits, 'q') qc = QuantumCircuit(num_qubits) if measure or conditional: cr = ClassicalRegister(num_qubits, 'c') qc.add_register(cr) if reset: one_q_ops += [Reset] if seed is None: seed = np.random.randint(0, np.iinfo(np.int32).max) rng = np.random.default_rng(seed) # apply arbitrary random operations at every depth for _ in range(depth): # choose either 1, 2, or 3 qubits for the operation remaining_qubits = list(range(num_qubits)) while remaining_qubits: max_possible_operands = min(len(remaining_qubits), max_operands) num_operands = rng.choice(range(max_possible_operands)) + 1 rng.shuffle(remaining_qubits) operands = remaining_qubits[:num_operands] remaining_qubits = [q for q in remaining_qubits if q not in operands] if num_operands == 1: operation = rng.choice(one_q_ops) elif num_operands == 2: operation = rng.choice(two_q_ops) elif num_operands == 3: operation = rng.choice(three_q_ops) if operation in one_param: num_angles = 1 elif operation in two_param: num_angles = 2 elif operation in three_param: num_angles = 3 else: num_angles = 0 angles = [rng.uniform(0, 2 * np.pi) for x in range(num_angles)] register_operands = [qr[i] for i in operands] op = operation(*angles) # with some low probability, condition on classical bit values if conditional and rng.choice(range(10)) == 0: value = rng.integers(0, np.power(2, num_qubits)) op.condition = (cr, value) qc.append(op, register_operands) if measure: qc.measure(qr, cr) return qc