Add python bindings for the mlir QASM→QC→QCO pipeline #1783
Add python bindings for the mlir QASM→QC→QCO pipeline #1783InderpalSuthar wants to merge 10 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
Thanks for opening this PR @InderpalSuthar 🙏🏼 As it stands, this is not ready for review. As pointed out in other reviews to similar PRs already, we would also like to expose all of the dialects and passes from the compiler collection. The current implementation also does not quite fit into the existing infrastructure of MQT Core. Its existing bindings live in the top-level |
|
Thanks for the feedback @burgholzer, I made significant progress : I have exposed all dialects and passes. The capi now registers every dialect (qc, qco, QTensor, Jeff) and all conversion + transform passes, and python runs any of them via the standard PassManager with run_pipeline so it's no longer limited to qc-to-qco. And fitting the existing infrastructure nanobind module moved to bindings/mlir/ (built with add_mqt_python_binding_nanobind, like the other bindings) and is gated on BUILD_MQT_CORE_BINDINGS + BUILD_MQT_CORE_MLIR; the python package stays under python/mqt/core/mlir/.I also merged latest main, which needed adapting the C-API to the QCToQIR → QIRBase/QIRAdaptive refactor. (this is edited message this test failed 7 hours ago, Now all checks have passed) : |
denialhaag
left a comment
There was a problem hiding this comment.
Also from my side, thanks for your interest in contributing to mqt-cc, @InderpalSuthar! 🙂
I briefly reviewed your PR and left some suggestions; you can find them below.
There is still one major issue: none of your code is currently being tested in our CI. As you might have noticed, the MLIR installation we use in our CI currently does not support Python bindings. We are trying to make this work as soon as possible. In the meantime, I'd be curious to know if you can run the tests locally. If so, please ensure your implementation is properly tested. This is necessary for us to consider your contribution. If you are looking for inspiration, feel free to have a look at mlir/unittests (first OpenQASM tests are being added in #1780.
| text = Path(source).read_text(encoding="utf-8") | ||
| else: | ||
| text = source | ||
| return QASMProgram(source=text) |
There was a problem hiding this comment.
This function and the QASMProgram class seem unnecessary to me. In the current state, they barely add any value. 🤔
| return QASMProgram(source=text) | ||
|
|
||
|
|
||
| def translate_to_qc(program: QASMProgram | str, context: Context | None = None) -> Module: |
There was a problem hiding this comment.
I think it would be nice to be a bit more verbose here and call this translate_qasm3_to_qc.
| return module | ||
|
|
||
|
|
||
| def transform_to_qco(module: Module) -> Module: |
There was a problem hiding this comment.
If we decide to keep this helper function, it should be called convert_qc_to_qco because a transformation between two MLIR dialects is called a conversion.
There was a problem hiding this comment.
The tests should be expanded significantly. The tests should cover at least one example of each pass. Furthermore, the tests could be a bit more assertive and compare the output programs with the expected programs (e.g., by using regex matching).
| # Distribution / packaging | ||
| .Python | ||
| /build/ | ||
| /build_*/ |
There was a problem hiding this comment.
This change shouldn't be necessary.
| /build_*/ |
There was a problem hiding this comment.
For consistency, the path should probably be mlir/include/CAPI/Registration.h. 🤔
| # The MLIR bindings require an MLIR toolchain built with Python bindings. | ||
| '*/mqt/core/mlir/*', |
| # The MLIR Python bindings require an MLIR toolchain built with Python | ||
| - "python/mqt/core/mlir/**" |
Description
This PR adds Python bindings for the MQT Compiler Collection's MLIR pipeline, exposing the
(py:qasm) → (mlir:qc) → (mlir:qco)flow to Python through MLIR's own Python bindings.A new
mqt.core.mlirpackage provides three thin functions:read_qasm(source)— load an OpenQASM 3 program (string or.qasmpath)translate_to_qc(program)— translate it to a QC-dialectmlir.ir.Moduletransform_to_qco(module)— run theqc-to-qcopass, yielding a QCO-dialect moduleThe QC and QCO stages are returned as native
mlir.ir.Moduleobjects, so thein-memory representation can be printed, walked, and further processed with the
standard MLIR Python API. All transformation logic stays in C++; the bindings
only trigger the existing code.
Implementation: a small C-API (
mqt-core-c) that registers the QC/QCO/QTensordialects, imports OpenQASM 3 to the QC dialect, and runs the
qc-to-qcoconversion; a nanobind module built on MLIR's
NanobindAdaptors; and a Pythonwrapper. Everything is gated behind a new
BUILD_MQT_CORE_MLIR_PYTHONCMakeoption. No existing dialects or passes were modified (~300 lines of binding code).
Dependencies / how to build: requires an LLVM/MLIR 22.1.x toolchain built with
-DMLIR_ENABLE_BINDINGS_PYTHON=ON -DLLVM_ENABLE_RTTI=ON -DLLVM_ENABLE_EH=ON. Theprebuilt MLIR toolchain currently does not ship Python bindings, so this is not yet
exercised in CI — enabling bindings in the packaged toolchain is a separate upstream
task. Built and verified locally against LLVM 22.1.7; the new pytest suite passes.
Fixes #1693