3
$\begingroup$

For our study with Yosi Rinott and Tomer Shoham we need the following simple data:

Starting with a quantum circuit $C$ on $n$ qubits we need two files:

a) A file of probabilities (or amplitudes) for the $2^n$ bitstrings as described by the (ideal) circuit $C$. (Namely, the probability distribution on $2^n$ bitstrings described by $C$.)

b) A file of probabilities (or amplitudes) for the $2^n$ bitstrings as described by the a noisy version of the circuit $C$. Where the noise is simply a depolarizing noise on the gates of $C$. (But other forms of noise are also welcome.)

We need such pairs of files for 12-24 qubits (say). Since our main study is that of Google 2019 experiment we have some preferences for random circuits (or even the Google experimental circuits themselves) but data from other circuits will also be welcome.

We know that this data can be obtained by several available simulators:

  1. Google's simulators
  2. the IBM simulators
  3. The NASA simulators. Given with an open-sourced code that combines tensor contraction, Clifford expansion, and state vector simulation: https://github.com/nasa/hybridq

https://arxiv.org/abs/2111.06868

Our question is if such pairs of files representing the noisy and noiseless distribution are publicly available, or could be made available for us.

$\endgroup$
2
  • $\begingroup$ By “probabilities” you mean probability distribution over the $2^n$ bitstrings? $\endgroup$
    – Ohad
    Dec 20, 2022 at 6:28
  • $\begingroup$ Yes! This is what I mean. $\endgroup$
    – Gil Kalai
    Dec 20, 2022 at 12:12

1 Answer 1

1
$\begingroup$

I if get your point correct, then the following Qiskit code would do the job. The requested "job", to my understanding, is saving probability distributions of an ideal simulation and a noisy simulation of a given quantum circuit, to a pair of files.

Imports

import json

from qiskit import Aer, transpile
from qiskit.circuit.random import random_circuit
from qiskit.providers.aer import noise
from qiskit.providers.aer.noise import NoiseModel

Defining auxiliary functions

def decimal_to_fixed_size_binary(num, length):
    """
    Transforms a decimal number to a binary number of length `length`.
    
    Args:
        num (int) - an integer to transform.
        length (int) - the desired fixed length of the returned bitstring.
        
    Returns:
        bitstring (str) - the binary string representation of `num`, of length `length`.
    """
    
    bin_num = bin(num)[2:]
    bin_len = len(bin_num)
    
    assert length >= bin_len, "`num` is too big for `length`"
    
    num_leading_zeros = length - bin_len
    bitstring = f"{'0' * num_leading_zeros}{bin_num}"
    
    return bitstring

def counts_to_p_dist(counts, shots, n=None, precision=3):
    """
    Transforms `Counts` object into a probability distribution dictionary.
    
    Args:
        counts - the `Counts` object.
        shots (int) - number of shots, i.e repeated runs of a circuit.
        n (int) - number of qubits (default=`None`).
            # If specfied, all 2^n bitstrings will be included in
            the returned dictionary, otherwise only those with more
            than 0 samples.
        precision (int) - number of digits to keep after the decimal point (default=3).
            
    Returns:
        p_dist (dict) - a dictionary of the results' probability distribution.
    
    """
    
    p_dist = {}
    
    if n is None:        
        for binary_string, value in counts.items():
            p_dist[binary_string] = round(value / shots, precision)
    else:
        for i in range(2**n):
            bitstring = decimal_to_fixed_size_binary(i, n)
            
            try:
                p_dist[bitstring] = round(counts[bitstring] / shots, precision)
            except KeyError:
                p_dist[bitstring] = 0
        
    return p_dist

Circuit construction

n = 12
depth = 5
C = random_circuit(num_qubits=n, depth=depth, measure=True)

This piece of code generates a random circuit with 12 qubits, but of course any other circuit can be defined.

Simple Depolarizing noise model construction

depolarizing_error_1 = noise.depolarizing_error(0.001, 1)
depolarizing_error_2 = noise.depolarizing_error(0.01, 2)
noise_model = NoiseModel()
noise_model.add_all_qubit_quantum_error(depolarizing_error_1, instructions=['rz', 'sx', 'x'])
noise_model.add_all_qubit_quantum_error(depolarizing_error_2, instructions=['cx'])

This defines a probabilistic error rate of 1% for $CNOT$ gates and 0.1% for single qubit gates.

Global settings

backend = Aer.get_backend('aer_simulator')
shots = 1024
exp_name = "exp_1"
ideal_data_file = f"{exp_name}__{n}_qubits__ideal_data.json"
noisy_data_file = f"{exp_name}__{n}_qubits__noisy_data.json"

Simulating results [1] - noiseless ideal simulator

job_ideal = backend.run(transpile(C, backend), shots=shots)
ideal_counts = job_ideal.result().get_counts()

Simulating results [2] - depolarizing noise model

job_noisy = backend.run(transpile(C, backend), shots=shots, noise_model=noise_model)
noisy_counts = job_noisy.result().get_counts()

Transforming counts into probability distributions

p_dist_ideal = counts_to_p_dist(counts=ideal_counts, shots=shots, n=n)
p_dist_noisy = counts_to_p_dist(counts=noisy_counts, shots=shots, n=n)

Saving the results into JSON files

with open(ideal_data_file, 'w') as write_to_file:
    json.dump(p_dist_ideal, write_to_file)
    
with open(noisy_data_file, 'w') as write_to_file:
    json.dump(p_dist_noisy, write_to_file)

Assuming Qiskit is installed, the ideal and noisy data will be saved into a pair of JSON files in a JSON format (i.e a dictionary).

If you meant something else let me know.

$\endgroup$
1
  • $\begingroup$ Great answer! Many thanks, Ohad. $\endgroup$
    – Gil Kalai
    Dec 20, 2022 at 20:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.