Skip to content

Pre-Trajectory Sampling with Batch Execution#3995

Merged
sacpis merged 88 commits intomainfrom
features/ptsbe
Feb 27, 2026
Merged

Pre-Trajectory Sampling with Batch Execution#3995
sacpis merged 88 commits intomainfrom
features/ptsbe

Conversation

@sacpis
Copy link
Collaborator

@sacpis sacpis commented Feb 18, 2026

Adding Pre-Trajectory Sampling with Batch Execution (PTSBE) for noisy circuit sampling. Noise is pre-sampled into trajectories, circuits are run in batches per trajectory and results are aggregated. This enables noisy sampling on simulators.

Refer paper: https://arxiv.org/abs/2504.16297 and https://arxiv.org/pdf/2508.04880

Features

  • PTSBE pipeline
    • Trace capture -> noise-site extraction -> trajectory generation (strategies: probabilistic, exhaustive, ordered, conditional) -> shot allocation (PROPORTIONAL (default), UNIFORM, LOW_WEIGHT_BIAS, HIGH_WEIGHT_BIAS) -> batch execution -> result aggregation.
  • Dedicated API
    • C++
      • cudaq::ptsbe::sample()
      • cudaq::ptsbe::sample_async()
    • Python
      • cudaq.ptsbe.sample()
      • cudaq.ptsbe.sample_async()
  • Noise sources
    • Gate-based noise via NoiseModel
      • add_channel, add_all_qubit_channel
    • Inline
      • cudaq.apply_noise(...) in the kernel
      • noise_model is optional when using apply_noise
  • Execution data (optional)
    • Circuit structure (Gate/Noise/Measurement), trajectory specs, and per-trajectory counts via
      return_execution_data=True (Python) or options.ptsbe.return_execution_data (C++)
  • Trace and apply_noise
    • Common Trace extended with instruction type enum (Gate / Noise) and appendNoiseInstruction
    • NVQIR records apply_noise in tracer mode
    • PTSBE skips Noise in gate conversion and resolves channels in the noise extractor

Limitations

  • Simulator-only (no remote)
  • No mid-circuit measurements or conditional feedback (deterministic gate sequence only)
  • Noise channels must be unitary mixtures (for trajectory sampling)

Co-authored-by: @taylorpatti, @1tnguyen, @taalexander

sacpis and others added 30 commits February 7, 2026 16:36
* * Adding the following data structures along with unittests for ptsbe
	- KrausSelection
	- KrausTrajectory
	- PTSBEResult
	- ShotAllocationStrategy
	- TrajectoryMetadata

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* formatting, spell fix

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* removing metadata

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* removing description

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* renaming KrausOperatorIndex to KrausOperatorType

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* pulling out 1e-9 as a constant

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* moving countErrors to trajectory

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* allocating remaining shots in a batch mode

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* allocating shots in one iteration for uniform shots allocation strategy

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* adding ordering validation for krausSelection

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* * Adding functions for shot allocation strategies
* Throwing runtime error on 0 shots

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* Updating year in the header

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* updating year

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* updating year

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* adding a builder pattern for building a KrausTrajectory object

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* fix spell check

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* removing a test

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

---------

Signed-off-by: Sachin Pisal <spisal@nvidia.com>
* Add interface unittests for TDD.

* Complete initial interface definition/testing.

* Test tracing intercept.

* Add ptsbe injection.

* Add core sample integration.

* Do a pass over code.

* Address review comment. Rename variables.

* Fix pre-checks.

* Make ptsbe error if no noise model.
* Add interface stubs.

* Add gate conversion. Make tests/enqeue tasks public.

* Implement task + trajectory merging.

* Add generic simulator.

* Update testing.

* Refactor implementation and add generic invocation.

* CI fixes.

* CI formatting.

* Fix field names in sample_intercept test.

Use camelCase field names (kernelTrace, measureQubits) to match
PTSBatch struct definition.
* Refactor sampling/ptsbe approaches.

* Additional refactor of sampling.

* address reviewer comments.

* Add async/broadcast support.

* Fix clang-format issues.

* Update spelling allow list.

* Formatting.

* Remove changes to spelling allow list.
Signed-off-by: Thomas Alexander <talexander@nvidia.com>
* Add ptsbe generic implementation and early testing with  (#3832)

* Add interface stubs.

* Add gate conversion. Make tests/enqeue tasks public.

* Implement task + trajectory merging.

* Add generic simulator.

* Update testing.

* Refactor implementation and add generic invocation.

* CI fixes.

* CI formatting.

* Fix field names in sample_intercept test.

Use camelCase field names (kernelTrace, measureQubits) to match
PTSBatch struct definition.

* Adding sampling strategies

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* adding unittests for sampling strategy

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* formatting

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* fix spell checker

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* * Expose isScaledUnitary() and computeUnitaryMixture() as public functions
* Added docs to describe full validation requirements
* Add a tolerance parameter

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* Added overflow protection

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* adding PTSSamplingStrategy to cmake

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* Modified ConditionalSamplingStartegy logic to be based on probabilistic sampling

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* format

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* fix spellings

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* adding optimized attempts, overflow protection

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* format

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* adding sampling strategies a sub directory

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* * Using cudaq's random seed if set
* Using computeTotalTrajectories() in ExhaustiveSamplingStrategy and OrderedSamplingStrategy

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* fix spell check

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* using constant, removed irrelevant code

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

---------

Signed-off-by: Sachin Pisal <spisal@nvidia.com>
Co-authored-by: Thomas Alexander <thomasalexander2718@gmail.com>
…3870)

* Adding NoiseExtractor to extract noise from a circuit trace

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* formatting

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* * NoisePoint now stores cudaq::kraus_channel instead of separate kraus_operators and probabilities vectors
* Remove NoisePoint::isUnitaryMixture() method (validation now handled by kraus_channel itself)
* Update computeTotalTrajectories() to use channel.size()

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* removing PTSSamplingStrategy.cpp from cmake

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* * NoiseExtractor simplified
* Strategies use NoisePoint/channel API
* NoiseExtractorTester fixes
* PTSSamplingStrategyTester fixes

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* * Remove redundant NoiseExtractor tests
* Add constants to make qubit/gate relationship explicit
* Remove unused createParameterizedCircuit() helper

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

---------

Signed-off-by: Sachin Pisal <spisal@nvidia.com>
#3881)

Split PTSBESampler.h into public header (no nvqir dependencies) and
internal PTSBESamplerImpl.h. Move template bodies to PTSBESampler.cpp
with explicit instantiations for float and double. Remove unnecessary
cudaq/simulators.h include from PTSBESampleIntegration.h.

Signed-off-by: Thomas Alexander <talexander@nvidia.com>
* Adding trajectory deduplication logic based on kraus selection content

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* Adding unittests for trajectory deduplication

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* fix spelling

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* removing PTSSamplingStrategy

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* * Implement hashTrajectoryContent and deduplicateTrajectories keyed by kraus_selections
* Representatives keep first prob/id/shots

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* fixing spelling

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* providing noise model to fix mcm test

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* removing duplicate documentation (already defined in PTSBEInterface.h)

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* Catching std::exception instead of runtime_error

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

---------

Signed-off-by: Sachin Pisal <spisal@nvidia.com>
Signed-off-by: Sachin Pisal <spisal@nvidia.com>
Signed-off-by: Sachin Pisal <spisal@nvidia.com>
* Adding shots allocations in the sample API

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* adding end-to-end test

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

---------

Signed-off-by: Sachin Pisal <spisal@nvidia.com>
* * Adding probability validation to noise channels

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* validate in Python to avoid abort in JIT path

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* fix spelling and formatting

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

* skip sample(kernel_invalid) in noise prob test to avoid JIT abort in CI

Signed-off-by: Sachin Pisal <spisal@nvidia.com>

---------

Signed-off-by: Sachin Pisal <spisal@nvidia.com>
Signed-off-by: Luca Mondada <luca@mondada.net>
* [python] Replace bindings for QIS types with stubs

Signed-off-by: Luca Mondada <luca@mondada.net>

* fix test

Signed-off-by: Luca Mondada <luca@mondada.net>

---------

Signed-off-by: Luca Mondada <luca@mondada.net>
* Add PTSBE trace.

Signed-off-by: Thomas Alexander <talexander@nvidia.com>

* Restructure/extend ptsbe options.

Signed-off-by: Thomas Alexander <talexander@nvidia.com>

* Add instruction tracing.

Signed-off-by: Thomas Alexander <talexander@nvidia.com>

* Add trace integration testing.

Signed-off-by: Thomas Alexander <talexander@nvidia.com>

* Add initial pybind interface for ptsbe.

Signed-off-by: Thomas Alexander <talexander@nvidia.com>

* Add python tests.

Signed-off-by: Thomas Alexander <talexander@nvidia.com>

* Fix spelling.

Signed-off-by: Thomas Alexander <talexander@nvidia.com>

* Spelling.

Signed-off-by: Thomas Alexander <talexander@nvidia.com>

* Spelling.

Signed-off-by: Thomas Alexander <talexander@nvidia.com>

* Some PR cleanup/documentation.

Signed-off-by: Thomas Alexander <talexander@nvidia.com>

* MOre review.

Signed-off-by: Thomas Alexander <talexander@nvidia.com>

* Spelling.

Signed-off-by: Thomas Alexander <talexander@nvidia.com>

* Remove tracing for now.

Signed-off-by: Thomas Alexander <talexander@nvidia.com>

* Wire up PTSBE.

---------

Signed-off-by: Thomas Alexander <talexander@nvidia.com>
* More careful checking in SROA

Signed-off-by: Adam Geller <adgeller@nvidiae.com>

* Add test for issue

Signed-off-by: Adam Geller <adgeller@nvidiae.com>

* * Missing continue in outer loop
* Added Python test

Signed-off-by: Pradnya Khalate <pkhalate@nvidia.com>

---------

Signed-off-by: Adam Geller <adgeller@nvidiae.com>
Signed-off-by: Pradnya Khalate <pkhalate@nvidia.com>
Co-authored-by: Adam Geller <adgeller@nvidiae.com>
Co-authored-by: Pradnya Khalate <pkhalate@nvidia.com>
Co-authored-by: Pradnya Khalate <148914294+khalatepradnya@users.noreply.github.com>
…::ptsbe::sample (#3914)

<!--
Thanks for helping us improve CUDA-Q!

⚠️ The pull request title should be concise and understandable for all.
⚠️ If your pull request fixes an open issue, please link to the issue.

Checklist:
- [ ] I have added tests to cover my changes.
- [ ] I have updated the documentation accordingly.
- [ ] I have read the CONTRIBUTING document.
-->

### Description
Part 1./2. of the successor to #3902. This PR decouples PTSBE from the
standard Cuda-Q sampling infrastructure. We treat it as a completely
separate execution pathway through Cuda-Q. This mirrors
async/broadcasting support for cpp/python.

This PR also fixed a bug in the generation of noisy unitary gates. Now
we use the noise channel directly indexing into the corresponding
operation. This allows us to work with any type of unitary noise (we
should probably fix the enum for noise point to an integer in a follow
up PR).

---------

Signed-off-by: Thomas Alexander <talexander@nvidia.com>
Co-authored-by: Sachin Pisal <spisal@nvidia.com>
<!--
Thanks for helping us improve CUDA-Q!

⚠️ The pull request title should be concise and understandable for all.
⚠️ If your pull request fixes an open issue, please link to the issue.

Checklist:
- [ ] I have added tests to cover my changes.
- [ ] I have updated the documentation accordingly.
- [ ] I have read the CONTRIBUTING document.
-->

### Description
<!-- Include relevant issues here, describe what changed and why -->

There is a sort of circular dependency in `cudaq-python-interop`.

It now has explicit dependencies on MLIR (via `ExecutionEngine`), which
is available in `CUDAQuantumPythonSources.Extension`.
However, `cudaq-python-interop` is a dependency of
`CUDAQuantumPythonSources.Extension`.

Hence, breaking this loop at `marshal_and_retain_module` in
`py_alt_launch_kernel.cpp`, where we have access to the existing
`JITExecutionCache` utility. The cache key is returned for clean-up
purposes.

---------

Signed-off-by: Thien Nguyen <thiennguyen@nvidia.com>
<!--
Thanks for helping us improve CUDA-Q!

⚠️ The pull request title should be concise and understandable for all.
⚠️ If your pull request fixes an open issue, please link to the issue.

Checklist:
- [x] I have added tests to cover my changes.
- [x] I have updated the documentation accordingly.
- [x] I have read the CONTRIBUTING document.
-->

### Description
As observed in #3910 `test_run_async` has infrequent issues in CI on
macOS Python 3.12. I was unable to replicate locally despite trying a
variety of mechanisms. This PR adds a flaky retry decorator to the test
for macOS. I will try and run the specific CI test a number of times to
see if I can trigger the retry (looking at the output messages).

Perhaps a better fix would be to add an exponential backoff for command
submission but that seems overkill for this limited CI failure right
now.

---------

Signed-off-by: Thomas Alexander <talexander@nvidia.com>
<!--
Thanks for helping us improve CUDA-Q!

⚠️ The pull request title should be concise and understandable for all.
⚠️ If your pull request fixes an open issue, please link to the issue.

Checklist:
- [ ] I have added tests to cover my changes.
- [ ] I have updated the documentation accordingly.
- [ ] I have read the CONTRIBUTING document.
-->

### Description
<!-- Include relevant issues here, describe what changed and why -->
Disable test11 in test_list_of_dataclass_update_failures which is flaky
on py3.11 + arm64 + cuda12.6. The struct argument marshaling was fixed
in PR #3879, but kernel-internal deep copy and list mutation still
produce intermittently wrong results on that configuration.
ref: https://nvidia.slack.com/archives/C03KV6A81HT/p1770744080083629 
I'll re-enable this test once I find the cause.

Signed-off-by: huaweil <huaweil@nvidia.com>
Co-authored-by: Mitchell <mitch_dz@hotmail.com>
…(cpp+python) (#3915)

<!--
Thanks for helping us improve CUDA-Q!

⚠️ The pull request title should be concise and understandable for all.
⚠️ If your pull request fixes an open issue, please link to the issue.

Checklist:
- [ ] I have added tests to cover my changes.
- [ ] I have updated the documentation accordingly.
- [ ] I have read the CONTRIBUTING document.
-->

### Description
Part 2./2. of #3902. This PR is based on #3914 and should be
reviewed/rebased after. This PR adds support for returning execution
data (instructions traces, trajectories, individual trajectory shot
outcomes). I've put a bit of thought into future extension paths for
dynamic circuits/observe which is documented as inline comments.

Now we are able to run a demo like below end-to-end with PTSBE execution
(ie., this is *mostly* feature complete for the PTSBE demo).

```python
import cudaq

@cudaq.kernel
def bell():
    q = cudaq.qvector(2)
    h(q[0])
    cx(q[0], q[1])
    mz(q)

# Set up noise on the H gate
noise = cudaq.NoiseModel()
noise.add_all_qubit_channel("h", cudaq.DepolarizationChannel(0.01))

# Sample with execution data
result = cudaq.ptsbe.sample(
    bell,
    shots_count=1000,
    noise_model=noise,
    max_trajectories=50,
    return_execution_data=True)

# Standard sample_result access
print(result)  # { 00:517 11:483 }

# Access execution data
data = result.ptsbe_execution_data

# Inspect the circuit structure
for inst in data.instructions:
    print(f"{inst.type}: {inst.name} on qubits {inst.targets}")
# Gate: h on qubits [0]
# Noise: depolarization_channel on qubits [0]
# Gate: x on qubits [1]
# Measurement: mz on qubits [0]
# Measurement: mz on qubits [1]

# Count by type
print(data.count_instructions(cudaq.ptsbe.TraceInstructionType.Gate))   # 2
print(data.count_instructions(cudaq.ptsbe.TraceInstructionType.Noise))  # 1

# Per-trajectory results
for traj in data.trajectories:
    print(f"Trajectory {traj.trajectory_id}: "
          f"p={traj.probability:.4f}, "
          f"shots={traj.num_shots}, "
          f"counts={dict(traj.measurement_counts)}")

```

---------

Signed-off-by: Adam Geller <adgeller@nvidiae.com>
Signed-off-by: Pradnya Khalate <pkhalate@nvidia.com>
Signed-off-by: Thomas Alexander <talexander@nvidia.com>
Signed-off-by: Mitchell <mitch_dz@hotmail.com>
Signed-off-by: Thien Nguyen <thiennguyen@nvidia.com>
Signed-off-by: Luca Mondada <luca@mondada.net>
Signed-off-by: Luca Mondada <72734770+lmondada@users.noreply.github.com>
Co-authored-by: Adam T. Geller <adgeller@nvidia.com>
Co-authored-by: Adam Geller <adgeller@nvidiae.com>
Co-authored-by: Pradnya Khalate <pkhalate@nvidia.com>
Co-authored-by: Pradnya Khalate <148914294+khalatepradnya@users.noreply.github.com>
Co-authored-by: Mitchell <mitch_dz@hotmail.com>
Co-authored-by: Sachin Pisal <spisal@nvidia.com>
Co-authored-by: Thien Nguyen <58006629+1tnguyen@users.noreply.github.com>
Co-authored-by: Luca Mondada <72734770+lmondada@users.noreply.github.com>
<!--
Thanks for helping us improve CUDA-Q!

⚠️ The pull request title should be concise and understandable for all.
⚠️ If your pull request fixes an open issue, please link to the issue.

Checklist:
- [ ] I have added tests to cover my changes.
- [ ] I have updated the documentation accordingly.
- [ ] I have read the CONTRIBUTING document.
-->

### Description
<!-- Include relevant issues here, describe what changed and why -->
As the NVQIR simulator is retrieved as a base class pointer in the
runtime, it seems like dynamic casting is the solution for simulator
implementations to provide `sampleWithPTSBE`.

Signed-off-by: Thien Nguyen <thiennguyen@nvidia.com>
# Bump actions/checkout reusable workflow version

Bumps `actions/checkout@v4` -> `actions/checkout@v6`

Release notes are located at
https://github.com/actions/checkout?tab=readme-ov-file#whats-new

The main update to target this is the security posture:
* Improved credential security: persist-credentials now stores
credentials in a separate file under $RUNNER_TEMP instead of directly in
.git/config

Signed-off-by: Mitchell <mitch_dz@hotmail.com>
Bumps [nbconvert](https://github.com/jupyter/nbconvert) from 7.16.6 to
7.17.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/jupyter/nbconvert/releases">nbconvert's
releases</a>.</em></p>
<blockquote>
<h2>v7.17.0</h2>
<h2>7.17.0</h2>
<p>(<a
href="https://github.com/jupyter/nbconvert/compare/v7.16.6...c9ac1d1040459ed1ff9eb34e9918ce5a87cf9d71">Full
Changelog</a>)</p>
<h3>Enhancements made</h3>
<ul>
<li>Add support for arbitrary browser arguments <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2227">#2227</a>
(<a href="https://github.com/shreve"><code>@​shreve</code></a>, <a
href="https://github.com/Carreau"><code>@​Carreau</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
</ul>
<h3>Bugs fixed</h3>
<ul>
<li>Fix QtPNGExporter returning empty bytes on macOS <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2264">#2264</a>
(<a href="https://github.com/h3pdesign"><code>@​h3pdesign</code></a>, <a
href="https://github.com/Carreau"><code>@​Carreau</code></a>, <a
href="https://github.com/QuLogic"><code>@​QuLogic</code></a>)</li>
<li>Fix CVE-2025-53000: Secure Inkscape Windows path (registry first +
block CWD) <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2261">#2261</a>
(<a href="https://github.com/h3pdesign"><code>@​h3pdesign</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>, <a
href="https://github.com/mberlanda"><code>@​mberlanda</code></a>, <a
href="https://github.com/minrk"><code>@​minrk</code></a>, <a
href="https://github.com/salmankadaya"><code>@​salmankadaya</code></a>,
<a
href="https://github.com/th3gowtham"><code>@​th3gowtham</code></a>)</li>
<li>Fix get_export_names and get_exporter default args <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2228">#2228</a>
(<a href="https://github.com/shreve"><code>@​shreve</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
<li>PyPA-Compliant Summary <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2226">#2226</a>
(<a
href="https://github.com/hackowitz-af"><code>@​hackowitz-af</code></a>,
<a href="https://github.com/Carreau"><code>@​Carreau</code></a>)</li>
</ul>
<h3>Maintenance and upkeep improvements</h3>
<ul>
<li>avoid cov environment on free-threaded Pythons <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2267">#2267</a>
(<a href="https://github.com/minrk"><code>@​minrk</code></a>)</li>
<li>update pre-commit, and fix all issues. <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2238">#2238</a>
(<a href="https://github.com/Carreau"><code>@​Carreau</code></a>)</li>
<li>Drop test on 3.9, test on 3.13, 3.14, 3.14t <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2237">#2237</a>
(<a href="https://github.com/Carreau"><code>@​Carreau</code></a>)</li>
<li>Bump the actions group across 1 directory with 2 updates <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2231">#2231</a>
(<a href="https://github.com/Carreau"><code>@​Carreau</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
<li>Replace <code>@flaky.flaky</code> decorate with pytest marker <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2229">#2229</a>
(<a href="https://github.com/mgorny"><code>@​mgorny</code></a>, <a
href="https://github.com/Carreau"><code>@​Carreau</code></a>)</li>
<li>update to mermaid 11.10.0 <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2224">#2224</a>
(<a href="https://github.com/bollwyvl"><code>@​bollwyvl</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
<li>Drop support for Python 3.8, fix the CI tests <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2221">#2221</a>
(<a href="https://github.com/shreve"><code>@​shreve</code></a>, <a
href="https://github.com/minrk"><code>@​minrk</code></a>)</li>
</ul>
<h3>Documentation improvements</h3>
<ul>
<li>Use <code>intersphinx_registry</code> <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2232">#2232</a>
(<a href="https://github.com/Carreau"><code>@​Carreau</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
</ul>
<h3>Contributors to this release</h3>
<p>The following people contributed discussions, new ideas, code and
documentation contributions, and review.
See <a
href="https://github-activity.readthedocs.io/en/latest/use/#how-does-this-tool-define-contributions-in-the-reports">our
definition of contributors</a>.</p>
<p>(<a
href="https://github.com/jupyter/nbconvert/graphs/contributors?from=2025-01-28&amp;to=2026-01-29&amp;type=c">GitHub
contributors page for this release</a>)</p>
<p><a href="https://github.com/bollwyvl"><code>@​bollwyvl</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Abollwyvl+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/Carreau"><code>@​Carreau</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3ACarreau+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/h3pdesign"><code>@​h3pdesign</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Ah3pdesign+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a
href="https://github.com/hackowitz-af"><code>@​hackowitz-af</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Ahackowitz-af+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/krassowski"><code>@​krassowski</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Akrassowski+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/mberlanda"><code>@​mberlanda</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Amberlanda+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/mgorny"><code>@​mgorny</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Amgorny+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/minrk"><code>@​minrk</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Aminrk+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/MSeal"><code>@​MSeal</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3AMSeal+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/QuLogic"><code>@​QuLogic</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3AQuLogic+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a
href="https://github.com/salmankadaya"><code>@​salmankadaya</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Asalmankadaya+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/shreve"><code>@​shreve</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Ashreve+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/th3gowtham"><code>@​th3gowtham</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Ath3gowtham+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/jupyter/nbconvert/blob/main/CHANGELOG.md">nbconvert's
changelog</a>.</em></p>
<blockquote>
<h2>7.17.0</h2>
<p>(<a
href="https://github.com/jupyter/nbconvert/compare/v7.16.6...c9ac1d1040459ed1ff9eb34e9918ce5a87cf9d71">Full
Changelog</a>)</p>
<h3>Enhancements made</h3>
<ul>
<li>Add support for arbitrary browser arguments <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2227">#2227</a>
(<a href="https://github.com/shreve"><code>@​shreve</code></a>, <a
href="https://github.com/Carreau"><code>@​Carreau</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
</ul>
<h3>Bugs fixed</h3>
<ul>
<li>Fix QtPNGExporter returning empty bytes on macOS <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2264">#2264</a>
(<a href="https://github.com/h3pdesign"><code>@​h3pdesign</code></a>, <a
href="https://github.com/Carreau"><code>@​Carreau</code></a>, <a
href="https://github.com/QuLogic"><code>@​QuLogic</code></a>)</li>
<li>Fix CVE-2025-53000: Secure Inkscape Windows path (registry first +
block CWD) <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2261">#2261</a>
(<a href="https://github.com/h3pdesign"><code>@​h3pdesign</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>, <a
href="https://github.com/mberlanda"><code>@​mberlanda</code></a>, <a
href="https://github.com/minrk"><code>@​minrk</code></a>, <a
href="https://github.com/salmankadaya"><code>@​salmankadaya</code></a>,
<a
href="https://github.com/th3gowtham"><code>@​th3gowtham</code></a>)</li>
<li>Fix get_export_names and get_exporter default args <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2228">#2228</a>
(<a href="https://github.com/shreve"><code>@​shreve</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
<li>PyPA-Compliant Summary <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2226">#2226</a>
(<a
href="https://github.com/hackowitz-af"><code>@​hackowitz-af</code></a>,
<a href="https://github.com/Carreau"><code>@​Carreau</code></a>)</li>
</ul>
<h3>Maintenance and upkeep improvements</h3>
<ul>
<li>avoid cov environment on free-threaded Pythons <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2267">#2267</a>
(<a href="https://github.com/minrk"><code>@​minrk</code></a>)</li>
<li>update pre-commit, and fix all issues. <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2238">#2238</a>
(<a href="https://github.com/Carreau"><code>@​Carreau</code></a>)</li>
<li>Drop test on 3.9, test on 3.13, 3.14, 3.14t <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2237">#2237</a>
(<a href="https://github.com/Carreau"><code>@​Carreau</code></a>)</li>
<li>Bump the actions group across 1 directory with 2 updates <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2231">#2231</a>
(<a href="https://github.com/Carreau"><code>@​Carreau</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
<li>Replace <code>@flaky.flaky</code> decorate with pytest marker <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2229">#2229</a>
(<a href="https://github.com/mgorny"><code>@​mgorny</code></a>, <a
href="https://github.com/Carreau"><code>@​Carreau</code></a>)</li>
<li>update to mermaid 11.10.0 <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2224">#2224</a>
(<a href="https://github.com/bollwyvl"><code>@​bollwyvl</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
<li>Drop support for Python 3.8, fix the CI tests <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2221">#2221</a>
(<a href="https://github.com/shreve"><code>@​shreve</code></a>, <a
href="https://github.com/minrk"><code>@​minrk</code></a>)</li>
</ul>
<h3>Documentation improvements</h3>
<ul>
<li>Use <code>intersphinx_registry</code> <a
href="https://redirect.github.com/jupyter/nbconvert/pull/2232">#2232</a>
(<a href="https://github.com/Carreau"><code>@​Carreau</code></a>, <a
href="https://github.com/krassowski"><code>@​krassowski</code></a>)</li>
</ul>
<h3>Contributors to this release</h3>
<p>The following people contributed discussions, new ideas, code and
documentation contributions, and review.
See <a
href="https://github-activity.readthedocs.io/en/latest/use/#how-does-this-tool-define-contributions-in-the-reports">our
definition of contributors</a>.</p>
<p>(<a
href="https://github.com/jupyter/nbconvert/graphs/contributors?from=2025-01-28&amp;to=2026-01-29&amp;type=c">GitHub
contributors page for this release</a>)</p>
<p><a href="https://github.com/bollwyvl"><code>@​bollwyvl</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Abollwyvl+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/Carreau"><code>@​Carreau</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3ACarreau+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/h3pdesign"><code>@​h3pdesign</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Ah3pdesign+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a
href="https://github.com/hackowitz-af"><code>@​hackowitz-af</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Ahackowitz-af+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/krassowski"><code>@​krassowski</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Akrassowski+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/mberlanda"><code>@​mberlanda</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Amberlanda+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/mgorny"><code>@​mgorny</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Amgorny+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/minrk"><code>@​minrk</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Aminrk+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/MSeal"><code>@​MSeal</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3AMSeal+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/QuLogic"><code>@​QuLogic</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3AQuLogic+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a
href="https://github.com/salmankadaya"><code>@​salmankadaya</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Asalmankadaya+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/shreve"><code>@​shreve</code></a> (<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Ashreve+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)
| <a href="https://github.com/th3gowtham"><code>@​th3gowtham</code></a>
(<a
href="https://github.com/search?q=repo%3Ajupyter%2Fnbconvert+involves%3Ath3gowtham+updated%3A2025-01-28..2026-01-29&amp;type=Issues">activity</a>)</p>
<!-- raw HTML omitted -->
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/jupyter/nbconvert/commit/21b35d85b46f5ff0956d3d088a52b9bef00e8196"><code>21b35d8</code></a>
Publish 7.17.0</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/c9ac1d1040459ed1ff9eb34e9918ce5a87cf9d71"><code>c9ac1d1</code></a>
Fix CVE-2025-53000: Secure Inkscape Windows path (registry first + block
CWD)...</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/b13276d80ae6fadbfda981304810e26f421c4ced"><code>b13276d</code></a>
avoid cov environment on free-threaded Pythons (<a
href="https://redirect.github.com/jupyter/nbconvert/issues/2267">#2267</a>)</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/7c7055fe833fe9832e6f9a64fa5f67d66692c8d6"><code>7c7055f</code></a>
[pre-commit.ci] auto fixes from pre-commit.com hooks</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/74f3ddd37ef4b7ffb5eee9acbf52062217c15852"><code>74f3ddd</code></a>
Fix QtPNGExporter returning empty bytes on macOS</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/216550b2aae4c329f4dab597a96ae7cac30de79a"><code>216550b</code></a>
fix links</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/39777ac5716350e994171d025a7369c58b0afc8c"><code>39777ac</code></a>
try to comment fialing test</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/7b591ca526f2598dbae3256a53765659c3edcf14"><code>7b591ca</code></a>
ruff-check</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/6ec7638a3dc7a0bc2c533c116202d7f9b07ce9d9"><code>6ec7638</code></a>
parent</li>
<li><a
href="https://github.com/jupyter/nbconvert/commit/59414b36f94e318d4207e8af863167047d936c19"><code>59414b3</code></a>
fix mypy</li>
<li>Additional commits viewable in <a
href="https://github.com/jupyter/nbconvert/compare/v7.16.6...v7.17.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=nbconvert&package-manager=pip&previous-version=7.16.6&new-version=7.17.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/NVIDIA/cuda-quantum/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Mitchell <mitch_dz@hotmail.com>
<!--
Thanks for helping us improve CUDA-Q!

⚠️ The pull request title should be concise and understandable for all.
⚠️ If your pull request fixes an open issue, please link to the issue.

Checklist:
- [ ] I have added tests to cover my changes.
- [ ] I have updated the documentation accordingly.
- [ ] I have read the CONTRIBUTING document.
-->

### Description
<!-- Include relevant issues here, describe what changed and why -->

Signed-off-by: Thien Nguyen <thiennguyen@nvidia.com>
@github-actions
Copy link

CUDA Quantum Docs Bot: A preview of the documentation can be found here.

Copy link
Collaborator

@lmondada lmondada left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll keep reviewing. So far I've mostly been going through the tests. It's looking very clean and nice thank you!

My only major comment so far is: you need to be careful when defining kernels in-line for testing. These kernels do not go through the standard cudaq compilation pipeline, thus you are not actually testing the behaviour of your code on "real" kernels. In theory, it could be possible that the kernels you wrote get compiled to something totally different by nvq++ that your tracing would miss (in practice, behaviour should be broadly similar, given that we support "library mode"; however, the execution path in the runtime is still different in subtle ways).

I think you should add at least a couple of tests that make sure that kernels compiled through nvq++ still get traced properly by capturePTSBatch.

Whilst I'm on it: consider renaming capturePTSBatch to tracePTSBatch. I am just coming from Python land where we've been doing a lot of work on "capturing" variables, so it is confusing to me.

<!--
Thanks for helping us improve CUDA-Q!

⚠️ The pull request title should be concise and understandable for all.
⚠️ If your pull request fixes an open issue, please link to the issue.

Checklist:
- [ ] I have added tests to cover my changes.
- [ ] I have updated the documentation accordingly.
- [ ] I have read the CONTRIBUTING document.
-->

### Description
Fixes for PTSBE identified in my [second AI-assisted
review](#3995 (review))
of the feature branch.

Changes:
- Update flaky statistical test
- PTSBESample.h: runSamplingAsyncPTSBE copies noise model into async
lambda, wraps execution in try/catch with set_exception, both
sample_async overloads call platform.reset_noise() after enqueue
- PTSBESample.h: runSamplingPTSBE builds PTSBE trace once and shares it
between execution data and batch construction, removed
buildPTSBatchWithTrajectories
- PTSBESample.cpp: replaced buildPTSBatchWithTrajectories with
buildPTSBatchFromTrace that accepts pre-built trace, removed stub
trajectory block in populateExecutionDataTrajectories
- py_sample_ptsbe.cpp: pySampleAsyncPTSBE calls platform.reset_noise()
after enqueue, added qubits and op_name bindings to KrausSelection
- SampleResult.h: made ~sample_result() virtual
- PTSSamplingStrategy.h: computeTotalTrajectories skips empty channels
instead of dividing by zero
- OrderedSamplingStrategy.cpp: sorts operator indices by descending
probability before enumeration, delegates to shared
enumerateLexicographic
- ExhaustiveSamplingStrategy.h: declared enumerateLexicographic free
function with optional index mapping
- ExhaustiveSamplingStrategy.cpp: implemented shared enumeration loop,
ExhaustiveSamplingStrategy delegates to it
- ShotAllocationStrategy.cpp: allocateShots zeroes num_shots before
dispatching
- TrajectoryDeduplication.cpp: accumulates num_shots when merging
duplicates
- PTSBESampleTester.cpp: added SampleAsyncNoiseModelDestroyed and
SampleAsyncPropagatesException tests
- PTSSamplingStrategyTester.cpp: added TopKWithNonZeroIdentityIndex and
ComputeTotalTrajectoriesSkipsEmptyChannel tests
- ShotAllocationTester.cpp: added DoubleAllocationDoesNotAccumulate test
- TrajectoryDeduplicationTester.cpp: updated
SameContentDifferentIdAndShots to expect accumulated num_shots
- test_execution_data.py: augmented
test_trajectory_measurement_counts_populated to check qubits and op_name

---------

Signed-off-by: Thomas Alexander <talexander@nvidia.com>
Copy link
Collaborator

@taalexander taalexander left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the merger of #4043 I have addressed my merge blocking concerns for this PR. All other comments of mine are to be done in follow-up PRs once landing on main.

Copy link
Collaborator

@1tnguyen 1tnguyen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved changes to .github config

lmondada and others added 3 commits February 25, 2026 15:31
This PR introduces "deferred compilation" in Python. By default, kernels
are no longer compiled to MLIR (aka pre-compiled) at kernel definition
time, but only when the kernel is invoked for the first time. As before,
the MLIR module is then cached for further invocation. For example,

```python
import cudaq

@cudaq.kernel
def foo():
    pass
```

would not trigger any compilation, until `foo()` is called for the first
time. This enables:
1. Faster package load times: `import cudaq` takes ~4s now, versus `~8s`
before, as the kernels included with `cudaq` are no longer compiled when
the package is loaded. This will also apply to any other library that
provides kernel definitions.
2. Kernels can be defined out-of-order: previously, calling kernel B
from kernel A would error if B was defined after A. This is now
supported (see tests).
3. Captured variables that aren't defined at kernel definition time but
are defined at invocation time are now supported.

Compilation can be forced (thus recovering the old behaviour) using the
`defer_compilation=False` flag. The following:

```python
@cudaq.kernel(defer_compilation=False)
def foo():
    pass
```

triggers compilation immediately.

## Limitations
To limit the scope of this PR, I introduced two limitations (see tests
for examples):
1. Recursive kernel calls are still not supported. The way kernels are
captured and lifted into arguments would have to handle recursive calls
specially.
2. A kernel builder A cannot call another kernel B using `apply_call(B)`
if B wasn't compiled beforehand. In that case, the user will receive a
clear error suggesting to either use `defer_compilation=False` or
calling `B.compile()` directly, e.g.
```python
@cudaq.kernel(defer_compilation=True)
def notPrecompiledKernel():
    pass

kernel = cudaq.make_kernel()
kernel.apply_call(notPrecompiledKernel)  # fails. User must set `defer_compilation=False`
                                         # or call `notPrecompiledKernel.compile()`
```

---------

Signed-off-by: Luca Mondada <luca@mondada.net>
…n` (#4017)

This PR adds a migration guide for transitioning CUDA-Q quantum kernels
from the `sample` API to the `run` API, following a breaking change in
PR #3731. The update
clarifies when and how to use each API, provides migration steps and
examples in both Python and C++, and adds supporting code samples and
references in the documentation.

---------

Signed-off-by: Pradnya Khalate <pkhalate@nvidia.com>
@github-actions
Copy link

CUDA Quantum Docs Bot: A preview of the documentation can be found here.

@github-actions
Copy link

CUDA Quantum Docs Bot: A preview of the documentation can be found here.

Copy link
Collaborator

@lmondada lmondada left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the great work!!

@github-actions
Copy link

CUDA Quantum Docs Bot: A preview of the documentation can be found here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.