Skip to content

Format floating-point values in the Rust circuit drawer#15899

Merged
eliarbel merged 4 commits intoQiskit:mainfrom
eliarbel:rust-circ-drawer-f64-fmt
Apr 27, 2026
Merged

Format floating-point values in the Rust circuit drawer#15899
eliarbel merged 4 commits intoQiskit:mainfrom
eliarbel:rust-circ-drawer-f64-fmt

Conversation

@eliarbel
Copy link
Copy Markdown
Member

@eliarbel eliarbel commented Mar 29, 2026

This commit adds formatting functionality to render floating-point values (e.g. rotation angles) in a way similar to the g formatting flag in Python.

This PR addresses item 3 in #15849

Details and comments

For example, this results in an output like this:

global phase: 6.0168
      ┌────────────┐ ┌────────────┐ ┌───────────────┐
q_0: ─┤ Rx(1.2346) ├─┤ Rx(123.46) ├─┤ Ry(1.23456*ϕ) ├
     ┌┴────────────┴┐├────────────┴┐├───────────────┤
q_1: ┤ Rz(1.2346e8) ├┤ Rx(0.12346) ├┤ Rx(1.2346e-5) ├
     └──────────────┘└─────────────┘└───────────────┘

instead of:

global phase: 6.0168146928204145
     ┌──────────────┐ ┌──────────────┐  ┌───────────────┐
q_0: ┤ Rx(1.234567) ├─┤ Rx(123.4567) ├──┤ Ry(1.23456*ϕ) ├──
     ├──────────────┴┐├──────────────┴┐┌┴───────────────┴─┐
q_1: ┤ Rz(123456789) ├┤ Rx(0.1234567) ├┤ Rx(0.0000123456) ├
     └───────────────┘└───────────────┘└──────────────────┘

@eliarbel eliarbel added this to the 2.5.0 milestone Mar 29, 2026
@eliarbel eliarbel requested a review from a team as a code owner March 29, 2026 17:35
@eliarbel eliarbel added Changelog: None Do not include in the GitHub Release changelog. Rust This PR or issue is related to Rust code in the repository labels Mar 29, 2026
@qiskit-bot
Copy link
Copy Markdown
Collaborator

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

  • @Qiskit/terra-core

Copy link
Copy Markdown
Collaborator

@Cryoris Cryoris left a comment

Choose a reason for hiding this comment

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

Thanks, this output is much more legible! I left some comments below.

Comment thread crates/circuit/src/circuit_drawer.rs Outdated
Comment thread crates/circuit/src/circuit_drawer.rs
}

/// Formats the input number based on the formatting options.
/// This Can be called multiple times, but the internal buffer is overwritten on each call.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Are we testing anywhere that this can be called multiple times? Looking at the code it seems that a new formatter is instantiated every time when we call .format.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

While I did call one formatter multiple times while I was testing this manually, I thought that since the crate is built around the notion of using a static buffer anyway, it's not worth to add explicit tests for that and that we can just go with the other circuit output tests which for the formatting aspect itself.
That said, I've added such test anyway in d9c2307 since a) it woudln't hurt and b) I want to extend it after #15917 is merged to have a test which covers both $\pi$-based formatting and decimal formatting.

Comment thread crates/circuit/src/circuit_drawer.rs Outdated
.iter()
.map(|param| match param {
Param::Float(f) => f.to_string(),
Param::Float(f) => F64UiFormatter::new(5).format(*f).to_string(),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What do you think of making the formatter an attribute of the TextDrawer? That would allow us to easily expose this as config later on, and allows to only allocate the buffer once and reuse it (ok likely an unnecessary optimization, but still haha)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I thought about it while implementing this and decided to skip it for now. Most of the functions in TextDrawer are associative but should be instance methods IMO to make the code more idiomatic, but I would defer this to a different PR. I still wrote the formatter as a struct instead of a simple function though to allow easy reuse of the buffer in case this will ever become a bottleneck, but for now I went with the more straightforward usage of instantiating and calling it on-the-fly.
Regarding performance, TBH, there are a lot of performance and memory optimization opportunities in the Rust circuit writer, but I think for now, besides functionality, the major consideration with the writer should be readability and easy extendibility.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Ok sounds good to me. Since we also are testing now that the re-usable buffer works, I'm good deferring this 👍🏻

@eliarbel
Copy link
Copy Markdown
Member Author

@Cryoris FYI: I'm putting this on hold for now until #15917 is merged since I would like to incorporate the $\pi$-formatting logic of the other PR inside F64UiFormatter.

@eliarbel eliarbel added the on hold Can not fix yet label Apr 14, 2026
This commit adds formatting functionality to render floating-point
values (e.g. rotation angles) in a way similar to the `g`
formatting flag in Python.
* change input parameter of the formatter to usize
* add tests
@eliarbel eliarbel force-pushed the rust-circ-drawer-f64-fmt branch from d9c2307 to fd79443 Compare April 24, 2026 15:51
@eliarbel eliarbel removed the on hold Can not fix yet label Apr 24, 2026
@eliarbel
Copy link
Copy Markdown
Member Author

@Cryoris this is now rebased on top of main to include the $\pi$-formatting functionality of #15917. I'd appreciate it if you can give it another look.

Copy link
Copy Markdown
Collaborator

@Cryoris Cryoris left a comment

Choose a reason for hiding this comment

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

Just one question, otherwise LGTM! It might be nice to expose the number of significant bits as option at some point in the future, but I'm favor of the short 5-digits for drawing as default.

Comment thread crates/circuit/src/circuit_drawer.rs
@eliarbel
Copy link
Copy Markdown
Member Author

It might be nice to expose the number of significant bits as option at some point in the future, but I'm favor of the short 5-digits for drawing as default.

I'm thinking it might be nice to split the code into several files which should reside in their own sub-directory. Especially with #16063 which is going to add a lot of code relatively. Once this is done, we can put the formatter in its own file (or in a general utils file) and generalize it more, including having that parameter accept Option

@Cryoris Cryoris added this pull request to the merge queue Apr 27, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Apr 27, 2026
@eliarbel eliarbel added this pull request to the merge queue Apr 27, 2026
Merged via the queue into Qiskit:main with commit ff3d001 Apr 27, 2026
26 checks passed
@eliarbel eliarbel deleted the rust-circ-drawer-f64-fmt branch April 27, 2026 13:58
@github-project-automation github-project-automation Bot moved this from Ready to Done in Qiskit 2.5 Apr 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Changelog: None Do not include in the GitHub Release changelog. mod: visualization qiskit.visualization Rust This PR or issue is related to Rust code in the repository

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants