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

Make CircuitData inner data accessible in Rust #12766

Merged
merged 4 commits into from
Jul 12, 2024

Conversation

raynelfss
Copy link
Contributor

Summary

The following commits aim to add a way to iterate through all the instructions contained in CircuitData to make these instructions accessible through Rust.

Details and comments

Use cases:

In #12585 there's a temporary struct called CircuitRep which aims to represent the circuit. This struct has a data() method that retrieves the data from the circuit once and stores it as a Vec<CircuitInstruction>.
https://github.com/raynelfss/qiskit/blob/bf9aedd72b019600b223e71f46e0107a295457b3/crates/circuit/src/equivalence.rs#L311-L319

    pub fn data(&mut self, py: Python) -> PyResult<&[CircuitInstruction]> {
        if self.data.is_none() {
            let data = self.object.bind(py).getattr("data")?.extract()?;
            self.data = Some(data);
            return Ok(self.data.as_ref().unwrap());
        }
        return Ok(self.data.as_ref().unwrap());
    }

The method is used once to create a set of instructions based on their name and the number of qubits they affect. https://github.com/raynelfss/qiskit/blob/bf9aedd72b019600b223e71f46e0107a295457b3/crates/circuit/src/equivalence.rs#L448-L452

        let sources: HashSet<Key> =
            HashSet::from_iter(equivalent_circuit.data(py)?.iter().map(|inst| Key {
                name: inst.operation.name().to_string(),
                num_qubits: inst.operation.num_qubits(),
            }));

By extracting from CircuitData and avoiding an extra conversion to a different DataType, it will be easier for us to access those instruction attributes from the Rust side of things without needing to invoke Python.

- Make `PackedInstruction` public.
@raynelfss raynelfss requested a review from a team as a code owner July 11, 2024 23:38
@qiskit-bot
Copy link
Collaborator

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

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

@raynelfss raynelfss added Rust This PR or issue is related to Rust code in the repository mod: circuit Related to the core of the `QuantumCircuit` class or the circuit library labels Jul 11, 2024
@raynelfss raynelfss changed the title Make CircuitData inner data accessible Make CircuitData inner data accessible in Rust Jul 11, 2024
@coveralls
Copy link

coveralls commented Jul 12, 2024

Pull Request Test Coverage Report for Build 9910126058

Details

  • 0 of 3 (0.0%) changed or added relevant lines in 1 file are covered.
  • 9 unchanged lines in 4 files lost coverage.
  • Overall coverage increased (+0.01%) to 89.889%

Changes Missing Coverage Covered Lines Changed/Added Lines %
crates/circuit/src/circuit_data.rs 0 3 0.0%
Files with Coverage Reduction New Missed Lines %
crates/qasm2/src/expr.rs 1 94.02%
qiskit/synthesis/clifford/clifford_decompose_ag.py 2 93.59%
qiskit/transpiler/passes/synthesis/unitary_synthesis.py 2 88.35%
crates/qasm2/src/lex.rs 4 93.13%
Totals Coverage Status
Change from base Build 9908506798: 0.01%
Covered Lines: 65755
Relevant Lines: 73151

💛 - Coveralls

Copy link
Member

@jakelishman jakelishman left a comment

Choose a reason for hiding this comment

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

This seems generally very sensible to me. Will CircuitData::iter be enough - will you not need to access the actual qubits / clbits at some point? If so, we'll not get far without having access to the interners as well.

crates/circuit/src/circuit_data.rs Outdated Show resolved Hide resolved
@raynelfss
Copy link
Contributor Author

will you not need to access the actual qubits / clbits at some point? If so, we'll not get far without having access to the interners as well.

For the time being I only need access to the instructions name and the number of qubits affected by it.

Although it will be needed to know what qargs and/or cargs is the instruction affecting, I'd rather wait for #12730 to merge and do a follow up to this to use the newer architecture your rebalancing will introduce.

@Cryoris
Copy link
Contributor

Cryoris commented Jul 12, 2024

I've also come across this but would need access to the qubits and clbits. Couldn't we just already include that info in this PR and extend iter to something like

    pub fn iter(&self) -> impl Iterator<Item = (&PackedInstruction, &Vec<Qubit>, &Vec<Clbit>)> {
        self.data.iter().map(|inst| {
            (
                inst,
                self.qargs_interner.intern(inst.qubits_id).value,
                self.cargs_interner.intern(inst.clbits_id).value,
            )
        })
    }

We could argue that iterating over circuit data should not just give the instructions but all the information (including qubits/clbits) 🙂

@jakelishman
Copy link
Member

jakelishman commented Jul 12, 2024

Julien: what you're getting at here is kind of the "middle type" between PackedInstruction and CircuitInstruction that you might have heard referred to in meetings / on PRs with Ray, me or Kevin, etc.

Can you give a bit more context at what exactly you're doing that wants it?

Some points: in general, we want to avoid doing work that we don't always need to do. Not all uses of the iterator actually need to unwrap the qubit/clbit slices, which means we don't need to look them up at all, and don't need to copy around the references. Having access to the intern index gives the most performant access to the qubits/clbits in situations like copy, etc - if you have the intern key and access to the interner, you can just ask for it when you need it (my comment above). That's not at all to say that there aren't uses for a middle, fully unwrapped type as a convenience (why I'm asking), but we most likely don't want the non-critical-loop convenience method to be the only thing available.

@jakelishman
Copy link
Member

Just as a very rough example, consider lots of block-collection passes for peephole quantum optimisation. They don't care what the clbits are other than if they're 0 or not; for those, we don't need to waste time and memory unpacking the clbit from the intern index on each iteration through.

Copy link
Member

@jakelishman jakelishman left a comment

Choose a reason for hiding this comment

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

Thanks Ray.

From offline discussion: Julien's going to take a look at reimplementing QuantumCircuit.compose with an inner CircuitData::compose, which will immediately alleviate some of the things he's talking about, but is also an entry point to us figuring out more of what we might need with the "middle type".

The concerns are still real, but I don't think we need to address them immediately as part of this PR, since we don't know exactly what path we'll take.

@jakelishman jakelishman added the Changelog: None Do not include in changelog label Jul 12, 2024
@jakelishman jakelishman added this pull request to the merge queue Jul 12, 2024
Merged via the queue into Qiskit:main with commit 2a2b806 Jul 12, 2024
15 checks passed
@raynelfss raynelfss deleted the circuit-data-accessible branch July 13, 2024 20:06
Procatv pushed a commit to Procatv/qiskit-terra-catherines that referenced this pull request Aug 1, 2024
* Add: `iter()` method to `CircuitData`
- Make `PackedInstruction` public.

* Docs: Remove "rust-native method" from docstring.
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 mod: circuit Related to the core of the `QuantumCircuit` class or the circuit library Rust This PR or issue is related to Rust code in the repository
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants