From 895b7245c6f6ac21f91e70c327af1a4a2b5b13c3 Mon Sep 17 00:00:00 2001 From: Leonardo Andreta de Castro Date: Wed, 1 Apr 2020 13:46:23 +1100 Subject: [PATCH 1/5] Eliminating the need to test for end times > start times in each pulse --- .../driven_controls.py | 30 +++++++------------ 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py b/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py index c4a37f87..6bb116d0 100644 --- a/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py +++ b/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py @@ -77,17 +77,17 @@ def _check_maximum_rotation_rate( """ # check against global parameters - if maximum_rabi_rate < 0. or maximum_rabi_rate > UPPER_BOUND_RABI_RATE: + if maximum_rabi_rate <= 0. or maximum_rabi_rate > UPPER_BOUND_RABI_RATE: raise ArgumentsValueError( - 'Maximum rabi rate must be between 0. and maximum value of {0}'.format( + 'Maximum rabi rate must be greater than 0. and less or equal to {0}'.format( UPPER_BOUND_RABI_RATE), {'maximum_rabi_rate': maximum_rabi_rate}, extras={'maximum_detuning_rate': maximum_detuning_rate, 'allowed_maximum_rabi_rate': UPPER_BOUND_RABI_RATE}) - if maximum_detuning_rate < 0. or maximum_detuning_rate > UPPER_BOUND_DETUNING_RATE: + if maximum_detuning_rate <= 0. or maximum_detuning_rate > UPPER_BOUND_DETUNING_RATE: raise ArgumentsValueError( - 'Maximum detuning rate must be between 0. and maximum value of {0}'.format( + 'Maximum detuning rate must be greater than 0. and less or equalt o {0}'.format( UPPER_BOUND_DETUNING_RATE), {'maximum_detuning_rate': maximum_detuning_rate, }, extras={'maximum_rabi_rate': maximum_rabi_rate, @@ -112,9 +112,9 @@ def convert_dds_to_driven_control( dynamic_decoupling_sequence : qctrlopencontrols.DynamicDecouplingSequence The base DDS maximum_rabi_rate : float, optional - Maximum Rabi Rate; Defaults to 2*pi + Maximum Rabi Rate. Defaults to 2*pi, and must be greater than 0 if set. maximum_detuning_rate : float, optional - Maximum Detuning Rate; Defaults to 2*pi + Maximum Detuning Rate; Defaults to 2*pi, and must be greater than 0 if set. minimum_segment_duration : float, optional If set, further restricts the duration of every segment of the Driven Controls. Defaults to 0, in which case it does not affect the duration of the pulses. @@ -182,15 +182,6 @@ def convert_dds_to_driven_control( extras={'maximum_rabi_rate': maximum_rabi_rate, 'maximum_detuning_rate': maximum_detuning_rate}) - # check if detuning rate is supplied if there is a detuning_rotation > 0 - if np.any(detuning_rotations > 0.) and maximum_detuning_rate is None: - raise ArgumentsValueError( - 'Sequence operation includes detuning rotations. Please supply a valid ' - 'maximum_detuning_rate.', - {'detuning_rotations': dynamic_decoupling_sequence.detuning_rotations, - 'maximum_detuning_rate': maximum_detuning_rate}, - extras={'maximum_rabi_rate': maximum_rabi_rate}) - if offsets.size == 0: offsets = np.array([0, sequence_duration]) rabi_rotations = np.array([0, 0]) @@ -227,7 +218,7 @@ def convert_dds_to_driven_control( half_pulse_duration = 0. if not np.isclose(operations[1, op_idx], 0.): # Rabi rotation - half_pulse_duration = 0.5 * max(operations[1, op_idx] / maximum_rabi_rate, + half_pulse_duration = 0.5 * max(np.abs(operations[1, op_idx]) / maximum_rabi_rate, minimum_segment_duration) elif not np.isclose(operations[3, op_idx], 0.): # Detuning rotation half_pulse_duration = 0.5 * max(np.abs(operations[3, op_idx]) / maximum_detuning_rate, @@ -257,11 +248,9 @@ def convert_dds_to_driven_control( # four conditions to check # 1. Control segment start times should be monotonically increasing # 2. Control segment end times should be monotonically increasing - # 3. Control segment start time must be less than its end time - # 4. Adjacent segments should not be overlapping + # 3. Adjacent segments should not be overlapping if (np.any(pulse_start_ends[0:-1, 0] - pulse_start_ends[1:, 0] > 0.) or np.any(pulse_start_ends[0:-1, 1] - pulse_start_ends[1:, 1] > 0.) or - np.any(pulse_start_ends[:, 0] - pulse_start_ends[:, 1] > 0.) or np.any(pulse_start_ends[1:, 0]-pulse_start_ends[0:-1, 1] < 0.)): raise ArgumentsValueError('Pulse timing could not be properly deduced from ' @@ -284,7 +273,8 @@ def convert_dds_to_driven_control( 'maximum_detuning_rate': maximum_detuning_rate, 'minimum_segment_duration': minimum_segment_duration}, extras={'deduced_pulse_start_timing': pulse_start_ends[:, 0], - 'deduced_pulse_end_timing': pulse_start_ends[:, 1]}) + 'deduced_pulse_end_timing': pulse_start_ends[:, 1], + 'gap_durations': gap_durations}) if np.allclose(pulse_start_ends, 0.0): From fc2aea4a41cd7322f0e0f6af381cf9588587a20b Mon Sep 17 00:00:00 2001 From: Leonardo Andreta de Castro Date: Wed, 1 Apr 2020 13:50:06 +1100 Subject: [PATCH 2/5] Typo fixes --- .../dynamic_decoupling_sequences/driven_controls.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py b/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py index 6bb116d0..f67e2a2e 100644 --- a/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py +++ b/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py @@ -79,7 +79,7 @@ def _check_maximum_rotation_rate( # check against global parameters if maximum_rabi_rate <= 0. or maximum_rabi_rate > UPPER_BOUND_RABI_RATE: raise ArgumentsValueError( - 'Maximum rabi rate must be greater than 0. and less or equal to {0}'.format( + 'Maximum rabi rate must be greater than 0 and less or equal to {0}'.format( UPPER_BOUND_RABI_RATE), {'maximum_rabi_rate': maximum_rabi_rate}, extras={'maximum_detuning_rate': maximum_detuning_rate, @@ -87,11 +87,10 @@ def _check_maximum_rotation_rate( if maximum_detuning_rate <= 0. or maximum_detuning_rate > UPPER_BOUND_DETUNING_RATE: raise ArgumentsValueError( - 'Maximum detuning rate must be greater than 0. and less or equalt o {0}'.format( + 'Maximum detuning rate must be greater than 0 and less or equal to {0}'.format( UPPER_BOUND_DETUNING_RATE), {'maximum_detuning_rate': maximum_detuning_rate, }, extras={'maximum_rabi_rate': maximum_rabi_rate, - 'allowed_maximum_rabi_rate': UPPER_BOUND_RABI_RATE, 'allowed_maximum_detuning_rate': UPPER_BOUND_DETUNING_RATE}) @@ -112,9 +111,11 @@ def convert_dds_to_driven_control( dynamic_decoupling_sequence : qctrlopencontrols.DynamicDecouplingSequence The base DDS maximum_rabi_rate : float, optional - Maximum Rabi Rate. Defaults to 2*pi, and must be greater than 0 if set. + Maximum Rabi Rate; Defaults to 2*pi. + Must be greater than 0 and less or equal to UPPER_BOUND_RABI_RATE, if set. maximum_detuning_rate : float, optional - Maximum Detuning Rate; Defaults to 2*pi, and must be greater than 0 if set. + Maximum Detuning Rate; Defaults to 2*pi. + Must be greater than 0 and less or equal to UPPER_BOUND_DETUNING_RATE, if set. minimum_segment_duration : float, optional If set, further restricts the duration of every segment of the Driven Controls. Defaults to 0, in which case it does not affect the duration of the pulses. From 69c64a71972d82d8bf869813061567656e7a1061 Mon Sep 17 00:00:00 2001 From: Leonardo Andreta de Castro Date: Wed, 1 Apr 2020 14:10:55 +1100 Subject: [PATCH 3/5] Removing unnecessary tests --- .../driven_controls.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py b/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py index f67e2a2e..a935a50d 100644 --- a/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py +++ b/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py @@ -231,20 +231,12 @@ def convert_dds_to_driven_control( # check if any of the pulses have gone outside the time limit [0, sequence_duration] # if yes, adjust the segment timing if pulse_start_ends[0, 0] < 0.: - - if np.sum(np.abs(pulse_start_ends[0, :])) == 0: - pulse_start_ends[0, 0] = 0 - else: - translation = 0. - (pulse_start_ends[0, 0]) - pulse_start_ends[0, :] = pulse_start_ends[0, :] + translation + translation = 0. - (pulse_start_ends[0, 0]) + pulse_start_ends[0, :] = pulse_start_ends[0, :] + translation if pulse_start_ends[-1, 1] > sequence_duration: - - if np.sum(np.abs(pulse_start_ends[0, :])) == 2 * sequence_duration: - pulse_start_ends[-1, 1] = sequence_duration - else: - translation = pulse_start_ends[-1, 1] - sequence_duration - pulse_start_ends[-1, :] = pulse_start_ends[-1, :] - translation + translation = pulse_start_ends[-1, 1] - sequence_duration + pulse_start_ends[-1, :] = pulse_start_ends[-1, :] - translation # four conditions to check # 1. Control segment start times should be monotonically increasing From 3d279afd466ca6dcc800ee2df8bf3493e9be89d9 Mon Sep 17 00:00:00 2001 From: Leonardo Andreta de Castro Date: Wed, 1 Apr 2020 15:31:38 +1100 Subject: [PATCH 4/5] four -> three --- .../dynamic_decoupling_sequences/driven_controls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py b/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py index a935a50d..bdd9dca8 100644 --- a/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py +++ b/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py @@ -238,7 +238,7 @@ def convert_dds_to_driven_control( translation = pulse_start_ends[-1, 1] - sequence_duration pulse_start_ends[-1, :] = pulse_start_ends[-1, :] - translation - # four conditions to check + # three conditions to check # 1. Control segment start times should be monotonically increasing # 2. Control segment end times should be monotonically increasing # 3. Adjacent segments should not be overlapping From 0fede636326d314cd3c5536bdbc51a262ffc6115 Mon Sep 17 00:00:00 2001 From: Leonardo Andreta de Castro Date: Wed, 1 Apr 2020 16:34:02 +1100 Subject: [PATCH 5/5] Adding extra test for rabi rotations below zero. --- .../dynamic_decoupling_sequences/driven_controls.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py b/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py index bdd9dca8..0eb996b5 100644 --- a/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py +++ b/qctrlopencontrols/dynamic_decoupling_sequences/driven_controls.py @@ -173,6 +173,12 @@ def convert_dds_to_driven_control( azimuthal_angles = dynamic_decoupling_sequence.azimuthal_angles detuning_rotations = dynamic_decoupling_sequence.detuning_rotations + # check if all Rabi rotations are valid (i.e. have positive values) + if np.any(np.less(rabi_rotations, 0.)): + raise ArgumentsValueError( + 'Sequence contains negative values for Rabi rotations.', + {'dynamic_decoupling_sequence': str(dynamic_decoupling_sequence)}) + # check for valid operation if not _check_valid_operation(rabi_rotations=rabi_rotations, detuning_rotations=detuning_rotations): @@ -219,7 +225,7 @@ def convert_dds_to_driven_control( half_pulse_duration = 0. if not np.isclose(operations[1, op_idx], 0.): # Rabi rotation - half_pulse_duration = 0.5 * max(np.abs(operations[1, op_idx]) / maximum_rabi_rate, + half_pulse_duration = 0.5 * max(operations[1, op_idx] / maximum_rabi_rate, minimum_segment_duration) elif not np.isclose(operations[3, op_idx], 0.): # Detuning rotation half_pulse_duration = 0.5 * max(np.abs(operations[3, op_idx]) / maximum_detuning_rate,