diff --git a/CHANGELOG.md b/CHANGELOG.md index 5380e3f303..dad0d3abf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ This project adheres to [Semantic Versioning], with the exception that minor rel - ✨ Add conversions between `jeff` and QCO ([#1479], [#1548], [#1565], [#1637], [#1676], [#1706]) ([**@denialhaag**], [**@burgholzer**]) - ✨ Add a `place-and-route` pass for mapping circuits to architectures with restricted topologies ([#1537], [#1547], [#1568], [#1581], [#1583], [#1588], [#1600], [#1664], [#1709], [#1716], [#1748]) ([**@MatthiasReumann**], [**@burgholzer**]) - ✨ Add initial infrastructure for new QC and QCO MLIR dialects - ([#1264], [#1330], [#1402], [#1428], [#1430], [#1436], [#1443], [#1446], [#1464], [#1465], [#1470], [#1471], [#1472], [#1474], [#1475], [#1506], [#1510], [#1513], [#1521], [#1542], [#1548], [#1550], [#1554], [#1567], [#1569], [#1570], [#1572], [#1573], [#1580], [#1602], [#1620], [#1623], [#1624], [#1626], [#1627], [#1635], [#1638], [#1673], [#1675], [#1700], [#1717], [#1728], [#1730]) + ([#1264], [#1330], [#1402], [#1428], [#1430], [#1436], [#1443], [#1446], [#1464], [#1465], [#1470], [#1471], [#1472], [#1474], [#1475], [#1506], [#1510], [#1513], [#1521], [#1542], [#1548], [#1550], [#1554], [#1567], [#1569], [#1570], [#1572], [#1573], [#1580], [#1602], [#1620], [#1623], [#1624], [#1626], [#1627], [#1635], [#1638], [#1673], [#1675], [#1700], [#1717], [#1728], [#1730], [#1749]) ([**@burgholzer**], [**@denialhaag**], [**@taminob**], [**@DRovara**], [**@li-mingbao**], [**@Ectras**], [**@MatthiasReumann**], [**@simon1hofmann**]) ### Changed @@ -402,6 +402,7 @@ _📚 Refer to the [GitHub Release Notes](https://github.com/munich-quantum-tool +[#1749]: https://github.com/munich-quantum-toolkit/core/pull/1749 [#1748]: https://github.com/munich-quantum-toolkit/core/pull/1748 [#1737]: https://github.com/munich-quantum-toolkit/core/pull/1737 [#1730]: https://github.com/munich-quantum-toolkit/core/pull/1730 diff --git a/mlir/lib/Conversion/QCToQCO/QCToQCO.cpp b/mlir/lib/Conversion/QCToQCO/QCToQCO.cpp index 2e4833a565..b4a4b0a151 100644 --- a/mlir/lib/Conversion/QCToQCO/QCToQCO.cpp +++ b/mlir/lib/Conversion/QCToQCO/QCToQCO.cpp @@ -515,13 +515,7 @@ static void extractQubitsAfterOp(LoweringState& state, Operation* target, */ static std::pair, SetVector> collectQubitValuesInsideSCFOps(Operation* op, LoweringState* state) { - // Get the regions of the current operation - const auto& regions = op->getRegions(); - auto& regionQubitMap = state->regionQubitMap[op]; - auto& regionRegisterMap = state->regionRegisterMap[op]; - - for (auto& region : regions) { - auto& qubitInfoMap = state->qubitInfoMap[®ion]; + for (auto& region : op->getRegions()) { // Skip empty regions e.g. empty else region of an If operation if (region.empty()) { continue; @@ -534,12 +528,16 @@ collectQubitValuesInsideSCFOps(Operation* op, LoweringState* state) { if (operation.getNumRegions() > 0) { auto [qubits, registers] = collectQubitValuesInsideSCFOps(&operation, state); + auto& regionQubitMap = state->regionQubitMap[op]; + auto& qubitInfoMap = state->qubitInfoMap[®ion]; regionQubitMap.set_union(qubits); // Remove duplicate qubits regionQubitMap.remove_if( [&](Value qubit) { return qubitInfoMap.contains(qubit); }); - regionRegisterMap.set_union(registers); + state->regionRegisterMap[op].set_union(registers); } + auto& qubitInfoMap = state->qubitInfoMap[®ion]; + auto& regionRegisterMap = state->regionRegisterMap[op]; // Track qubits from loadOp if (auto loadOp = dyn_cast(operation)) { QubitInfo info{.reg = loadOp.getMemRef(), @@ -548,6 +546,7 @@ collectQubitValuesInsideSCFOps(Operation* op, LoweringState* state) { regionRegisterMap.insert(loadOp.getMemRef()); continue; } + auto& regionQubitMap = state->regionQubitMap[op]; // Add the QC qubit and memref operands to the maps for (const auto& operand : operation.getOperands()) { if (isa(operand.getType())) { @@ -564,7 +563,7 @@ collectQubitValuesInsideSCFOps(Operation* op, LoweringState* state) { } } - return {regionQubitMap, regionRegisterMap}; + return {state->regionQubitMap[op], state->regionRegisterMap[op]}; } namespace { diff --git a/mlir/unittests/Conversion/QCOToQC/test_qco_to_qc.cpp b/mlir/unittests/Conversion/QCOToQC/test_qco_to_qc.cpp index fec35911b7..4bd2b24615 100644 --- a/mlir/unittests/Conversion/QCOToQC/test_qco_to_qc.cpp +++ b/mlir/unittests/Conversion/QCOToQC/test_qco_to_qc.cpp @@ -527,10 +527,13 @@ INSTANTIATE_TEST_SUITE_P( QCOToQCTestCase{"SingleControlledX", MQT_NAMED_BUILDER(qco::singleControlledX), MQT_NAMED_BUILDER(qc::singleControlledX)}, + QCOToQCTestCase{"MultipleControlledX", + MQT_NAMED_BUILDER(qco::multipleControlledX), + MQT_NAMED_BUILDER(qc::multipleControlledX)}, QCOToQCTestCase{ - "MultipleControlledX", - MQT_NAMED_BUILDER(qco::multipleControlledX), - MQT_NAMED_BUILDER(qc::multipleControlledX)})); + "RepeatedControlledX", + MQT_NAMED_BUILDER(qco::repeatedControlledX), + MQT_NAMED_BUILDER(qc::repeatedControlledX)})); /// @} /// \name QCOToQC/Operations/StandardGates/XxMinusYyOp.cpp diff --git a/mlir/unittests/Conversion/QCToQCO/test_qc_to_qco.cpp b/mlir/unittests/Conversion/QCToQCO/test_qc_to_qco.cpp index eff8c5ca12..3f0df25542 100644 --- a/mlir/unittests/Conversion/QCToQCO/test_qc_to_qco.cpp +++ b/mlir/unittests/Conversion/QCToQCO/test_qc_to_qco.cpp @@ -525,15 +525,19 @@ INSTANTIATE_TEST_SUITE_P( /// @{ INSTANTIATE_TEST_SUITE_P( QCXOpTest, QCToQCOTest, - testing::Values(QCToQCOTestCase{"X", MQT_NAMED_BUILDER(qc::x), - MQT_NAMED_BUILDER(qco::x)}, - QCToQCOTestCase{"SingleControlledX", - MQT_NAMED_BUILDER(qc::singleControlledX), - MQT_NAMED_BUILDER(qco::singleControlledX)}, - QCToQCOTestCase{ - "MultipleControlledX", + testing::Values( + QCToQCOTestCase{"X", MQT_NAMED_BUILDER(qc::x), + MQT_NAMED_BUILDER(qco::x)}, + QCToQCOTestCase{"SingleControlledX", + MQT_NAMED_BUILDER(qc::singleControlledX), + MQT_NAMED_BUILDER(qco::singleControlledX)}, + QCToQCOTestCase{"MultipleControlledX", MQT_NAMED_BUILDER(qc::multipleControlledX), - MQT_NAMED_BUILDER(qco::multipleControlledX)})); + MQT_NAMED_BUILDER(qco::multipleControlledX)}, + QCToQCOTestCase{"RepeatedControlledX", + MQT_NAMED_BUILDER(qc::repeatedControlledX), + MQT_NAMED_BUILDER(qco::repeatedControlledX)})); + /// @} /// \name QCToQCO/Operations/StandardGates/XxMinusYyOp.cpp diff --git a/mlir/unittests/programs/qc_programs.cpp b/mlir/unittests/programs/qc_programs.cpp index c6ba8b013f..373452252a 100644 --- a/mlir/unittests/programs/qc_programs.cpp +++ b/mlir/unittests/programs/qc_programs.cpp @@ -271,6 +271,15 @@ void trivialControlledX(QCProgramBuilder& b) { b.mcx({}, q[0]); } +void repeatedControlledX(QCProgramBuilder& b) { + auto control = b.allocQubit(); + b.h(control); + for (auto i = 0; i < 50; i++) { + auto qubit = b.allocQubit(); + b.cx(control, qubit); + } +} + void inverseX(QCProgramBuilder& b) { auto q = b.allocQubitRegister(1); b.inv([&]() { b.x(q[0]); }); diff --git a/mlir/unittests/programs/qc_programs.h b/mlir/unittests/programs/qc_programs.h index 124bb2be50..e6569f7648 100644 --- a/mlir/unittests/programs/qc_programs.h +++ b/mlir/unittests/programs/qc_programs.h @@ -171,6 +171,9 @@ void nestedControlledX(QCProgramBuilder& b); /// Creates a circuit with a trivial controlled X gate. void trivialControlledX(QCProgramBuilder& b); +/// Creates a circuit with repeated controlled X gates. +void repeatedControlledX(QCProgramBuilder& b); + /// Creates a circuit with an inverse modifier applied to an X gate. void inverseX(QCProgramBuilder& b); diff --git a/mlir/unittests/programs/qco_programs.cpp b/mlir/unittests/programs/qco_programs.cpp index afb5a6bf59..0ad96fbb10 100644 --- a/mlir/unittests/programs/qco_programs.cpp +++ b/mlir/unittests/programs/qco_programs.cpp @@ -271,6 +271,15 @@ void trivialControlledX(QCOProgramBuilder& b) { b.mcx({}, q[0]); } +void repeatedControlledX(QCOProgramBuilder& b) { + auto q0 = b.allocQubit(); + auto control = b.h(q0); + for (auto i = 0; i < 50; i++) { + auto qubit = b.allocQubit(); + control = b.cx(control, qubit).first; + } +} + void inverseX(QCOProgramBuilder& b) { auto q = b.allocQubitRegister(1); b.inv({q[0]}, [&](ValueRange qubits) { return SmallVector{b.x(qubits[0])}; }); diff --git a/mlir/unittests/programs/qco_programs.h b/mlir/unittests/programs/qco_programs.h index a056d91ca6..b4197c5a7f 100644 --- a/mlir/unittests/programs/qco_programs.h +++ b/mlir/unittests/programs/qco_programs.h @@ -158,6 +158,9 @@ void nestedControlledX(QCOProgramBuilder& b); /// Creates a circuit with a trivial controlled X gate. void trivialControlledX(QCOProgramBuilder& b); +/// Creates a circuit with repeated controlled X gates. +void repeatedControlledX(QCOProgramBuilder& b); + /// Creates a circuit with an inverse modifier applied to an X gate. void inverseX(QCOProgramBuilder& b);