Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ParameterExpression.numeric to cast to number #11109

Merged
merged 2 commits into from
Dec 19, 2023

Conversation

jakelishman
Copy link
Member

Summary

This is largely a wrap-up of the if ParameterExpression.is_real(): ... logic present in a few places across the library, but a bit more efficient for Symengine because it can re-use cases where it needed to force an evaluation to produce accurate results. Mostly, though, it simplifies a few call sites.

Details and comments

Depends on #11107, because .evalf(real=True) is a symengine-specific extension, and when TemplateOptimization produces mismatched ParameterExpressions it breaks this handling.

The additional handling in numeric to reduce the impact of the spurious imaginary components makes this generally more reliable. I came across problems with global phases during binding in a PR built on top of this - at the moment, the type of the global_phase in QuantumCircuit.assign_parameters isn't validated in the same way, but in a unification PR I had it was, and some deeply nested (but completely valid) assignments were failing.

@jakelishman jakelishman added Changelog: New Feature Include in the "Added" section of the changelog mod: circuit Related to the core of the `QuantumCircuit` class or the circuit library labels Oct 25, 2023
@jakelishman jakelishman added this to the 1.0.0pre1 milestone Oct 25, 2023
@jakelishman jakelishman requested a review from a team as a code owner October 25, 2023 11:38
@qiskit-bot
Copy link
Collaborator

One or more of the the following people are requested to review this:

  • @Qiskit/terra-core

This is largely a wrap-up of the `if ParameterExpression.is_real(): ...`
logic present in a few places across the library, but a bit more
efficient for Symengine because it can re-use cases where it needed to
force an evaluation to produce accurate results.  Mostly, though, it
simplifies a few call sites.
@jakelishman
Copy link
Member Author

Now rebased over #11107 and other changes to main (notably #10902) that have merged since this was created. Ready for review / merge.

@coveralls
Copy link

coveralls commented Dec 18, 2023

Pull Request Test Coverage Report for Build 7259881506

Warning: This coverage report may be inaccurate.

We've detected an issue with your CI configuration that might affect the accuracy of this pull request's coverage report.
To ensure accuracy in future PRs, please see these guidelines.
A quick fix for this PR: rebase it; your next report should be accurate.

  • 17 of 19 (89.47%) changed or added relevant lines in 3 files are covered.
  • 27 unchanged lines in 3 files lost coverage.
  • Overall coverage increased (+0.02%) to 87.547%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/circuit/quantumcircuit.py 3 4 75.0%
qiskit/transpiler/passes/basis/basis_translator.py 3 4 75.0%
Files with Coverage Reduction New Missed Lines %
crates/qasm2/src/lex.rs 5 91.67%
crates/qasm2/src/parse.rs 6 97.6%
qiskit/providers/basicaer/unitary_simulator.py 16 80.54%
Totals Coverage Status
Change from base Build 7250858362: 0.02%
Covered Lines: 59173
Relevant Lines: 67590

💛 - Coveralls

Copy link
Member

@1ucian0 1ucian0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! Just some comments here and there.

self.assertIsInstance(one_imaginary.numeric(), complex)
self.assertEqual(one_imaginary.numeric(), 1j)

# This is one particular case where symengine 0.9.2 (and probably others) struggles when
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This corner case can be removed with #11315 ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd leave it in regardless - it still works as a regression test for us.

# Symengine returns `complex` if any imaginary floating-point enters at all, even if
# the result is zero. The best we can do is detect that and decay to a float.
out = complex(self._symbol_expr)
return out.real if out.imag == 0.0 else out
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be a math.isclose? Zero-checking floats is always hard to me...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I'd say no - the only times we've seen uses where bad imaginary components enter is from bugs within Symengine itself (which this function works around), where the coefficient scales with the operation being done, so could be arbitrarily large. Auto clipping to zero also makes it tricky for people who were expecting to deal with very small numbers (which floating point is good at).

As an interface thing, a user can always clip the output themselves if needed, so I think not clipping is the safer choice.

qiskit/circuit/parameterexpression.py Outdated Show resolved Hide resolved
qiskit/transpiler/passes/basis/basis_translator.py Outdated Show resolved Hide resolved
qiskit/circuit/quantumcircuit.py Outdated Show resolved Hide resolved
Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com>
Co-authored-by: Luciano Bello <bel@zurich.ibm.com>
Copy link
Contributor

@ElePT ElePT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (I'll add it to the queue in the interest of unblocking #11428)

@ElePT ElePT added this pull request to the merge queue Dec 19, 2023
Merged via the queue into Qiskit:main with commit 43c6713 Dec 19, 2023
13 checks passed
@jakelishman jakelishman deleted the parameterexpression-numeric branch December 19, 2023 21:37
1ucian0 added a commit that referenced this pull request May 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: New Feature Include in the "Added" section of the changelog mod: circuit Related to the core of the `QuantumCircuit` class or the circuit library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants