Skip to content
Merged
Show file tree
Hide file tree
Changes from 81 commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
6cc3f1c
Adding PTSBE data structures (#3808)
sacpis Jan 29, 2026
46c2644
Ptsbe simulator interface (#3823)
taalexander Jan 30, 2026
f00b5d3
Add ptsbe generic implementation and early testing with (#3832)
taalexander Feb 3, 2026
44f22f6
[PTSBE] Add support for async/broadcasting (#3851)
taalexander Feb 4, 2026
e11d51a
Fix rebasing issues surrounding context handling updates for PTSBE.
taalexander Feb 4, 2026
2c961c2
[PTSBE] Adding sampling strategies (#3848)
sacpis Feb 5, 2026
b8449ef
[PTSBE] Adding NoiseExtractor to extract noise from a circuit trace (…
sacpis Feb 6, 2026
e054205
Refactor PTSBE to avoid leaking nvqir headers in public include chain…
taalexander Feb 6, 2026
d0ef8f1
[PTSBE] Trajectory Deduplication (#3878)
sacpis Feb 7, 2026
5ac3373
Fix mcm_rejection: catch (...) for dynamic circuit rejection
sacpis Feb 8, 2026
63d7fb4
* Accept any exception type in throw to fix CI jobs
sacpis Feb 7, 2026
ad170bb
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 9, 2026
3be6898
[PTSBE] Allocate shots to trajectories (#3899)
sacpis Feb 10, 2026
e38ca8a
Adding probability validation to noise channels (#3890)
sacpis Feb 9, 2026
a07423c
[python] Remove GlobalAstRegistry (#3896)
lmondada Feb 9, 2026
846fec6
[python] Replace bindings for QIS types with stubs (#3882)
lmondada Feb 9, 2026
4e244b6
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 10, 2026
8f93639
[PTSBE] CPP/Python interface stubs with initial trace definition (#3887)
taalexander Feb 10, 2026
ea711bc
Restrain SROA to prevent memory corruption (#3868)
atgeller Feb 10, 2026
443c7d4
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 11, 2026
79e693e
[PTSBE] Decouple PTSBE support for sample from cudaq::sample to cudaq…
taalexander Feb 11, 2026
fe0ef45
Resolving the dependency of `cudaq-python-interop` lib (#3908)
1tnguyen Feb 11, 2026
d932ccd
Add flaky retry on macos for test_run_async (#3911)
taalexander Feb 11, 2026
eee843b
[python] Disable flaky struct deep copy test (#3921)
huaweil-nv Feb 11, 2026
fcdf802
[PTSBE] Define and return execution data for PTSBE execution to user …
taalexander Feb 11, 2026
7ee202f
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 11, 2026
d586ab7
[PTSBE] Use `dynamic_cast` for `sampleWithPTSBE` opt-in (#3922)
1tnguyen Feb 11, 2026
066236b
Bump actions/checkout@v4 -> actions/checkout@v6 (#3924)
mitchdz Feb 11, 2026
33d8ef9
Bump nbconvert from 7.16.6 to 7.17.0 (#3903)
dependabot[bot] Feb 11, 2026
b08a726
Update mgpu SHA to incorporate PTSBE support (#3937)
1tnguyen Feb 12, 2026
aebde0d
[PTSBE] Notebooks for demo (#3934)
sacpis Feb 12, 2026
1401f72
Change device key lookup behavior in python bridge (#3917)
atgeller Feb 12, 2026
0adb970
C++ API doc (#3898)
Renaud-K Feb 12, 2026
fde98e4
Type erased jit engine (#3933)
Renaud-K Feb 12, 2026
c5f3ea8
[python] Remove unused CapturedDataStorage (#3932)
lmondada Feb 12, 2026
fb0cf66
Add operation names to noise model (#3928)
taalexander Feb 12, 2026
a2f8c68
fix header
sacpis Feb 12, 2026
63df827
[PTSBE] Fix PTSBESampler (#3939)
sacpis Feb 12, 2026
768393d
[PTSBE] Integration tests (#3942)
sacpis Feb 12, 2026
5121b10
[PTSBE] Fix documentation (#3945)
sacpis Feb 13, 2026
e29a25b
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 13, 2026
835e416
[PTSBE] Integration tests with edge cases (#3944)
sacpis Feb 13, 2026
a2fb30b
Fix macos devdeps cache invalidation on Github actions runner update …
taalexander Feb 13, 2026
e04af64
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 14, 2026
7d1b739
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 15, 2026
0150984
[PTSBE] Increase attempts for low trajectories (#3961)
sacpis Feb 16, 2026
144e5cb
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 16, 2026
b5de579
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 16, 2026
f06d3dc
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 17, 2026
e478fe9
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 17, 2026
7df1b7c
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 17, 2026
360f1cc
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 17, 2026
678e775
[PTSBE] Apply noise style api (#3990)
sacpis Feb 18, 2026
15ca5c6
Remove unused support_conditional_feedback (#3959)
Renaud-K Feb 17, 2026
4cc7a0b
Fix wheel packaging macos (#3955)
taalexander Feb 17, 2026
ebb11c2
Passing the execution context as an argument to the compiler. (#3986)
Renaud-K Feb 18, 2026
72d7135
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 18, 2026
f66e654
Fix: recover_kernel_decorator fails for nested if blocks, added check…
derek-yux Feb 18, 2026
22d2e30
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 18, 2026
065c0c3
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 18, 2026
d481009
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 18, 2026
746a266
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 19, 2026
4040956
Add measurement noise support and unify PTSBE trace representation (#…
taalexander Feb 19, 2026
6416fe8
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 19, 2026
506e399
[PTSBE] Handle default-constructed `sample_result` (#4003)
1tnguyen Feb 19, 2026
8644f68
Fix an oversight in test case
1tnguyen Feb 19, 2026
dbb453b
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 19, 2026
0ba0d89
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 19, 2026
0d30cb8
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 20, 2026
0d413a9
Fix publishing failure for notebooks (#4007)
sacpis Feb 19, 2026
d2a3c89
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 20, 2026
934e964
[PTSBE] Fixing proportional shot allocation (#4012)
sacpis Feb 20, 2026
df86c9f
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 20, 2026
fe0a297
[PTSBE] Sampling fixes and improvements from verification testing (#4…
taalexander Feb 23, 2026
7173b3e
[PTSBE] Fix "sample" context bug (#4027)
taalexander Feb 23, 2026
0105d0d
Update mgpu SHA to top of main (#4029)
1tnguyen Feb 23, 2026
3d928c3
[PTSBE] follow up verification fixes (#4028)
taalexander Feb 23, 2026
b010293
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 24, 2026
f0538d1
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 24, 2026
ff279ab
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 25, 2026
183a81d
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 25, 2026
bac2cde
[PTSBE] Core code fixes to merge (#4043)
taalexander Feb 25, 2026
b078932
[python] Defer MLIR compilation until kernel invocation (#3948)
lmondada Feb 25, 2026
3f1bd7c
[docs] Add a migration guide for porting kernels from `sample` to `ru…
khalatepradnya Feb 25, 2026
932fcc9
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 25, 2026
a3767f1
Add ptsbe tests for nvq++ (#4049)
taalexander Feb 26, 2026
c15f311
Merge branch 'main' into features/ptsbe
lmondada Feb 26, 2026
849a199
Merge remote-tracking branch 'upstream/main' into features/ptsbe
sacpis Feb 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/pre-commit/spelling_allowlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ macOS
makefiles
merchantability
mps
multinomial
multithreaded
mutex
namespace
Expand Down Expand Up @@ -319,6 +320,7 @@ qumode
qumodes
reStructuredText
reconfigurable
reproducibility
runtime
runtimes
rvalue
Expand Down
1 change: 1 addition & 0 deletions .github/pre-commit/spelling_allowlist_cxx.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
clang
gcc
nullary
pre
typedef
2 changes: 1 addition & 1 deletion .github/workflows/config/gitlab_commits.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
nvidia-mgpu-repo: cuda-quantum/cuquantum-mgpu.git
nvidia-mgpu-commit: e41bb18a5e5ff5be44090dfc4cb6c59fb511e9c7
nvidia-mgpu-commit: 69fa05df00a069c3bc5c040294678014a396fa68
4 changes: 4 additions & 0 deletions docs/sphinx/api/languages/cpp_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ Common
.. doxygenclass:: cudaq::sample_result
:members:

.. _classcudaq_1_1ptsbe_1_1sample__result:

**cudaq::`ptsbe`::sample_result** — Result type returned by ``ptsbe::sample()``, extending `cudaq::sample_result` with optional execution data (trace and per-trajectory info). See ``PTSBESampleResult.h`` and ``PTSBEExecutionData.h``.

.. doxygenstruct:: cudaq::sample_options
:members:

Expand Down
217 changes: 217 additions & 0 deletions docs/sphinx/examples/python/ptsbe_end_to_end_workflow.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## PTSBE end-to-end workflow\n",
"\n",
"**PTSBE** (Pre-Trajectory Sampling with Batch Execution) is a method for sampling from **noisy** quantum circuits efficiently. Instead of simulating the full density matrix and sampling once per shot, PTSBE:\n",
"\n",
"1. **Traces** the kernel to get the gate sequence and qubit layout.\n",
"2. **Extracts noise sites** by matching the noise model to the trace (each noisy gate becomes a *noise site* with a set of Kraus outcomes, e.g. I, X, Y, Z for depolarization).\n",
"3. **Generates trajectories** — each trajectory is one possible *realization* of noise (one Kraus outcome per site). A **sampling strategy** decides which trajectories to use (e.g. **Exhaustive**: all combinations, or **Probabilistic**: sample by probability).\n",
"4. **Allocates shots** across trajectories (e.g. **proportional** to trajectory probability, or **uniform**).\n",
"5. **Runs batches** — for each trajectory, the circuit is run as a **noiseless** circuit with that trajectory's outcomes applied; results are collected.\n",
"6. **Aggregates** all per-trajectory counts into a single `SampleResult`.\n",
"\n",
"You get the same statistics as density-matrix sampling (in the limit of many shots), but with the ability to batch many shots per trajectory and to control cost via the number of trajectories. This notebook runs the full workflow with a single API call: `cudaq.ptsbe.sample()`."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 1. Set up the environment\n",
"\n",
"Use the density-matrix simulator target (required for PTSBE). Set a random seed for reproducibility."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import cudaq\n",
"\n",
"cudaq.set_target(\"density-matrix-cpu\")\n",
"cudaq.set_random_seed(42)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 2. Define the circuit and noise model\n",
"\n",
"Define a kernel and attach a noise model. Each gate you add to the noise model becomes a **noise site** when that gate appears in the circuit. For **single-qubit** gates (e.g. H) use **DepolarizationChannel** with one qubit; for **CNOTs** pass the **qubit pair** `[control, target]` and use **Depolarization2** (two-qubit depolarization). Here we use a small Bell-style circuit with depol on the Hadamard and on the controlled-X (qubit pair [0, 1])."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"@cudaq.kernel\n",
"def bell_with_noise():\n",
" q = cudaq.qvector(2)\n",
" h(q[0])\n",
" x.ctrl(q[0], q[1])\n",
" mz(q)\n",
"\n",
"noise = cudaq.NoiseModel()\n",
"noise.add_channel(\"h\", [0], cudaq.DepolarizationChannel(0.05))\n",
"noise.add_channel(\"x\", [0, 1], cudaq.Depolarization2(0.03))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 3. Run PTSBE sampling\n",
"\n",
"Call `cudaq.ptsbe.sample()` with the kernel, noise model, and shot count. Optional arguments:\n",
"\n",
"- **sampling_strategy** — how trajectories are chosen:\n",
" - **ExhaustiveSamplingStrategy()**: use all possible trajectories (every combination of Kraus outcomes per noise site).\n",
" - **ProbabilisticSamplingStrategy(seed=...)**: sample trajectories randomly according to their probabilities; use a seed for reproducibility.\n",
" - **OrderedSamplingStrategy()**: use the top-$k$ trajectories by probability (highest first), up to `max_trajectories`.\n",
"- **shot_allocation** — how shots are split across the chosen trajectories:\n",
" - **PROPORTIONAL** (default): allocate shots in proportion to each trajectory’s probability.\n",
" - **UNIFORM**: give each trajectory the same number of shots.\n",
" - **LOW_WEIGHT_BIAS**: bias more shots toward low-weight (fewer errors) trajectories; optional `bias_strength` (default 2.0).\n",
" - **HIGH_WEIGHT_BIAS**: bias more shots toward high-weight trajectories; optional `bias_strength` (default 2.0).\n",
" Example: `ShotAllocationStrategy(type=cudaq.ptsbe.ShotAllocationType.UNIFORM)` or `ShotAllocationStrategy(type=cudaq.ptsbe.ShotAllocationType.LOW_WEIGHT_BIAS, bias_strength=5.0)`.\n",
"- **max_trajectories**: cap the number of trajectories (useful for large shot counts).\n",
"- **return_execution_data** (bool): If ``True``, the result includes trace instructions and per-trajectory data (``result.ptsbe_execution_data``); see section 6 at the end."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"shots = 1000000\n",
"\n",
"strategy = cudaq.ptsbe.ProbabilisticSamplingStrategy(seed=42)\n",
"result = cudaq.ptsbe.sample(\n",
" bell_with_noise,\n",
" noise_model=noise,\n",
" shots_count=shots,\n",
" sampling_strategy=strategy,\n",
")\n",
"\n",
"print(\"PTSBE sample result:\")\n",
"print(result)\n",
"print(f\"Total shots: {result.get_total_shots()}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 4. Compare with standard (density-matrix) sampling\n",
"\n",
"To verify that PTSBE matches the usual noisy simulation, run standard `cudaq.sample()` with the same kernel and noise model. With enough shots, the two outcome distributions should be close (see the **PTSBE accuracy validation** example for a Hellinger fidelity comparison)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"result_standard = cudaq.sample(bell_with_noise, noise_model=noise, shots_count=shots)\n",
"print(\"Standard (density-matrix) sample result:\")\n",
"print(result_standard)\n",
"print(f\"Total shots: {result_standard.get_total_shots()}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 5. Return execution data\n",
"\n",
"Pass `return_execution_data=True` to get the PTSBE execution data: the trace (gate, noise, measurement instructions) and the list of trajectories with their probabilities and shot allocations. Use `result.ptsbe_execution_data` and `result.has_execution_data()`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"result_with_data = cudaq.ptsbe.sample(\n",
" bell_with_noise,\n",
" noise_model=noise,\n",
" shots_count=shots,\n",
" sampling_strategy=strategy,\n",
" return_execution_data=True,\n",
")\n",
"assert result_with_data.has_execution_data()\n",
"data = result_with_data.ptsbe_execution_data\n",
"\n",
"Gate = cudaq.ptsbe.TraceInstructionType.Gate\n",
"Noise = cudaq.ptsbe.TraceInstructionType.Noise\n",
"Measurement = cudaq.ptsbe.TraceInstructionType.Measurement\n",
"print(\"Execution data:\")\n",
"print(f\" Instructions: {len(data.instructions)} total\")\n",
"n_gate = sum(1 for i in data.instructions if i.type == Gate)\n",
"n_noise = sum(1 for i in data.instructions if i.type == Noise)\n",
"n_meas = sum(1 for i in data.instructions if i.type == Measurement)\n",
"print(f\" Gates: {n_gate}, Noise: {n_noise}, Measurements: {n_meas}\")\n",
"print(f\" Trajectories: {len(data.trajectories)}\")\n",
"total_traj_shots = sum(t.num_shots for t in data.trajectories)\n",
"print(f\" Sum of trajectory shots: {total_traj_shots} (expected {shots})\")\n",
"print(\" Trace instructions (first 5):\")\n",
"for i, inst in enumerate(data.instructions[:5]):\n",
" print(f\" [{i}] type={inst.type}, name={inst.name}, targets={list(inst.targets)}\")\n",
"if data.trajectories:\n",
" t0 = data.trajectories[0]\n",
" print(f\" Example trajectory: id={t0.trajectory_id}, probability={t0.probability:.6f}, num_shots={t0.num_shots}\")\n",
" print(\" Selected trajectory (kraus_selections):\")\n",
" for sel in t0.kraus_selections:\n",
" print(f\" circuit_location={sel.circuit_location}, kraus_operator_index={sel.kraus_operator_index}, is_error={sel.is_error}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 6. Two API options:\n",
"\n",
"We have two ways to sample from a noisy circuit:\n",
"\n",
"1. **`cudaq.sample(kernel, noise_model=noise, use_ptsbe=..., ...)`** — The main sample API with a **`use_ptsbe`** option. When `use_ptsbe=False` (or omitted), sampling uses the standard density-matrix path; when `use_ptsbe=True`, sampling uses the PTSBE (trajectory) path.\n",
"2. **`cudaq.ptsbe.sample(kernel, noise_model=noise, ...)`** — The dedicated PTSBE API. There is no `use_ptsbe` option; sampling always uses the PTSBE path (trajectories, strategies, execution data, etc.).\n",
"\n",
"**When to choose which:** Use **`cudaq.sample`** with `use_ptsbe=True` when you want PTSBE from the main sample API (one call, one place for all sampling). Use **`cudaq.ptsbe.sample`** when you want the dedicated PTSBE API (explicit PTSBE entry point, no flag). Both provide the same PTSBE path (large shot counts, batching, trajectory strategies, execution data)."
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
1 change: 1 addition & 0 deletions docs/sphinx/using/examples/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Examples that illustrate how to use CUDA-Q for application development are avail
Multi-GPU Workflows <multi_gpu_workflows.rst>
Optimizers & Gradients <../../examples/python/optimizers_gradients.ipynb>
Noisy Simulations <../../examples/python/noisy_simulations.ipynb>
PTSBE End-to-End Workflow <../../examples/python/ptsbe_end_to_end_workflow.ipynb>
Constructing Operators <operators.rst>
Performance Optimizations <../../examples/python/performance_optimizations.ipynb>
Using Quantum Hardware Providers <hardware_providers.rst>
Expand Down
1 change: 1 addition & 0 deletions python/cudaq/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def _configure_cuda_library_paths() -> None:
from .runtime.observe import observe_async
from .runtime.run import run
from .runtime.run import run_async
from .runtime import ptsbe
from .runtime.translate import translate
from .runtime.state import (get_state, get_state_async, to_cupy)
from .runtime.draw import draw
Expand Down
Loading
Loading