Expose simulator RNG seed via SimulatorConfig.seed#27
Conversation
Add an optional `seed` to SimulatorConfig so Python users can make the
simulator's multi-shot terminal sampling reproducible.
The seed is plumbed through ConfigureNetwork -> network "seed" config ->
SimpleDisconnectedNetwork, which injects it onto the executing optSim
(after ChooseBestSimulator) via QCSimState::Configure("seed"), reseeding
the mt19937_64 used by SampleCountsMany.
Scope: only the statevector and path-integral terminal-sampling paths draw
from this rng, and both run single-threaded, so results are fully portable
and reproducible. MPS / stabilizer / tensor-network sampling, plus
mid-circuit and single-shot measurements, delegate to the underlying qcsim
backends (whose RNGs fold in wall-clock time and expose no reseed setter)
and therefore remain non-deterministic. QCSimSimulator::Clone derives a
deterministic, distinct per-clone seed (splitmix64) as a defensive measure
for any future rng-driven multi-threaded path.
Adds Python tests (tests/python/test_bindings.py::TestSimulatorSeed) for
reproducibility, seed difference, None default, repr/field, and
path-integral reproducibility.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
58ac686 to
0522874
Compare
Greptile SummaryThis PR exposes a simulator RNG seed through Python configuration. It changes:
Confidence Score: 3/5I don't think this is safe to merge yet.
Network/SimpleDisconnectedNetwork.h needs the seed propagation fixed across all simulator creation and clone paths.
What T-Rex did
|
| Filename | Overview |
|---|---|
| Network/SimpleDisconnectedNetwork.h | Adds seed storage and host-execution injection, but misses sibling execution, job-created simulators, and network clones. |
| Simulators/QCSimState.h | Adds seed parsing and RNG seeding for terminal sampling paths. |
| Simulators/QCSimSimulator.h | Adds deterministic clone seed derivation when a user seed is configured. |
| python/bindings.cpp | Adds the Python seed field and forwards it during network setup. |
| tests/python/test_bindings.py | Adds direct simple_execute seed tests, but does not cover the missed network paths. |
Comments Outside Diff (2)
-
Network/SimpleDisconnectedNetwork.h, line 591-593 (link)RepeatedExecute()builds the same optimized simulator path asRepeatedExecuteOnHost(), but it never applies the storedseedto the returnedoptSim. Callers that execute through this network-level path can configureseedand still receive non-deterministic terminal sampling, while the host-specific path is deterministic.Prompt To Fix With AI
This is a comment left during a code review. Path: Network/SimpleDisconnectedNetwork.h Line: 591-593 Comment: **Seed skipped here** `RepeatedExecute()` builds the same optimized simulator path as `RepeatedExecuteOnHost()`, but it never applies the stored `seed` to the returned `optSim`. Callers that execute through this network-level path can configure `seed` and still receive non-deterministic terminal sampling, while the host-specific path is deterministic. How can I resolve this? If you propose a fix, please make it concise.
-
Network/SimpleDisconnectedNetwork.h, line 1900-1903 (link)Clone()copies the other stored simulator configuration fields, but it does not copy the newseedmember. Any scheduler or clone-based network path will lose the user-provided seed on the cloned network and fall back to non-deterministic sampling.Prompt To Fix With AI
This is a comment left during a code review. Path: Network/SimpleDisconnectedNetwork.h Line: 1900-1903 Comment: **Clone drops seed** `Clone()` copies the other stored simulator configuration fields, but it does not copy the new `seed` member. Any scheduler or clone-based network path will lose the user-provided seed on the cloned network and fall back to non-deterministic sampling. How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 3
Network/SimpleDisconnectedNetwork.h:591-593
**Seed skipped here**
`RepeatedExecute()` builds the same optimized simulator path as `RepeatedExecuteOnHost()`, but it never applies the stored `seed` to the returned `optSim`. Callers that execute through this network-level path can configure `seed` and still receive non-deterministic terminal sampling, while the host-specific path is deterministic.
### Issue 2 of 3
Network/SimpleDisconnectedNetwork.h:793
**Job simulators stay unseeded**
This only seeds `optSim` when `ChooseBestSimulator()` returns one. If no optimized simulator is selected, `ExecuteJob` creates its own simulator later and only forwards MPS-related options, so the configured seed is dropped and terminal sampling stays random for that execution path.
### Issue 3 of 3
Network/SimpleDisconnectedNetwork.h:1900-1903
**Clone drops seed**
`Clone()` copies the other stored simulator configuration fields, but it does not copy the new `seed` member. Any scheduler or clone-based network path will lose the user-provided seed on the cloned network and fall back to non-deterministic sampling.
Reviews (1): Last reviewed commit: "Expose simulator RNG seed via SimulatorC..." | Re-trigger Greptile
| // Seed the executing simulator's terminal sampling RNG, if requested. The | ||
| // single-thread path uses optSim directly; in the multi-thread path each | ||
| // Clone() derives a distinct deterministic seed from this one. | ||
| if (optSim && !seed.empty()) optSim->Configure("seed", seed.c_str()); |
There was a problem hiding this comment.
This only seeds optSim when ChooseBestSimulator() returns one. If no optimized simulator is selected, ExecuteJob creates its own simulator later and only forwards MPS-related options, so the configured seed is dropped and terminal sampling stays random for that execution path.
Prompt To Fix With AI
This is a comment left during a code review.
Path: Network/SimpleDisconnectedNetwork.h
Line: 793
Comment:
**Job simulators stay unseeded**
This only seeds `optSim` when `ChooseBestSimulator()` returns one. If no optimized simulator is selected, `ExecuteJob` creates its own simulator later and only forwards MPS-related options, so the configured seed is dropped and terminal sampling stays random for that execution path.
How can I resolve this? If you propose a fix, please make it concise.
What
Adds an optional
seedfield toSimulatorConfig, letting Python users makethe simulator's multi-shot terminal sampling reproducible:
seed=None(default) keeps today's non-deterministic behavior.How
QCSimState::Configure("seed", ...)reseeds themt19937_64used bySampleCountsMany.SimulatorConfig.seed→ConfigureNetwork→network->Configure("seed", ...),stored on
SimpleDisconnectedNetworkand injected onto the executingoptSimright after
ChooseBestSimulatorinRepeatedExecuteOnHost(network->Configurealone does not reach
optSim).QCSimSimulator::Clone()derives a deterministic, distinct per-clone seed(splitmix64) — defensive for any future rng-driven multi-threaded path.
Scope / limitations
single-threaded, so results are fully portable.
and mid-circuit / single-shot measurements delegate to the underlying qcsim
backends. qcsim's simulators do take an
addseedctor arg, but they fold instd::chrono::high_resolution_clock::now()and expose no reseed setter, somaking them deterministic would require an upstream qcsim change. Out of scope
here by design.
Tests
tests/python/test_bindings.py::TestSimulatorSeed— same-seed reproducibility,different-seed difference,
Nonedefault, repr/field, path-integralreproducibility. All 6 pass locally (statevector + path-integral verified
deterministic).