Skip to content

✨ Enable Python Bindings for the MQT Compiler Collection#1772

Draft
jmoosburger wants to merge 2 commits into
munich-quantum-toolkit:mainfrom
jmoosburger:feat/enable_mlir_python_bindings
Draft

✨ Enable Python Bindings for the MQT Compiler Collection#1772
jmoosburger wants to merge 2 commits into
munich-quantum-toolkit:mainfrom
jmoosburger:feat/enable_mlir_python_bindings

Conversation

@jmoosburger

Copy link
Copy Markdown

Description

TBD :)

Fixes #1693

Checklist

  • The pull request only contains commits that are focused and relevant to this change.
  • I have added appropriate tests that cover the new/changed functionality.
  • I have updated the documentation to reflect these changes.
  • I have added entries to the changelog for any noteworthy additions, changes, fixes, or removals.
  • I have added migration instructions to the upgrade guide (if needed).
  • The changes follow the project's style guidelines and introduce no new warnings.
  • The changes are fully tested and pass the CI checks.
  • I have reviewed my own code changes.

If PR contains AI-assisted content:

  • I have disclosed the use of AI tools in the PR description as per our AI Usage Guidelines.
  • AI-assisted commits include an Assisted-by: [Model Name] via [Tool Name] footer.
  • I confirm that I have personally reviewed and understood all AI-generated content, and accept full responsibility for it.

@jmoosburger

jmoosburger commented Jun 8, 2026

Copy link
Copy Markdown
Author

hey @MatthiasReumann,

no code yet, but i did quite some research through the weekend to answer the questions mentioned in the issue.
according to that a few notes for clarification:

the current mqt-cc tool reads a mlir- or qasm-file, transforms it to a mlir-module and feeds it to a compilation pipeline. the output is a qir-representation of the input-circuit printed to standard-out.
transferring the exact functionality to python would be fairly easy, by just creating eg. a qasm-file from a qiskit-circuit in python and pass it to the existing mqt-compilation-pipeline in c++.
i'm pretty sure this is not the desired output of this ticket as there is no need for mlir python bindings at all °^^
In this respect: the mqt-cc's purpose is to orchestrate the compilation pipeline with its passes and dialects. this is what shall be replicated in python, right?

the completion criteria says it must be possible to load a qasm circuit, translate it to qc-dialect and further to a qco-circuit.

  1. so what i need is a qc/qco representation in python? (which might come from table-gen)
  2. the execution of the passes/transforms/conversions/optimisations is still in c++, but is triggered in python code, right? (mlir python binding might be used)
  3. may i ask: what are possible next steps from a users perspective if he has the circuits qco-representation in python?

Thanks in beforehand, answering this will help me proceeding enormously :)

@denialhaag denialhaag self-requested a review June 8, 2026 10:32
@denialhaag

Copy link
Copy Markdown
Member

Hi @jmoosburger,

The idea is that a user can define an OpenQASM string in Python and then call a, say, load_qasm() function (in Python) to translate the OpenQASM circuit to a QC program. The load_qasm() function should return an object that can be passed to a different convert_qc_to_qco() function (in Python) to convert the QC program to a QCO program. The MLIR Python bindings facilitate that.

Regarding your questions:

  1. so what i need is a qc/qco representation in python? (which might come from table-gen)

Kind of. There is no need for any sort of builder just yet, but we want an MLIR module that comprises a QC or QCO program in Python. The MLIR Python bindings are made for that.

  1. the execution of the passes/transforms/conversions/optimisations is still in c++, but is triggered in python code, right? (mlir python binding might be used)

Exactly, we just want to have rather minimal functions to execute the existing C++ code.

  1. may i ask: what are possible next steps from a users perspective if he has the circuits qco-representation in python?

That's a fair point! Given the proposals in #1763 and #1770, we believe it is feasible to implement a compile_program() function that wraps mqt-cc 's functionality in the context of this issue.

I hope this clears things up! In general, it probably makes sense to have a look at #1763 and #1770 and the review comments we have provided there. While these two PRs are still far from what we need, they should offer a good starting point. In particular, a first draft that tests the translation from OpenQASM to QC in our CI would already be great. It should then be relatively easy to add the functionality required to close #1693.

Feel free to reach out if any of the points do not make sense!

@jmoosburger

Copy link
Copy Markdown
Author

@denialhaag thanks a lot for you input, that helped a lot!

following are just some of my notes, if you are interested in my progress and what my further research resulted in:

step 1: compile mlir with MLIR_ENABLE_BINDINGS_PYTHON:ON

  • set cmake-configuration-option whenever BUILD_MQT_CORE_MLIR and BUILD_MQT_CORE_BINDINGS are active

step 2: load_qasm_to_qc(string)

  • read qasm string
  • pass it to some c++-mlir-converter
  • get back mlir-module in qc dialect
    (in c++ its easy to convert a qasm string to a qc-mlir-module -> see loadQASMFile() in mqt-cc)

step 3: compile_program(module)

  • take qc-mlir-module from step 2
  • call existing c++-pipeline QuantumCompilerPipeline::runPipeline() with this module from python
  • get qir as result

step 4: qc to qco

  • take qc-mlir-module from step 2
  • use pass QCToQCO via python binding
  • get mlir module in qco-dialect

step 5: further passes

  • integrate other passes to python according step 4

whats next

  • i'll start some first implementations with that!
  • using test driven development
  • feedback is always welcome!

@burgholzer burgholzer added feature New feature or request c++ Anything related to C++ code python Anything related to Python code MLIR Anything related to MLIR unitaryHACK Issues and PRs intended for unitaryHACK labels Jun 10, 2026
@burgholzer burgholzer added this to the MLIR Support milestone Jun 10, 2026
@burgholzer

Copy link
Copy Markdown
Member

Hey @jmoosburger 👋🏼
Just checking in to see how it's going so far. Any progress?

@jmoosburger

jmoosburger commented Jun 10, 2026

Copy link
Copy Markdown
Author

hey @burgholzer,

slowly, to be haunest °^^

i struggled with the cmake build, as there are linking issues in a module mqt-core-mlir-unittest-qir-ir after i checked out the current main-branch and i have no idea why exactly...

i'm in contact with @MatthiasReumann on this one.

But i won't give up, let's see what i can do tomorrow! :)

@jmoosburger

Copy link
Copy Markdown
Author

there is progress 💪

first of all, i excluded the corrupted module mqt-core-mlir-unittest-qir-ir in the cmake-files as a workaroud to proceed.

i additionally managed to build llvm/mlir locally with python bindings on. i've referenced it from a python file test-wise and executed a simple test successfully.

i probably need some input from you on this point: at the moment you recommend taking the mlir-package as a prebuild from munich-quantum-software that does not contain the python bindings by now. as far as i figured out it is not possible to somehow generate them from that stage, which means the configuration must be changed at the point where the prebuilds are actually built. shall i figure that out in the munich-quantum-software/setup-mlir-project?

in any case i can go on with my steps from above tomorrow as the setup seems to work - at least for now on my local machine 👍

@burgholzer

Copy link
Copy Markdown
Member

i probably need some input from you on this point: at the moment you recommend taking the mlir-package as a prebuild from munich-quantum-software that does not contain the python bindings by now. as far as i figured out it is not possible to somehow generate them from that stage, which means the configuration must be changed at the point where the prebuilds are actually built. shall i figure that out in the munich-quantum-software/setup-mlir-project?

Hm. Interestingly, none of the other open PRs encountered that problem so far.
But then again, none of them really managed to actually test their contribution in CI.
#1770 came close, but may have also not hit that. Or the include-cleaner ignores are already an indication that it did not work properly in CI.

@denialhaag Could you look into what it would take to enable that for our portable-mlir-toolchain project and whether it is moderately easy to enable and package the resulting artifact. In particular, whether the resulting builds actively depend on a particular Python version and we would technically have to ship multiple. There are quite a few things to clarify there.

@jmoosburger I think it is fine for you to focus on this repository and your local setup for now.

@denialhaag

denialhaag commented Jun 11, 2026

Copy link
Copy Markdown
Member

Hm. Interestingly, none of the other open PRs encountered that problem so far. But then again, none of them really managed to actually test their contribution in CI. #1770 came close, but may have also not hit that. Or the include-cleaner ignores are already an indication that it did not work properly in CI.

I just tried to build #1770, but to no avail. 🤠

@denialhaag Could you look into what it would take to enable that for our portable-mlir-toolchain project and whether it is moderately easy to enable and package the resulting artifact. In particular, whether the resulting builds actively depend on a particular Python version and we would technically have to ship multiple. There are quite a few things to clarify there.

Sure, I'll have a look tomorrow! 😌

@jmoosburger

jmoosburger commented Jun 12, 2026

Copy link
Copy Markdown
Author

@denialhaag

just fyi: what i've done to make mlir python bindings available in a python file:

  • checkout llvm: $ git clone git@github.com:llvm/llvm-project.git
  • $ cd llvm-project/llvm
  • configure: $ cmake -G Ninja -S . -B build -DLLVM_ENABLE_PROJECTS="mlir" -DLLVM_TARGETS_TO_BUILD="Native" -DCMAKE_BUILD_TYPE=Release -DMLIR_ENABLE_BINDINGS_PYTHON=ON
    optional parameters as i used a venv for building:
    • -Dnanobind_DIR=/<somepath>/.venv/mlirdev/lib/python3.14/site-packages/nanobind/cmake
    • -DPython3_EXECUTABLE=/<somepath>/.venv/mlirdev/bin/python3.14
  • build: $ cmake --build build
    -> careful: build consumes a lot of ram and might cause trouble
    -> limit parallel jobs with argument: -j 6

the full python package is then in: /<somepath>/llvm-project/llvm/build/tools/mlir/python_packages/mlir_core/

either export this path to an environment variable PYTHONPATH or pass it to pytest/python temporarily:
$ PYTHONPATH=/<somepath>/llvm-project/llvm/build/tools/mlir/python_packages/mlir_core/ pytest

this makes the following python import successful in mqt: from mlir.ir import Module

hope this helps...
just ask if there are any questions!

@jmoosburger

Copy link
Copy Markdown
Author

question for clarification:

are the existing nanobinds in the bindings-directory actually in use somewhere?
in the python-directory there are mainly python-interfaces, but i cannot figure out if/how they are connected to these nanobinds.

background:

i want to publish the function translateQuantumComputationToQC() with nanobind for usage in python. the cpp file in the bindings-directory exists, the cmake-file as well and a build/release/bindings/mlir/mlir.cpython-314-x86_64-linux-gnu.so is generated on cmake build. everything's going well so far 🎉

now i need to reference this .so-file from python, that's why i wanted to check on current implementations :)

PS: i probably need to rename the nanobind from mlir to something else to avoid conflicts with the actual mlir-namespace from llvm, but that might be another concern.

@denialhaag

denialhaag commented Jun 12, 2026

Copy link
Copy Markdown
Member

are the existing nanobinds in the bindings-directory actually in use somewhere? in the python-directory there are mainly python-interfaces, but i cannot figure out if/how they are connected to these nanobinds.

An example: The bindings defined in register_quantum_computation.cpp can be imported from mqt.core.ir. They are technically not required, but the corresponding interfaces can be found in python/mqt/core/ir/__init__.pyi. When you import QuantumComputation from mqt.core.ir, you will get a class that is exclusively defined in register_quantum_computation.cpp (i.e., you will not find a Python definition anywhere in the repository).

The binding targets must be added to this list to ensure that the bindings are available in Python:

core/pyproject.toml

Lines 87 to 101 in e595087

build.targets = [
"mqt-core-ir",
"mqt-core-algorithms",
"mqt-core-circuit-optimizer",
"mqt-core-dd",
"mqt-core-zx",
"mqt-core-na",
"mqt-core-ir-bindings",
"mqt-core-dd-bindings",
"mqt-core-fomac-bindings",
"mqt-core-na-bindings",
"mqt-core-qdmi-ddsim-device",
"mqt-core-qdmi-na-device",
"mqt-core-qdmi-sc-device",
]

Does this help? 🤔

@denialhaag denialhaag removed their request for review June 12, 2026 14:20
@jmoosburger

Copy link
Copy Markdown
Author

i certainly does! where exactly do these build-target-strings come from?

@denialhaag

denialhaag commented Jun 12, 2026

Copy link
Copy Markdown
Member

i certainly does! where exactly do these build-target-strings come from?

It's defined here:

${MQT_CORE_TARGET_NAME}-ir-bindings

Edit: MQT_CORE_TARGET_NAME expands to mqt-core.

@jmoosburger

Copy link
Copy Markdown
Author

that's what i expected 👍 the -bindings is just a postfix for the cmake-function then?

additionally, this is where the namespace is defined, in which the bound functionality is available in python, right?
mqt.core.ir in this case:

@denialhaag

Copy link
Copy Markdown
Member

that's what i expected 👍 the -bindings is just a postfix for the cmake-function then?

additionally, this is where the namespace is defined, in which the bound functionality is available in python, right? mqt.core.ir in this case:

Exactly!

@denialhaag denialhaag marked this pull request as draft June 13, 2026 21:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Anything related to C++ code feature New feature or request MLIR Anything related to MLIR python Anything related to Python code unitaryHACK Issues and PRs intended for unitaryHACK

Projects

None yet

Development

Successfully merging this pull request may close these issues.

✨ Enable Python Bindings for the MQT Compiler Collection

3 participants