Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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 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
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
23 changes: 22 additions & 1 deletion mlir/include/mlir/Compiler/CompilerPipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,27 @@ struct QuantumCompilerConfig {

/// Disable quaternion-based single-qubit rotation gate merging
bool disableMergeSingleQubitRotationGates = false;

/// Comma-separated native gate menu. Recognised tokens: `u`, `x`, `sx`,
/// `rz` (or `p`), `rx`, `ry`, `r`, `cx`, `cz`, `rzz`.
/// Illustrative menus (use `cx` or `cz` as the entangler, or
/// both):
/// - `"x,sx,rz,cx"` / `"x,sx,rz,cz"` — IBM basic (no fractional 2q)
/// - `"x,sx,rz,rx,rzz,cx"` / `"...,cz"` — IBM fractional
/// - `"u,cx"` / `"u,cz"` — generic single-qubit U3 + CX/CZ
/// - `"r,cz"` — IQM-style default
/// - `"rx,rz,cx"`, `"rx,ry,cz"`, `"ry,rz,cx"` — supported RX/RY/RZ pairs plus
/// entangler
std::string nativeGates;

/// Weight for two-qubit gates in local candidate scoring
double nativeGateScoreWeightTwoQ = 1.0;

/// Weight for single-qubit gates in local candidate scoring
double nativeGateScoreWeightOneQ = 0.1;

/// Weight for local candidate depth in local candidate scoring
double nativeGateScoreWeightDepth = 0.01;
};

/**
Expand Down Expand Up @@ -78,7 +99,7 @@ struct CompilationRecord {
* 2. QC cleanup pipeline
* 3. QCO dialect (value semantics) - enables SSA-based optimizations
* 4. QCO cleanup pipeline
* 5. Quantum optimization passes
* 5. Optimization and native gate synthesis
* 6. QCO cleanup pipeline
* 7. QC dialect - converted back for backend lowering
* 8. QC cleanup pipeline
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
/*
* 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>
#include <vector>

namespace mlir::qco::decomposition {

/// Intermediate single-qubit ``2×2`` unitaries produced while expanding a
/// two-qubit basis decomposition.
using TwoQubitLocalUnitaryList =
std::vector<Eigen::Matrix2cd, Eigen::aligned_allocator<Eigen::Matrix2cd>>;

/**
* 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 Stored in ``TwoQubitLocalUnitaryList`` so each matrix is allocated
* with Eigen's required alignment (portable across hosts / CRTs).
*/
[[nodiscard]] static TwoQubitLocalUnitaryList
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 Stored in ``TwoQubitLocalUnitaryList`` (see ``decomp0``).
*/
[[nodiscard]] TwoQubitLocalUnitaryList
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 Stored in ``TwoQubitLocalUnitaryList`` (see ``decomp0``).
*/
[[nodiscard]] TwoQubitLocalUnitaryList 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 Stored in ``TwoQubitLocalUnitaryList`` (see ``decomp0``).
*/
[[nodiscard]] TwoQubitLocalUnitaryList 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
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
Loading
Loading