From 96607f6b2068594f216928b954db0f516e1466ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iy=C3=A1n?= Date: Thu, 16 May 2024 08:52:54 +0200 Subject: [PATCH] Avoid lossing precision when scaling frequencies (#12392) * Avoid lossing precision when scaling frequencies Classes in pulse_instruction.py scale frequency values to GHz by multipliying `ParameterExpression` with float 1e9. This can lead to numerical errors on some systems using symengine. Instead, this scaling can be done multiplying by integer 10**9. See: https://github.com/Qiskit/qiskit/issues/12359#issuecomment-2104426621 * Add release note --------- Co-authored-by: Jake Lishman --- qiskit/qobj/converters/pulse_instruction.py | 12 ++++++------ .../fix-symbolic-unit-scaling-c3eb4d9be674dfd6.yaml | 8 ++++++++ 2 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 releasenotes/notes/fix-symbolic-unit-scaling-c3eb4d9be674dfd6.yaml diff --git a/qiskit/qobj/converters/pulse_instruction.py b/qiskit/qobj/converters/pulse_instruction.py index 77e811100f37..80c332aaab4a 100644 --- a/qiskit/qobj/converters/pulse_instruction.py +++ b/qiskit/qobj/converters/pulse_instruction.py @@ -234,7 +234,7 @@ def _convert_set_frequency( "name": "setf", "t0": time_offset + instruction.start_time, "ch": instruction.channel.name, - "frequency": instruction.frequency / 1e9, + "frequency": instruction.frequency / 10**9, } return self._qobj_model(**command_dict) @@ -257,7 +257,7 @@ def _convert_shift_frequency( "name": "shiftf", "t0": time_offset + instruction.start_time, "ch": instruction.channel.name, - "frequency": instruction.frequency / 1e9, + "frequency": instruction.frequency / 10**9, } return self._qobj_model(**command_dict) @@ -746,7 +746,7 @@ def _convert_setf( .. note:: We assume frequency value is expressed in string with "GHz". - Operand value is thus scaled by a factor of 1e9. + Operand value is thus scaled by a factor of 10^9. Args: instruction: SetFrequency qobj instruction @@ -755,7 +755,7 @@ def _convert_setf( Qiskit Pulse set frequency instructions """ channel = self.get_channel(instruction.ch) - frequency = self.disassemble_value(instruction.frequency) * 1e9 + frequency = self.disassemble_value(instruction.frequency) * 10**9 yield instructions.SetFrequency(frequency, channel) @@ -768,7 +768,7 @@ def _convert_shiftf( .. note:: We assume frequency value is expressed in string with "GHz". - Operand value is thus scaled by a factor of 1e9. + Operand value is thus scaled by a factor of 10^9. Args: instruction: ShiftFrequency qobj instruction @@ -777,7 +777,7 @@ def _convert_shiftf( Qiskit Pulse shift frequency schedule instructions """ channel = self.get_channel(instruction.ch) - frequency = self.disassemble_value(instruction.frequency) * 1e9 + frequency = self.disassemble_value(instruction.frequency) * 10**9 yield instructions.ShiftFrequency(frequency, channel) diff --git a/releasenotes/notes/fix-symbolic-unit-scaling-c3eb4d9be674dfd6.yaml b/releasenotes/notes/fix-symbolic-unit-scaling-c3eb4d9be674dfd6.yaml new file mode 100644 index 000000000000..5ca00904a9ae --- /dev/null +++ b/releasenotes/notes/fix-symbolic-unit-scaling-c3eb4d9be674dfd6.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - | + Fixed a floating-point imprecision when scaling certain pulse units + between seconds and nanoseconds. If the pulse was symbolically defined, + an unnecessary floating-point error could be introduced by the scaling + for certain builds of ``symengine``, which could manifest in unexpected + results once the symbols were fully bound. See `#12392 `__.