Skip to content

Commit

Permalink
Fix ParameterExpression.is_real if symengine is installed (#8456
Browse files Browse the repository at this point in the history
)

* Fix is_real on ParameterExpression

* typo in reno

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
Cryoris and mergify[bot] authored Aug 4, 2022
1 parent 3705798 commit 2bab09c
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 2 deletions.
11 changes: 9 additions & 2 deletions qiskit/circuit/parameterexpression.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,14 +508,21 @@ def __eq__(self, other):
def is_real(self):
"""Return whether the expression is real"""

if not self._symbol_expr.is_real and self._symbol_expr.is_real is not None:
# workaround for symengine behavior that const * (0 + 1 * I) is not real
# see https://github.com/symengine/symengine.py/issues/414
if _optionals.HAS_SYMENGINE and self._symbol_expr.is_real is None:
symbol_expr = self._symbol_expr.evalf()
else:
symbol_expr = self._symbol_expr

if not symbol_expr.is_real and symbol_expr.is_real is not None:
# Symengine returns false for is_real on the expression if
# there is a imaginary component (even if that component is 0),
# but the parameter will evaluate as real. Check that if the
# expression's is_real attribute returns false that we have a
# non-zero imaginary
if _optionals.HAS_SYMENGINE:
if self._symbol_expr.imag != 0.0:
if symbol_expr.imag != 0.0:
return False
else:
return False
Expand Down
14 changes: 14 additions & 0 deletions releasenotes/notes/fix-paramexpr-isreal-8d20348b4ce6cbe7.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
fixes:
- |
Fix a bug where a bound :class:`.ParameterExpression` was not identified as real
if ``symengine`` was installed and the bound expression was not a plain ``1j``.
For example::
from qiskit.circuit import Parameter
x = Parameter("x")
expr = 1j * x
bound = expr.bind({x: 2})
print(bound.is_real()) # used to be True, but is now False
8 changes: 8 additions & 0 deletions test/python/circuit/test_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -1718,6 +1718,14 @@ def test_parameter_expression_grad(self):
self.assertEqual(expr.gradient(x), 2 * x)
self.assertEqual(expr.gradient(x).gradient(x), 2)

def test_bound_expression_is_real(self):
"""Test is_real on bound parameters."""
x = Parameter("x")
expr = 1j * x
bound = expr.bind({x: 2})

self.assertFalse(bound.is_real())


class TestParameterEquality(QiskitTestCase):
"""Test equality of Parameters and ParameterExpressions."""
Expand Down

0 comments on commit 2bab09c

Please sign in to comment.