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

[Stretch] Support Float type in classical expressions. #13832

Open
wants to merge 45 commits into
base: main
Choose a base branch
from

Conversation

kevinhartman
Copy link
Contributor

@kevinhartman kevinhartman commented Feb 12, 2025

Summary

Adds a new Float type to the classical expression system. This is necessary to express timing relationships between durations and stretches in expressions.

In a follow-up(s), I'll add Duration and Stretch types as well as binary operators for +, -, * and /, and then plumb all of this into the existing circuit variable tracking infra, integrate with the Delay instruction, support serialization, etc.

Details and comments

Currently based on #13811. Here's a readable diff in the meantime.

  • The Float type is considered of an "unspecified width", in accordance with the machine-precision float in OpenQASM3. If we add a fixed-width float (similar to what we've got for Uint), then it shouldn't be difficult to add an optional constructor argument to Float for width, defaulted to None. I didn't opt to do this since I imagine fixed-width floats aren't desperately needed for stretches, and they would've taken too long to stamp out.
  • expr.lift now supports Python floats.
    • Floats can indeed be const.
  • Qiskit is stricter than QASM, in that its type system considers casts from Uint or Bool to Float to be unsafe.
    • You can still do it, but it requires an explicit cast node.
  • For this reason, Float cannot be mixed with Uint in binary operations. You must cast one of them, first.
  • Floats are only directly usable with the existing binary relation operations. The rest forbid direct use of Float for one reason or another (e.g. not losslessly coercable to Bool). The arithmetic operations to come (+, -, * and /) will support them.

To-do

  • QPY support.
  • QASM support.

Types that have some natural order no longer have an ordering
when one of them is strictly greater but has an incompatible
const-ness (i.e. when the greater type is const but the other
type is not).
We need to reject types with const=True in QPY until it supports them.

For now, I've also made the Index and shift operator constructors
lift their RHS to the same const-ness as the target to make it
less likely that existing users of expr run into issues when
serializing to older QPY versions.
This is probably a better default in general, since we
don't really have much use for const except for timing
stuff.
Since we're going for using a Cast node when const-ness
differs, this will be fine.
@kevinhartman kevinhartman requested a review from a team as a code owner February 12, 2025 21:39
@qiskit-bot
Copy link
Collaborator

One or more of the following people are relevant to this code:

  • @Qiskit/terra-core
  • @mtreinish
  • @nkanazawa1989

@coveralls
Copy link

coveralls commented Feb 13, 2025

Pull Request Test Coverage Report for Build 13444665656

Details

  • 190 of 199 (95.48%) changed or added relevant lines in 13 files are covered.
  • 52 unchanged lines in 5 files lost coverage.
  • Overall coverage decreased (-0.04%) to 88.082%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/circuit/classical/types/types.py 20 21 95.24%
qiskit/circuit/quantumcircuit.py 14 15 93.33%
qiskit/qasm3/exporter.py 2 4 50.0%
qiskit/qpy/binary_io/value.py 54 59 91.53%
Files with Coverage Reduction New Missed Lines %
crates/qasm2/src/expr.rs 1 94.23%
crates/accelerate/src/unitary_synthesis.rs 3 94.29%
crates/qasm2/src/lex.rs 8 91.23%
qiskit/qpy/binary_io/value.py 10 85.69%
crates/qasm2/src/parse.rs 30 95.76%
Totals Coverage Status
Change from base Build 13441968406: -0.04%
Covered Lines: 78424
Relevant Lines: 89035

💛 - Coveralls

Also removes the assumption that a const-type can never be an l-value
in favor of just restricting l-values with const types from being
added to circuits for now.

We will (in a separate PR) add support for adding stretch variables
to circuits, which are const. However, we may track those
differently, or at least not report them as variable when users
query the circuit for variables.
This one I'd added thinking I ought to block store from using
a const var target. But since I figured it's better to just
restrict adding vars to the circuit that are const (and leave
the decision of whether or not a const var can be an l-value
till later), this test no longer makes sense.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
on hold Can not fix yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants