diff --git a/qualang_tools/characterization/two_qubit_rb/two_qubit_rb/TwoQubitRBDebugger.py b/qualang_tools/characterization/two_qubit_rb/two_qubit_rb/TwoQubitRBDebugger.py index 113d3a23..a509685e 100644 --- a/qualang_tools/characterization/two_qubit_rb/two_qubit_rb/TwoQubitRBDebugger.py +++ b/qualang_tools/characterization/two_qubit_rb/two_qubit_rb/TwoQubitRBDebugger.py @@ -11,6 +11,25 @@ from .verification import SequenceTracker +phased_xz_command_sequences = { + r"I \otimes I": [720], # Identity on both qubits + r"I \otimes Z": [732], # Z on qubit 1, Identity on qubit 2 + r"Z \otimes I": [723], # Z on qubit 2, Identity on qubit 1 + r"I \otimes X": [724], # X on qubit 1, Identity on qubit 2 + r"X \otimes I": [721], # X on qubit 2, Identity on qubit 1 + r"X \otimes X": [725], # X on both qubits + r"\frac{X}{2} \otimes I": [1], # X/2 on qubit 2, Identity on qubit 1 + r"I \otimes \frac{X}{2}": [6], # X/2 on qubit 1, Identity on qubit 2 + r"\frac{X}{2} \otimes \frac{X}{2}": [7], # X/2 on both qubits + r"\text{CZ}": [74], # Controlled-Z (CZ) gate + r"(\frac{Y}{2} \otimes -\frac{Y}{2}), \text {CZ}, (I \otimes \frac{Y}{2}) \Rightarrow |\Phi^+\rangle_{Bell}": [252], + r"\text{CNOT}": [12, 347], # X/2 on qubit 2, followed by CNOT + r"(\frac{X}{2} \otimes I), \text{CNOT}": [1, 4, 63], # X/2 on qubit 2, followed by CNOT + r"(X \otimes I), \text{CNOT}": [724, 4, 63], # X/2 on qubit 2, followed by CNOT + r"(I \otimes X), \text{SWAP}": [724, 39, 489], # X on qubit 1, followed by SWAP +} + + class TwoQubitRbDebugger: def __init__(self, rb: TwoQubitRb): """ @@ -26,25 +45,7 @@ def run_phased_xz_commands(self, qmm: QuantumMachinesManager, num_averages: int) gates and other fundamental gates, which lead to a variety of transformations on the |00> state. This is useful for testing the 1Q component of the gate implementation. """ - sequences_dict = { - r"I \otimes I": [720], # Identity on both qubits - r"I \otimes Z": [732], # Z on qubit 1, Identity on qubit 2 - r"Z \otimes I": [723], # Z on qubit 2, Identity on qubit 1 - r"I \otimes X": [724], # X on qubit 1, Identity on qubit 2 - r"X \otimes I": [721], # X on qubit 2, Identity on qubit 1 - r"X \otimes X": [725], # X on both qubits - r"\frac{X}{2} \otimes I": [1], # X/2 on qubit 2, Identity on qubit 1 - r"I \otimes \frac{X}{2}": [6], # X/2 on qubit 1, Identity on qubit 2 - r"\frac{X}{2} \otimes \frac{X}{2}": [7], # X/2 on both qubits - r"\text{CZ}": [74], # Controlled-Z (CZ) gate - r"(\frac{X}{2} \otimes \frac{X}{2}), \text{CZ}, (\frac{X}{2} \otimes \frac{X}{2})": [7, 74, 7], - r"\text{CNOT}": [12, 347], # X/2 on qubit 2, followed by CNOT - r"(\frac{X}{2} \otimes I), \text{CNOT}": [1, 4, 63], # X/2 on qubit 2, followed by CNOT - r"(X \otimes I), \text{CNOT}": [724, 4, 63], # X/2 on qubit 2, followed by CNOT - r"(I \otimes X), \text{SWAP}": [724, 39, 489], # X on qubit 1, followed by SWAP - } - - sequences = sequences_dict.values() + sequences = phased_xz_command_sequences.values() self.sequence_tracker = SequenceTracker(self.rb._command_registry) @@ -59,15 +60,15 @@ def run_phased_xz_commands(self, qmm: QuantumMachinesManager, num_averages: int) state = job.result_handles.get("state").fetch_all() self.sequence_tracker.print_sequences() - self._analyze_phased_xz_commands_program(state, list(sequences_dict.keys())) + self._analyze_phased_xz_commands_program(state, list(phased_xz_command_sequences.keys())) @run_in_thread def _insert_all_input_stream(self, job, sequences): for sequence in tqdm(sequences, desc='Running test-sequences', unit='sequence'): self.sequence_tracker.make_sequence(sequence) - job.insert_input_stream("__gates_len_is__", len(sequence)) - for qe in self.rb._rb_baker.all_elements: - job.insert_input_stream(f"{qe}_is", self.rb._decode_sequence_for_element(qe, sequence)) + # job.insert_input_stream("__gates_len_is__", len(sequence)) + # for qe in self.rb._rb_baker.all_elements: + # job.insert_input_stream(f"{qe}_is", self.rb._decode_sequence_for_element(qe, sequence)) def _phased_xz_commands_program(self, num_sequences: int, num_averages: int) -> Program: with program() as prog: diff --git a/tests/two_qubit_rb/test_verification.py b/tests/two_qubit_rb/test_verification.py index 6529fe0b..ad8ed070 100644 --- a/tests/two_qubit_rb/test_verification.py +++ b/tests/two_qubit_rb/test_verification.py @@ -1,12 +1,15 @@ import os from pathlib import Path +import numpy as np import pytest +import tqdm cirq = pytest.importorskip("cirq") from qualang_tools.bakery.bakery import Baking from qualang_tools.characterization.two_qubit_rb import TwoQubitRb, TwoQubitRbDebugger +from qualang_tools.characterization.two_qubit_rb.two_qubit_rb.TwoQubitRBDebugger import phased_xz_command_sequences def test_all_verification(config): @@ -59,7 +62,7 @@ def meas(): rb.verify_sequences() -def test_debugger(config): +def test_debugger_bell_state_circuit(config): def bake_phased_xz(baker: Baking, q, x, z, a): pass @@ -81,5 +84,29 @@ def meas(): config, bake_phased_xz, cz_generator, prep, meas, verify_generation=False, interleaving_gate=None ) + parent_dir = Path(os.path.dirname(os.path.abspath(__file__))) + rb.save_command_mapping_to_file(parent_dir / "commands.txt") + + bell_state_circuit_string = r"(\frac{Y}{2} \otimes -\frac{Y}{2}), \text {CZ}, (I \otimes \frac{Y}{2}) \Rightarrow |\Phi^+\rangle_{Bell}" + bell_state = (1 / np.sqrt(2)) * ( + np.kron(np.array([1, 0]), np.array([1, 0])) + + np.kron(np.array([0, 1]), np.array([0, 1])) + ) + bell_state_rho = np.outer(bell_state, bell_state.conj()) + + # search for commands producing bell-state + # for i in tqdm.tqdm(range(736)): + # sequence = [] + # for command_id in [i]: + # sequence.extend(rb._sequence_tracker.command_registry.get_command_by_id(command_id)) + # if np.allclose(rb._sequence_tracker.calculate_resultant_state(sequence), np.array(bell_state_rho)): + # print("Found!", i) + + sequence = [] + for command_id in phased_xz_command_sequences[bell_state_circuit_string]: + sequence.extend(rb._sequence_tracker.command_registry.get_command_by_id(command_id)) + + assert np.allclose(rb._sequence_tracker.calculate_resultant_state(sequence), np.array(bell_state_rho)) + rb_debugger = TwoQubitRbDebugger(rb) rb_debugger.run_phased_xz_commands(None, 100) \ No newline at end of file