From ea50ed5d73b7a7a34809ff0aa944b297d2f37174 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Jaskula <99367153+jcjaskula-aws@users.noreply.github.com> Date: Tue, 20 Jun 2023 09:04:06 -0400 Subject: [PATCH 1/4] fix: pulse plotting with barriers that have no argument (#577) * fix: increase pulse plotting test accuracy * fix: pulse plot with barriers without argument --- src/braket/pulse/ast/approximation_parser.py | 3 + .../pulse/ast/test_approximation_parser.py | 160 +++++++++--------- 2 files changed, 81 insertions(+), 82 deletions(-) diff --git a/src/braket/pulse/ast/approximation_parser.py b/src/braket/pulse/ast/approximation_parser.py index 51d5851a2..68a36b453 100644 --- a/src/braket/pulse/ast/approximation_parser.py +++ b/src/braket/pulse/ast/approximation_parser.py @@ -155,6 +155,9 @@ def visit_QuantumBarrier(self, node: ast.QuantumBarrier, context: _ParseState) - context (_ParseState): The parse state context. """ frames = self._get_frame_parameters(node.qubits, context) + if len(frames) == 0: + # barrier without arguments is applied to all the frames of the context + frames = list(context.frame_data.keys()) dts = [context.frame_data[frame_id].dt for frame_id in frames] max_time = max([context.frame_data[frame_id].current_time for frame_id in frames]) # All frames are delayed till the first multiple of the LCM([port.dts]) diff --git a/test/unit_tests/braket/pulse/ast/test_approximation_parser.py b/test/unit_tests/braket/pulse/ast/test_approximation_parser.py index 1521875ce..2f83730f6 100644 --- a/test/unit_tests/braket/pulse/ast/test_approximation_parser.py +++ b/test/unit_tests/braket/pulse/ast/test_approximation_parser.py @@ -41,13 +41,11 @@ def test_bare_pulsequence(): def test_delay(port): frame = Frame(frame_id="frame1", port=port, frequency=1e8, phase=0, is_predefined=False) pulse_seq = PulseSequence().delay(frame, 3e-9) - # 3 datapoints for delay expected_amplitudes = {"frame1": TimeSeries()} expected_frequencies = {"frame1": TimeSeries()} expected_phases = {"frame1": TimeSeries()} - # 2 datapoints for first delay expected_amplitudes["frame1"].put(0, 0).put(2e-9, 0) expected_frequencies["frame1"].put(0, 1e8).put(2e-9, 1e8) expected_phases["frame1"].put(0, 0).put(2e-9, 0) @@ -60,13 +58,11 @@ def test_delay(port): def test_predefined_frame(port): frame = Frame(frame_id="frame1", port=port, frequency=1e8, phase=0, is_predefined=True) pulse_seq = PulseSequence().delay(frame, 3e-9) - # 3 datapoints for delay expected_amplitudes = {"frame1": TimeSeries()} expected_frequencies = {"frame1": TimeSeries()} expected_phases = {"frame1": TimeSeries()} - # 2 datapoints for first delay expected_amplitudes["frame1"].put(0, 0).put(2e-9, 0) expected_frequencies["frame1"].put(0, 1e8).put(2e-9, 1e8) expected_phases["frame1"].put(0, 0).put(2e-9, 0) @@ -93,15 +89,10 @@ def test_set_shift_phase(port): expected_frequencies = {"frame1": TimeSeries()} expected_phases = {"frame1": TimeSeries()} - # 2 datapoints for first delay - # Parser does not like delay 2ns expected_amplitudes["frame1"].put(0, 0).put(1e-9, 0) expected_frequencies["frame1"].put(0, 1e8).put(1e-9, 1e8) expected_phases["frame1"].put(0, 1).put(1e-9, 1) - # set_shift_phase should be instantaneous (result on current or next datapoint?) - # 5 dt for second delay - # shift_phase adds 2 to the phase of the last point -> 3 expected_amplitudes["frame1"].put(2e-9, 0).put(6e-9, 0) expected_frequencies["frame1"].put(2e-9, 1e8).put(6e-9, 1e8) expected_phases["frame1"].put(2e-9, 3).put(6e-9, 3) @@ -125,13 +116,11 @@ def test_set_shift_phase_beyond_2_pi(port): expected_frequencies = {"frame1": TimeSeries()} expected_phases = {"frame1": TimeSeries()} - # 2 datapoints for first delay # 5pi/2 is reduced to pi/2 expected_amplitudes["frame1"].put(0, 0).put(1e-9, 0) expected_frequencies["frame1"].put(0, 1e8).put(1e-9, 1e8) expected_phases["frame1"].put(0, np.pi / 2).put(1e-9, np.pi / 2) - # set_shift_phase should be instantaneous (result on current or next datapoint?) # shift_phase adds -pi to the phase of the last point -> 3pi/2 expected_amplitudes["frame1"].put(2e-9, 0).put(6e-9, 0) expected_frequencies["frame1"].put(2e-9, 1e8).put(6e-9, 1e8) @@ -151,22 +140,15 @@ def test_set_shift_frequency(port): .shift_frequency(frame, -0.1e8) .delay(frame, 10e-9) ) - # 2 datapoints for delay - # set_shift_phase should be instantaneous (result on current or next datapoint?) - # shift_phase adds 2 to the phase of the last point -> 3 expected_amplitudes = {"frame1": TimeSeries()} expected_frequencies = {"frame1": TimeSeries()} expected_phases = {"frame1": TimeSeries()} - # 2 datapoints for first delay expected_amplitudes["frame1"].put(0, 0).put(19e-9, 0) expected_frequencies["frame1"].put(0, 2e8).put(19e-9, 2e8) expected_phases["frame1"].put(0, 0).put(19e-9, 0) - # set_shift_phase should be instantaneous (result on current or next datapoint?) - # 5 dt for second delay - # shift_phase adds 2 to the phase of the last point -> 3 expected_amplitudes["frame1"].put(20e-9, 0).put(29e-9, 0) expected_frequencies["frame1"].put(20e-9, 1.9e8).put(29e-9, 1.9e8) expected_phases["frame1"].put(20e-9, 0).put(29e-9, 0) @@ -180,7 +162,6 @@ def test_play_arbitrary_waveforms(port): frame = Frame(frame_id="frame1", port=port, frequency=1e8, phase=0, is_predefined=False) my_arb_wf = ArbitraryWaveform([0.4 + 0.1j, -0.8 + 0.1j, 1 + 0.2j]) pulse_seq = PulseSequence().play(frame, my_arb_wf).capture_v0(frame) - # 3 datapoints for arb wf play expected_amplitudes = {"frame1": TimeSeries()} expected_frequencies = {"frame1": TimeSeries()} @@ -201,7 +182,6 @@ def test_play_literal(port): frame = Frame(frame_id="frame1", port=port, frequency=1e8, phase=0, is_predefined=False) pulse_seq = PulseSequence() pulse_seq._program.play(frame=frame, waveform=[0.4 + 0.1j, -0.8 + 0.1j, 1 + 0.2j]) - # 3 datapoints for arb wf play expected_amplitudes = {"frame1": TimeSeries()} expected_frequencies = {"frame1": TimeSeries()} @@ -290,7 +270,6 @@ def test_play_gaussian_waveforms(port): length=1e-8, sigma=1.69e-9, amplitude=1.0, zero_at_edges=False ) pulse_seq = PulseSequence().play(frame1, gaussian_wf_ZaE_False) - # X datapoints... times = np.arange(0, 1e-8, port.dt) values = np.array( @@ -329,21 +308,20 @@ def test_play_gaussian_waveforms(port): length=1e-8, sigma=1.69e-9, amplitude=1.0, zero_at_edges=True ) pulse_seq.play(frame1, gaussian_wf_ZaE_True) - # X datapoints... times = np.arange(0, 1e-8, port.dt) values = np.array( [ - 0.0 + 0.0j, - complex(0.04879311), - complex(0.1967938), - complex(0.49004931), - complex(0.83735931), + complex(0.0), + complex(0.04879310874736347), + complex(0.1967938049565093), + complex(0.49004931075238933), + complex(0.8373593063365198), complex(1.0), - complex(0.83735931), - complex(0.49004931), - complex(0.1967938), - complex(0.04879311), + complex(0.8373593063365196), + complex(0.49004931075238906), + complex(0.1967938049565092), + complex(0.048793108747363416), ], dtype=np.complex128, ) @@ -412,16 +390,16 @@ def test_play_drag_gaussian_waveforms(port): times = np.arange(0, 1e-8, port.dt) values = np.array( [ - 0.0 + 0.0j, - 0.04879311 + 0.06833529j, - 0.1967938 + 0.20670894j, - 0.49004931 + 0.34315977j, - 0.83735931 + 0.29318277j, - 1.0 + 0.0j, - 0.83735931 - 0.29318277j, - 0.49004931 - 0.34315977j, - 0.1967938 - 0.20670894j, - 0.04879311 - 0.06833529j, + complex(0.0, 0.0), + complex(0.04879310874736347, 0.0683352946288484), + complex(0.1967938049565093, 0.20670894396888342), + complex(0.49004931075238933, 0.34315977084303023), + complex(0.8373593063365198, 0.2931827689284408), + complex(1.0, 0), + complex(0.8373593063365196, -0.293182768928441), + complex(0.49004931075238906, -0.34315977084303023), + complex(0.1967938049565092, -0.20670894396888334), + complex(0.048793108747363416, -0.06833529462884834), ], dtype=np.complex128, ) @@ -490,29 +468,67 @@ def test_barrier_same_dt(port): expected_frequencies["frame2"].put(shift_time_frame2 + t, 1e8) expected_phases["frame2"].put(shift_time_frame2 + t, 0) - # # Pad frame2 - # shift_time_frame2 = shift_time_frame2 + pulse_length - # last_time_frame1 = expected_amplitudes["frame1"].times()[-1] + parser = _ApproximationParser(program=pulse_seq._program, frames=to_dict([frame1, frame2])) + + verify_results(parser, expected_amplitudes, expected_frequencies, expected_phases) + + +def test_barrier_no_args(port): + frame1 = Frame(frame_id="frame1", port=port, frequency=1e8, phase=0, is_predefined=False) + frame2 = Frame(frame_id="frame2", port=port, frequency=1e8, phase=0, is_predefined=False) + pulse_seq = ( + PulseSequence() + .play(frame1, ConstantWaveform(12e-9, 0.75)) # Inst1 + .barrier([]) # Inst2 + .play(frame1, ConstantWaveform(16e-9, 1)) # Inst3 + .play(frame2, ConstantWaveform(8e-9, -1)) # Inst4 + ) + + expected_amplitudes = {"frame1": TimeSeries(), "frame2": TimeSeries()} + expected_frequencies = {"frame1": TimeSeries(), "frame2": TimeSeries()} + expected_phases = {"frame1": TimeSeries(), "frame2": TimeSeries()} + + # Inst1 + shift_time_frame1 = 0 + pulse_length = 12e-9 + times = np.arange(0, pulse_length, port.dt) + values = 0.75 * np.ones_like(times) + for t, v in zip(times, values): + expected_amplitudes["frame1"].put(shift_time_frame1 + t, v) + expected_frequencies["frame1"].put(shift_time_frame1 + t, 1e8) + expected_phases["frame1"].put(shift_time_frame1 + t, 0) + + # Inst2 + # Delay frame2 from 0ns to 11ns + shift_time_frame2 = 0 + + expected_amplitudes["frame2"].put(0, 0).put(11e-9, 0) + expected_frequencies["frame2"].put(0, 1e8).put(11e-9, 1e8) + expected_phases["frame2"].put(0, 0).put(11e-9, 0) - # # Do we need to pad frame1? - # expected_amplitudes["frame1"].put(last_time_frame1 + port.dt, 0) - # expected_frequencies["frame1"].put(last_time_frame1 + port.dt, 1e8) - # expected_phases["frame1"].put(last_time_frame1 + port.dt, 0) + # Inst3 + shift_time_frame1 = shift_time_frame1 + pulse_length + pulse_length = 16e-9 + times = np.arange(0, pulse_length, port.dt) + values = 1 * np.ones_like(times) + for t, v in zip(times, values): + expected_amplitudes["frame1"].put(shift_time_frame1 + t, v) + expected_frequencies["frame1"].put(shift_time_frame1 + t, 1e8) + expected_phases["frame1"].put(shift_time_frame1 + t, 0) - # expected_amplitudes["frame2"].put(shift_time_frame2, 0).put( - # last_time_frame1 + port.dt, 0 - # ) - # expected_frequencies["frame2"].put(shift_time_frame2, 1e8).put( - # last_time_frame1 + port.dt, 1e8 - # ) - # expected_phases["frame2"].put(shift_time_frame2, 0).put(last_time_frame1 + port.dt, 0) + # Inst4 + shift_time_frame2 = shift_time_frame1 + pulse_length = 8e-9 + times = np.arange(0, pulse_length, port.dt) + values = -1 * np.ones_like(times) + for t, v in zip(times, values): + expected_amplitudes["frame2"].put(shift_time_frame2 + t, v) + expected_frequencies["frame2"].put(shift_time_frame2 + t, 1e8) + expected_phases["frame2"].put(shift_time_frame2 + t, 0) parser = _ApproximationParser(program=pulse_seq._program, frames=to_dict([frame1, frame2])) verify_results(parser, expected_amplitudes, expected_frequencies, expected_phases) - # Array retrievable with - # x=np.arange(0, ts.times()+1e-9, 1e-9) - # np.interp(x, ts.times(), ts.values()) # See last cells of SDK Testing.ipynb def test_barrier_different_dt(port): @@ -543,8 +559,7 @@ def test_barrier_different_dt(port): expected_phases["frame1"].put(shift_time_frame1 + t, 0) # Inst2 - # barrier at 35ns (first point coinciding with frame2: np.ceil(max(20,0)/np.lcm(dt1=5,dt2=7))*np.lcm(dt1=5,dt2=7)) # noqa - # reset shift_time_frame1 = shift_time_frame2 = 35 + # barrier at 40ns (first point coinciding with frame2 (every 20ns)) shift_time_frame1 = shift_time_frame2 = 40e-9 latest_time_frame1 = expected_amplitudes["frame1"].times()[-1] @@ -580,13 +595,6 @@ def test_barrier_different_dt(port): expected_frequencies["frame2"].put(shift_time_frame2 + t, 1e8) expected_phases["frame2"].put(shift_time_frame2 + t, 0) - # # Pad frame2 - # shift_time_frame2 = shift_time_frame2 + pulse_length - # last_time = 80e-9 - # expected_amplitudes["frame2"].put(shift_time_frame2, 0).put(last_time, 0) - # expected_frequencies["frame2"].put(shift_time_frame2, 1e8).put(last_time, 1e8) - # expected_phases["frame2"].put(shift_time_frame2, 0).put(last_time, 0) - parser = _ApproximationParser(program=pulse_seq._program, frames=to_dict([frame1, frame2])) verify_results(parser, expected_amplitudes, expected_frequencies, expected_phases) @@ -628,18 +636,6 @@ def test_pad_different_dt(port): expected_frequencies["frame2"].put(shift_time_frame2 + t, 1e8) expected_phases["frame2"].put(shift_time_frame2 + t, 0) - # # Pad all frames to end up - # last_time_frame1 = expected_amplitudes["frame1"].times()[-1] - # last_time_frame2 = expected_amplitudes["frame2"].times()[-1] - - # last_time = 40e-9 - # expected_amplitudes["frame1"].put(last_time_frame1 + port1.dt, 0).put(last_time, 0) - # expected_frequencies["frame1"].put(last_time_frame1 + port1.dt, 1e8).put(last_time, 1e8) # noqa - # expected_phases["frame1"].put(last_time_frame1 + port1.dt, 0).put(last_time, 0) - # expected_amplitudes["frame2"].put(last_time_frame2 + port2.dt, 0).put(last_time, 0) - # expected_frequencies["frame2"].put(last_time_frame2 + port2.dt, 1e8).put(last_time, 1e8) # noqa - # expected_phases["frame2"].put(last_time_frame2 + port2.dt, 0).put(last_time, 0) - parser = _ApproximationParser(program=pulse_seq._program, frames=to_dict([frame1, frame2])) verify_results(parser, expected_amplitudes, expected_frequencies, expected_phases) @@ -709,9 +705,9 @@ def test_duration_literal(): def verify_results(results, expected_amplitudes, expected_frequencies, expected_phases): for frame_id in expected_amplitudes.keys(): - assert _all_close(results.amplitudes[frame_id], expected_amplitudes[frame_id]) - assert _all_close(results.frequencies[frame_id], expected_frequencies[frame_id]) - assert _all_close(results.phases[frame_id], expected_phases[frame_id]) + assert _all_close(results.amplitudes[frame_id], expected_amplitudes[frame_id], 1e-10) + assert _all_close(results.frequencies[frame_id], expected_frequencies[frame_id], 1e-10) + assert _all_close(results.phases[frame_id], expected_phases[frame_id], 1e-10) def to_dict(frames: Union[Frame, List]): From 512ab9398990a7860067297e2e45da5fd497970e Mon Sep 17 00:00:00 2001 From: ci Date: Tue, 20 Jun 2023 16:53:57 +0000 Subject: [PATCH 2/4] prepare release v1.42.2 --- CHANGELOG.md | 6 ++++++ src/braket/_sdk/_version.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d375dfe9..87e5ff78d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v1.42.2 (2023-06-20) + +### Bug Fixes and Other Changes + + * pulse plotting with barriers that have no argument + ## v1.42.1 (2023-06-07) ### Bug Fixes and Other Changes diff --git a/src/braket/_sdk/_version.py b/src/braket/_sdk/_version.py index 79e25b181..b27143b5d 100644 --- a/src/braket/_sdk/_version.py +++ b/src/braket/_sdk/_version.py @@ -15,4 +15,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "1.42.2.dev0" +__version__ = "1.42.2" From 8dcbcd00786030c1455c2a27d93bd7cde378e96b Mon Sep 17 00:00:00 2001 From: ci Date: Tue, 20 Jun 2023 16:53:57 +0000 Subject: [PATCH 3/4] update development version to v1.42.3.dev0 --- src/braket/_sdk/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/braket/_sdk/_version.py b/src/braket/_sdk/_version.py index b27143b5d..d6b9e29ac 100644 --- a/src/braket/_sdk/_version.py +++ b/src/braket/_sdk/_version.py @@ -15,4 +15,4 @@ Version number (major.minor.patch[-label]) """ -__version__ = "1.42.2" +__version__ = "1.42.3.dev0" From a6093b488ec236717004cf7a67e23a0659c2eca2 Mon Sep 17 00:00:00 2001 From: Abe Coull <85974725+math411@users.noreply.github.com> Date: Tue, 20 Jun 2023 15:34:27 -0700 Subject: [PATCH 4/4] infra: cleanup the tox env between runs (#576) Co-authored-by: Viraj Chaudhari <72896239+virajvchaudhari@users.noreply.github.com> --- tox.ini | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index ba688287b..b0eace765 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,10 @@ [tox] -envlist = linters,docs,unit-tests +envlist = clean,linters,docs,unit-tests + +[testenv:clean] +deps = coverage +skip_install = true +commands = coverage erase [testenv:unit-tests] basepython = python3