-
-
Notifications
You must be signed in to change notification settings - Fork 55
✨ Add native gate synthesis MLIR pass and decomposition stack #1665
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
simon1hofmann
wants to merge
44
commits into
main
Choose a base branch
from
native_gate_synthesis
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 29 commits
Commits
Show all changes
44 commits
Select commit
Hold shift + click to select a range
38b5498
✨ Refactor unitary matrix calculations in quantum gate operations to …
simon1hofmann db72760
✨ Implement quantum gate decomposition utilities, including two-qubit…
simon1hofmann 741e4c1
✨ Introduce native gate synthesis pass.
simon1hofmann f55f1cd
✨ Enhance quantum gate decomposition tests with new utility functions…
simon1hofmann 09942df
✨ Add comprehensive tests for native synthesis and gate decomposition…
simon1hofmann 8833b72
✨ Update documentation for native gate synthesis pass with enhanced e…
simon1hofmann b4257de
📝 Add docstrings
simon1hofmann 1ade32b
✅ Refactor native synthesis tests.
simon1hofmann 4b5f1b2
✨ Enhance two-qubit gate sequence emission by adding support for resi…
simon1hofmann d719a64
✨ Euler sequence support for matrix synthesis in single-qubit operations
simon1hofmann 0597cee
✨ Refactor parameter ordering for U and U2 gates in decomposition and…
simon1hofmann b8ff476
📝 Clean up documentation and comments.
simon1hofmann cc9dfc5
✨ Support arbitrary single controlled operation in native synthesis.
simon1hofmann 12cb303
📝 Update documentation for native gate menu in QuantumCompilerConfig,…
simon1hofmann 76dd5af
🚨 Fix linter warnings
simon1hofmann 9a6e85e
🚨 Fix linter warnings
simon1hofmann dddc7d4
🚨 Fix linter warnings
simon1hofmann d30e3f1
🚨 Fix linter warnings
simon1hofmann 92b3ab4
🚨 Fix linter warnings
simon1hofmann b9bbfea
✅ Introduce helper functions for retrieving unitary qubit operands an…
simon1hofmann 170dee3
🔧 Update qubit comparison logic in mergeTwoTargetOneParameter to ensu…
simon1hofmann 36cf394
🔧 Refactor single-qubit matrix extraction logic to use raw operation …
simon1hofmann 0b102ae
🔧 Enhance qubit comparison logic in QCO operations to validate both q…
simon1hofmann cece82a
🐛 Fix Ubuntu Tests
simon1hofmann f0034c4
✅ Increase Coverage
simon1hofmann 56e46f7
🚨 Fix linter warning
simon1hofmann bf0a02b
✅ Increase Coverage
simon1hofmann 39509e3
Merge branch 'main' into native_gate_synthesis
simon1hofmann 5f8ce03
🐛 Fix Windows Tests
simon1hofmann de8e474
🐇 Address Rabbit's Comments
simon1hofmann 04a3312
🐇 Address Rabbit's Comments
simon1hofmann f66e820
🐛 Skip stale windows in TwoQubitWindowConsolidator to avoid erasing c…
simon1hofmann 750ce8d
🐇 Address Rabbit's Comments
simon1hofmann 1f20168
🐛 Fix Windows Tests
simon1hofmann 5c0f2d1
🐛 Fix Windows Tests
simon1hofmann 98d4bea
🐛 Fix Windows Tests
simon1hofmann 12c3eac
🐇 Address Rabbit's Comments
simon1hofmann 01aa915
🐛 Fix Windows Tests
simon1hofmann 7c8aeb9
🐛 Fix Windows Tests
simon1hofmann db83356
🎨 Revert unitary matrix calculations in QCO standard gates to use std…
simon1hofmann 304eb58
Merge branch 'main' into native_gate_synthesis
simon1hofmann 1af1116
Merge branch 'main' into native_gate_synthesis
simon1hofmann 98f1108
🐛 Try to fix Windows Tests
simon1hofmann 0226c36
🐛 Try to fix Windows Tests
simon1hofmann File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
244 changes: 244 additions & 0 deletions
244
mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/BasisDecomposer.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,244 @@ | ||
| /* | ||
| * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM | ||
| * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH | ||
| * All rights reserved. | ||
| * | ||
| * SPDX-License-Identifier: MIT | ||
| * | ||
| * Licensed under the MIT License | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include "EulerBasis.h" | ||
| #include "GateSequence.h" | ||
| #include "WeylDecomposition.h" | ||
|
|
||
| #include <Eigen/Core> | ||
| #include <llvm/ADT/SmallVector.h> | ||
|
|
||
| #include <array> | ||
| #include <complex> | ||
| #include <cstdint> | ||
| #include <optional> | ||
| #include <utility> | ||
|
|
||
| namespace mlir::qco::decomposition { | ||
|
|
||
| /** | ||
| * Decomposer that must be initialized with a two-qubit basis gate that will | ||
| * be used to generate a circuit equivalent to a canonical gate (RXX+RYY+RZZ). | ||
| * | ||
| * @note Adapted from TwoQubitBasisDecomposer in the IBM Qiskit framework. | ||
| * (C) Copyright IBM 2023 | ||
| * | ||
| * This code is licensed under the Apache License, Version 2.0. You may | ||
| * obtain a copy of this license in the LICENSE.txt file in the root | ||
| * directory of this source tree or at | ||
| * https://www.apache.org/licenses/LICENSE-2.0. | ||
| * | ||
| * Any modifications or derivative works of this code must retain this | ||
| * copyright notice, and modified files need to carry a notice | ||
| * indicating that they have been altered from the originals. | ||
| */ | ||
| class TwoQubitBasisDecomposer { | ||
| public: | ||
| /** | ||
| * Create decomposer that allows two-qubit decompositions based on the | ||
| * specified basis gate. | ||
| * This basis gate will appear between 0 and 3 times in each decomposition. | ||
| * The order of qubits is relevant and will change the results accordingly. | ||
| * The decomposer cannot handle different basis gates in the same | ||
| * decomposition (different order of the qubits also counts as a different | ||
| * basis gate). | ||
| */ | ||
| [[nodiscard]] static TwoQubitBasisDecomposer create(const Gate& basisGate, | ||
| double basisFidelity); | ||
|
|
||
| /** | ||
| * Perform decomposition using the basis gate of this decomposer. | ||
| * | ||
| * @param targetDecomposition Prepared Weyl decomposition of unitary matrix | ||
| * to be decomposed. | ||
| * @param target1qEulerBases List of Euler bases that should be tried out to | ||
| * find the best one for each euler decomposition. | ||
| * All bases will be mixed to get the best overall | ||
| * result. | ||
| * @param basisFidelity Fidelity for lowering the number of basis gates | ||
| * required | ||
| * @param approximate If true, use basisFidelity or, if std::nullopt, use | ||
| * basisFidelity of this decomposer. If false, fidelity | ||
| * of 1.0 will be assumed. | ||
| * @param numBasisGateUses Force use of given number of basis gates. | ||
| */ | ||
| [[nodiscard]] std::optional<TwoQubitGateSequence> twoQubitDecompose( | ||
| const decomposition::TwoQubitWeylDecomposition& targetDecomposition, | ||
| const llvm::SmallVector<EulerBasis>& target1qEulerBases, | ||
| std::optional<double> basisFidelity, bool approximate, | ||
| std::optional<std::uint8_t> numBasisGateUses) const; | ||
|
|
||
| protected: | ||
| // NOLINTBEGIN(modernize-pass-by-value) | ||
| /** | ||
| * Constructs decomposer instance. | ||
| */ | ||
| TwoQubitBasisDecomposer( | ||
| Gate basisGate, double basisFidelity, | ||
| const decomposition::TwoQubitWeylDecomposition& basisDecomposer, | ||
| bool isSuperControlled, const Eigen::Matrix2cd& u0l, | ||
| const Eigen::Matrix2cd& u0r, const Eigen::Matrix2cd& u1l, | ||
| const Eigen::Matrix2cd& u1ra, const Eigen::Matrix2cd& u1rb, | ||
| const Eigen::Matrix2cd& u2la, const Eigen::Matrix2cd& u2lb, | ||
| const Eigen::Matrix2cd& u2ra, const Eigen::Matrix2cd& u2rb, | ||
| const Eigen::Matrix2cd& u3l, const Eigen::Matrix2cd& u3r, | ||
| const Eigen::Matrix2cd& q0l, const Eigen::Matrix2cd& q0r, | ||
| const Eigen::Matrix2cd& q1la, const Eigen::Matrix2cd& q1lb, | ||
| const Eigen::Matrix2cd& q1ra, const Eigen::Matrix2cd& q1rb, | ||
| const Eigen::Matrix2cd& q2l, const Eigen::Matrix2cd& q2r) | ||
| : basisGate{std::move(basisGate)}, basisFidelity{basisFidelity}, | ||
| basisDecomposer{basisDecomposer}, isSuperControlled{isSuperControlled}, | ||
| u0l{u0l}, u0r{u0r}, u1l{u1l}, u1ra{u1ra}, u1rb{u1rb}, u2la{u2la}, | ||
| u2lb{u2lb}, u2ra{u2ra}, u2rb{u2rb}, u3l{u3l}, u3r{u3r}, q0l{q0l}, | ||
| q0r{q0r}, q1la{q1la}, q1lb{q1lb}, q1ra{q1ra}, q1rb{q1rb}, q2l{q2l}, | ||
| q2r{q2r} {} | ||
| // NOLINTEND(modernize-pass-by-value) | ||
|
|
||
| /** | ||
| * Calculate decompositions when no basis gate is required. | ||
| * | ||
| * Decompose target :math:`\sim U_d(x, y, z)` with 0 uses of the | ||
| * basis gate. Result :math:`U_r` has trace: | ||
| * | ||
| * .. math:: | ||
| * | ||
| * \Big\vert\text{Tr}(U_r\cdot U_\text{target}^{\dag})\Big\vert = | ||
| * 4\Big\vert (\cos(x)\cos(y)\cos(z)+ j \sin(x)\sin(y)\sin(z)\Big\vert | ||
| * | ||
| * which is optimal for all targets and bases | ||
| * | ||
| * @note The inline storage of llvm::SmallVector must be set to 0 to ensure | ||
| * correct Eigen alignment via heap allocation | ||
| */ | ||
| [[nodiscard]] static llvm::SmallVector<Eigen::Matrix2cd, 0> | ||
| decomp0(const decomposition::TwoQubitWeylDecomposition& target); | ||
|
|
||
| /** | ||
| * Calculate decompositions when one basis gate is required. | ||
| * | ||
| * Decompose target :math:`\sim U_d(x, y, z)` with 1 use of the | ||
| * basis gate :math:`\sim U_d(a, b, c)`. Result :math:`U_r` has trace: | ||
| * | ||
| * .. math:: | ||
| * | ||
| * \Big\vert\text{Tr}(U_r \cdot U_\text{target}^{\dag})\Big\vert = | ||
| * 4\Big\vert \cos(x-a)\cos(y-b)\cos(z-c) + j | ||
| * \sin(x-a)\sin(y-b)\sin(z-c)\Big\vert | ||
| * | ||
| * which is optimal for all targets and bases with ``z==0`` or ``c==0``. | ||
| * | ||
| * @note The inline storage of llvm::SmallVector must be set to 0 to ensure | ||
| * correct Eigen alignment via heap allocation | ||
| */ | ||
| [[nodiscard]] llvm::SmallVector<Eigen::Matrix2cd, 0> | ||
| decomp1(const decomposition::TwoQubitWeylDecomposition& target) const; | ||
|
|
||
| /** | ||
| * Calculate decompositions when two basis gates are required. | ||
| * | ||
| * Decompose target :math:`\sim U_d(x, y, z)` with 2 uses of the | ||
| * basis gate. | ||
| * | ||
| * For supercontrolled basis :math:`\sim U_d(\pi/4, b, 0)`, all b, result | ||
| * :math:`U_r` has trace | ||
| * | ||
| * .. math:: | ||
| * | ||
| * \Big\vert\text{Tr}(U_r \cdot U_\text{target}^\dag) \Big\vert = | ||
| * 4\cos(z) | ||
| * | ||
| * which is the optimal approximation for basis of CNOT-class | ||
| * :math:`\sim U_d(\pi/4, 0, 0)` or DCNOT-class | ||
| * :math:`\sim U_d(\pi/4, \pi/4, 0)` and any target. It may be sub-optimal | ||
| * for :math:`b \neq 0` (i.e. there exists an exact decomposition for any | ||
| * target using :math:`B \sim U_d(\pi/4, \pi/8, 0)`, but it may not be this | ||
| * decomposition). This is an exact decomposition for supercontrolled basis | ||
| * and target :math:`\sim U_d(x, y, 0)`. No guarantees for | ||
| * non-supercontrolled basis. | ||
| * | ||
| * @note The inline storage of llvm::SmallVector must be set to 0 to ensure | ||
| * correct Eigen alignment via heap allocation | ||
| */ | ||
| [[nodiscard]] llvm::SmallVector<Eigen::Matrix2cd, 0> decomp2Supercontrolled( | ||
| const decomposition::TwoQubitWeylDecomposition& target) const; | ||
|
|
||
| /** | ||
| * Calculate decompositions when three basis gates are required. | ||
| * | ||
| * Decompose target with 3 uses of the basis. | ||
| * | ||
| * This is an exact decomposition for supercontrolled basis | ||
| * :math:`\sim U_d(\pi/4, b, 0)`, all b, and any target. No guarantees for | ||
| * non-supercontrolled basis. | ||
| * | ||
| * @note The inline storage of llvm::SmallVector must be set to 0 to ensure | ||
| * correct Eigen alignment via heap allocation | ||
| */ | ||
| [[nodiscard]] llvm::SmallVector<Eigen::Matrix2cd, 0> decomp3Supercontrolled( | ||
| const decomposition::TwoQubitWeylDecomposition& target) const; | ||
|
|
||
| /** | ||
| * Calculate traces for a combination of the parameters of the canonical | ||
| * gates of the target and basis decompositions. | ||
| * This can be used to determine the smallest number of basis gates that are | ||
| * necessary to construct an equivalent to the canonical gate. | ||
| */ | ||
| [[nodiscard]] std::array<std::complex<double>, 4> | ||
| traces(const decomposition::TwoQubitWeylDecomposition& target) const; | ||
| /** | ||
| * Decompose a single-qubit unitary matrix into a single-qubit gate | ||
| * sequence. Multiple Euler bases may be specified and the one with the | ||
| * least complexity will be chosen. | ||
| */ | ||
| [[nodiscard]] static OneQubitGateSequence | ||
| unitaryToGateSequence(const Eigen::Matrix2cd& unitaryMat, | ||
| const llvm::SmallVector<EulerBasis>& targetBasisList, | ||
| bool simplify, std::optional<double> atol); | ||
|
|
||
| [[nodiscard]] static bool relativeEq(double lhs, double rhs, double epsilon, | ||
| double maxRelative); | ||
|
|
||
| private: | ||
| // basis gate of this decomposer instance | ||
| Gate basisGate{}; | ||
| // fidelity with which the basis gate decomposition has been calculated | ||
| double basisFidelity; | ||
| // cached decomposition for basis gate | ||
| decomposition::TwoQubitWeylDecomposition basisDecomposer; | ||
| // true if basis gate is super-controlled | ||
| bool isSuperControlled; | ||
|
|
||
| // pre-built components for decomposition with 3 basis gates | ||
| Eigen::Matrix2cd u0l; | ||
| Eigen::Matrix2cd u0r; | ||
| Eigen::Matrix2cd u1l; | ||
| Eigen::Matrix2cd u1ra; | ||
| Eigen::Matrix2cd u1rb; | ||
| Eigen::Matrix2cd u2la; | ||
| Eigen::Matrix2cd u2lb; | ||
| Eigen::Matrix2cd u2ra; | ||
| Eigen::Matrix2cd u2rb; | ||
| Eigen::Matrix2cd u3l; | ||
| Eigen::Matrix2cd u3r; | ||
|
|
||
| // pre-built components for decomposition with 2 basis gates | ||
| Eigen::Matrix2cd q0l; | ||
| Eigen::Matrix2cd q0r; | ||
| Eigen::Matrix2cd q1la; | ||
| Eigen::Matrix2cd q1lb; | ||
| Eigen::Matrix2cd q1ra; | ||
| Eigen::Matrix2cd q1rb; | ||
| Eigen::Matrix2cd q2l; | ||
| Eigen::Matrix2cd q2r; | ||
| }; | ||
|
|
||
| } // namespace mlir::qco::decomposition |
55 changes: 55 additions & 0 deletions
55
mlir/include/mlir/Dialect/QCO/Transforms/Decomposition/EulerBasis.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| /* | ||
| * Copyright (c) 2023 - 2026 Chair for Design Automation, TUM | ||
| * Copyright (c) 2025 - 2026 Munich Quantum Software Company GmbH | ||
| * All rights reserved. | ||
| * | ||
| * SPDX-License-Identifier: MIT | ||
| * | ||
| * Licensed under the MIT License | ||
| */ | ||
|
|
||
| #pragma once | ||
|
|
||
| #include "GateKind.h" | ||
|
|
||
| #include <llvm/ADT/SmallVector.h> | ||
|
|
||
| #include <cstdint> | ||
|
|
||
| namespace mlir::qco::decomposition { | ||
| /** | ||
| * Default absolute tolerance used to treat small Euler angles as zero during | ||
| * simplification. | ||
| */ | ||
| inline constexpr auto DEFAULT_ATOL = 1e-12; | ||
|
|
||
| /** | ||
| * Supported single-qubit Euler-style output bases. | ||
| * | ||
| * The listed values describe the gate alphabet that `EulerDecomposition` | ||
| * targets when converting a 2x2 unitary into a `OneQubitGateSequence`. | ||
| * Several entries share the angle-extraction routine and only differ in how | ||
| * the final circuit is emitted (e.g. `U3` vs `U321`, or `ZSX` vs `ZSXX`). | ||
| */ | ||
| enum class EulerBasis : std::uint8_t { | ||
| U3 = 0, ///< Single `u(theta, phi, lambda)` gate. | ||
| U321 = 1, ///< `u1`/`u2`/`u3` family — picks the smallest form per angles. | ||
| U = 2, ///< Same ZYZ angle extraction as `U3`, emitted as a single `u`. | ||
| ZYZ = 3, ///< `rz · ry · rz`. | ||
| ZXZ = 4, ///< `rz · rx · rz`. | ||
| XZX = 5, ///< `rx · rz · rx`. | ||
| XYX = 6, ///< `rx · ry · rx`. | ||
| ZSXX = 7, ///< `rz · sx` chain, with `sx · rz(±π) · sx` collapsed to `x`. | ||
| ZSX = 8, ///< Like `ZSXX` but without the `x` shortcut. | ||
| }; | ||
|
|
||
| /** | ||
| * Return the gate types that may appear in a circuit emitted for `eulerBasis`. | ||
| * | ||
| * The result describes the basis alphabet, not the exact gate count. Some | ||
| * decompositions emit fewer than three gates after simplification. | ||
| */ | ||
| [[nodiscard]] llvm::SmallVector<GateKind, 3> | ||
| getGateTypesForEulerBasis(EulerBasis eulerBasis); | ||
|
|
||
| } // namespace mlir::qco::decomposition |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.