# Simulation files for noisy quantum circuits

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:

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.

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

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"

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()


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.