Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
147 commits
Select commit Hold shift + click to select a range
38b5498
✨ Refactor unitary matrix calculations in quantum gate operations to …
simon1hofmann Apr 22, 2026
db72760
✨ Implement quantum gate decomposition utilities, including two-qubit…
simon1hofmann Apr 22, 2026
741e4c1
✨ Introduce native gate synthesis pass.
simon1hofmann Apr 22, 2026
f55f1cd
✨ Enhance quantum gate decomposition tests with new utility functions…
simon1hofmann Apr 22, 2026
09942df
✨ Add comprehensive tests for native synthesis and gate decomposition…
simon1hofmann Apr 22, 2026
8833b72
✨ Update documentation for native gate synthesis pass with enhanced e…
simon1hofmann Apr 23, 2026
b4257de
📝 Add docstrings
simon1hofmann Apr 23, 2026
1ade32b
✅ Refactor native synthesis tests.
simon1hofmann Apr 23, 2026
4b5f1b2
✨ Enhance two-qubit gate sequence emission by adding support for resi…
simon1hofmann Apr 23, 2026
d719a64
✨ Euler sequence support for matrix synthesis in single-qubit operations
simon1hofmann Apr 24, 2026
0597cee
✨ Refactor parameter ordering for U and U2 gates in decomposition and…
simon1hofmann Apr 24, 2026
b8ff476
📝 Clean up documentation and comments.
simon1hofmann Apr 24, 2026
cc9dfc5
✨ Support arbitrary single controlled operation in native synthesis.
simon1hofmann Apr 24, 2026
12cb303
📝 Update documentation for native gate menu in QuantumCompilerConfig,…
simon1hofmann Apr 24, 2026
76dd5af
🚨 Fix linter warnings
simon1hofmann Apr 24, 2026
9a6e85e
🚨 Fix linter warnings
simon1hofmann Apr 24, 2026
dddc7d4
🚨 Fix linter warnings
simon1hofmann Apr 24, 2026
d30e3f1
🚨 Fix linter warnings
simon1hofmann Apr 24, 2026
92b3ab4
🚨 Fix linter warnings
simon1hofmann Apr 24, 2026
b9bbfea
✅ Introduce helper functions for retrieving unitary qubit operands an…
simon1hofmann Apr 24, 2026
170dee3
🔧 Update qubit comparison logic in mergeTwoTargetOneParameter to ensu…
simon1hofmann Apr 24, 2026
36cf394
🔧 Refactor single-qubit matrix extraction logic to use raw operation …
simon1hofmann Apr 24, 2026
0b102ae
🔧 Enhance qubit comparison logic in QCO operations to validate both q…
simon1hofmann Apr 24, 2026
cece82a
🐛 Fix Ubuntu Tests
simon1hofmann Apr 27, 2026
f0034c4
✅ Increase Coverage
simon1hofmann Apr 27, 2026
56e46f7
🚨 Fix linter warning
simon1hofmann Apr 27, 2026
bf0a02b
✅ Increase Coverage
simon1hofmann Apr 27, 2026
39509e3
Merge branch 'main' into native_gate_synthesis
simon1hofmann Apr 27, 2026
5f8ce03
🐛 Fix Windows Tests
simon1hofmann Apr 27, 2026
de8e474
🐇 Address Rabbit's Comments
simon1hofmann Apr 27, 2026
04a3312
🐇 Address Rabbit's Comments
simon1hofmann Apr 27, 2026
f66e820
🐛 Skip stale windows in TwoQubitWindowConsolidator to avoid erasing c…
simon1hofmann Apr 27, 2026
750ce8d
🐇 Address Rabbit's Comments
simon1hofmann Apr 27, 2026
1f20168
🐛 Fix Windows Tests
simon1hofmann Apr 27, 2026
5c0f2d1
🐛 Fix Windows Tests
simon1hofmann Apr 27, 2026
98d4bea
🐛 Fix Windows Tests
simon1hofmann Apr 27, 2026
12c3eac
🐇 Address Rabbit's Comments
simon1hofmann Apr 27, 2026
01aa915
🐛 Fix Windows Tests
simon1hofmann Apr 27, 2026
7c8aeb9
🐛 Fix Windows Tests
simon1hofmann Apr 27, 2026
db83356
🎨 Revert unitary matrix calculations in QCO standard gates to use std…
simon1hofmann Apr 29, 2026
304eb58
Merge branch 'main' into native_gate_synthesis
simon1hofmann Apr 29, 2026
1af1116
Merge branch 'main' into native_gate_synthesis
simon1hofmann Apr 30, 2026
98f1108
🐛 Try to fix Windows Tests
simon1hofmann Apr 30, 2026
0226c36
🐛 Try to fix Windows Tests
simon1hofmann Apr 30, 2026
2c1c5ad
Merge branch 'main' into native_gate_synthesis
simon1hofmann Jun 18, 2026
d2b472b
🔥 Remove `Eigen` and old single qubit synthesis
simon1hofmann Jun 18, 2026
4d19551
🔥 Remove `fuseRzAcrossCtrlControls` method
simon1hofmann Jun 18, 2026
8a2d90e
🔥 Remove `Gate.h` and `GateKind.h`
simon1hofmann Jun 18, 2026
5aa7660
🔥 Remove dead code
simon1hofmann Jun 18, 2026
bd07e69
✨ Add `fuse-two-qubit-unitary-runs` pass for fusing compile-time two-…
simon1hofmann Jun 18, 2026
fc42ea8
🔥 Remove and merge tests
simon1hofmann Jun 18, 2026
742632d
🔥 Remove and merge files
simon1hofmann Jun 19, 2026
9bb75bf
Merge branch 'main' into native_gate_synthesis
simon1hofmann Jun 19, 2026
a6b7c98
🔥 More merging and clean up
simon1hofmann Jun 19, 2026
6da8de8
🚨 Fix linter warnings
simon1hofmann Jun 19, 2026
6a3b138
✨ Refactor unit tests for two-qubit unitary fusion
simon1hofmann Jun 21, 2026
9c56c00
Merge branch 'main' into native_gate_synthesis
simon1hofmann Jun 21, 2026
b8cd395
🎨 Refactor and streamline native gate profile and synthesis for two-q…
simon1hofmann Jun 21, 2026
41d0077
🚨 Fix linter warnings
simon1hofmann Jun 21, 2026
7e23b01
🚨 Fix linter warnings
simon1hofmann Jun 21, 2026
239ed34
✨ Enhance Matrix functionality with new methods and optimizations
simon1hofmann Jun 22, 2026
be39369
Merge branch 'matrix-utilities' into native_gate_synthesis
simon1hofmann Jun 22, 2026
7a27165
Merge branch 'main' into matrix-utilities
simon1hofmann Jun 22, 2026
f892baf
🚨 Fix linter warnings
simon1hofmann Jun 22, 2026
7e3fe1a
☂️ Increase coverage
simon1hofmann Jun 22, 2026
a2484a1
⚡️ Suggestions from code review to improve performance
simon1hofmann Jun 22, 2026
01cfccb
📝 Update CHANGELOG to include PR #1802
simon1hofmann Jun 22, 2026
aa593ac
🚨 Fix linter warnings
simon1hofmann Jun 22, 2026
3f38d9c
🐇 Address rabbit's comments
simon1hofmann Jun 22, 2026
7be668a
🔀 Merge branch 'matrix-utilities' into native_gate_synthesis
simon1hofmann Jun 22, 2026
7bba64d
🎨 Simplify code
simon1hofmann Jun 22, 2026
662912f
Merge remote-tracking branch 'origin/main' into native_gate_synthesis
simon1hofmann Jun 22, 2026
c853e08
🚨 Fix linter warnings
simon1hofmann Jun 22, 2026
3ca7f74
✨ Weyl decomposition
simon1hofmann Jun 22, 2026
2f5ef13
✨ Add specialized matrix test cases for Weyl decomposition and improv…
simon1hofmann Jun 22, 2026
61ed245
📝 Simplify comments and docstrings
simon1hofmann Jun 22, 2026
5d27f04
🚨 Fix linter warnings
Jun 22, 2026
d57dab2
📝 Add comment about fixed perturbation coefficients for deterministic…
Jun 22, 2026
eaa1097
🎨 pre-commit fixes
pre-commit-ci[bot] Jun 22, 2026
362692c
✨ Add project options for MLIRQCOTransforms in CMake configuration
simon1hofmann Jun 23, 2026
5069916
Merge branch 'main' into decomp/weyl
simon1hofmann Jun 23, 2026
425a03d
☂️ Increase coverage
simon1hofmann Jun 23, 2026
426f300
☂️ Increase coverage
simon1hofmann Jun 23, 2026
392f608
🎨 Align implementation
simon1hofmann Jun 23, 2026
65408d6
🚨 Fix linter warnings
simon1hofmann Jun 23, 2026
846a4ed
⚡️ Enhance TwoQubitBasisDecomposer with caching functionality for tar…
simon1hofmann Jun 23, 2026
7e4e69a
✨ Move basis decomposition into TwoQubitBasisDecomposer and enhance W…
simon1hofmann Jun 23, 2026
341cfc8
🚨 Fix linter warnings
simon1hofmann Jun 23, 2026
8114583
🐇 Address rabbit's comments
simon1hofmann Jun 23, 2026
004ee40
📜 Update CHANGELOG.md to include PR #1803
simon1hofmann Jun 23, 2026
573a72f
Merge remote-tracking branch 'origin/main' into native_gate_synthesis
simon1hofmann Jun 24, 2026
2da076c
Merge branch 'decomp/weyl' into native_gate_synthesis
simon1hofmann Jun 24, 2026
325b669
🎨 Clean up
simon1hofmann Jun 24, 2026
e364224
☂️ Increase coverage
simon1hofmann Jun 24, 2026
5668e42
🚨 Fix linter warnings
simon1hofmann Jun 24, 2026
27201b5
✨ Add composeSingleQubitBodyMatrix function and integrate into CtrlOp…
simon1hofmann Jun 24, 2026
fb1792b
Merge remote-tracking branch 'origin/main' into native_gate_synthesis
simon1hofmann Jun 25, 2026
33fc33a
✨ Add whitespace for improved readability in UOp's getUnitaryMatrix f…
simon1hofmann Jun 25, 2026
e1c4915
🚨 Fix linter warnings
simon1hofmann Jun 25, 2026
5564809
Merge remote-tracking branch 'origin/main' into native_gate_synthesis
simon1hofmann Jun 30, 2026
51cff23
🔥 Remove unused cmath include from QCOUtils.h
simon1hofmann Jun 30, 2026
12ab2e4
🧹 Clean up QCO matrix tests by removing unused controlledXH test and …
simon1hofmann Jun 30, 2026
a405a94
Merge remote-tracking branch 'origin/main' into native_gate_synthesis
simon1hofmann Jun 30, 2026
bbb3987
🧹 Refactor QCO matrix utilities by removing unused functions and intr…
simon1hofmann Jun 30, 2026
73f05d9
🎨 Move `isEquivalentUpToGlobalPhase` function to `Matrix.h`
simon1hofmann Jun 30, 2026
2086102
✨ Add native gate profile parsing and Euler R-basis synthesis
simon1hofmann Jul 1, 2026
3d5eafb
🔥 Remove isEquivalentUpToGlobalPhase function and update related tests
simon1hofmann Jul 1, 2026
f0eaa65
✨ Move emitGPhaseIfNeeded function to handle global phase emission
simon1hofmann Jul 1, 2026
537787e
✨ Enhance QCO transformations with Euler basis support and code cleanup
simon1hofmann Jul 1, 2026
170e4ab
🔧 Revert header file collection in QCO transforms CMakeLists.txt
simon1hofmann Jul 1, 2026
e69d61a
Merge branch 'main' into native-profile-euler
simon1hofmann Jul 1, 2026
f1a2a76
🚨 Fix linter warnings
simon1hofmann Jul 1, 2026
a8b0b5d
☂️ Increase coverage
simon1hofmann Jul 2, 2026
3bf1324
Merge branch 'main' into native-profile-euler
simon1hofmann Jul 2, 2026
78898f0
🎨 Refactor NativeProfile.cpp for clarity and correctness
simon1hofmann Jul 2, 2026
36afb23
🐇 Address rabbit's comments
simon1hofmann Jul 2, 2026
b8003e2
🎨 Refactor Weyl decomposition tests and improve matrix handling
simon1hofmann Jul 2, 2026
23c2bf8
🎨 Refactor Weyl decomposition logic for improved clarity and efficiency
simon1hofmann Jul 2, 2026
c751462
🚨 Fix linter warnings
simon1hofmann Jul 2, 2026
da8c95a
📝 Update CHANGELOG to include PR #1832
simon1hofmann Jul 2, 2026
6b266d4
Merge branch 'main' into native-profile-euler
simon1hofmann Jul 5, 2026
a63c322
Merge remote-tracking branch 'origin/native-profile-euler' into nativ…
simon1hofmann Jul 6, 2026
e6649e3
Merge remote-tracking branch 'origin/main' into native_gate_synthesis
simon1hofmann Jul 7, 2026
beedf9d
🔥 Remove NativeProfile header and implementation files, refactor rela…
simon1hofmann Jul 7, 2026
8824b8e
⏪️ Revert changes introduced after merge
simon1hofmann Jul 7, 2026
23e2715
✨ Add fuse-two-qubit-unitary-runs pass
simon1hofmann Jul 7, 2026
9bde3bf
🔥 Remove the `isEquivalentUpToGlobalPhase` function from the matrix u…
simon1hofmann Jul 7, 2026
408b514
📝 Update CHANGELOG.md to reflect changes in the `fuse-two-qubit-unita…
simon1hofmann Jul 7, 2026
6a23d6b
🔧 Refactor CMakeLists.txt to simplify header file collection for QCO …
simon1hofmann Jul 7, 2026
66e5465
🎨 Simplify FuseTwoQubitUnitaryRuns
simon1hofmann Jul 7, 2026
3a1b758
🎨 Refactor unit tests for two-qubit unitary fusion
simon1hofmann Jul 7, 2026
f79d12f
✨ Enhance FuseTwoQubitUnitaryRuns pass with improved run scanning and…
simon1hofmann Jul 7, 2026
cf5b04f
🚨 Fix linter warnings
simon1hofmann Jul 7, 2026
0b7922d
☂️ Increase coverage
simon1hofmann Jul 7, 2026
c4e0969
🐇 Address rabbit's comments
simon1hofmann Jul 7, 2026
707cd97
☂️ Increase coverage
simon1hofmann Jul 7, 2026
872132b
🎨 Drop llvm and std clarifiers
simon1hofmann Jul 7, 2026
2f322eb
📝 Update CHANGELOG.md
simon1hofmann Jul 7, 2026
7d117b5
🚨 Fix linter warnings
simon1hofmann Jul 7, 2026
ce80118
🔀 Merge main and adapt tests
simon1hofmann Jul 13, 2026
bc67413
📝 Reorder CHANGELOG.md
simon1hofmann Jul 13, 2026
a2ceb53
Merge branch 'main' into feat/fuse-two-qubit-unitary-runs
simon1hofmann Jul 13, 2026
2236c0c
✨ Add missing empty line
simon1hofmann Jul 13, 2026
170eb49
🚨 Fix linter warnings
simon1hofmann Jul 13, 2026
9effa4e
Merge branch 'main' into feat/fuse-two-qubit-unitary-runs
simon1hofmann Jul 15, 2026
4f592f3
🔀 Merge main
simon1hofmann Jul 16, 2026
533212d
🔀 Merge feat/fuse-two-qubit-unitary-runs
simon1hofmann Jul 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ releases may include breaking changes.

### Added

- ✨ Add a `fuse-two-qubit-unitary-runs` pass for fusing compile-time two-qubit
unitary windows via Weyl/KAK resynthesis ([#1865]) ([**@simon1hofmann**],
[**@burgholzer**])
- ✨ Add Python bindings for the MQT Compiler Collection ([#1815])
([**@burgholzer**], [**@denialhaag**])
- ✨ Add support for QDMI child devices to the driver and FoMaC libraries
Expand All @@ -22,10 +25,12 @@ releases may include breaking changes.
([#1887]) ([**@flowerthrower**], [**@burgholzer**])
- ✨ Add QIR Output Schemas support to the QIR runtime ([#1877])
([**@rturrado**])
- ✨ Add a `fuse-two-qubit-unitary-runs` pass for fusing compile-time two-qubit
unitary windows via Weyl/KAK resynthesis ([#1655]) ([**@simon1hofmann**])
- ✨ Add support for IQM's `move` gate in the QDMI Qiskit backend converter
([#1844], [#1848]) ([**@burgholzer**], [**@marcelwa**])
- 🚸 Add `const` version of the `CompoundOperation`'s `getOps()` function
([#1826]) ([**@ystade])
([#1826]) ([**@ystade**])
- 🐳 Add dev container configuration for consistent local development
environment ([#1786]) ([**@denialhaag**])
- ✨ Add two-qubit Weyl (KAK) decomposition and native-gateset synthesis support
Expand Down Expand Up @@ -646,6 +651,7 @@ changelogs._
[#1872]: https://github.com/munich-quantum-toolkit/core/pull/1872
[#1870]: https://github.com/munich-quantum-toolkit/core/pull/1870
[#1869]: https://github.com/munich-quantum-toolkit/core/pull/1869
[#1865]: https://github.com/munich-quantum-toolkit/core/pull/1865
[#1850]: https://github.com/munich-quantum-toolkit/core/pull/1850
[#1849]: https://github.com/munich-quantum-toolkit/core/pull/1849
[#1848]: https://github.com/munich-quantum-toolkit/core/pull/1848
Expand Down Expand Up @@ -704,6 +710,7 @@ changelogs._
[#1664]: https://github.com/munich-quantum-toolkit/core/pull/1664
[#1662]: https://github.com/munich-quantum-toolkit/core/pull/1662
[#1660]: https://github.com/munich-quantum-toolkit/core/pull/1660
[#1655]: https://github.com/munich-quantum-toolkit/core/pull/1655
[#1652]: https://github.com/munich-quantum-toolkit/core/pull/1652
[#1638]: https://github.com/munich-quantum-toolkit/core/pull/1638
[#1637]: https://github.com/munich-quantum-toolkit/core/pull/1637
Expand Down
5 changes: 5 additions & 0 deletions bindings/mlir/register_mlir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,11 @@ operations.)pb");
&mlir::QCOProgram::fuseSingleQubitUnitaryRuns>::call,
nb::kw_only(), "basis"_a = "zyz",
"Fuse single-qubit unitary runs into the chosen decomposition basis.")
.def("fuse_two_qubit_unitary_runs",
&BooleanMemberAdapter<
&mlir::QCOProgram::fuseTwoQubitUnitaryRuns>::call,
nb::kw_only(), "native_gates"_a = "",
"Lower unitaries to a comma-separated native gate menu.")
.def("unroll_quantum_loops",
&BooleanMemberAdapter<&mlir::QCOProgram::unrollQuantumLoops>::call,
nb::kw_only(), "unroll_factor"_a = -1,
Expand Down
8 changes: 8 additions & 0 deletions mlir/include/mlir/Compiler/Programs.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,14 @@ class QCOProgram final : public Program {
/** @brief Fuse single-qubit unitary runs into the selected Euler basis. */
[[nodiscard]] bool fuseSingleQubitUnitaryRuns(std::string_view basis = "zyz");

/**
* @brief Lower unitaries to a comma-separated native gate menu.
*
* @details An empty or whitespace-only menu is a no-op. Unrecognised tokens
* cause the pass to fail.
*/
[[nodiscard]] bool fuseTwoQubitUnitaryRuns(std::string_view nativeGates = "");

/** @brief Unroll loops containing quantum operations. */
[[nodiscard]] bool unrollQuantumLoops(int64_t factor = -1);

Expand Down
15 changes: 15 additions & 0 deletions mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/Euler.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
#include <cstdint>
#include <optional>

namespace mlir {
class RewritePatternSet;
} // namespace mlir

namespace mlir::qco::decomposition {

/**
Expand Down Expand Up @@ -99,4 +103,15 @@ synthesizeUnitary1QEuler(OpBuilder& builder, Location loc, Value qubit,
*/
void emitGPhaseIfNeeded(OpBuilder& builder, Location loc, double phase);

/**
* @brief Populates @p patterns with the single-qubit run fusion rewrite for
* @p basis (the reusable core of `fuse-single-qubit-unitary-runs`).
*
* @param skipControlledBodies When set, single-qubit gates nested in `qco.ctrl`
* bodies are left untouched.
*/
void populateFuseSingleQubitUnitaryRunsPatterns(
RewritePatternSet& patterns, EulerBasis basis,
bool skipControlledBodies = false);

} // namespace mlir::qco::decomposition
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
#include <cstdint>
#include <optional>

namespace mlir {
class Operation;
} // namespace mlir

namespace mlir::qco::decomposition {

/**
Expand Down Expand Up @@ -63,6 +67,15 @@ struct NativeGateset {
*/
[[nodiscard]] std::optional<TwoQubitNativeDecomposition>
decomposeTarget(const Matrix4x4& target) const;

/**
* @brief Whether @p op is already on this native gateset.
*
* `qco.barrier` and `qco.gphase` are always allowed. Single-qubit primitives
* and single-target `qco.ctrl` shells (with an `X`/`Z` body) are checked
* against @p gates. All other ops are rejected.
*/
[[nodiscard]] bool allowsOp(Operation* op) const;
};

} // namespace mlir::qco::decomposition
51 changes: 51 additions & 0 deletions mlir/include/mlir/Dialect/QCO/Transforms/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,57 @@ def FuseSingleQubitUnitaryRuns
"Target Euler basis (zyz, zxz, xzx, xyx, u, zsxx, r).">];
}

def FuseTwoQubitUnitaryRuns
: Pass<"fuse-two-qubit-unitary-runs", "mlir::ModuleOp"> {
let dependentDialects = ["mlir::qco::QCODialect"];
let summary = "Lower QCO unitary gates to a user-specified native gate menu.";
let description = [{
Rewrites unitaries to match the comma-separated `native-gates` gateset.
`qco.barrier` and `qco.gphase` are preserved. A `qco.ctrl` is treated as a
two-qubit gate only when it has a single control and a single target; gates
acting on more than two qubits (e.g. multi-controlled `qco.ctrl`) are out of
scope and left untouched for a dedicated multi-controlled synthesis pass.

The gateset is a comma-separated list of gate tokens (order not
significant) from which the pass resolves a single-qubit Euler basis
(generic `qco.u` when `u` is present; IBM-style surface gates when all of
`x`, `sx`, and `rz` are present; IQM-style `qco.r` when `r` is present;
or a supported rotation pair chosen from `rx`, `ry`, `rz`) plus the
two-qubit entangler `cx` or `cz`.

Recognised tokens: `u`, `x`, `sx`, `rz`, `rx`, `ry`, `r`, `cx`,
`cz`. An empty or whitespace-only gateset is a no-op, which is the intended
pipeline default when synthesis is not needed. An unrecognised token causes
the pass to fail.

Example gatesets (each line is one illustrative gateset; pick either `cx`
or `cz` as the entangler, or list both if both are native):
- IBM: `x,sx,rz,cx` or `x,sx,rz,cz`
- Generic single-qubit U: `u,cx` or `u,cz`
- IQM default: `r,cz` (or `r,cx` if CX is the native entangler)
- Rotation pair + entangler: `rx,rz,cx`, `rx,ry,cz`, `ry,rz,cx`, etc.
Supported pairs are exactly `rx`+`rz`, `rx`+`ry`, and `ry`+`rz`.

Stages: fuse single-qubit runs (reusing `fuse-single-qubit-unitary-runs`,
which also lowers lone off-gateset single-qubit gates); fuse two-qubit runs
and lower any remaining off-gateset two-qubit ops via Weyl synthesis; fuse
the single-qubit seams introduced by that synthesis. The pass fails if any
single- or two-qubit op remains off the native gateset afterwards; gates on
more than two qubits are left untouched and do not cause a failure.

Lowering is deterministic: `cx` is preferred over `cz`, single-qubit
factors use the resolved Euler basis, and two-qubit run replacement uses
the minimal entangler count from the synthesizer.
}];
let options = [Option<
"nativeGates", "native-gates", "std::string", "\"\"",
"Comma-separated native gateset. Empty or whitespace-only is "
"a no-op. Tokens: u, x, sx, rz, rx, ry, r, cx, cz. "
"Examples: x,sx,rz,cx; u,cx; r,cz; rx,rz,cx.">];
}

//===----------------------------------------------------------------------===//

def QuantumLoopUnroll
: InterfacePass<"quantum-loop-unroll", "FunctionOpInterface"> {
let dependentDialects = ["mlir::qco::QCODialect", "mlir::scf::SCFDialect"];
Expand Down
27 changes: 27 additions & 0 deletions mlir/include/mlir/Dialect/QCO/Utils/Matrix.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <mlir/Support/LLVM.h>

#include <array>
#include <cmath>
#include <complex>
#include <concepts>
#include <cstddef>
Expand Down Expand Up @@ -866,6 +867,32 @@ concept SupportedMatrix =
std::same_as<T, Matrix1x1> || std::same_as<T, Matrix2x2> ||
std::same_as<T, Matrix4x4> || std::same_as<T, DynamicMatrix>;

/**
* @brief Checks whether two unitaries are equal up to a global phase.
*
* Uses `trace(rhs.adjoint() * lhs)` to infer a unit-modulus phase factor, then
* compares `lhs` to `factor * rhs` with @ref isApprox. A near-zero overlap
* (`|trace| <= tol`) is treated as not equivalent to avoid dividing by a tiny
* number.
*
* @tparam Matrix Any supported fixed- or dynamic-size matrix type.
* @param lhs Left-hand unitary.
* @param rhs Right-hand unitary.
* @param tol Absolute tolerance for overlap and entry-wise comparison.
* @return True when @p lhs and @p rhs differ only by a global phase.
*/
template <SupportedMatrix Matrix>
[[nodiscard]] bool isEquivalentUpToGlobalPhase(const Matrix& lhs,
const Matrix& rhs,
double tol = MATRIX_TOLERANCE) {
const auto overlap = (rhs.adjoint() * lhs).trace();
if (std::abs(overlap) <= tol) {
return false;
}
const auto factor = overlap / std::abs(overlap);
return lhs.isApprox(factor * rhs, tol);
}

/// Scalar-on-the-left multiply `scalar * matrix` (commutes with the member
/// `matrix * scalar`). Provided so generic code can scale a matrix from
/// either side.
Expand Down
11 changes: 11 additions & 0 deletions mlir/lib/Compiler/Programs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,17 @@ bool QCOProgram::fuseSingleQubitUnitaryRuns(const std::string_view basis) {
"failed to fuse single-qubit unitary runs"));
}

bool QCOProgram::fuseTwoQubitUnitaryRuns(const std::string_view nativeGates) {
qco::FuseTwoQubitUnitaryRunsOptions options;
options.nativeGates = nativeGates;
return succeeded(runPasses(
module(),
[&options](OpPassManager& pm) {
pm.addPass(qco::createFuseTwoQubitUnitaryRuns(options));
},
"failed to fuse two-qubit unitary runs"));
}

bool QCOProgram::unrollQuantumLoops(const int64_t factor) {
qco::QuantumLoopUnrollOptions options;
options.unrollFactor = factor;
Expand Down
10 changes: 5 additions & 5 deletions mlir/lib/Dialect/QCO/Transforms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ add_mlir_library(

mqt_mlir_target_use_project_options(MLIRQCOTransforms)

# collect header files
file(GLOB_RECURSE PASSES_HEADERS_SOURCE
${MQT_MLIR_SOURCE_INCLUDE_DIR}/mlir/Dialect/QCO/Transforms/*.h)
file(GLOB_RECURSE PASSES_HEADERS_BUILD
${MQT_MLIR_BUILD_INCLUDE_DIR}/mlir/Dialect/QCO/Transforms/*.inc)
# collect header files (subdirs: Decomposition/, …)
file(GLOB_RECURSE PASSES_HEADERS_SOURCE CONFIGURE_DEPENDS
"${MQT_MLIR_SOURCE_INCLUDE_DIR}/mlir/Dialect/QCO/Transforms/*.h")
file(GLOB_RECURSE PASSES_HEADERS_BUILD CONFIGURE_DEPENDS
"${MQT_MLIR_BUILD_INCLUDE_DIR}/mlir/Dialect/QCO/Transforms/*.inc")

# add public headers using file sets
target_sources(
Expand Down
46 changes: 46 additions & 0 deletions mlir/lib/Dialect/QCO/Transforms/Decomposition/NativeGateset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@

#include "mlir/Dialect/QCO/Transforms/Decomposition/NativeGateset.h"

#include "mlir/Dialect/QCO/IR/QCOInterfaces.h"
#include "mlir/Dialect/QCO/IR/QCOOps.h"
#include "mlir/Dialect/QCO/Transforms/Decomposition/Euler.h"
#include "mlir/Dialect/QCO/Transforms/Decomposition/Weyl.h"
#include "mlir/Dialect/QCO/Utils/Matrix.h"

#include <llvm/ADT/StringSwitch.h>
#include <llvm/ADT/TypeSwitch.h>
#include <llvm/Support/ErrorHandling.h>
#include <mlir/IR/Operation.h>
#include <mlir/Support/LLVM.h>

#include <optional>
Expand Down Expand Up @@ -141,6 +145,48 @@ NativeGateset::decomposeTarget(const Matrix4x4& target) const {
return cachedNativeBasisDecomposer(*entangler).decomposeTarget(target);
}

static std::optional<NativeGateKind> gateKindFor(UnitaryOpInterface op) {
return TypeSwitch<Operation*, std::optional<NativeGateKind>>(
op.getOperation())
.Case<UOp>([](UOp) { return NativeGateKind::U; })
.Case<XOp>([](XOp) { return NativeGateKind::X; })
.Case<SXOp>([](SXOp) { return NativeGateKind::SX; })
.Case<RZOp>([](RZOp) { return NativeGateKind::RZ; })
.Case<RXOp>([](RXOp) { return NativeGateKind::RX; })
.Case<RYOp>([](RYOp) { return NativeGateKind::RY; })
.Case<ROp>([](ROp) { return NativeGateKind::R; })
.Default([](Operation*) { return std::nullopt; });
}

static std::optional<NativeGateKind> entanglerKindFor(CtrlOp ctrl) {
if (ctrl.getNumControls() != 1 || ctrl.getNumTargets() != 1 ||
ctrl.getNumBodyUnitaries() != 1) {
return std::nullopt;
}
return TypeSwitch<Operation*, std::optional<NativeGateKind>>(
ctrl.getBodyUnitary(0).getOperation())
.Case<XOp>([](XOp) { return NativeGateKind::CX; })
.Case<ZOp>([](ZOp) { return NativeGateKind::CZ; })
.Default([](Operation*) { return std::nullopt; });
}

bool NativeGateset::allowsOp(Operation* op) const {
return TypeSwitch<Operation*, bool>(op)
.Case<BarrierOp, GPhaseOp>([](auto) { return true; })
.Case<CtrlOp>([&](CtrlOp ctrl) {
const auto kind = entanglerKindFor(ctrl);
return kind && gates.contains(*kind);
})
.Case<UnitaryOpInterface>([&](UnitaryOpInterface unitary) {
if (!unitary.isSingleQubit()) {
return false;
}
const auto gate = gateKindFor(unitary);
return gate && gates.contains(*gate);
})
.Default([](Operation*) { return false; });
}

std::optional<NativeGateset> NativeGateset::parse(StringRef nativeGates) {
auto gates = parseGateSet(nativeGates);
if (!gates) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,13 @@ namespace {
struct FuseSingleQubitUnitaryRunsPattern final
: OpInterfaceRewritePattern<UnitaryOpInterface> {
FuseSingleQubitUnitaryRunsPattern(MLIRContext* context,
const decomposition::EulerBasis basis)
: OpInterfaceRewritePattern(context), basis(basis) {}
const decomposition::EulerBasis basis,
const bool skipControlledBodies)
: OpInterfaceRewritePattern(context), basis(basis),
skipControlledBodies(skipControlledBodies) {}

decomposition::EulerBasis basis;
bool skipControlledBodies;

/**
* @brief Whether `op` starts a run.
Expand All @@ -165,6 +168,10 @@ struct FuseSingleQubitUnitaryRunsPattern final
*/
LogicalResult matchAndRewrite(UnitaryOpInterface op,
PatternRewriter& rewriter) const override {
if (skipControlledBodies &&
(op.getOperation()->getParentOfType<CtrlOp>() != nullptr)) {
return failure();
}
if (!isRunStart(op)) {
return failure();
}
Expand Down Expand Up @@ -208,8 +215,8 @@ struct FuseSingleQubitUnitaryRunsPass final
}

RewritePatternSet patterns(&getContext());
patterns.add<FuseSingleQubitUnitaryRunsPattern>(patterns.getContext(),
*parsed);
decomposition::populateFuseSingleQubitUnitaryRunsPatterns(
patterns, *parsed, /*skipControlledBodies=*/false);

if (failed(applyPatternsGreedily(module, std::move(patterns)))) {
signalPassFailure();
Expand All @@ -220,3 +227,14 @@ struct FuseSingleQubitUnitaryRunsPass final
} // namespace

} // namespace mlir::qco

namespace mlir::qco::decomposition {

void populateFuseSingleQubitUnitaryRunsPatterns(
RewritePatternSet& patterns, const EulerBasis basis,
const bool skipControlledBodies) {
patterns.add<FuseSingleQubitUnitaryRunsPattern>(patterns.getContext(), basis,
skipControlledBodies);
}

} // namespace mlir::qco::decomposition
Loading
Loading