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

Create qiskit_circuit::dag submodule #13721

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

Conversation

jakelishman
Copy link
Member

This rearranges some of the files of the qiskit_circuit crate to localise a dag-specific module. This is primarily a code-organisation thing, but also intended to allow some better visibility scoping in follow-up commits, particularly around the boundaries where unsafe functions must be considered.

Summary

Details and comments

The follow-up I'm referring to in the commit message is the comment chain here: #13696 (comment).

This rearranges some of the files of the `qiskit_circuit` crate to
localise a `dag`-specific module.  This is primarily a code-organisation
thing, but also intended to allow some better visibility scoping in
follow-up commits, particularly around the boundaries where `unsafe`
functions must be considered.
@jakelishman jakelishman added type: qa Issues and PRs that relate to testing and code quality Changelog: None Do not include in changelog Rust This PR or issue is related to Rust code in the repository labels Jan 22, 2025
@jakelishman jakelishman requested a review from a team as a code owner January 22, 2025 15:10
@qiskit-bot
Copy link
Collaborator

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

  • @Qiskit/terra-core

@coveralls
Copy link

coveralls commented Jan 22, 2025

Pull Request Test Coverage Report for Build 13134192504

Details

  • 41 of 42 (97.62%) changed or added relevant lines in 4 files are covered.
  • 5 unchanged lines in 3 files lost coverage.
  • Overall coverage increased (+0.006%) to 88.824%

Changes Missing Coverage Covered Lines Changed/Added Lines %
crates/circuit/src/operations.rs 16 17 94.12%
Files with Coverage Reduction New Missed Lines %
crates/accelerate/src/unitary_synthesis.rs 1 92.97%
crates/qasm2/src/expr.rs 1 94.23%
crates/qasm2/src/lex.rs 3 92.23%
Totals Coverage Status
Change from base Build 13118695608: 0.006%
Covered Lines: 79767
Relevant Lines: 89803

💛 - Coveralls

Copy link
Contributor

@kevinhartman kevinhartman left a comment

Choose a reason for hiding this comment

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

This looks like the right factoring to me. I imagine you're still going to have to put OperationIndex inside DAGCircuit as an inline submodule (I'm a fan of these, so I take no issue there).

@@ -20,8 +20,7 @@ use hashbrown::HashMap;
use pyo3::prelude::*;

use pyo3::types::{PyDict, PyList};
use qiskit_circuit::dag_circuit::{DAGCircuit, NodeType, Wire};
use rustworkx_core::petgraph::stable_graph::NodeIndex;
use qiskit_circuit::dag::{DAGCircuit, NodeIndex, NodeType, Wire};
Copy link
Contributor

Choose a reason for hiding this comment

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

It's nice to now have petgraph's NodeIndex reexported under dag :)

Copy link
Member Author

Choose a reason for hiding this comment

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

ha yeah, mostly this is speculative because of the follow-up of #13696, where OperationIndex will be imported from there too

@@ -18,7 +18,7 @@
use std::collections::BTreeMap;
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably out of scope, but I wonder if we should make dot_utils an inline submodule of circuit so that we can make DAGCircuit::dag() private (IIRC, dot_utils is the only external module that uses it).

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 was actually really surprised to learn that dot_utils is the only place that accesses the petgraph object directly - I could totally imagine more places where it would make sense to have mutable access to the raw DAG tbh. I'm almost sure we used to have more raw accessors of DAGCircuit._multi_graph from Python space.

Right now, I think having dot_utils hidden away in its own file is possibly better - I can't think of any way you can break anything with immutable access to the petgraph object, and I wouldn't be surprised if we start wanting it a bit more in the future?

///
/// These keys are [Eq], but this is semantically valid only for keys from the same owning object.
#[derive(Copy, Clone, Debug, Hash, Ord, PartialOrd, Eq, PartialEq)]
pub struct Var(pub BitType);
Copy link
Contributor

Choose a reason for hiding this comment

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

I suppose this is fine here, though I had intended to make it completely opaque outside of DAGCircuit (this I tried to do here, though I'm likely to close that PR in favor of another that changes ::new(usize) to ::new(u32) for our bit types).

The issue I have with it being transparent is that unlike index for Qubit and Clbit, its index doesn't mean anything—it's just an implementation detail of how DAGCircuit happens to store variables. But maybe hiding that is hairier than just letting it leak. Thoughts?

Copy link
Member Author

Choose a reason for hiding this comment

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

DAG consumers have to be able to inspect wires, so they need to be able to inspect the type of the Var wires, so it'll never manage to be properly private, and I was thinking it makes most sense to be forcibly consistent with the other things it's like.

For bit types: I'm in the process of writing a series of PRs (of which #13734 is the first) that restrict the Qubit, Clbit and Var types to 30 bits, so that the DAG wire can become a u32 instead of being 64 bits (we talked about this in the team meeting on Thursday while you were out, but if you're strongly opposed we can reconsider). A side effect of that is that it divorces us from the idea that there's a natural type that consumers of the type can pass in that's provably statically lossless for conversions, so I wasn't really worrying about it in typing anymore, and typically having new be usize is most convenient. If nothing else, it's consistent with the petgraph indices, so we're already in that boat with other types.

(Fwiw, that patch series also very heavily touches BitData, though I'll probably reconsider exactly how much I touch it while Ray's #13686 is still in flight.)

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, to finish the thought on it: my patch series also makes the internals of Qubit, Clbit and Var private, and you can only get at them through the index method that returns a usize; the type is logically supposed to be the indexer into a list, because there's a promise in both circuits that the values are 0..num_qubits.

(I also stuck in impls between all primitive unsigned types and Qubit, Clbit, Var for whichever of From and TryFrom made sense, but new and index are the only named constructor methods.)

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 changelog Rust This PR or issue is related to Rust code in the repository type: qa Issues and PRs that relate to testing and code quality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants