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

Remove Python dependency from circuit construction #13986

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

Conversation

mtreinish
Copy link
Member

Summary

In preparation for providing a C API for building and interacting with circuits this commit removes the required Python component from the circuit construction APIs on CircuitData. After #13860 the only use case of Python in the circuit constructor is to manipulate a ParameterExpression global phase as ParameterExpression is still a Python only construct. This moves to using Python::with_gil() in those places only when it's needed. This gives us a path for building a circuit without the Python interpreter for the C API.

Details and comments

In preparation for providing a C API for building and interacting with
circuits this commit removes the required Python component from the
circuit construction APIs on CircuitData. After Qiskit#13860 the only use case
of Python in the circuit constructor is to manipulate a
ParameterExpression global phase as ParameterExpression is still a
Python only construct. This moves to using Python::with_gil() in those
places only when it's needed. This gives us a path for building a
circuit without the Python interpreter for the C API.
@mtreinish mtreinish added Changelog: None Do not include in changelog Rust This PR or issue is related to Rust code in the repository C API Related to the C API labels Mar 10, 2025
@mtreinish mtreinish added this to the 2.1.0 milestone Mar 10, 2025
@mtreinish mtreinish requested a review from a team as a code owner March 10, 2025 22:56
@qiskit-bot
Copy link
Collaborator

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

  • @Qiskit/terra-core
  • @levbishop

@coveralls
Copy link

coveralls commented Mar 10, 2025

Pull Request Test Coverage Report for Build 13820220898

Details

  • 76 of 76 (100.0%) changed or added relevant lines in 12 files are covered.
  • 4 unchanged lines in 2 files lost coverage.
  • Overall coverage increased (+0.01%) to 88.131%

Files with Coverage Reduction New Missed Lines %
crates/accelerate/src/unitary_synthesis.rs 1 94.69%
crates/qasm2/src/lex.rs 3 92.48%
Totals Coverage Status
Change from base Build 13819553093: 0.01%
Covered Lines: 72686
Relevant Lines: 82475

💛 - Coveralls

Copy link
Contributor

@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.

This looks like a nice start, it'll allow us to add C API functions to generate a circuit and add standard gates. I left one comment about copying below and another question is how we can allow circuit inspection; e.g. it would be nice if we can give index access to CircuitInstructions -- but these are very py-heavy right now 😅

self_.reserve(py, reserve);
self_.extend(py, data)?;
self_.reserve(reserve);
Python::with_gil(|py| -> PyResult<()> { self_.extend(py, data) })?;
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be nice if we could also do this without the py token to enable copying circuits. What do you think about moving the with_gil inside extend in a way that we check if an instruction has parameter expressions and only then acquire the GIL? Maybe this has too much overhead and we can just wait for the Rust parameter expressions, too 😄

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 left it here because extend() was being passed a Bound<PyAny> I can drop the py here and just use it from the bound.

Copy link
Member Author

@mtreinish mtreinish Mar 11, 2025

Choose a reason for hiding this comment

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

Fixed in 004b7b8 If we need to call extend() in a no python context we'll probably want to split the method into two variants, one for rust data types the other for python. We can save that for a follow up PR though.

@@ -159,7 +158,7 @@ impl CircuitData {
qubit_indices: BitLocator::new(),
Copy link
Contributor

Choose a reason for hiding this comment

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

The BitLocator has a cached: OnceLock<Py<PyDict>>, can this become an issue at runtime or is this fine since there's no way we can populate the cache with Python objects?

Copy link
Member Author

Choose a reason for hiding this comment

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

It shouldn't be a problem we should only be initializing or working with the cached attribute when returning to python. There shouldn't be any code paths we access from cext where we could use this (or BitLocator more broadly tbh). We can refactor more if we do encounter issues though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C API Related to the C API Changelog: None Do not include in changelog 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.

4 participants