munich-quantum-toolkit / munich-quantum-toolkit/core
✨ Support qubit-register arguments in reusable functions
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 133
- Forks
- 73
- Avg merge
- 17h 34m
- Merged PRs (30d)
- 261
Description
🤖 AI text below 🤖
Problem Statement
MQT Core can represent qubit registers as memref values in QC and linear QTensor values in QCO, but reusable functions cannot carry those registers consistently across builders, QC↔QCO conversion, and compiler targets. The current paths either reject register operands, require direct allocations, flatten the function, or fail later in target conversion.
This blocks modular algorithms that operate on a complete register and makes each frontend or target solve the same ownership problem independently.
Proposed Solution
Define one shared register-call contract in QC and QCO, then implement only the target mappings that preserve it:
// QC borrows the register by reference.
func.func @f(%q: memref<4x!qc.qubit>)
// QCO transfers linear state through an explicit result.
func.func @f(%q: tensor<4x!qco.qubit>)
-> tensor<4x!qco.qubit>
- Use ordinary
func.call. Do not extend the scalar-unitaryqc.callorqco.callcontract. - Support rank-one static and dynamic register types in the core IR contract.
- In QCO, place ordinary results first, followed by one pass-through result for every scalar-qubit or qubit-register argument in argument order.
- In QC, treat corresponding register arguments as borrowed references and erase only those pass-through results during QCO→QC conversion.
- Reject unsupported declarations, recursion, views, casts, uncertain aliases, and incomplete quantum-result correspondence with diagnostics.
Delivery
Implement the feature as three dependent pull requests:
- #2428 defines the QC/QCO contract and proves it through a jeff round trip.
- #2429 imports and exports the supported OpenQASM 3
defsubset. - #2430 lowers retained fixed-size register functions to QIR Adaptive.
These implementation issues are also attached as native sub-issues.
Target decisions
jeff
jeff already has linear qureg values and typed function calls. Existing QCO↔jeff type and call conversion should need regression coverage, not a separate implementation layer.
OpenQASM 3
OpenQASM 3 subroutines accept typed qubit[N] arguments by reference and require distinct quantum operands. Preserve a deliberately small initial subset: fixed-size, defined, non-recursive, void subroutines with whole-register operands.
QIR
QIR 2.1 Adaptive supports arrays and IR functions. Preserve fixed-size borrowed register helpers with a caller-owned array ABI. Keep Base Profile inlining. Defer dynamic register formals until an explicit (ptr, length) ABI and lifetime contract are required.
Qiskit
Qiskit Gate and Instruction use a fixed flat sequence of qubit operands and do not preserve register-formal boundaries. Register-taking helpers must be inlined before Qiskit export. Qiskit import cannot reconstruct the boundary. Do not add private metadata or claim a lossless round trip. Add target-specific selective inlining only after a concrete export use case shows that callers cannot run the existing inliner themselves.
Completion criteria
- The core contract is documented, verified, and tested for static and dynamic rank-one registers.
- jeff serialization preserves register helper signatures and calls.
- OpenQASM 3 round trips preserve supported fixed register boundaries.
- QIR Adaptive emits valid retained helpers with
arrays=trueandir_functions=true; Base Profile does not retain them. - Unsupported programs fail with diagnostics and never assert or crash.
- Library and
mqt-ccpipelines agree.
Related issues
- #1733 tracks the broader OpenQASM frontend backlog.
- #1734 tracks the broader QIR backlog.
- #2109 tracks general OpenQASM classical arrays.
- #2110 tracks OpenQASM register slices.
- #2069 tracks Qiskit register aliases and layouts; it does not provide function-parameter semantics.
Non-goals
Register-valued unitary modifiers; arbitrary memref layouts or memory spaces; register views and slices; recursive register functions; Qiskit-specific boundary metadata; dynamic register parameters in OpenQASM or QIR.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Begin with dependent sub-issues #2428, #2429, and #2430, then inspect the existing QCO↔jeff type and call conversion. Use the stated completion criteria to verify static and dynamic register coverage, supported target round trips, and diagnostics for unsupported programs without crashes.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100