✨ Extend QCO DD construction/simulation beyond static unitaries - #1973
✨ Extend QCO DD construction/simulation beyond static unitaries#1973simon1hofmann wants to merge 18 commits into
Conversation
…ements, resets, and control-flow operations. Added new simulation functions and updated existing functionality to handle classical branching and multi-shot sampling.
…, resets, and advanced control-flow operations. Introduced new simulation functions and updated existing ones to accommodate classical branching and multi-shot sampling capabilities. Updated changelog and added Python bindings for new functionalities.
… in QCO DD simulation. Updated functionality to handle allocation, storage, and loading of classical registers, enhancing the simulation capabilities. Changelog updated to reflect these changes.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Signed-off-by: simon1hofmann <119581649+simon1hofmann@users.noreply.github.com>
|
@coderabbitai full review |
✅ Action performedFull review finished. |
|
Warning Review limit reached
Next review available in: 3 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis PR adds measurement-aware QCO decision-diagram simulation, sampling, classical control flow, memref-backed registers, public C++ APIs, Python bindings, and extensive C++ and Python tests. ChangesQCO DD simulation and sampling
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant Python
participant QCOProgram
participant DDFunctionality
participant DDPackage
Python->>QCOProgram: provide QCO program
QCOProgram->>DDFunctionality: select entry FuncOp
DDFunctionality->>DDPackage: build, simulate, or sample DD state
DDPackage-->>DDFunctionality: return quantum and classical histograms
DDFunctionality-->>Python: return VectorDD, histogram, or SampleResult
Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches✨ Simplify code
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 |
There was a problem hiding this comment.
Actionable comments posted: 13
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
mlir/lib/Dialect/QCO/Utils/CMakeLists.txt (1)
63-69: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winLink
MLIRArithDialectinMLIRQCODDFunctionality.
MLIRQCODialectdeclaresMLIRArithDialectonly as aPRIVATEdependency, whileDDFunctionality.cppdirectly usesmlir/Dialect/Arith/IR/Arith.hand instantiatesarith::*types. AddMLIRArithDialecttoMLIRQCODDFunctionality’sLINK_LIBS.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@mlir/lib/Dialect/QCO/Utils/CMakeLists.txt` around lines 63 - 69, Update the MLIRQCODDFunctionality LINK_LIBS list in the CMake configuration to include MLIRArithDialect alongside the existing public dependencies, ensuring DDFunctionality.cpp’s direct arith::* usage is linked explicitly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@bindings/mlir/register_mlir.cpp`:
- Around line 612-618: Add a nanobind call guard releasing the GIL to both QCO
sampling bindings around the lambdas invoking mlir::qco::sample, including the
second binding noted at lines 636-642. Confirm the sampled dd::Package is not
shared across threads before applying the guard, and keep the existing sampling
and error propagation unchanged.
- Around line 559-566: Add the nanobind keep-alive policy <nb::keep_alive<0,
1>()> to the `build_functionality` binding, matching the existing DD package
bindings, so the returned DD objects retain `ddPackage` for their lifetime.
- Around line 123-130: Update takeFailureOr and its call sites to capture MLIR
diagnostics with a ScopedDiagnosticHandler on the relevant program context,
accumulating emitted messages into a std::string before checking the FailureOr
result. When failure occurs, append the collected diagnostics to the supplied
message in the raised nb::value_error, while preserving the existing successful
return behavior.
- Around line 610-656: Update the sample and sample_with_classics bindings to
accept an optional uint64 seed with a None/empty default, matching simulate
semantics; invoke makeRng only for an explicitly provided seed and otherwise use
nondeterministic RNG initialization. Revise both docstrings to document None as
nondeterministic rather than 0, and regenerate the Python stub to reflect the
optional seed signatures.
In `@mlir/include/mlir/Dialect/QCO/Utils/DDFunctionality.h`:
- Around line 63-66: Update the non-RNG simulate documentation near simulateImpl
to remove the claim that loops and multi-block function bodies are unsupported,
and accurately state that concrete-bound scf.for loops and non-recursive
single-block func.call operations are supported independently of RNG; retain the
existing limitations for unsupported cases and the reference-consumption
behavior.
- Around line 149-167: Move the sampling `@brief/`@details documentation from
SampleResult to the two sampleWithClassics overloads, documenting their shared
behavior while leaving SampleResult without that function-level description.
Update both overload signatures to use std::size_t consistently with the
existing sample overloads.
In `@mlir/lib/Dialect/QCO/Utils/DDFunctionality.cpp`:
- Around line 1129-1145: Adjust the callee traversal around walkFunction so
func::ReturnOp is not subjected to the entry-function-only validateReturn
canonical wire-order rule. Preserve return/result arity validation and bind the
callee return operands to call results, while retaining canonical return
validation for the top-level simulated function.
- Around line 686-735: Update the cmpi evaluation around the i1 handling and
signed predicate cases so boolean true is interpreted with arith’s
sign-extension semantics as -1 rather than 1 for signed comparisons. Preserve
unsigned comparisons as 0/1 and keep equality/inequality behavior unchanged,
using the existing cmp.getPredicate() and result calculation.
- Around line 628-657: Update the arith::AddIOp, arith::SubIOp, and
arith::MulIOp handlers using applyBinaryIndex to perform wrapping uint64_t
arithmetic before storing the resulting index, avoiding signed-overflow UB. In
the arith::ShLIOp handler, preserve the existing shift-range validation, convert
the left operand to uint64_t before shifting, and store the wrapped result
without signed-shift UB.
- Around line 1000-1028: In the IndexSwitchOp handler, validate the default
block and yield obtained from getDefaultBlock() and getDefaultYield() before
dereferencing them, matching the existing IfOp guard behavior. Emit an operation
diagnostic and return failure for an absent or empty default region; otherwise
preserve the case-selection and applyRegionBranch flow.
- Around line 1296-1332: Update requiresDynamicSampling to account for MeasureOp
and ResetOp in functions invoked through func.call, either by recursively
visiting callees or conservatively treating calls as dynamically sampled. Ensure
sampleImpl selects the dynamic per-shot simulation path whenever a reachable
callee contains measurement or reset, avoiding simulateImpl with a null RNG for
these programs.
In `@mlir/unittests/Dialect/QCO/Utils/test_dd_functionality.cpp`:
- Around line 784-798: Add a companion QCODDFunctionalityTest using scfFor with
exactly 10000 trips, retaining the identity iterArgs body and sink setup from
RejectsScfForTripCountLimit, then assert module construction and simulation
succeed. Keep the existing 10001-trip rejection test unchanged so both sides of
the boundary are covered.
In `@test/python/test_qco_dd.py`:
- Around line 33-51: Expand test_unitary_x_build_simulate_and_sample and add
focused Python binding tests covering documented ValueError paths: simulate
without a seed must reject mid-circuit measure/reset, while supplying a seed
must allow it. Also add coverage for a QCO program without a func.func to verify
entryFunc validation and exception translation; remove the vacuous matrix is not
None assertion while retaining valid cleanup and success-path checks.
---
Outside diff comments:
In `@mlir/lib/Dialect/QCO/Utils/CMakeLists.txt`:
- Around line 63-69: Update the MLIRQCODDFunctionality LINK_LIBS list in the
CMake configuration to include MLIRArithDialect alongside the existing public
dependencies, ensuring DDFunctionality.cpp’s direct arith::* usage is linked
explicitly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 6290089f-62d0-45cf-ac89-59611528846a
📒 Files selected for processing (11)
CHANGELOG.mdbindings/mlir/CMakeLists.txtbindings/mlir/register_mlir.cppmlir/include/mlir/Compiler/Programs.hmlir/include/mlir/Dialect/QCO/Utils/DDFunctionality.hmlir/lib/Compiler/Programs.cppmlir/lib/Dialect/QCO/Utils/CMakeLists.txtmlir/lib/Dialect/QCO/Utils/DDFunctionality.cppmlir/unittests/Dialect/QCO/Utils/test_dd_functionality.cpppython/mqt/core/mlir.pyitest/python/test_qco_dd.py
Signed-off-by: simon1hofmann <119581649+simon1hofmann@users.noreply.github.com>
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
bindings/mlir/register_mlir.cpp (2)
613-630:⚠️ Potential issue | 🟠 MajorRetain
dd_packagefor the simulated result.🤖 AI text below 🤖
mlir::qco::simulatereturns add::VectorDDbacked byddPackage. Unlikebuild_functionality, this binding does not retain argument 3. If Python releasesdd_package, the returnedVectorDDcan retain invalid package-owned storage. Addnb::keep_alive<0, 3>(). Nanobind uses index 0 for the return value and indexes free-function arguments from 1. (nanobind.readthedocs.io)Proposed fix
"program"_a, "initial_state"_a, "dd_package"_a, "seed"_a = nb::none(), + nb::keep_alive<0, 3>(), R"pb(Simulate a QCO program on a DD state.#!/bin/bash set -euo pipefail sed -n '579,645p' bindings/mlir/register_mlir.cpp echo "== Existing DD lifetime policies ==" fd -i 'register_*dd*.cpp' bindings -x rg -n -C2 'keep_alive|reference_internal' {} echo "== Python lifetime regression coverage ==" rg -n -C3 'simulate\(|build_functionality\(|gc\.collect|del package' test/python🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@bindings/mlir/register_mlir.cpp` around lines 613 - 630, Add the nanobind lifetime policy keep_alive<0, 3>() to the simulate binding after its argument declarations, ensuring the returned VectorDD keeps ddPackage alive. Do not alter the simulation logic or seed handling.
109-116: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winUse API-neutral error text for
entryFunc.🤖 AI text below 🤖
entryFuncalso servesbuild_functionality,sample, andsample_with_classics. The text"to simulate"is incorrect for those APIs. Use an API-neutral message such as"QCO program has no func.func entry point".Proposed fix
- throw nb::value_error("QCO program has no func.func to simulate"); + throw nb::value_error("QCO program has no func.func entry point");🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@bindings/mlir/register_mlir.cpp` around lines 109 - 116, Update the missing-function error in entryFunc to use API-neutral wording, replacing the simulation-specific phrase with a message indicating that the QCO program has no func.func entry point. Preserve the existing validation and exception type.mlir/lib/Dialect/QCO/Utils/DDFunctionality.cpp (1)
1082-1144: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winGuard
scf.fortrip-count computation against signed-overflow UB.
*ub - *lb - 1operates onint64_tvalues that come from arbitrary classical index SSA values (constants, prior arithmetic, or measurement-derived indices). Whenlbandubare far apart (for examplelb = INT64_MIN,ub = INT64_MAX), the subtraction overflows before thetrips > maxTripscheck runs. Signed-integer overflow is undefined behavior in C++, even under the project's C++20 target (C++20 guarantees two's-complement representation, not that overflow is defined). A UBSan build aborts on this input instead of producing the "trip count exceeds ... limit" diagnostic.Compute the span and trip count in
uint64_t, and compare againstmaxTripsbefore casting back toint64_t, the same way this file already avoids overflow in thearith.addi/arith.subi/arith.mulihandlers.🛡️ Suggested fix
- const int64_t trips = (*ub > *lb) ? ((*ub - *lb - 1) / *step) + 1 : 0; constexpr int64_t maxTrips = 10000; - if (trips > maxTrips) { - return forOp.emitError() - << "scf.for trip count exceeds QCO DD simulation limit of " - << maxTrips; - } + int64_t trips = 0; + if (*ub > *lb) { + const auto span = static_cast<uint64_t>(*ub) - + static_cast<uint64_t>(*lb); + const uint64_t tripsU = + (span - 1) / static_cast<uint64_t>(*step) + 1; + if (tripsU > static_cast<uint64_t>(maxTrips)) { + return forOp.emitError() + << "scf.for trip count exceeds QCO DD simulation limit " + "of " + << maxTrips; + } + trips = static_cast<int64_t>(tripsU); + }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@mlir/lib/Dialect/QCO/Utils/DDFunctionality.cpp` around lines 1082 - 1144, Update the trip-count calculation in the scf::ForOp handler to avoid signed overflow when computing the bound span: perform the bound comparison and span/trip arithmetic in uint64_t, including the nonnegative lower-to-upper difference, then compare the resulting trip count against maxTrips before converting it to int64_t for the existing loop. Preserve zero trips for ub <= lb and the current limit diagnostic for oversized counts.mlir/unittests/Dialect/QCO/Utils/test_dd_functionality.cpp (1)
69-74: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winGuard
mainFuncagainst an empty function range.
mainFuncdereferencesmod.getBody()->getOps<func::FuncOp>().begin()without checking that the range is non-empty. If a future test parses or builds a module with nofunc::FuncOp, this dereferences an end iterator, which is undefined behavior. Add an assertion so a missing function fails with a clear message instead of an ambiguous crash.🛡️ Proposed fix
[[nodiscard]] static func::FuncOp mainFunc(ModuleOp mod) { if (auto main = mod.lookupSymbol<func::FuncOp>("main")) { return main; } - return *mod.getBody()->getOps<func::FuncOp>().begin(); + auto funcs = mod.getBody()->getOps<func::FuncOp>(); + assert(funcs.begin() != funcs.end() && "module must contain a func.func"); + return *funcs.begin(); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@mlir/unittests/Dialect/QCO/Utils/test_dd_functionality.cpp` around lines 69 - 74, Update mainFunc to capture the func::FuncOp range and assert that it is non-empty before dereferencing begin(), using a clear failure message for modules without a function. Preserve the existing lookup of the "main" symbol and return the first function when the range contains one.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@bindings/mlir/register_mlir.cpp`:
- Around line 613-630: Add the nanobind lifetime policy keep_alive<0, 3>() to
the simulate binding after its argument declarations, ensuring the returned
VectorDD keeps ddPackage alive. Do not alter the simulation logic or seed
handling.
- Around line 109-116: Update the missing-function error in entryFunc to use
API-neutral wording, replacing the simulation-specific phrase with a message
indicating that the QCO program has no func.func entry point. Preserve the
existing validation and exception type.
In `@mlir/lib/Dialect/QCO/Utils/DDFunctionality.cpp`:
- Around line 1082-1144: Update the trip-count calculation in the scf::ForOp
handler to avoid signed overflow when computing the bound span: perform the
bound comparison and span/trip arithmetic in uint64_t, including the nonnegative
lower-to-upper difference, then compare the resulting trip count against
maxTrips before converting it to int64_t for the existing loop. Preserve zero
trips for ub <= lb and the current limit diagnostic for oversized counts.
In `@mlir/unittests/Dialect/QCO/Utils/test_dd_functionality.cpp`:
- Around line 69-74: Update mainFunc to capture the func::FuncOp range and
assert that it is non-empty before dereferencing begin(), using a clear failure
message for modules without a function. Preserve the existing lookup of the
"main" symbol and return the first function when the range contains one.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 6128b128-c640-4ace-9dac-2034df0715b0
📒 Files selected for processing (9)
CHANGELOG.mdbindings/mlir/register_mlir.cppmlir/include/mlir/Dialect/QCO/Utils/DDFunctionality.hmlir/lib/Dialect/QCO/Utils/CMakeLists.txtmlir/lib/Dialect/QCO/Utils/DDFunctionality.cppmlir/unittests/Compiler/test_compiler_pipeline.cppmlir/unittests/Dialect/QCO/Utils/test_dd_functionality.cpppython/mqt/core/mlir.pyitest/python/test_qco_dd.py
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
mlir/include/mlir/Dialect/QCO/Utils/DDFunctionality.h (1)
60-62: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winCorrect the classical-register type in the API contract.
🤖 AI text below 🤖
Line 62 and Line 91 state that
memref<?xi1>is supported. That type has a dynamic dimension.isStaticI1MemRefandapplyMemRefAllocaccept only static-shape registers and reject dynamic allocation. Documentmemref<Nxi1>for a concrete staticN, or use equivalent static-shape wording.Proposed documentation fix
- * `memref<?xi1>` classical registers (`alloc`/`store`/`load`/`dealloc`). + * static-shape 1-D `memref<Nxi1>` classical registers + * (`alloc`/`store`/`load`/`dealloc`).Also applies to: 90-92
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@mlir/include/mlir/Dialect/QCO/Utils/DDFunctionality.h` around lines 60 - 62, Update the API contract documentation near the classical-register description and the corresponding lines around the allocation APIs to describe only statically shaped 1-D i1 memrefs, using memref<Nxi1> for a concrete static N instead of memref<?xi1>. Align the wording with the static-shape requirements enforced by isStaticI1MemRef and applyMemRefAlloc.mlir/lib/Dialect/QCO/Utils/DDFunctionality.cpp (1)
1099-1128: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winCompute
scf.forinduction values with unsigned arithmetic.🤖 AI text below 🤖
Line 1128 still evaluates
*lb + (t * *step)in signedint64_t. Valid extreme bounds can overflow this intermediate expression even when the loop result is in range. Forlb = INT64_MIN,ub = INT64_MAX, andstep = 3074457345618258603, the induction value att = 3should be1, but signed overflow fromt * stepmakes the stored value invalid.Use
uint64_tfor the offset and cast the sum back toint64_t, matching the trip-count arithmetic.Proposed fix
for (int64_t t = 0; t < trips; ++t) { - walk.classical.indices[body.getArgument(0)] = *lb + (t * *step); + const auto offset = static_cast<uint64_t>(t) * + static_cast<uint64_t>(*step); + walk.classical.indices[body.getArgument(0)] = + static_cast<int64_t>(static_cast<uint64_t>(*lb) + offset);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@mlir/lib/Dialect/QCO/Utils/DDFunctionality.cpp` around lines 1099 - 1128, Update the induction-value assignment in the scf.for simulation loop around body.getArgument(0) to compute t * *step and the lower-bound sum using uint64_t, then cast the final two’s-complement result to int64_t before storing it. Preserve the existing trip-count logic and loop behavior.bindings/mlir/register_mlir.cpp (3)
581-586: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse the project’s raw-string form for Python docstrings.
🤖 AI text below 🤖
The new
SampleResultand property docstrings use ordinary C++ string literals. UseR"pb(...)pb"for these Python-facing docstrings, consistent with the binding convention.Proposed change
- "Histograms from QCO DD sampling.") + R"pb(Histograms from QCO DD sampling.)pb")Based on learnings, nanobind bindings under
bindings/should define Python docstrings in the binding code withR"pb(...)pb"syntax.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@bindings/mlir/register_mlir.cpp` around lines 581 - 586, Update the Python-facing docstrings in the SampleResult binding, including the class description and the shots and classical property descriptions, to use the project’s R"pb(...)pb" raw-string syntax instead of ordinary C++ string literals.Source: Learnings
601-611: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winCorrect the
build_functionalityargument documentation.🤖 AI text below 🤖
The
programargument says that its entryfunc.funcis simulated.build_functionalitybuilds a matrix DD; it does not simulate the program.- program: A QCO program whose entry ``func.func`` is simulated. + program: A QCO program whose entry ``func.func`` is used to build a matrix DD.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@bindings/mlir/register_mlir.cpp` around lines 601 - 611, Update the build_functionality documentation for the program argument to describe that its entry func.func is used to construct the program’s functionality or matrix DD, not simulated. Leave the remaining argument, return, and exception documentation unchanged.
648-676: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winDocument that
dd_packageis not thread-safe.
sampleandsample_with_classicsrelease the GIL while using a mutabledd::Packagewhose tables and memory manager are not locked. Add explicit ownership/GIL-free constraints to both docstrings.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@bindings/mlir/register_mlir.cpp` around lines 648 - 676, Update the `sample` and `sample_with_classics` docstrings to explicitly state that the caller-provided `dd_package` is mutable and not thread-safe, and must not be used concurrently, including while the GIL is released. Keep the existing argument documentation and behavior unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@bindings/mlir/register_mlir.cpp`:
- Around line 581-586: Update the Python-facing docstrings in the SampleResult
binding, including the class description and the shots and classical property
descriptions, to use the project’s R"pb(...)pb" raw-string syntax instead of
ordinary C++ string literals.
- Around line 601-611: Update the build_functionality documentation for the
program argument to describe that its entry func.func is used to construct the
program’s functionality or matrix DD, not simulated. Leave the remaining
argument, return, and exception documentation unchanged.
- Around line 648-676: Update the `sample` and `sample_with_classics` docstrings
to explicitly state that the caller-provided `dd_package` is mutable and not
thread-safe, and must not be used concurrently, including while the GIL is
released. Keep the existing argument documentation and behavior unchanged.
In `@mlir/include/mlir/Dialect/QCO/Utils/DDFunctionality.h`:
- Around line 60-62: Update the API contract documentation near the
classical-register description and the corresponding lines around the allocation
APIs to describe only statically shaped 1-D i1 memrefs, using memref<Nxi1> for a
concrete static N instead of memref<?xi1>. Align the wording with the
static-shape requirements enforced by isStaticI1MemRef and applyMemRefAlloc.
In `@mlir/lib/Dialect/QCO/Utils/DDFunctionality.cpp`:
- Around line 1099-1128: Update the induction-value assignment in the scf.for
simulation loop around body.getArgument(0) to compute t * *step and the
lower-bound sum using uint64_t, then cast the final two’s-complement result to
int64_t before storing it. Preserve the existing trip-count logic and loop
behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: a7678d2c-06fa-4b42-a000-c2da05f8738c
📒 Files selected for processing (5)
CHANGELOG.mdbindings/mlir/register_mlir.cppmlir/include/mlir/Dialect/QCO/Utils/DDFunctionality.hmlir/lib/Dialect/QCO/Utils/DDFunctionality.cppmlir/unittests/Dialect/QCO/Utils/test_dd_functionality.cpp
|
@coderabbitai review |
✅ Action performedReview finished.
|
Signed-off-by: simon1hofmann <119581649+simon1hofmann@users.noreply.github.com>
🤖 AI text below 🤖
Summary
Extends QCO decision-diagram APIs beyond static unitaries (#1915) so programs with mid-circuit dynamics and concrete classical control can be simulated and sampled.
mlir::qco): RNGsimulateformeasure/reset; concreteqco.if/index_switch; richer classical SSA (cmpi, arith, shifts,select, casts);scf.for(concrete bounds, ≤10000 trips); non-recursive single-blockfunc.call; static 1-Dmemref<?xi1>classical registers; dense embed fork>3unitaries (≤12 qubits);sampleandsampleWithClassics(mid-circuit bits in encounter order).build_functionality,simulate,sample,sample_with_classics,SampleResultonmqt.core.mlir, reusingmqt.core.ddpackage/DD types;QCOProgram.entry_funcsupport viaentryFunc().scf.while, noise/density matrix.Checklist
If PR contains AI-assisted content:
🤖 *AI text below* 🤖(titles are exempt).