From f44a37e4f609fa301353493664229e5b278fb307 Mon Sep 17 00:00:00 2001 From: Hayk Sargsyan <52532457+hay-k@users.noreply.github.com> Date: Fri, 8 Nov 2024 11:37:35 +0400 Subject: [PATCH 1/3] Fix compiler unnecessarily pushing pulses to late start in certain situations --- src/qibolab/compilers/compiler.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/qibolab/compilers/compiler.py b/src/qibolab/compilers/compiler.py index 38fb9c762..6fa8cec7e 100644 --- a/src/qibolab/compilers/compiler.py +++ b/src/qibolab/compilers/compiler.py @@ -104,7 +104,6 @@ def _compile_gate( platform, sequence, virtual_z_phases, - moment_start, delays, wire_names, ): @@ -120,13 +119,12 @@ def _compile_gate( # update global pulse sequence # determine the right start time based on the availability of the qubits involved - all_qubits = {*gate_sequence.qubits, *gate.qubits} + all_qubits = {*gate_sequence.qubits, *gate.qubits, *gate_phases.keys()} start = max( - *[ + [ sequence.get_qubit_pulses(qubit).finish + delays[qubit] for qubit in all_qubits - ], - moment_start, + ] ) # shift start time and phase according to the global sequence for pulse in gate_sequence: @@ -159,7 +157,6 @@ def compile(self, circuit, platform): # process circuit gates delays = defaultdict(int) for moment in circuit.queue.moments: - moment_start = sequence.finish for gate in set(filter(lambda x: x is not None, moment)): if isinstance(gate, gates.Align): for qubit in gate.qubits: @@ -170,7 +167,6 @@ def compile(self, circuit, platform): platform, sequence, virtual_z_phases, - moment_start, delays, circuit.wire_names, ) From 551dbca9769d833a32f32c9a6ef3409001e6d69f Mon Sep 17 00:00:00 2001 From: Hayk Sargsyan <52532457+hay-k@users.noreply.github.com> Date: Mon, 11 Nov 2024 11:50:22 +0400 Subject: [PATCH 2/3] compiler tests for f44a37e4f609fa301353493664229e5b278fb307 --- tests/test_compiler.py | 59 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 tests/test_compiler.py diff --git a/tests/test_compiler.py b/tests/test_compiler.py new file mode 100644 index 000000000..5d5e4da45 --- /dev/null +++ b/tests/test_compiler.py @@ -0,0 +1,59 @@ +import numpy as np +import pytest +from qibo import Circuit, gates + +from qibolab import create_platform +from qibolab.compilers.compiler import Compiler + + +@pytest.fixture +def dummy(): + return create_platform("dummy") + + +@pytest.fixture +def dummy_couplers(): + return create_platform("dummy_couplers") + + +@pytest.fixture +def compiler(): + return Compiler.default() + + +def test_measurement_timings(dummy, compiler): + q0, q1 = 0, 1 + circ = Circuit(2) + circ.add(gates.GPI2(q0, phi=0.0)) + circ.add(gates.GPI2(q1, phi=np.pi / 2)) + circ.add(gates.GPI2(q1, phi=np.pi)) + + # put measurement in different moments + circ.add(gates.M(q0)) + circ.add(gates.M(q1)) + + # make sure they are in different moments before proceeding + assert not any([len([gate for gate in m if isinstance(gate, gates.M)]) == 2 for m in circ.queue.moments]) + + circ._wire_names = [q0, q1] + sequence, _ = compiler.compile(circ, dummy) + + MEASUREMENT_DURATION = 2000 + for pulse in sequence.ro_pulses: + # assert that measurements don't happen one after another + assert not pulse.start >= MEASUREMENT_DURATION + + +def test_coupler_pulse_timing(dummy_couplers, compiler): + q0, q1, q2 = 0, 1, 2 + circ = Circuit(3) + circ.add(gates.GPI2(q0, phi=0.0)) + circ.add(gates.GPI2(q0, phi=np.pi)) + circ.add(gates.GPI2(q1, phi=0.0)) + circ.add(gates.CZ(q1, q2)) + + circ._wire_names = [q0, q1, q2] + sequence, _ = compiler.compile(circ, dummy_couplers) + + coupler_pulse = sequence.cf_pulses[0] + assert coupler_pulse.start == 40 From 985a953fbb545c9b242b114b19cb55ba34601fbf Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 11 Nov 2024 08:07:03 +0000 Subject: [PATCH 3/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/test_compiler.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/tests/test_compiler.py b/tests/test_compiler.py index 5d5e4da45..6ca651c4d 100644 --- a/tests/test_compiler.py +++ b/tests/test_compiler.py @@ -27,22 +27,27 @@ def test_measurement_timings(dummy, compiler): circ.add(gates.GPI2(q0, phi=0.0)) circ.add(gates.GPI2(q1, phi=np.pi / 2)) circ.add(gates.GPI2(q1, phi=np.pi)) - + # put measurement in different moments circ.add(gates.M(q0)) circ.add(gates.M(q1)) - + # make sure they are in different moments before proceeding - assert not any([len([gate for gate in m if isinstance(gate, gates.M)]) == 2 for m in circ.queue.moments]) - + assert not any( + [ + len([gate for gate in m if isinstance(gate, gates.M)]) == 2 + for m in circ.queue.moments + ] + ) + circ._wire_names = [q0, q1] sequence, _ = compiler.compile(circ, dummy) - + MEASUREMENT_DURATION = 2000 for pulse in sequence.ro_pulses: # assert that measurements don't happen one after another assert not pulse.start >= MEASUREMENT_DURATION - + def test_coupler_pulse_timing(dummy_couplers, compiler): q0, q1, q2 = 0, 1, 2 @@ -51,9 +56,9 @@ def test_coupler_pulse_timing(dummy_couplers, compiler): circ.add(gates.GPI2(q0, phi=np.pi)) circ.add(gates.GPI2(q1, phi=0.0)) circ.add(gates.CZ(q1, q2)) - + circ._wire_names = [q0, q1, q2] sequence, _ = compiler.compile(circ, dummy_couplers) - + coupler_pulse = sequence.cf_pulses[0] assert coupler_pulse.start == 40