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.