diff --git a/test/measurement_calibration/generate_data.py b/test/measurement_calibration/generate_data.py new file mode 100644 index 000000000..be44f540e --- /dev/null +++ b/test/measurement_calibration/generate_data.py @@ -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')) diff --git a/test/quantum_volume/generate_data.py b/test/quantum_volume/generate_data.py new file mode 100644 index 000000000..9591702a1 --- /dev/null +++ b/test/quantum_volume/generate_data.py @@ -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')) diff --git a/test/rb/generate_data.py b/test/rb/generate_data.py new file mode 100644 index 000000000..852da2b73 --- /dev/null +++ b/test/rb/generate_data.py @@ -0,0 +1,586 @@ +# -*- 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 rb fitters tests +""" + +import os +import sys +import json +from test.utils import save_results_as_json, convert_ndarray_to_list_in_data +import numpy as np +import qiskit +import qiskit.ignis.verification.randomized_benchmarking as rb +from qiskit.ignis.verification.randomized_benchmarking import \ + RBFitter, InterleavedRBFitter, PurityRBFitter, CNOTDihedralRBFitter +from qiskit.providers.aer.noise import NoiseModel +from qiskit.providers.aer.noise.errors.standard_errors import depolarizing_error,\ + thermal_relaxation_error, coherent_unitary_error + +# fixed seed for simulations +SEED = 42 + + +def rb_circuit_execution(rb_opts: dict, shots: int): + """ + Create rb circuits with depolarizing error and simulates them + + Args: + rb_opts: the options for the rb circuits + shots: number of shots for each circuit simulation + + Returns: + list: list of Results of the circuits simulations + list: the xdata of the rb circuit + + """ + # Load simulator + backend = qiskit.Aer.get_backend('qasm_simulator') + basis_gates = ['u1', 'u2', 'u3', 'cx'] + + rb_circs, xdata = rb.randomized_benchmarking_seq(**rb_opts) + + noise_model = NoiseModel() + p1q = 0.002 + p2q = 0.01 + 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') + + results = [] + for circuit in rb_circs: + results.append(qiskit.execute(circuit, backend=backend, + basis_gates=basis_gates, + shots=shots, + noise_model=noise_model, + seed_simulator=SEED).result()) + return results, xdata + + +def rb_circuit_execution_2(rb_opts: dict, shots: int): + """ + Create rb circuits with T1 and T2 errors and simulates them + + Args: + rb_opts: the options for the rb circuits + shots: number of shots for each circuit simulation + + Returns: + list: list of Results of the circuits simulations + list: the xdata of the rb circuit + + """ + # Load simulator + backend = qiskit.Aer.get_backend('qasm_simulator') + basis_gates = ['u1', 'u2', 'u3', 'cx'] + + rb_circs, xdata = rb.randomized_benchmarking_seq(**rb_opts) + + noise_model = NoiseModel() + + # Add T1/T2 noise to the simulation + t_1 = 100. + t_2 = 80. + gate1q = 0.1 + gate2q = 0.5 + noise_model.add_all_qubit_quantum_error(thermal_relaxation_error(t_1, t_2, gate1q), 'u2') + noise_model.add_all_qubit_quantum_error(thermal_relaxation_error(t_1, t_2, 2 * gate1q), 'u3') + noise_model.add_all_qubit_quantum_error( + thermal_relaxation_error(t_1, t_2, gate2q).tensor( + thermal_relaxation_error(t_1, t_2, gate2q)), 'cx') + + results = [] + for circuit in rb_circs: + results.append(qiskit.execute(circuit, backend=backend, + basis_gates=basis_gates, + shots=shots, + noise_model=noise_model, + seed_simulator=SEED).result()) + return results, xdata + + +def rb_interleaved_execution(rb_opts: dict, shots: int): + """ + Create interleaved rb circuits with depolarizing error and simulates them + Args: + rb_opts: the options for the rb circuits + shots: number of shots for each circuit simulation + + Returns: + list: list of Results of the original circuits simulations + list: the xdata of the rb circuit + list: list of Results of the interleaved circuits simulations + + """ + # Load simulator + backend = qiskit.Aer.get_backend('qasm_simulator') + basis_gates = ['u1', 'u2', 'u3', 'cx'] + + rb_original_circs, xdata, rb_interleaved_circs = rb.randomized_benchmarking_seq(**rb_opts) + + noise_model = NoiseModel() + p1q = 0.002 + p2q = 0.01 + 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') + + results = [] + for circuit in rb_original_circs: + results.append(qiskit.execute(circuit, backend=backend, + basis_gates=basis_gates, + shots=shots, + noise_model=noise_model, + seed_simulator=SEED).result()) + interleaved_results = [] + for circuit in rb_interleaved_circs: + interleaved_results.append(qiskit.execute(circuit, backend=backend, + basis_gates=basis_gates, + shots=shots, noise_model=noise_model, + seed_simulator=SEED).result()) + return results, xdata, interleaved_results + + +def rb_cnotdihedral_execution(rb_opts: dict, shots: int): + """ + Create cnot-dihedral rb circuits with depolarizing errors and simulates them + + Args: + rb_opts: the options for the rb circuits + shots: number of shots for each circuit simulation + + Returns: + list: list of Results of the cnot-dihedral circuits simulations in the x plane + list: the xdata of the rb circuit + list: list of Results of the cnot-dihedral circuits simulations in the z plane + + """ + # Load simulator + backend = qiskit.Aer.get_backend('qasm_simulator') + basis_gates = ['u1', 'u2', 'u3', 'cx'] + + rb_cnotdihedral_z_circs, xdata, rb_cnotdihedral_x_circs = \ + rb.randomized_benchmarking_seq(**rb_opts) + + # Add depolarizing noise to the simulation + noise_model = NoiseModel() + p1q = 0.002 + p2q = 0.01 + 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') + + cnotdihedral_x_results = [] + for circuit in rb_cnotdihedral_x_circs: + cnotdihedral_x_results.append(qiskit.execute(circuit, backend=backend, + basis_gates=basis_gates, + shots=shots, + noise_model=noise_model, + seed_simulator=SEED).result()) + cnotdihedral_z_results = [] + for circuit in rb_cnotdihedral_z_circs: + cnotdihedral_z_results.append(qiskit.execute(circuit, backend=backend, + basis_gates=basis_gates, + shots=shots, noise_model=noise_model, + seed_simulator=SEED).result()) + return cnotdihedral_x_results, xdata, cnotdihedral_z_results + + +def rb_purity_circuit_execution(rb_opts: dict, shots: int): + """ + Create purity rb circuits with depolarizing errors and simulates them + + Args: + rb_opts: the options for the rb circuits + shots: number of shots for each circuit simulation + + Returns: + list: list of Results of the purity circuits simulations + list: the xdata of the rb circuit + int: npurity (3^(number of qubits)) + list: list of Results of the coherent circuits simulations + + """ + # Load simulator + backend = qiskit.Aer.get_backend('qasm_simulator') + basis_gates = ['u1', 'u2', 'u3', 'cx'] + + rb_purity_circs, xdata, npurity = rb.randomized_benchmarking_seq(**rb_opts) + + # Add depolarizing noise to the simulation + noise_model = NoiseModel() + p1q = 0.002 + p2q = 0.01 + 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') + + # coherent noise + err_unitary = np.zeros([2, 2], dtype=complex) + angle_err = 0.1 + for i in range(2): + err_unitary[i, i] = np.cos(angle_err) + err_unitary[i, (i + 1) % 2] = np.sin(angle_err) + err_unitary[0, 1] *= -1.0 + + error = coherent_unitary_error(err_unitary) + coherent_noise_model = NoiseModel() + coherent_noise_model.add_all_qubit_quantum_error(error, 'u3') + + purity_results = [] + coherent_results = [] + for circuit_list in rb_purity_circs: + for purity_num in range(npurity): + current_circ = circuit_list[purity_num] + # non-coherent purity results + purity_results.append(qiskit.execute(current_circ, backend=backend, + basis_gates=basis_gates, + shots=shots, + noise_model=noise_model, + seed_simulator=SEED).result()) + # coherent purity results + coherent_results.append(qiskit.execute(current_circ, backend=backend, + basis_gates=basis_gates, + shots=shots, + noise_model=coherent_noise_model, + seed_simulator=SEED).result()) + + return purity_results, xdata, npurity, coherent_results + + +def generate_fitter_data_1(results_file_path: str, expected_results_file_path: str): + """ + Create rb circuits with depolarizing error and simulate them, + then write the results in a json file. + also creates fitter for the data results, + and also write the fitter results in another json file. + + The simulation results file will contain a list of Result objects in a dictionary format. + The fitter data file will contain dictionary with the following keys: + - 'ydata', value is stored in the form of list of dictionaries with keys of: + - mean, list of integers + - std, list of integers + - fit, value is stored in the form of list of dictionaries with keys of: + - params, list of integers + - params_err, list of integers + - epc, list of integers + - epc_err, list of integers + + Args: + results_file_path: path of the json file of the simulation results file + expected_results_file_path: path of the json file of the fitter results file + """ + + rb_opts = {} + shots = 1024 + rb_opts['nseeds'] = 5 + rb_opts['rb_pattern'] = [[0, 1], [2]] + rb_opts['length_multiplier'] = [1, 2] + rb_opts['length_vector'] = np.arange(1, 200, 20) + + rb_results, xdata = rb_circuit_execution(rb_opts, shots) + save_results_as_json(rb_results, results_file_path) + + # generate also the expected results of the fitter + rb_fit = RBFitter(rb_results, xdata, rb_opts['rb_pattern']) + ydata = rb_fit.ydata + fit = rb_fit.fit + # convert ndarray to list + ydata = convert_ndarray_to_list_in_data(ydata) + fit = convert_ndarray_to_list_in_data(fit) + + expected_result = {"ydata": ydata, "fit": fit} + with open(expected_results_file_path, "w") as expected_results_file: + json.dump(expected_result, expected_results_file) + + +def generate_fitter_data_2(results_file_path: str, expected_results_file_path: str): + """ + Create rb circuits with T1 and T2 errors and simulate them, + then write the results in a json file. + also creates fitter for the data results, + and also write the fitter results in another json file. + + The simulation results file will contain a list of Result objects in a dictionary format. + The fitter data file will contain dictionary with the following keys: + - 'ydata', value is stored in the form of list of dictionaries with keys of: + - mean, list of integers + - std, list of integers + - fit, value is stored in the form of list of dictionaries with keys of: + - params, list of integers + - params_err, list of integers + - epc, list of integers + - epc_err, list of integers + + Args: + results_file_path: path of the json file of the simulation results file + expected_results_file_path: path of the json file of the fitter results file + """ + rb_opts = {} + shots = 1024 + rb_opts['nseeds'] = 5 + rb_opts['rb_pattern'] = [[0]] + rb_opts['length_vector'] = np.arange(1, 200, 20) + + rb_results, xdata = rb_circuit_execution_2(rb_opts, shots) + save_results_as_json(rb_results, results_file_path) + + # generate also the expected results of the fitter + rb_fit = RBFitter(rb_results, xdata, rb_opts['rb_pattern']) + ydata = rb_fit.ydata + fit = rb_fit.fit + # convert ndarray to list + ydata = convert_ndarray_to_list_in_data(ydata) + fit = convert_ndarray_to_list_in_data(fit) + + expected_result = {"ydata": ydata, "fit": fit} + with open(expected_results_file_path, "w") as expected_results_file: + json.dump(expected_result, expected_results_file) + + +def generate_interleaved_data(results_file_path_original: str, + results_file_path_interleaved: str, + expected_results_file_path: str): + """ + Create interleaved rb circuits with depolarizing error and simulate them, + then write the results in a json file. + also creates fitter for the data results, + and also write the fitter results in another json file. + + The simulation results file will contain a list of Result objects in a dictionary format. + The fitter data file will contain dictionary with the following keys: + - 'original_ydata', value is stored in the form of list of dictionaries with keys of: + - mean, list of integers + - std, list of integers + - 'interleaved_ydata', value is stored in the form of list of dictionaries with keys of: + - mean, list of integers + - std, list of integers + - joint_fit, value is stored in the form of list of dictionaries with keys of: + - alpha, list of integers + - alpha_err, list of integers + - alpha_c, list of integers + - alpha_c_err, list of integers + - epc_est, list of integers + - epc_est_err, list of integers + - systematic_err, list of integers + - systematic_err_L, list of integers + - systematic_err_R, list of integers + + Args: + results_file_path_original: path of the json file of the simulation results file + of the original circuits + results_file_path_interleaved: path of the json file of the simulation results file + of the interleaved circuits + expected_results_file_path: path of the json file of the fitter results file + """ + + rb_opts = {} + shots = 200 + rb_opts['nseeds'] = 2 + rb_opts['rb_pattern'] = [[0, 2], [1]] + rb_opts['length_vector'] = np.arange(1, 100, 10) + rb_opts['length_multiplier'] = [1, 3] + rb_opts['interleaved_gates'] = [['x 0', 'x 1', 'cx 0 1'], ['x 0']] + + results, xdata, interleaved_results = rb_interleaved_execution(rb_opts, shots) + save_results_as_json(results, results_file_path_original) + save_results_as_json(interleaved_results, results_file_path_interleaved) + + # generate also the expected results of the fitter + joint_rb_fit = InterleavedRBFitter(results, interleaved_results, xdata, + rb_opts['rb_pattern']) + joint_fit = joint_rb_fit.fit_int + original_ydata = joint_rb_fit.ydata[0] + interleaved_ydata = joint_rb_fit.ydata[1] + # convert ndarray to list + original_ydata = convert_ndarray_to_list_in_data(original_ydata) + interleaved_ydata = convert_ndarray_to_list_in_data(interleaved_ydata) + joint_fit = convert_ndarray_to_list_in_data(joint_fit) + + expected_result = {"original_ydata": original_ydata, + "interleaved_ydata": interleaved_ydata, "joint_fit": joint_fit} + with open(expected_results_file_path, "w") as expected_results_file: + json.dump(expected_result, expected_results_file) + + +def generate_cnotdihedral_data(results_file_path_cnotdihedral_x: str, + results_file_path_cnotdihedral_z: str, + expected_results_file_path: str): + """ + Create cnot-dihedral rb circuits with depolarizing error and simulate them, + then write the results in a json file (separate files for x and z). + also creates fitter for the data results, + and also write the fitter results in another json file. + + The simulation results file will contain a list of Result objects in a dictionary format. + The fitter data file will contain dictionary with the following keys: + - 'cnotdihedral_Z_ydata', value is stored in the form of list of dictionaries with keys of: + - mean, list of integers + - std, list of integers + - 'cnotdihedral_X_ydata', value is stored in the form of list of dictionaries with keys of: + - mean, list of integers + - std, list of integers + - joint_fit, value is stored in the form of list of dictionaries with keys of: + - alpha, list of integers + - alpha_err, list of integers + - epc_est, list of integers + - epc_est_err, list of integers + + Args: + results_file_path_cnotdihedral_z: path of the json file of the simulation results file + of the cnot-dihedral in the z plane circuits + results_file_path_cnotdihedral_x: path of the json file of the simulation results file + of the cnot-dihedral in the x plane circuits + expected_results_file_path: path of the json file of the fitter results file + """ + + rb_opts = {} + shots = 200 + rb_opts['nseeds'] = 5 + rb_opts['rb_pattern'] = [[0, 2], [1]] + rb_opts['length_vector'] = np.arange(1, 200, 20) + rb_opts['length_multiplier'] = [1, 3] + rb_opts['group_gates'] = 'CNOT-Dihedral' + + cnotdihedral_x_results, xdata, cnotdihedral_z_results = \ + rb_cnotdihedral_execution(rb_opts, shots) + save_results_as_json(cnotdihedral_x_results, results_file_path_cnotdihedral_x) + save_results_as_json(cnotdihedral_z_results, results_file_path_cnotdihedral_z) + + # generate also the expected results of the fitter + joint_rb_fit = CNOTDihedralRBFitter(cnotdihedral_z_results, cnotdihedral_x_results, xdata, + rb_opts['rb_pattern']) + + joint_fit = joint_rb_fit.fit_cnotdihedral + cnotdihedral_x_ydata = joint_rb_fit.ydata[0] + cnotdihedral_z_ydata = joint_rb_fit.ydata[1] + # convert ndarray to list + cnotdihedral_x_ydata = convert_ndarray_to_list_in_data(cnotdihedral_x_ydata) + cnotdihedral_z_ydata = convert_ndarray_to_list_in_data(cnotdihedral_z_ydata) + joint_fit = convert_ndarray_to_list_in_data(joint_fit) + + expected_result = {"cnotdihedral_Z_ydata": cnotdihedral_z_ydata, + "cnotdihedral_X_ydata": cnotdihedral_x_ydata, "joint_fit": joint_fit} + with open(expected_results_file_path, "w") as expected_results_file: + json.dump(expected_result, expected_results_file) + + +def generate_purity_data(results_file_path_purity: str, + results_file_path_coherent: str, + expected_results_file_path_purity: str, + expected_results_file_path_coherent: str): + """ + Create purity rb circuits with depolarizing error and simulate them, + then write the results in a json file (separate files for purity and coherent). + also creates fitter for the data results, + and also write the fitter results in another json file (separate files for purity + and coherent). + + The simulation results file will contain a list of Result objects in a dictionary format. + The fitter data file will contain dictionary with the following keys: + - 'ydata', value is stored in the form of list of dictionaries with keys of: + - mean, list of integers + - std, list of integers + - fit, value is stored in the form of list of dictionaries with keys of: + - params, list of integers + - params_err, list of integers + - epc, list of integers + - epc_err, list of integers + - pepc, list of integers + - pepc_err, list of integers + + Args: + results_file_path_purity: path of the json file of the purity simulation results file + results_file_path_coherent: path of the json file of the coherent simulation results + file + expected_results_file_path_purity: path of the json file of the purity fitter + results file + expected_results_file_path_coherent: path of the json file of the coherent fitter + results file + """ + rb_opts = {} + shots = 200 + rb_opts['nseeds'] = 3 + rb_opts['rb_pattern'] = [[0, 1]] + rb_opts['length_vector'] = np.arange(1, 200, 20) + rb_opts['is_purity'] = True + + rb_purity_results, xdata, npurity, rb_coherent_results = \ + rb_purity_circuit_execution(rb_opts, shots) + + # save the results + save_results_as_json(rb_purity_results, results_file_path_purity) + save_results_as_json(rb_coherent_results, results_file_path_coherent) + + # generate also the expected results of the fitter + rbfit_purity = PurityRBFitter(rb_purity_results, npurity, xdata, rb_opts['rb_pattern']) + + fit = rbfit_purity.fit + ydata = rbfit_purity.ydata + + # convert ndarray to list + ydata = convert_ndarray_to_list_in_data(ydata) + fit = convert_ndarray_to_list_in_data(fit) + + expected_result = {"ydata": ydata, + "fit": fit} + with open(expected_results_file_path_purity, "w") as expected_results_file: + json.dump(expected_result, expected_results_file) + + # generate also the expected results of the fitter for coherent + rbfit_coherent = rb.PurityRBFitter(rb_coherent_results, npurity, xdata, rb_opts['rb_pattern']) + + coherent_fit = rbfit_coherent.fit + coherent_ydata = rbfit_coherent.ydata + + # convert ndarray to list + coherent_ydata = convert_ndarray_to_list_in_data(coherent_ydata) + coherent_fit = convert_ndarray_to_list_in_data(coherent_fit) + + coherent_expected_result = {"ydata": coherent_ydata, "fit": coherent_fit} + with open(expected_results_file_path_coherent, "w") as expected_results_file: + json.dump(coherent_expected_result, expected_results_file) + + +if __name__ == '__main__': + DIRNAME = os.path.dirname(os.path.abspath(__file__)) + for rb_type in sys.argv[1:]: + if rb_type == 'standard': + generate_fitter_data_1(os.path.join(DIRNAME, 'test_fitter_results_1.json'), + os.path.join(DIRNAME, 'test_fitter_expected_results_1.json')) + generate_fitter_data_2(os.path.join(DIRNAME, 'test_fitter_results_2.json'), + os.path.join(DIRNAME, 'test_fitter_expected_results_2.json')) + elif rb_type == 'interleaved': + generate_interleaved_data(os.path.join(DIRNAME, 'test_fitter_original_results.json'), + os.path.join(DIRNAME, + 'test_fitter_interleaved_results.json'), + os.path.join(DIRNAME, + 'test_fitter_interleaved_' + 'expected_results.json')) + elif rb_type == 'cnotdihedral': + generate_cnotdihedral_data(os.path.join(DIRNAME, + 'test_fitter_cnotdihedral_X_results.json'), + os.path.join(DIRNAME, + 'test_fitter_cnotdihedral_Z_results.json'), + os.path.join(DIRNAME, + 'test_fitter_cnotdihedral_' + 'expected_results.json')) + elif rb_type == 'purity': + generate_purity_data(os.path.join(DIRNAME, 'test_fitter_purity_results.json'), + os.path.join(DIRNAME, 'test_fitter_coherent_purity_results.json'), + os.path.join(DIRNAME, 'test_fitter_purity_expected_results.json'), + os.path.join(DIRNAME, + 'test_fitter_coherent_purity_expected_results.json')) + else: + print('Skipping unknown argument ' + rb_type) diff --git a/test/rb/test_fitter_cnotdihedral_X_expected_results.json b/test/rb/test_fitter_cnotdihedral_X_expected_results.json deleted file mode 100644 index fc9a5b7ea..000000000 --- a/test/rb/test_fitter_cnotdihedral_X_expected_results.json +++ /dev/null @@ -1 +0,0 @@ -{"cnotdihedral_X_ydata": [{"mean": [0.961, 0.72, 0.565, 0.462, 0.353, 0.34, 0.303, 0.301, 0.28, 0.233], "std": [0.00969536, 0.01048809, 0.03271085, 0.03385262, 0.02839014, 0.02167948, 0.03919184, 0.03152777, 0.02280351, 0.0150333]}, {"mean": [0.995, 0.936, 0.894, 0.859, 0.82, 0.78, 0.763, 0.709, 0.695, 0.66], "std": [0.00547723, 0.02154066, 0.01593738, 0.0174356, 0.03937004, 0.03114482, 0.026, 0.01529706, 0.02387467, 0.02302173]}], "joint_fit": [{"alpha": 0.980236195543166, "alpha_err": 0.0008249166207232896, "epg_est": 0.014822853342625508, "epg_est_err": 0.0006311616203884836}, {"alpha": 0.99867758415237, "alpha_err": 0.00018607263163029097, "epg_est": 0.0006612079238150215, "epg_est_err": 9.315951142941721e-05}]} \ No newline at end of file diff --git a/test/rb/test_fitter_cnotdihedral_Z_expected_results.json b/test/rb/test_fitter_cnotdihedral_Z_expected_results.json deleted file mode 100644 index f53c7dc6a..000000000 --- a/test/rb/test_fitter_cnotdihedral_Z_expected_results.json +++ /dev/null @@ -1 +0,0 @@ -{"cnotdihedral_Z_ydata": [{"mean": [0.97, 0.725, 0.578, 0.462, 0.373, 0.348, 0.32, 0.311, 0.263, 0.268], "std": [0.01643168, 0.04301163, 0.0256125, 0.03059412, 0.03722902, 0.02063977, 0.01760682, 0.00860233, 0.03026549, 0.02976575]}, {"mean": [0.997, 0.953, 0.913, 0.855, 0.806, 0.772, 0.742, 0.7, 0.682, 0.654], "std": [0.006, 0.01630951, 0.01077033, 0.0083666, 0.02517936, 0.02014944, 0.00509902, 0.03193744, 0.00812404, 0.02782086]}], "joint_fit": [{"alpha": 0.980236195543166, "alpha_err": 0.0008249166207232896, "epg_est": 0.014822853342625508, "epg_est_err": 0.0006311616203884836}, {"alpha": 0.99867758415237, "alpha_err": 0.00018607263163029097, "epg_est": 0.0006612079238150215, "epg_est_err": 9.315951142941721e-05}]} \ No newline at end of file diff --git a/test/rb/test_fitter_cnotdihedral_expected_results.json b/test/rb/test_fitter_cnotdihedral_expected_results.json new file mode 100644 index 000000000..4aa75c5e1 --- /dev/null +++ b/test/rb/test_fitter_cnotdihedral_expected_results.json @@ -0,0 +1 @@ +{"cnotdihedral_Z_ydata": [{"mean": [0.97, 0.725, 0.578, 0.462, 0.373, 0.348, 0.32, 0.311, 0.263, 0.268], "std": [0.01643168, 0.04301163, 0.0256125, 0.03059412, 0.03722902, 0.02063977, 0.01760682, 0.00860233, 0.03026549, 0.02976575]}, {"mean": [0.997, 0.953, 0.913, 0.855, 0.806, 0.772, 0.742, 0.7, 0.682, 0.654], "std": [0.006, 0.01630951, 0.01077033, 0.0083666, 0.02517936, 0.02014944, 0.00509902, 0.03193744, 0.00812404, 0.02782086]}], "cnotdihedral_X_ydata": [{"mean": [0.961, 0.72, 0.565, 0.462, 0.353, 0.34, 0.303, 0.301, 0.28, 0.233], "std": [0.00969536, 0.01048809, 0.03271085, 0.03385262, 0.02839014, 0.02167948, 0.03919184, 0.03152777, 0.02280351, 0.0150333]}, {"mean": [0.995, 0.936, 0.894, 0.859, 0.82, 0.78, 0.763, 0.709, 0.695, 0.66], "std": [0.00547723, 0.02154066, 0.01593738, 0.0174356, 0.03937004, 0.03114482, 0.026, 0.01529706, 0.02387467, 0.02302173]}], "joint_fit": [{"alpha": 0.980236195543166, "alpha_err": 0.0008249166207232896, "epg_est": 0.014822853342625508, "epg_est_err": 0.0006311616203884836}, {"alpha": 0.99867758415237, "alpha_err": 0.00018607263163029097, "epg_est": 0.0006612079238150215, "epg_est_err": 9.315951142941721e-05}]} \ No newline at end of file diff --git a/test/rb/test_fitters.py b/test/rb/test_fitters.py index 90440223f..2b835befe 100644 --- a/test/rb/test_fitters.py +++ b/test/rb/test_fitters.py @@ -230,16 +230,13 @@ def test_cnotdihedral_fitters(self): os.path.join( os.path.dirname(__file__), 'test_fitter_cnotdihedral_X_results.json'), - 'cnotdihedral_X_expected_results_file': - os.path.join(os.path.dirname(__file__), - 'test_fitter_cnotdihedral_X_expected_results.json'), 'cnotdihedral_Z_results_file': os.path.join( os.path.dirname(__file__), 'test_fitter_cnotdihedral_Z_results.json'), - 'cnotdihedral_Z_expected_results_file': + 'cnotdihedral_expected_results_file': os.path.join(os.path.dirname(__file__), - 'test_fitter_cnotdihedral_Z_expected_results.json') + 'test_fitter_cnotdihedral_expected_results.json') } ] @@ -248,12 +245,9 @@ def test_cnotdihedral_fitters(self): tst_settings['cnotdihedral_X_results_file']) cnotdihedral_Z_result_list = load_results_from_json( tst_settings['cnotdihedral_Z_results_file']) - with open(tst_settings['cnotdihedral_X_expected_results_file'], "r")\ - as expected_results_file: - tst_cnotdihedral_X_expected_results = json.load(expected_results_file) - with open(tst_settings['cnotdihedral_Z_expected_results_file'], "r")\ + with open(tst_settings['cnotdihedral_expected_results_file'], "r")\ as expected_results_file: - tst_cnotdihedral_Z_expected_results = json.load(expected_results_file) + tst_cnotdihedral_expected_results = json.load(expected_results_file) # CNOTDihedralRBFitter class joint_rb_fit = CNOTDihedralRBFitter( @@ -266,15 +260,15 @@ def test_cnotdihedral_fitters(self): ydata_X = joint_rb_fit.ydata[1] self.compare_results_and_excpected(ydata_Z, - tst_cnotdihedral_Z_expected_results[ + tst_cnotdihedral_expected_results[ 'cnotdihedral_Z_ydata'], tst_index) self.compare_results_and_excpected(ydata_X, - tst_cnotdihedral_X_expected_results[ + tst_cnotdihedral_expected_results[ 'cnotdihedral_X_ydata'], tst_index) self.compare_results_and_excpected(joint_fit, - tst_cnotdihedral_X_expected_results['joint_fit'], + tst_cnotdihedral_expected_results['joint_fit'], tst_index) diff --git a/test/utils.py b/test/utils.py index ad097f116..1cf60a11d 100644 --- a/test/utils.py +++ b/test/utils.py @@ -16,6 +16,7 @@ import random from typing import List import json +import numpy as np from qiskit.result.result import Result @@ -83,3 +84,29 @@ def load_results_from_json(json_path: str): with open(json_path, "r") as results_file: results_json = json.load(results_file) return [Result.from_dict(result) for result in results_json] + + +def convert_ndarray_to_list_in_data(data: np.ndarray): + """ + converts ndarray format into list format (keeps all the dicts in the array) + also convert inner ndarrays into lists (recursively) + Args: + data: ndarray containing dicts or ndarrays in it + + Returns: + list: same array, converted to list format (in order to save it as json) + + """ + new_data = [] + for item in data: + if isinstance(item, np.ndarray): + new_item = convert_ndarray_to_list_in_data(item) + elif isinstance(item, dict): + new_item = {} + for key, value in item.items(): + new_item[key] = value.tolist() + else: + new_item = item + new_data.append(new_item) + + return new_data