✨ Extend Layout API for partial injections - #1956
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
@rturrado Thanks for another PR! 🙌 @MatthiasReumann care to take a first look here since this is closest to the stuff you have been working on? 😌 |
MatthiasReumann
left a comment
There was a problem hiding this comment.
@rturrado Thanks for the effort 🚀 Really appreciate it!
I've left one comment regarding the strategies for mapping SCF which probably shouldn't be reverted to "restore-all". The essential idea is that the SCF operations (besides scf.for) act like permutation networks changing the layout (which needs to be propagated to the parent). If you have any questions, feel free to reach out!
Thanks! This one touches a really beautiful area.
But I have to admit that it is also more complicated code, so human review here is essential. |
Many thanks!
Perfect, thanks! Yes, this was my main concern about this PR. That the new wire-index-equals-hardware-index invariant always has to restore to the parent layout and never converges. That |
I think the "wire-index-equals-hardware-index" is a pretty neat idea, which eventually I would have also looked into. In a previous version of the mapping pass (before SCF mapping), we implemented "wire-index-equals-program-index" which worked pretty nicely. Nonetheless, I think it would make sense to split this PR into two:
Especially since it's very likely that #1951 is merged before this one. |
|
🤖 AI text below 🤖 @MatthiasReumann Agreed on the split. Rough sketch: PR 1 (safe): PR 2 (invariant):
Assisted-by: Claude Opus 4.7 via Claude Code |
Layout: DenseMap storage and partial-injection API
Layout: DenseMap storage and partial-injection APILayout: DenseMap storage and partial-injection API
|
I think we'll try to get #1951 in asap (either tonight or tomorrow). Then PR1 can go on top 😌 |
25f536f to
b036d42
Compare
MatthiasReumann
left a comment
There was a problem hiding this comment.
Great work. Looking forward for merging this 🚀
Some notes / ideas:
We can now reasonably argue that the program and hardware qubits are a consecutive range of numbers (#1993). That is, a Layout holds [M] → [N], where M <= N. Maybe this allows us to avoid DenseMaps and use SmallVectors again. The Layout is an essential data structure in the mapping pass, so we need to make sure the implementation is very efficient.
Moreover, if we now already invest the time to improve this data structure, it could also make sense to add a generalized InjectiveMap<K, V>, where the Layout would then be a subclass of that (If that is even necessary). Using templates, we may need to keep DenseMap; or specialize on integer types using SmallVector. Just an idea - maybe a follow-up!
|
@MatthiasReumann Many thanks for the thorough review and the guidance. This PR was just the rebase onto |
Layout: DenseMap storage and partial-injection API|
@MatthiasReumann @rturrado Except for the minor conflict with |
@burgholzer Thanks for flagging this. I'll have a look into that conflict! |
Extend `Layout` to support `M <= N` program-to-hardware mappings where `N - M` hardware slots stay unmapped: - Unmapped hardware entries in `hardwareToProgram_` carry an `UNMAPPED` sentinel. - Split `nqubits()` into `nProgramQubits()` and `nHardwareQubits()`. `random()` takes both sizes. - Add `hasProgramAt(hw)` to distinguish mapped from unmapped hardware slots. Adapt `Mapping.cpp`: - rename `nqubits()` call sites to `nHardwareQubits()`, - pass both sizes to `Layout::random()`. Assisted-by: Claude Opus 4.7 via Claude Code Signed-off-by: rturrado <rturrado@gmail.com>
MatthiasReumann
left a comment
There was a problem hiding this comment.
Thanks for your continued work on this! @rturrado Much appreciated🙏
The pull request looks really good already! I've only left some very nitpicky comments, which should be fairly easy to resolve. Lastly, I think a changelog entry is missing also. Otherwise, let's get this PR merged ASAP 🛫
In that regard, please just fold this PR number into the existing changelog entry for the mapping pass (and add your name to it) 😌 |
Done, folded |
- Doc: describe `fromMapping` as bijective. - Test: use `llvm::count_if` / `llvm::seq` instead of `std::ranges::count_if` / `std::views::iota`. - Test: drop the defensive `(void)` cast in `EXPECT_DEATH`. - Add `munich-quantum-toolkit#1956` to the `place-and-route` changelog entry. Assisted-by: Claude Opus 4.7 via Claude Code Signed-off-by: rturrado <rturrado@gmail.com>
|
Important Approval pendingCodeRabbit has no unresolved comments, but it has not reviewed the latest commit. Use the checkbox below to review the latest commit. CodeRabbit will approve the changes if it finds no blocking issues.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
MatthiasReumann
left a comment
There was a problem hiding this comment.
Looks great! Many, many, thanks for your work on this @rturrado.
Let's merge this 🛫
burgholzer
left a comment
There was a problem hiding this comment.
Nice! Thanks for all the work. Let's get this in! 🚀
|
Many thanks for the kind words, guys! |
🤖 AI text below 🤖
Description
Extend
Layoutto supportM <= Nprogram-to-hardware mappings whereN - Mhardware slots stay unmapped:hardwareToProgram_carry anUNMAPPEDsentinel.nqubits()intonProgramQubits()andnHardwareQubits().random()takes both sizes.hasProgramAt(hw)to distinguish mapped from unmapped hardware slots.A possible follow-up could exercise
nProg < nHwand the new query API from inside the mapping pass.Part of #1867
Checklist
If PR contains AI-assisted content:
🤖 *AI text below* 🤖(titles are exempt).Assisted-by: [Model Name] via [Tool Name]footer.Assisted-by: Claude Opus 4.7 via Claude Code