Skip to content
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ releases may include breaking changes.
circuits to compiler-target topologies while preserving target site IDs and
materializing routing workspace on demand ([#1537], [#1547], [#1568], [#1581],
[#1583], [#1588], [#1600], [#1664], [#1709], [#1716], [#1748], [#1805],
[#1870], [#1904], [#1911], [#1951], [#1997], [#2016]) ([**@MatthiasReumann**],
[**@burgholzer**])
[#1870], [#1904], [#1911], [#1951], [#1997], [#2016], [#2060])
([**@MatthiasReumann**], [**@burgholzer**])
- ✨ Add a pass for qubit reuse in quantum programs, as well as related
auxiliary passes and patterns ([#1705], [#1755], [#1756], [#1923], [#1924])
([**@DRovara**], [**@burgholzer**])
Expand Down Expand Up @@ -737,6 +737,7 @@ for previous changelogs._

<!-- PR links -->

[#2060]: https://github.com/munich-quantum-toolkit/core/pull/2060
[#2058]: https://github.com/munich-quantum-toolkit/core/pull/2058
[#2030]: https://github.com/munich-quantum-toolkit/core/pull/2030
[#2042]: https://github.com/munich-quantum-toolkit/core/pull/2042
Expand Down
48 changes: 28 additions & 20 deletions mlir/lib/Dialect/QCO/Transforms/Mapping/Mapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -979,28 +979,36 @@ struct MappingPass : impl::MappingPassBase<MappingPass> {
return {layouts[0], std::move(swaps[0]), std::move(swaps[1])};
}

/// Return the "average" layout by computing the borda count, where each
/// layout is a voter and each hardware index counts as a candidate. One vote
/// is the order (the permutation) of program-to-hardware indices.
template <typename Range> static Layout vote(Range layouts) {
/// Compute a routing-friendly layout compromise between a range of layouts.
/// Using the first layout of the range as an anchor, the function repeatedly
/// nudges the current layout towards the next one using happy SWAP chains.
/// Inspired by SABRE and to reduce ordering bias, the function performs an
/// additional backward pass.
template <typename Range>
Layout driveby(Range layouts, const size_t niterations = 1) {
assert(!layouts.empty() && "expected at least one layout");
const auto ncandidates = (*layouts.begin()).nqubits();

SmallVector<size_t> scores(ncandidates, 0);
for (const Layout& layout : layouts) {
for (const auto [rank, hw] : enumerate(layout.getProgramToHardware())) {
scores[hw] += ncandidates - rank - 1;
FGraph f(*target);
Layout curr(*(layouts.begin()));

// Nudge curr towards target by applying a happy SWAP chain.
const auto merge = [&](const Layout& target) {
f.reset();
f.construct(curr, target);
if (const auto happy = f.findHappySWAPChain()) {
for (const auto& swap : *happy) {
curr.swap(swap.first, swap.second);
}
}
}
};

auto mapping = llvm::to_vector(llvm::seq(ncandidates));
llvm::sort(mapping, [&](const size_t lhs, const size_t rhs) {
return scores[lhs] != scores[rhs]
? scores[lhs] > scores[rhs]
: lhs < rhs; // Ensure order on borda equality.
});
// Perform multiple rounds of forward and backward drive-by's.
for (size_t i = 0; i < niterations; ++i) {
for_each(drop_begin(layouts), merge);
for_each(drop_begin(reverse(layouts)), merge);
}

return Layout::fromMapping(mapping);
return curr;
}

/// Skip to the end of the two-qubit block for both wire iterators, where
Expand Down Expand Up @@ -1466,15 +1474,15 @@ struct MappingPass : impl::MappingPassBase<MappingPass> {
return convergedLayout;
})
.template Case<IndexSwitchOp>([&](IndexSwitchOp) {
auto winner = vote(map_range(
auto compromise = driveby(map_range(
children, [](const RoutingBundle& b) -> const Layout& {
return b.layout;
}));
for (RoutingBundle& child : children) {
const auto swaps = restore(child.layout, winner);
const auto swaps = restore(child.layout, compromise);
insertSWAPs<Mode>(swaps, child, totalStats, rewriter);
}
return winner;
return compromise;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
});

if constexpr (Mode == RoutingMode::Hot) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1663,7 +1663,7 @@ TEST_P(MappingPassTest, MapIndexSwitchUsesVotedLayout) {
m->walk([&](SWAPOp) { ++numSwaps; });
// The three routed cases agree on the voted exit layout; only the default
// case must be restored to it. Restoring every case to the parent needs 12.
EXPECT_EQ(numSwaps, 4UL);
EXPECT_EQ(numSwaps, 6UL);
}

TEST_P(MappingPassTest, MapPaddedCXCZGrid) {
Expand Down
Loading