Source code for qiskit.ignis.verification.quantum_volume.circuits

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

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

"""
Generates quantum volume circuits
"""

import numpy as np
import qiskit
from qiskit.quantum_info.random import random_unitary


[docs]def qv_circuits(qubit_lists=None, ntrials=1, qr=None, cr=None): """ Return a list of square quantum volume circuits (depth=width) The qubit_lists is specified as a list of qubit lists. For each set of qubits, circuits the depth as the number of qubits in the list are generated Args: qubit_lists (list): list of list of qubits to apply qv circuits to. Assume the list is ordered in increasing number of qubits ntrials (int): number of random iterations qr (QuantumRegister): quantum register to act on (if None one is created) cr (ClassicalRegister): classical register to measure to (if None one is created) Returns: tuple: A tuple of the type (``circuits``, ``circuits_nomeas``) wheere: ``circuits`` is a list of lists of circuits for the qv sequences (separate list for each trial) and `` circuitss_nomeas`` is the same circuits but with no measurements for the ideal simulation """ circuits = [[] for e in range(ntrials)] circuits_nomeas = [[] for e in range(ntrials)] # get the largest qubit number out of all the lists (for setting the # register) depth_list = [len(qubit_list) for qubit_list in qubit_lists] # go through for each trial for trial in range(ntrials): # go through for each depth in the depth list for depthidx, depth in enumerate(depth_list): n_q_max = np.max(qubit_lists[depthidx]) qr = qiskit.QuantumRegister(int(n_q_max+1), 'qr') qr2 = qiskit.QuantumRegister(int(depth), 'qr') cr = qiskit.ClassicalRegister(int(depth), 'cr') qc = qiskit.QuantumCircuit(qr, cr) qc2 = qiskit.QuantumCircuit(qr2, cr) qc.name = 'qv_depth_%d_trial_%d' % (depth, trial) qc2.name = qc.name # build the circuit for _ in range(depth): # Generate uniformly random permutation Pj of [0...n-1] perm = np.random.permutation(depth) # For each pair p in Pj, generate Haar random SU(4) for k in range(int(np.floor(depth/2))): unitary = random_unitary(4) pair = int(perm[2*k]), int(perm[2*k+1]) qc.append(unitary, [qr[qubit_lists[depthidx][pair[0]]], qr[qubit_lists[depthidx][pair[1]]]]) qc2.append(unitary, [qr2[pair[0]], qr2[pair[1]]]) # append an id to all the qubits in the ideal circuits # to prevent a truncation error in the statevector # simulators qc2.u1(0, qr2) circuits_nomeas[trial].append(qc2) # add measurement for qind, qubit in enumerate(qubit_lists[depthidx]): qc.measure(qr[qubit], cr[qind]) circuits[trial].append(qc) return circuits, circuits_nomeas