From 76803d5919dcce926566a287b2229670f88e9cec Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Wed, 12 Jun 2024 07:49:59 +0200 Subject: [PATCH] Use hash of numeric value for bound parameter expressions (#12488) (#12548) * Use hash of numeric value for bound parameter expressions If a `ParameterExpression` has no unbound parameters, the underlying bound value can be hashed instead of the tuple that accounts for the symbolic expression. Doing this allows for the `ParameterExpression` to match the hash for the numeric value it compares equal to. Closes #12487 * Add release note (cherry picked from commit bc685d3002915327f3070ef8914c6c1484084b57) Co-authored-by: Will Shanks --- qiskit/circuit/parameterexpression.py | 3 +++ .../notes/parameterexpression-hash-d2593ab1715aa42c.yaml | 8 ++++++++ test/python/circuit/test_parameters.py | 1 + 3 files changed, 12 insertions(+) create mode 100644 releasenotes/notes/parameterexpression-hash-d2593ab1715aa42c.yaml diff --git a/qiskit/circuit/parameterexpression.py b/qiskit/circuit/parameterexpression.py index 4f6453f90f4c..b98a294b090f 100644 --- a/qiskit/circuit/parameterexpression.py +++ b/qiskit/circuit/parameterexpression.py @@ -439,6 +439,9 @@ def __int__(self): raise TypeError("could not cast expression to int") from exc def __hash__(self): + if not self._parameter_symbols: + # For fully bound expressions, fall back to the underlying value + return hash(self.numeric()) return hash((self._parameter_keys, self._symbol_expr)) def __copy__(self): diff --git a/releasenotes/notes/parameterexpression-hash-d2593ab1715aa42c.yaml b/releasenotes/notes/parameterexpression-hash-d2593ab1715aa42c.yaml new file mode 100644 index 000000000000..075de45b3b23 --- /dev/null +++ b/releasenotes/notes/parameterexpression-hash-d2593ab1715aa42c.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - | + :class:`.ParameterExpression` was updated so that fully bound instances + that compare equal to instances of Python's built-in numeric types (like + ``float`` and ``int``) also have hash values that match those of the other + instances. This change ensures that these types can be used interchangeably + as dictionary keys. See `#12488 `__. diff --git a/test/python/circuit/test_parameters.py b/test/python/circuit/test_parameters.py index 7bcc2cd35f3a..3681998c0638 100644 --- a/test/python/circuit/test_parameters.py +++ b/test/python/circuit/test_parameters.py @@ -1425,6 +1425,7 @@ def test_compare_to_value_when_bound(self): x = Parameter("x") bound_expr = x.bind({x: 2.3}) self.assertEqual(bound_expr, 2.3) + self.assertEqual(hash(bound_expr), hash(2.3)) def test_abs_function_when_bound(self): """Verify expression can be used with