diff --git a/src/qibocal/protocols/characterization/randomized_benchmarking/circuit_tools.py b/src/qibocal/protocols/characterization/randomized_benchmarking/circuit_tools.py index e16c30ba9..f0b5a0cb2 100644 --- a/src/qibocal/protocols/characterization/randomized_benchmarking/circuit_tools.py +++ b/src/qibocal/protocols/characterization/randomized_benchmarking/circuit_tools.py @@ -121,9 +121,12 @@ def add_inverse_2q_layer(circuit: Circuit, two_qubit_cliffords, file_inv): """ path = pathlib.Path(__file__).parent / file_inv - if not path.is_file(): - generate_inv_dict_cliffords_file(two_qubit_cliffords, file_inv) - clifford_matrices_inv = np.load(path) + if file_inv is None and not path.is_file(): + clifford_matrices_inv = generate_inv_dict_cliffords_file( + two_qubit_cliffords, file_inv + ) + else: + clifford_matrices_inv = np.load(path) if circuit.depth > 0: clifford = circuit.unitary() diff --git a/src/qibocal/protocols/characterization/randomized_benchmarking/standard_rb_2q.py b/src/qibocal/protocols/characterization/randomized_benchmarking/standard_rb_2q.py index 028d1e886..70a56c4ba 100644 --- a/src/qibocal/protocols/characterization/randomized_benchmarking/standard_rb_2q.py +++ b/src/qibocal/protocols/characterization/randomized_benchmarking/standard_rb_2q.py @@ -36,6 +36,8 @@ random_2q_clifford, ) +# TODO: BOTH measurements in plot and fit ??? + class Depthsdict(TypedDict): """dictionary used to build a list of depths as ``range(start, stop, step)``.""" @@ -263,7 +265,6 @@ def _acquisition( for i, depth in enumerate(params.depths): index = (i * params.niter, (i + 1) * params.niter) for nqubit, qubit_id in enumerate(targets): - data.register_qubit( RBType, (qubit_id[0], qubit_id[1], depth), diff --git a/src/qibocal/protocols/characterization/randomized_benchmarking/utils.py b/src/qibocal/protocols/characterization/randomized_benchmarking/utils.py index 9a36e49af..c5ee3df6f 100644 --- a/src/qibocal/protocols/characterization/randomized_benchmarking/utils.py +++ b/src/qibocal/protocols/characterization/randomized_benchmarking/utils.py @@ -44,57 +44,67 @@ SINGLE_QUBIT_CLIFFORDS_NAMES = { # Virtual gates "": gates.I, - "minusX,minusY": lambda q: gates.U3(q, 0, np.pi / 2, np.pi / 2), # Z + # Check the Z + "minusX,minusY": lambda q: gates.U3(q, 0, np.pi / 2, np.pi / 2), # Z, gp:exp(iπ) "sqrtX,sqrtMinusY,sqrtMinusX": lambda q: gates.U3( q, 0, -np.pi / 2, 0 - ), # gates.RZ(q, np.pi / 2), + ), # La U3 esta bien el nombre no ? # gates.RZ(q, np.pi / 2), gp:exp(iπ/4) "sqrtX,sqrtY,sqrtMinusX": lambda q: gates.U3( q, 0, np.pi / 2, 0 - ), # gates.U3(q, 0, -np.pi / 2, 0), - # pi rotations (Check the phase from qiskit) RX(π)=−iX; RY(π)=−iY - "minusX": lambda q: gates.U3(q, np.pi, -np.pi / 2, np.pi), # X, - "minusY": lambda q: gates.U3(q, np.pi, -np.pi / 2, 0), # Y, - # pi/2 rotations (Check the minus) - "sqrtX": lambda q: gates.U3(q, np.pi / 2, -np.pi / 2, np.pi / 2), # Rx(pi/2) - "sqrtMinusX": lambda q: gates.U3(q, -np.pi / 2, -np.pi / 2, np.pi / 2), # Rx(-pi/2) - "sqrtY": lambda q: gates.U3(q, np.pi / 2, 0, 0), # Ry(pi/2) - "sqrtMinusY": lambda q: gates.U3(q, -np.pi / 2, 0, 0), # Ry(-pi/2) - # 2pi/3 rotations - "sqrtX,sqrtY": lambda q: gates.U3(q, np.pi / 2, -np.pi / 2, 0), # Rx(pi/2)Ry(pi/2) + ), # gates.U3(q, 0, -np.pi / 2, 0), # Esta bien gates.RZ(q, -np.pi / 2), gp:exp(iπ/4) + # pi rotations + # 'X': lambda q: gates.U3(q, np.pi, 0, np.pi), # X, + # 'Y': lambda q: gates.U3(q, np.pi, 0, 0), # Y, + # pi rotations (For the minus exp(iπ) global phase) (Check the phase from qiskit) RX(π)=−iX; RY(π)=−iY + "minusX": lambda q: gates.U3(q, np.pi, -np.pi, 0), # X, gp:exp(iπ) + "minusY": lambda q: gates.U3(q, np.pi, 0, 0), # Y, gp:exp(iπ) + # pi/2 rotations (Check the minus) RX(π/2)=−exp(i π/4)SX + "sqrtX": lambda q: gates.U3(q, np.pi / 2, -np.pi / 2, np.pi / 2), # Rx(pi/2) gp: + "sqrtMinusX": lambda q: gates.U3( + q, -np.pi / 2, -np.pi / 2, np.pi / 2 + ), # Rx(-pi/2) gp: + "sqrtY": lambda q: gates.U3(q, np.pi / 2, 0, 0), # Ry(pi/2) gp: + "sqrtMinusY": lambda q: gates.U3(q, -np.pi / 2, 0, 0), # Ry(-pi/2) gp: + # 2pi/3 rotations Check the gp + "sqrtX,sqrtY": lambda q: gates.U3( + q, np.pi / 2, -np.pi / 2, 0 + ), # Rx(pi/2)Ry(pi/2) gp: "sqrtX,sqrtMinusY": lambda q: gates.U3( q, np.pi / 2, -np.pi / 2, np.pi - ), # Rx(pi/2)Ry(-pi/2) + ), # Rx(pi/2)Ry(-pi/2) gp: "sqrtMinusX,sqrtY": lambda q: gates.U3( q, np.pi / 2, np.pi / 2, 0 - ), # Rx(-pi/2)Ry(pi/2) + ), # Rx(-pi/2)Ry(pi/2) gp: "sqrtMinusX,sqrtMinusY": lambda q: gates.U3( q, np.pi / 2, np.pi / 2, -np.pi - ), # Rx(-pi/2)Ry(-pi/2) - "sqrtY,sqrtX": lambda q: gates.U3(q, np.pi / 2, 0, np.pi / 2), # Ry(pi/2)Rx(pi/2) + ), # Rx(-pi/2)Ry(-pi/2) gp: + "sqrtY,sqrtX": lambda q: gates.U3( + q, np.pi / 2, 0, np.pi / 2 + ), # Ry(pi/2)Rx(pi/2) gp: "sqrtY,sqrtMinusX": lambda q: gates.U3( q, np.pi / 2, 0, -np.pi / 2 - ), # Ry(pi/2)Rx(-pi/2) + ), # Ry(pi/2)Rx(-pi/2) gp: "sqrtMinusY,sqrtX": lambda q: gates.U3( q, np.pi / 2, -np.pi, np.pi / 2 - ), # Ry(-pi/2)Rx(pi/2) + ), # Ry(-pi/2)Rx(pi/2) gp: "sqrtMinusY,sqrtMinusX": lambda q: gates.U3( q, np.pi / 2, np.pi, -np.pi / 2 - ), # Ry(-pi/2)Rx(-pi/2) - # Hadamard-like - "minusX,sqrtY": lambda q: gates.U3(q, np.pi / 2, -np.pi, 0), # X Ry(pi/2) - "minusX,sqrtMinusY": lambda q: gates.U3(q, np.pi / 2, 0, np.pi), # X Ry(-pi/2) + ), # Ry(-pi/2)Rx(-pi/2) gp: + # Hadamard-like Check the gp + "minusX,sqrtY": lambda q: gates.U3(q, np.pi / 2, -np.pi, 0), # X Ry(pi/2) gp: + "minusX,sqrtMinusY": lambda q: gates.U3(q, np.pi / 2, 0, np.pi), # X Ry(-pi/2) gp: "minusY,sqrtX": lambda q: gates.U3( q, np.pi / 2, np.pi / 2, np.pi / 2 - ), # Y Rx(pi/2) + ), # Y Rx(pi/2) gp: "minusY,sqrtMinusX": lambda q: gates.U3( q, np.pi / 2, -np.pi / 2, -np.pi / 2 - ), # Y Rx(-pi/2) + ), # Y Rx(-pi/2) gp: "sqrtX,sqrtY,sqrtX": lambda q: gates.U3( q, np.pi, -np.pi / 4, np.pi / 4 - ), # Rx(pi/2)Ry(pi/2)Rx(pi/2) + ), # Rx(pi/2)Ry(pi/2)Rx(pi/2) gp: "sqrtX,sqrtMinusY,sqrtX": lambda q: gates.U3( q, np.pi, np.pi / 4, -np.pi / 4 - ), # Rx(-pi/2)Ry(pi/2)Rx(-pi/2) + ), # Rx(-pi/2)Ry(pi/2)Rx(-pi/2) gp: } @@ -203,6 +213,13 @@ def clifford_to_matrix(clifford): def generate_inv_dict_cliffords_file(two_qubit_cliffords, output_file): + """ + Generate an inverse dictionary of clifford matrices and save it to a npz file. + + Parameters: + two_qubit_cliffords (dict): A dictionary of two-qubit cliffords. + output_file (str): The path to the output npz file. + """ clifford_matrices = {} for i, clifford in enumerate(two_qubit_cliffords.values()): clifford = two_qubit_cliffords[str(i)] @@ -219,8 +236,10 @@ def generate_inv_dict_cliffords_file(two_qubit_cliffords, output_file): key_str = np.array2string(value, separator=",") clifford_matrices_inv_np[key_str] = key - # npz file to save the data - np.savez(output_file, **clifford_matrices_inv_np) + if output_file is not None: + np.savez(output_file, **clifford_matrices_inv_np) + + return clifford_matrices_inv_np def number_to_str( diff --git a/tests/test_randomized_benchmarking.py b/tests/test_randomized_benchmarking.py index b210508ca..915e345b1 100644 --- a/tests/test_randomized_benchmarking.py +++ b/tests/test_randomized_benchmarking.py @@ -1,3 +1,6 @@ +import json +import os +import pathlib from functools import reduce import numpy as np @@ -12,7 +15,7 @@ RB_Generator, ) from qibocal.protocols.characterization.randomized_benchmarking.utils import ( - number_to_str, + generate_inv_dict_cliffords_file, random_clifford, ) @@ -173,14 +176,24 @@ def test_random_clifford(qubits, seed): assert np.allclose(matrix, result) -@pytest.mark.parametrize("value", [0.555555, 2, -0.1 + 0.1j]) -def test_number_to_str(value): - assert number_to_str(value) == f"{value:.3f}" - assert number_to_str(value, [None, None]) == f"{value:.3f}" - assert number_to_str(value, 0.0123) == f"{value:.3f} \u00B1 0.012" - assert number_to_str(value, [0.0123, 0.012]) == f"{value:.3f} \u00B1 0.012" - assert number_to_str(value, 0.1 + 0.02j) == f"{value:.3f} \u00B1 0.100+0.020j" - assert number_to_str(value, [0.203, 0.001]) == f"{value:.4f} +0.0010 / -0.2030" - assert ( - number_to_str(value, [float("inf"), float("inf")]) == f"{value:.3f} \u00B1 inf" +def test_generate_inv_dict_cliffords_file(): + path = ( + pathlib.Path(__file__).parent.parent + / "src/qibocal/protocols/characterization/randomized_benchmarking/2qubitCliffs.json" ) + with open(path) as file: + two_qubit_cliffords = json.load(file) + + path_test_inv = pathlib.Path(__file__).parent / "test.npz" + clifford_inv = generate_inv_dict_cliffords_file(two_qubit_cliffords, path_test_inv) + clifford_inv = np.load(path_test_inv) + + path_inv = ( + pathlib.Path(__file__).parent.parent + / "src/qibocal/protocols/characterization/randomized_benchmarking/2qubitCliffsInv.npz" + ) + clifford_matrices_inv = np.load(path_inv) + + assert clifford_inv.files == clifford_matrices_inv.files + + os.remove(path_test_inv)