Skip to content
This repository has been archived by the owner on Jun 12, 2023. It is now read-only.

[WIP] Generate json files for tests (which used pickled data) #398

Closed
wants to merge 14 commits into from
Closed
193 changes: 193 additions & 0 deletions test/measurement_calibration/generate_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# -*- coding: utf-8 -*-

# This code is part of Qiskit.
#
# (C) Copyright IBM 2019, 2020.
#
# 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.
"""
Generate data for measurement calibration fitter tests
"""

import os
import json
from test.utils import convert_ndarray_to_list_in_data
import qiskit
from qiskit.ignis.mitigation.measurement import (CompleteMeasFitter, TensoredMeasFitter,
complete_meas_cal, tensored_meas_cal,
MeasurementFilter)
from qiskit.providers.aer.noise import NoiseModel
from qiskit.providers.aer.noise.errors.standard_errors import pauli_error

# fixed seed for simulations
SEED = 42


def meas_calibration_circ_execution(nqunits: int, shots: int, seed: int):
"""
create measurement calibration circuits and simulates them with noise
Args:
nqunits (int): number of qubits to run the measurement calibration on
shots (int): number of shots per simulation
seed (int): the seed to use in the simulations

Returns:
list: list of Results of the measurement calibration simulations
list: list of all the possible states with this amount of qubits
dict: dictionary of results counts of bell circuit simulation with measurement errors
"""
# define the circuits
qr = qiskit.QuantumRegister(nqunits)
meas_calibs, state_labels = complete_meas_cal(qr=qr, circlabel='test')
# define noise
prob = 0.2
error_meas = pauli_error([('X', prob), ('I', 1 - prob)])
noise_model = NoiseModel()
noise_model.add_all_qubit_quantum_error(error_meas, "measure")

# run the circuits multiple times
backend = qiskit.Aer.get_backend('qasm_simulator')
cal_results = qiskit.execute(meas_calibs, backend=backend, shots=shots, noise_model=noise_model,
seed_simulator=seed).result()

# create bell state and get it's results
qc = qiskit.QuantumCircuit(nqunits, nqunits)
qc.h(0)
qc.cx(0, 1)
qc.cx(0, 2)
qc.measure(qc.qregs[0], qc.cregs[0])

bell_results = qiskit.execute(qc, backend=backend, shots=shots, noise_model=noise_model,
seed_simulator=seed).result().get_counts()

return cal_results, state_labels, bell_results


def tensored_calib_circ_execution(shots: int, seed: int):
"""
create tensored measurement calibration circuits and simulates them with noise
Args:
shots (int): number of shots per simulation
seed (int): the seed to use in the simulations

Returns:
list: list of Results of the measurement calibration simulations
list: the mitigation pattern
dict: dictionary of results counts of bell circuit simulation with measurement errors
"""
# define the circuits
qr = qiskit.QuantumRegister(5)
mit_pattern = [[2], [4, 1]]
meas_calibs, mit_pattern = tensored_meas_cal(mit_pattern=mit_pattern, qr=qr, circlabel='test')
# define noise
prob = 0.2
error_meas = pauli_error([('X', prob), ('I', 1 - prob)])
noise_model = NoiseModel()
noise_model.add_all_qubit_quantum_error(error_meas, "measure")

# run the circuits multiple times
backend = qiskit.Aer.get_backend('qasm_simulator')
cal_results = qiskit.execute(meas_calibs, backend=backend, shots=shots, noise_model=noise_model,
seed_simulator=seed).result()

# create bell state and get it's results
cr = qiskit.ClassicalRegister(3)
qc = qiskit.QuantumCircuit(qr, cr)
qc.h(qr[2])
qc.cx(qr[2], qr[4])
qc.cx(qr[2], qr[1])
qc.measure(qr[2], cr[0])
qc.measure(qr[4], cr[1])
qc.measure(qr[1], cr[2])

bell_results = qiskit.execute(qc, backend=backend, shots=shots, noise_model=noise_model,
seed_simulator=seed).result()

return cal_results, mit_pattern, bell_results


def generate_meas_calibration(results_file_path: str, runs: int):
"""
run the measurement calibration circuits, calculates the fitter matrix in few methods
and saves the results
The simulation results files will contain a list of dictionaries with the keys:
cal_matrix - the matrix used to calculate the ideal measurement
fidelity - the calculated fidelity of using this matrix
results - results of a bell state circuit with noise
results_pseudo_inverse - the result of using the psedo-inverse method on the bell state
results_least_square - the result of using the least-squares method on the bell state

Args:
results_file_path: path of the json file of the results file
runs: the number of different runs to save
"""
results = []
for run in range(runs):
cal_results, state_labels, circuit_results = \
meas_calibration_circ_execution(3, 1000, SEED + run)

meas_cal = CompleteMeasFitter(cal_results, state_labels, circlabel='test')
meas_filter = MeasurementFilter(meas_cal.cal_matrix, state_labels)

# Calculate the results after mitigation
results_pseudo_inverse = meas_filter.apply(
circuit_results, method='pseudo_inverse')
results_least_square = meas_filter.apply(
circuit_results, method='least_squares')
results.append({"cal_matrix": convert_ndarray_to_list_in_data(meas_cal.cal_matrix),
"fidelity": meas_cal.readout_fidelity(),
"results": circuit_results,
"results_pseudo_inverse": results_pseudo_inverse,
"results_least_square": results_least_square})

with open(results_file_path, "w") as results_file:
json.dump(results, results_file)


def generate_tensormeas_calibration(results_file_path: str):
"""
run the tensored measurement calibration circuits, calculates the fitter in few methods
and saves the results
The simulation results files will contain a list of dictionaries with the keys:
cal_results - the results of the measurement calibration circuit
results - results of a bell state circuit with noise
mit_pattern - the mitigation pattern
fidelity - the calculated fidelity of using this matrix
results_pseudo_inverse - the result of using the psedo-inverse method on the bell state
results_least_square - the result of using the least-squares method on the bell state

Args:
results_file_path: path of the json file of the results file
"""
cal_results, mit_pattern, circuit_results = \
tensored_calib_circ_execution(1000, SEED)

meas_cal = TensoredMeasFitter(cal_results, mit_pattern=mit_pattern)
meas_filter = meas_cal.filter

# Calculate the results after mitigation
results_pseudo_inverse = meas_filter.apply(
circuit_results.get_counts(), method='pseudo_inverse')
results_least_square = meas_filter.apply(
circuit_results.get_counts(), method='least_squares')
results = {"cal_results": cal_results.to_dict(),
"results": circuit_results.to_dict(),
"mit_pattern": mit_pattern,
"fidelity": meas_cal.readout_fidelity(),
"results_pseudo_inverse": results_pseudo_inverse,
"results_least_square": results_least_square}

with open(results_file_path, "w") as results_file:
json.dump(results, results_file)


if __name__ == '__main__':
DIRNAME = os.path.dirname(os.path.abspath(__file__))
generate_meas_calibration(os.path.join(DIRNAME, 'test_meas_results.json'), 3)
generate_tensormeas_calibration(os.path.join(DIRNAME, 'test_tensored_meas_results.json'))
98 changes: 98 additions & 0 deletions test/quantum_volume/generate_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-

# This code is part of Qiskit.
#
# (C) Copyright IBM 2019, 2020.
#
# 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.
"""
Generate data for quantum volume fitter tests
"""

import os
from test.utils import save_results_as_json
import qiskit
import qiskit.ignis.verification.quantum_volume as qv
from qiskit.providers.aer.noise import NoiseModel
from qiskit.providers.aer.noise.errors.standard_errors import depolarizing_error

# fixed seed for simulations
SEED = 42


def qv_circuit_execution(qubit_lists: list, ntrials: int, shots: int):
"""
create quantum volume circuits, simulates the ideal state and run a noisy simulation
Args:
qubit_lists (list): list of lists of qubits to apply qv circuits to
ntrials (int): number of iterations
shots (int): number of shots per simulation

Returns:
tuple: a tuple of 2 lists:
list of Results of the ideal statevector simulations
list of Results of the noisy circuits simulations

"""
# create the qv circuit
qv_circs, qv_circs_nomeas = qv.qv_circuits(qubit_lists, ntrials)
# get the ideal state
statevector_backend = qiskit.Aer.get_backend('statevector_simulator')
ideal_results = []
for trial in range(ntrials):
ideal_results.append(qiskit.execute(qv_circs_nomeas[trial],
backend=statevector_backend).result())

# define noise_model
noise_model = NoiseModel()
p1q = 0.002
p2q = 0.02
noise_model.add_all_qubit_quantum_error(depolarizing_error(p1q, 1), 'u2')
noise_model.add_all_qubit_quantum_error(depolarizing_error(2 * p1q, 1), 'u3')
noise_model.add_all_qubit_quantum_error(depolarizing_error(p2q, 2), 'cx')

# get the noisy results
backend = qiskit.Aer.get_backend('qasm_simulator')
basis_gates = ['u1', 'u2', 'u3', 'cx'] # use U,CX for now
exp_results = []
for trial in range(ntrials):
print('Running trial %d' % trial)
exp_results.append(
qiskit.execute(qv_circs[trial], basis_gates=basis_gates, backend=backend,
noise_model=noise_model, shots=shots,
seed_simulator=SEED,
backend_options={'max_parallel_experiments': 0}).result())

return ideal_results, exp_results


def generate_qv_fitter_data(ideal_results_file_path: str, exp_results_file_path: str):
"""
run the quantum volume circuits and saves the results
The simulation results files will contain a list of Result objects in a dictionary format.

Args:
ideal_results_file_path: path of the json file of the ideal simulation results file
exp_results_file_path: path of the json file of the noisy simulation results file
"""
# parameters
qubit_lists = [[0, 1, 3], [0, 1, 3, 5], [0, 1, 3, 5, 7],
[0, 1, 3, 5, 7, 10]]
ntrials = 5
# execute the circuit
ideal_results, exp_results = qv_circuit_execution(qubit_lists, ntrials, shots=1024)
# save the results
save_results_as_json(ideal_results, ideal_results_file_path)
save_results_as_json(exp_results, exp_results_file_path)


if __name__ == '__main__':
DIRNAME = os.path.dirname(os.path.abspath(__file__))
generate_qv_fitter_data(os.path.join(DIRNAME, 'qv_ideal_results.json'),
os.path.join(DIRNAME, 'qv_exp_results.json'))
Loading