Skip to content

Commit 0def538

Browse files
🐛 Refactor unitary matrix calculations in ROp, UOp, XXMinusYYOp, and XXPlusYYOp (#1807)
## Description - Fix `getUnitaryMatrix()` for `ROp`, `UOp`, `XXMinusYYOp`, and `XXPlusYYOp` when rotation angles produce negative `sin(θ/2)` or `cos(θ/2)` scalars. - Replace `std::polar(magnitude, phase)` with `magnitude * std::exp(i·phase)`, which is well-defined for any real magnitude. ## Problem `std::polar(ρ, θ)` requires a **non-negative** `ρ` ([LWG 2459](https://cplusplus.github.io/LWG/issue2459)). For negative rotation angles, gates like `R(θ, φ)` use `sin(θ/2)` as a matrix entry scale, which can be negative (e.g. `θ = -π/2` → `sin(θ/2) < 0`). On libc++, `std::polar(negative, φ)` returns `NaN`, breaking unitary extraction for otherwise valid gates. ## Fix Build phased entries as ordinary complex multiplication: ```cpp const auto m01 = std::sin(halfTheta) * std::exp(1i * phase); ``` instead of: ```cpp std::polar(s, phase); // invalid when s < 0 ``` std::polar(1.0, φ) remains appropriate for unit-magnitude global phases. ## Checklist <!--- This checklist serves as a reminder of a couple of things that ensure your pull request will be merged swiftly. --> - [x] 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. - [x] 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). - [x] The changes follow the project's style guidelines and introduce no new warnings. - [x] The changes are fully tested and pass the CI checks. - [x] 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](https://github.com/munich-quantum-toolkit/core/blob/main/docs/ai_usage.md). - [ ] 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.
1 parent 4065349 commit 0def538

5 files changed

Lines changed: 25 additions & 17 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ with the exception that minor releases may include breaking changes.
4242
[#1569], [#1570], [#1572], [#1573], [#1580], [#1602], [#1620], [#1623],
4343
[#1624], [#1626], [#1627], [#1635], [#1638], [#1673], [#1675], [#1700],
4444
[#1710], [#1717], [#1728], [#1730], [#1749], [#1751], [#1762], [#1765],
45-
[#1774], [#1780], [#1781], [#1782], [#1787], [#1802])
45+
[#1774], [#1780], [#1781], [#1782], [#1787], [#1802], [#1807])
4646
([**@burgholzer**], [**@denialhaag**], [**@taminob**], [**@DRovara**],
4747
[**@li-mingbao**], [**@Ectras**], [**@MatthiasReumann**],
4848
[**@simon1hofmann**])
@@ -598,6 +598,7 @@ changelogs._
598598

599599
<!-- PR links -->
600600

601+
[#1807]: https://github.com/munich-quantum-toolkit/core/pull/1807
601602
[#1802]: https://github.com/munich-quantum-toolkit/core/pull/1802
602603
[#1787]: https://github.com/munich-quantum-toolkit/core/pull/1787
603604
[#1782]: https://github.com/munich-quantum-toolkit/core/pull/1782

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/ROp.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,13 @@ std::optional<Matrix2x2> ROp::getUnitaryMatrix() {
115115
return std::nullopt;
116116
}
117117

118-
const auto thetaSin = std::sin(*theta / 2);
119-
const auto m01 = std::polar(thetaSin, -*phi - (std::numbers::pi / 2));
120-
const auto m10 = std::polar(thetaSin, *phi - (std::numbers::pi / 2));
121-
const auto thetaCos = std::cos(*theta / 2);
122-
return Matrix2x2::fromElements(thetaCos, m01, // row 0
123-
m10, thetaCos); // row 1
118+
using namespace std::complex_literals;
119+
const auto halfTheta = *theta / 2;
120+
const auto c = std::cos(halfTheta);
121+
const auto s = std::sin(halfTheta);
122+
123+
const auto m01 = s * std::exp(1i * (-*phi - (std::numbers::pi / 2)));
124+
const auto m10 = s * std::exp(1i * (*phi - (std::numbers::pi / 2)));
125+
return Matrix2x2::fromElements(c, m01, // row 0
126+
m10, c); // row 1
124127
}

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/UOp.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,14 @@ std::optional<Matrix2x2> UOp::getUnitaryMatrix() {
133133
return std::nullopt;
134134
}
135135

136-
const auto c = std::cos(*theta / 2);
137-
const auto s = std::sin(*theta / 2);
138-
139-
const auto m01 = std::polar(s, *lambda + std::numbers::pi);
140-
const auto m10 = std::polar(s, *phi);
141-
const auto m11 = std::polar(c, *phi + *lambda);
136+
using namespace std::complex_literals;
137+
const auto halfTheta = *theta / 2;
138+
const auto c = std::cos(halfTheta);
139+
const auto s = std::sin(halfTheta);
140+
141+
const auto m01 = s * std::exp(1i * (*lambda + std::numbers::pi));
142+
const auto m10 = s * std::exp(1i * (*phi));
143+
const auto m11 = c * std::exp(1i * (*phi + *lambda));
142144
return Matrix2x2::fromElements(c, m01, // row 0
143145
m10, m11); // row 1
144146
}

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXMinusYYOp.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,11 @@ std::optional<Matrix4x4> XXMinusYYOp::getUnitaryMatrix() {
7979
return std::nullopt;
8080
}
8181

82+
using namespace std::complex_literals;
8283
const auto mc = std::cos(*theta / 2);
8384
const auto s = std::sin(*theta / 2);
84-
const auto msp = std::polar(s, *beta - (std::numbers::pi / 2));
85-
const auto msm = std::polar(s, -*beta - (std::numbers::pi / 2));
85+
const auto msp = s * std::exp(1i * (*beta - (std::numbers::pi / 2)));
86+
const auto msm = s * std::exp(1i * (-*beta - (std::numbers::pi / 2)));
8687
return Matrix4x4::fromElements(mc, 0, 0, msm, // row 0
8788
0, 1, 0, 0, // row 1
8889
0, 0, 1, 0, // row 2

mlir/lib/Dialect/QCO/IR/Operations/StandardGates/XXPlusYYOp.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,11 @@ std::optional<Matrix4x4> XXPlusYYOp::getUnitaryMatrix() {
7979
return std::nullopt;
8080
}
8181

82+
using namespace std::complex_literals;
8283
const auto mc = std::cos(*theta / 2);
8384
const auto s = std::sin(*theta / 2);
84-
const auto msp = std::polar(s, *beta - (std::numbers::pi / 2));
85-
const auto msm = std::polar(s, -*beta - (std::numbers::pi / 2));
85+
const auto msp = s * std::exp(1i * (*beta - (std::numbers::pi / 2)));
86+
const auto msm = s * std::exp(1i * (-*beta - (std::numbers::pi / 2)));
8687
return Matrix4x4::fromElements(1, 0, 0, 0, // row 0
8788
0, mc, msp, 0, // row 1
8889
0, msm, mc, 0, // row 2

0 commit comments

Comments
 (0)