Skip to content

Transpile C API#14760

Merged
jakelishman merged 25 commits into
Qiskit:mainfrom
mtreinish:transpile-c-wip
Aug 28, 2025
Merged

Transpile C API#14760
jakelishman merged 25 commits into
Qiskit:mainfrom
mtreinish:transpile-c-wip

Conversation

@mtreinish

@mtreinish mtreinish commented Jul 18, 2025

Copy link
Copy Markdown
Member

Summary

This commit adds the initial transpiler C API to Qiskit, it provides a
function for running the transpiler to compile a single circuit for a
provided target. This function is not designed to replace the Python
transpiler and should only be used with circuits defined solely using
the C API. It is backed by the same Rust implementation of the
transpiler passes, but when coming from the C/Rust API several
assumptions are made that the circuits only contain the feature set
defined in the C API and the results are only valid when called
with circuits built solely using the C API.

As this function is the initial version of the transpiler in C/Rust
there are still a few limitations beyond just the circuits come from C
and only have the features exposed to C. The first is that multi qubit
unitary synthesis does not exist in C yet, so if you construct any
3 or more qubit UnitaryGates the transpiler will error. Additionally,
there is no scheduling stage yet in the C transpiler yet, so there
are no options for scheduling circuits available. Finally, there is no
pluggability to the transpiler, unlike Python where the preset pass
managers and the transpile() function provide a great deal of
configurability and customization via composing your own passes or
using the plugin interface, these concepts do not exist in the C
transpiler. The limitations will be addressed in future releases,
but this first function is about enabling initial circuit
compilation support from C.

Details and comments

Closes #14245

This is very much blocked until most of he sub-issues on #14245 are implemented. This does not compile and won't be able to for sometime.

The current list of dependencies for this PR are:

While waiting for these PRs you can look at #14922 which speculatively merged all these in progress PRs ontop of this branch and is showing this PR working.

@mtreinish mtreinish added this to the 2.2.0 milestone Jul 18, 2025
@mtreinish mtreinish added the on hold Can not fix yet label Jul 18, 2025
mtreinish added a commit to mtreinish/qiskit-core that referenced this pull request Jul 22, 2025
This commit adds a Rust TranspileLayout object which is analgous to the
Python space object. It is a self contained struct that is only for
Rust and will be used by the C API for the C transpiler so that users
will be able to reason about the permutations caused by the transpiler.
This will also be used by Qiskit#14106 to apply a transpilation layout to the
SparseObservable in C. This commit only adds the rust struct and it's
associated tests, a subsequent PR will add the C API on top. This won't
be used until we have a full path transpiler in C though (see Qiskit#14760).
Comment thread crates/cext/src/transpiler/transpiler.rs Outdated
@mtreinish mtreinish force-pushed the transpile-c-wip branch 3 times, most recently from 8ed727a to 64bf2c2 Compare August 13, 2025 16:24
@raynelfss raynelfss added the Changelog: Added Add an "Added" entry in the GitHub Release changelog. label Aug 13, 2025
github-merge-queue Bot pushed a commit that referenced this pull request Aug 14, 2025
* Add TranspileLayout struct to rust

This commit adds a Rust TranspileLayout object which is analgous to the
Python space object. It is a self contained struct that is only for
Rust and will be used by the C API for the C transpiler so that users
will be able to reason about the permutations caused by the transpiler.
This will also be used by #14106 to apply a transpilation layout to the
SparseObservable in C. This commit only adds the rust struct and it's
associated tests, a subsequent PR will add the C API on top. This won't
be used until we have a full path transpiler in C though (see #14760).

* Add routing permutation composition method

* Improve routing permutation APIs and make more rust native

This commit improves the routing permutation method to make them more
rust native. It updates the return to be a slice of PhysicalQubits
instead of an owned vec. To get the explicit trivial permutation in the
case of None a new method explicit_routing_permutation is added that
returns `Cow<[PhysicalQubits]>` and only allocates in the None case.

* Update final layout methods

This commit updates the final layout method to return a NLayout and a
new method final_index_layout is added to return a Vec.

* Improve documentation

* Fix lint

* Add support for python interop

This commit adds methods to convert to and from the Python space
transpile layout class. This requires changing the data in the rust
struct slightly so that we are tracking the virtual bits to build the
view that the Python struct needs. This isn't strictly needed for a pure
rust view of the data, but doesn't add much overhead to track it to
support python.

* Fix lint

* Make initial_layout optional

This commit updates the initial_layout attribute to make it optional. In
the transpiler a layout doesn't necessarily need to be set so to account
for that this the attribute is made optional.

* Rename routing_permutation -> output_permutation

* Make output_permutation use Qubit instead of PhysicalQubit

Now that output_permutation is storing the abstract permutation whether
there is a layout or not it means the PhysicalQubit type doesn't
accurately reflect the purpose of the field anymore since it might not
be a physical qubit. This commit fixes this by using the Qubit type
which just represent the index in the circuit which is all the
permutation is.

* Fix Python accesses in `TranspileLayout::from_py_native`

---------

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
@mtreinish mtreinish force-pushed the transpile-c-wip branch 2 times, most recently from 19f288f to 43c0cee Compare August 14, 2025 21:58
@mtreinish mtreinish force-pushed the transpile-c-wip branch 3 times, most recently from 5210484 to 0de0503 Compare August 18, 2025 15:52
@mtreinish mtreinish mentioned this pull request Aug 20, 2025
1 task
@mtreinish mtreinish force-pushed the transpile-c-wip branch 2 times, most recently from 1196909 to 3b0fb9e Compare August 25, 2025 19:47

@raynelfss raynelfss left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Minor comments/questions from quick pass through the code.

/// members of the result struct are owned by the caller and you are responsible for freeing
/// the members using the respective free functions.
/// @param error A pointer to a pointer with an nul terminated string with an error description.
/// If the transpiler fails a pointer to the string with the error description will be written

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// If the transpiler fails a pointer to the string with the error description will be written
/// If the transpiler fails, a pointer to the string with the error description will be written

Also, should we adopt this pattern with the standalone passes in C?

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 think after we resolve the error handling story for C. Right now this pattern is kind of future facing and we just stuff a backtrace in the error string as that's the best we can do.

///
/// @param circuit A pointer to the circuit to run the transpiler on
/// @param target A pointer to the target to compile the circuit for
/// @params options A pointer to an options object that defines user options. If this is a null

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// @params options A pointer to an options object that defines user options. If this is a null
/// @params options A pointer to a ``QkTranspileOptions`` object that defines user options. If this is a null

This rewrites how permutations are mutated within the `TranspileLayout`
structure, avoiding exposing the internal state (which is desperately
easy to update incorrectly when done piecewise) and instead exposing
methods that let us either add in a new permutation between the circuit
and the existing tracked layout/permutation (the typical thing we're
doing), or to include (only) a permutation that was being tracked before
this new `TranspileLayout` object was created.

The `add_permutation_outside` method may well be obsoleted in the future
once Sabre is properly acting on `TranspileLayout` itself.

@jakelishman jakelishman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm happy enough to merge this for 2.2.0b1 and to continue further work in separated PRs.

@raynelfss raynelfss mentioned this pull request Aug 28, 2025
1 task
@jakelishman jakelishman added this pull request to the merge queue Aug 28, 2025
Merged via the queue into Qiskit:main with commit b712f98 Aug 28, 2025
26 checks passed
@mtreinish mtreinish deleted the transpile-c-wip branch August 28, 2025 16:57
littlebullGit pushed a commit to littlebullGit/qiskit that referenced this pull request Sep 5, 2025
* Add TranspileLayout struct to rust

This commit adds a Rust TranspileLayout object which is analgous to the
Python space object. It is a self contained struct that is only for
Rust and will be used by the C API for the C transpiler so that users
will be able to reason about the permutations caused by the transpiler.
This will also be used by Qiskit#14106 to apply a transpilation layout to the
SparseObservable in C. This commit only adds the rust struct and it's
associated tests, a subsequent PR will add the C API on top. This won't
be used until we have a full path transpiler in C though (see Qiskit#14760).

* Add routing permutation composition method

* Improve routing permutation APIs and make more rust native

This commit improves the routing permutation method to make them more
rust native. It updates the return to be a slice of PhysicalQubits
instead of an owned vec. To get the explicit trivial permutation in the
case of None a new method explicit_routing_permutation is added that
returns `Cow<[PhysicalQubits]>` and only allocates in the None case.

* Update final layout methods

This commit updates the final layout method to return a NLayout and a
new method final_index_layout is added to return a Vec.

* Improve documentation

* Fix lint

* Add support for python interop

This commit adds methods to convert to and from the Python space
transpile layout class. This requires changing the data in the rust
struct slightly so that we are tracking the virtual bits to build the
view that the Python struct needs. This isn't strictly needed for a pure
rust view of the data, but doesn't add much overhead to track it to
support python.

* Fix lint

* Make initial_layout optional

This commit updates the initial_layout attribute to make it optional. In
the transpiler a layout doesn't necessarily need to be set so to account
for that this the attribute is made optional.

* Rename routing_permutation -> output_permutation

* Make output_permutation use Qubit instead of PhysicalQubit

Now that output_permutation is storing the abstract permutation whether
there is a layout or not it means the PhysicalQubit type doesn't
accurately reflect the purpose of the field anymore since it might not
be a physical qubit. This commit fixes this by using the Qubit type
which just represent the index in the circuit which is all the
permutation is.

* Fix Python accesses in `TranspileLayout::from_py_native`

---------

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
littlebullGit pushed a commit to littlebullGit/qiskit that referenced this pull request Sep 5, 2025
* Add transpiler C API

This commit adds the initial transpiler C API to Qiskit, it provides a
function for running the transpiler to compile a single circuit for a
provided target. This function is not designed to replace the Python
transpiler and should only be used with circuits defined solely using
the C API. It is backed by the same Rust implementation of the
trnaspiler passes, but when coming from the C/Rust API several
assumptions are made that the circuits only contain the feature set
defined in the C API and the results are only valid when called
with circuits built solely using the C API.

As this function is the initial version of the transpiler in C/Rust
there are still a few limitations beyond just the circuits come from C
and only have the features exposed to C. The first is that multi qubit
unitary synthesis does not exist in C yet, so if you construct any
3 or more qubit UnitaryGates the transpiler will error. Additionally,
there is no scheduling stage yet in the C transpiler yet, so there
are no options for scheduling circuits available. Finally, there is no
pluggability to the transpiler, unlike Python where the preset pass
managers and the transpile() function provide a great deal of
configurability and customization via composing your own passes or
using the plugin interface, these concepts do no exist in the C
transpiler. The limitations will be addressed in future releases,
but this first function is about enabling initial circuit
compilation support from C.

* Add docs files

* Fix routing and level 0

* Fix clippy

* Fix VF2 layout allocation with idle qubits

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
Co-authored-by: Eli Arbel <46826214+eliarbel@users.noreply.github.com>

* Remove commented out vf2postlayout code

Co-authored-by: Jake Lishman <jake@binhbar.com>

* Run idle qubits test

* Add release note

* Move MinPointState definition outside transpile func and simplify interface

* Apply suggestions from code review

Co-authored-by: Julien Gacon <gaconju@gmail.com>
Co-authored-by: Jake Lishman <jake@binhbar.com>

* Docs updates

* Allow error to be null and just don't write out error msg

* Use an enum for optimization level

* Fix c test issues

* Use ExitCode enum for C return type

* Add comment about run_check_map return

* Fix rust tests

* Add permutation-mutation methods to `TranspileLayout`

This rewrites how permutations are mutated within the `TranspileLayout`
structure, avoiding exposing the internal state (which is desperately
easy to update incorrectly when done piecewise) and instead exposing
methods that let us either add in a new permutation between the circuit
and the existing tracked layout/permutation (the typical thing we're
doing), or to include (only) a permutation that was being tracked before
this new `TranspileLayout` object was created.

The `add_permutation_outside` method may well be obsoleted in the future
once Sabre is properly acting on `TranspileLayout` itself.

* Fix typing of tests

* Add QkTranspileResult to the correct docs section

* Fix docs typo in transpiler page preamble

* Fix merge conflict with function rename in tests

---------

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
Co-authored-by: Eli Arbel <46826214+eliarbel@users.noreply.github.com>
Co-authored-by: Jake Lishman <jake@binhbar.com>
Co-authored-by: Julien Gacon <gaconju@gmail.com>
aaryav-3 pushed a commit to aaryav-3/qiskit that referenced this pull request Oct 21, 2025
* Add TranspileLayout struct to rust

This commit adds a Rust TranspileLayout object which is analgous to the
Python space object. It is a self contained struct that is only for
Rust and will be used by the C API for the C transpiler so that users
will be able to reason about the permutations caused by the transpiler.
This will also be used by Qiskit#14106 to apply a transpilation layout to the
SparseObservable in C. This commit only adds the rust struct and it's
associated tests, a subsequent PR will add the C API on top. This won't
be used until we have a full path transpiler in C though (see Qiskit#14760).

* Add routing permutation composition method

* Improve routing permutation APIs and make more rust native

This commit improves the routing permutation method to make them more
rust native. It updates the return to be a slice of PhysicalQubits
instead of an owned vec. To get the explicit trivial permutation in the
case of None a new method explicit_routing_permutation is added that
returns `Cow<[PhysicalQubits]>` and only allocates in the None case.

* Update final layout methods

This commit updates the final layout method to return a NLayout and a
new method final_index_layout is added to return a Vec.

* Improve documentation

* Fix lint

* Add support for python interop

This commit adds methods to convert to and from the Python space
transpile layout class. This requires changing the data in the rust
struct slightly so that we are tracking the virtual bits to build the
view that the Python struct needs. This isn't strictly needed for a pure
rust view of the data, but doesn't add much overhead to track it to
support python.

* Fix lint

* Make initial_layout optional

This commit updates the initial_layout attribute to make it optional. In
the transpiler a layout doesn't necessarily need to be set so to account
for that this the attribute is made optional.

* Rename routing_permutation -> output_permutation

* Make output_permutation use Qubit instead of PhysicalQubit

Now that output_permutation is storing the abstract permutation whether
there is a layout or not it means the PhysicalQubit type doesn't
accurately reflect the purpose of the field anymore since it might not
be a physical qubit. This commit fixes this by using the Qubit type
which just represent the index in the circuit which is all the
permutation is.

* Fix Python accesses in `TranspileLayout::from_py_native`

---------

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
aaryav-3 pushed a commit to aaryav-3/qiskit that referenced this pull request Oct 21, 2025
* Add transpiler C API

This commit adds the initial transpiler C API to Qiskit, it provides a
function for running the transpiler to compile a single circuit for a
provided target. This function is not designed to replace the Python
transpiler and should only be used with circuits defined solely using
the C API. It is backed by the same Rust implementation of the
trnaspiler passes, but when coming from the C/Rust API several
assumptions are made that the circuits only contain the feature set
defined in the C API and the results are only valid when called
with circuits built solely using the C API.

As this function is the initial version of the transpiler in C/Rust
there are still a few limitations beyond just the circuits come from C
and only have the features exposed to C. The first is that multi qubit
unitary synthesis does not exist in C yet, so if you construct any
3 or more qubit UnitaryGates the transpiler will error. Additionally,
there is no scheduling stage yet in the C transpiler yet, so there
are no options for scheduling circuits available. Finally, there is no
pluggability to the transpiler, unlike Python where the preset pass
managers and the transpile() function provide a great deal of
configurability and customization via composing your own passes or
using the plugin interface, these concepts do no exist in the C
transpiler. The limitations will be addressed in future releases,
but this first function is about enabling initial circuit
compilation support from C.

* Add docs files

* Fix routing and level 0

* Fix clippy

* Fix VF2 layout allocation with idle qubits

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
Co-authored-by: Eli Arbel <46826214+eliarbel@users.noreply.github.com>

* Remove commented out vf2postlayout code

Co-authored-by: Jake Lishman <jake@binhbar.com>

* Run idle qubits test

* Add release note

* Move MinPointState definition outside transpile func and simplify interface

* Apply suggestions from code review

Co-authored-by: Julien Gacon <gaconju@gmail.com>
Co-authored-by: Jake Lishman <jake@binhbar.com>

* Docs updates

* Allow error to be null and just don't write out error msg

* Use an enum for optimization level

* Fix c test issues

* Use ExitCode enum for C return type

* Add comment about run_check_map return

* Fix rust tests

* Add permutation-mutation methods to `TranspileLayout`

This rewrites how permutations are mutated within the `TranspileLayout`
structure, avoiding exposing the internal state (which is desperately
easy to update incorrectly when done piecewise) and instead exposing
methods that let us either add in a new permutation between the circuit
and the existing tracked layout/permutation (the typical thing we're
doing), or to include (only) a permutation that was being tracked before
this new `TranspileLayout` object was created.

The `add_permutation_outside` method may well be obsoleted in the future
once Sabre is properly acting on `TranspileLayout` itself.

* Fix typing of tests

* Add QkTranspileResult to the correct docs section

* Fix docs typo in transpiler page preamble

* Fix merge conflict with function rename in tests

---------

Co-authored-by: Jake Lishman <jake.lishman@ibm.com>
Co-authored-by: Eli Arbel <46826214+eliarbel@users.noreply.github.com>
Co-authored-by: Jake Lishman <jake@binhbar.com>
Co-authored-by: Julien Gacon <gaconju@gmail.com>
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: Added Add an "Added" entry in the GitHub Release changelog.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add C FFI for transpilation

7 participants