Skip to content

Expose simulator RNG seed via SimulatorConfig.seed#27

Open
Shiro-Raven wants to merge 1 commit into
mainfrom
feat/simulator-seed
Open

Expose simulator RNG seed via SimulatorConfig.seed#27
Shiro-Raven wants to merge 1 commit into
mainfrom
feat/simulator-seed

Conversation

@Shiro-Raven

Copy link
Copy Markdown
Contributor

What

Adds an optional seed field to SimulatorConfig, letting Python users make
the simulator's multi-shot terminal sampling reproducible:

cfg = maestro.SimulatorConfig(seed=12345)
maestro.simple_execute(qasm, shots=4000, config=cfg)  # deterministic counts

seed=None (default) keeps today's non-deterministic behavior.

How

  • QCSimState::Configure("seed", ...) reseeds the mt19937_64 used by
    SampleCountsMany.
  • SimulatorConfig.seedConfigureNetworknetwork->Configure("seed", ...),
    stored on SimpleDisconnectedNetwork and injected onto the executing optSim
    right after ChooseBestSimulator in RepeatedExecuteOnHost (network->Configure
    alone 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

  • Reproducible: statevector and path-integral terminal sampling. Both run
    single-threaded, so results are fully portable.
  • Not reproducible (documented): MPS / stabilizer / tensor-network sampling
    and mid-circuit / single-shot measurements delegate to the underlying qcsim
    backends. qcsim's simulators do take an addseed ctor arg, but they fold in
    std::chrono::high_resolution_clock::now() and expose no reseed setter, so
    making 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, None default, repr/field, path-integral
reproducibility. All 6 pass locally (statevector + path-integral verified
deterministic).

@Shiro-Raven Shiro-Raven requested a review from aromanro June 17, 2026 09:54
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>
@Shiro-Raven Shiro-Raven force-pushed the feat/simulator-seed branch from 58ac686 to 0522874 Compare June 17, 2026 09:56
@greptile-apps

greptile-apps Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR exposes a simulator RNG seed through Python configuration. It changes:

  • Adds SimulatorConfig.seed to the nanobind Python API.
  • Stores and forwards the seed through ConfigureNetwork and SimpleDisconnectedNetwork.
  • Seeds the QCSim terminal sampling RNG for statevector and path-integral multi-shot sampling.
  • Derives deterministic per-clone seeds in QCSimSimulator::Clone().
  • Adds Python tests for seeded sampling behavior.

Confidence Score: 3/5

I don't think this is safe to merge yet.

  • Some execution paths can accept a configured seed but still sample randomly.
  • Job-created simulators do not receive the new seed option.
  • Cloned networks lose the stored seed before execution.
  • The direct simple_execute path is wired correctly, but the network-level paths need the same propagation.

Network/SimpleDisconnectedNetwork.h needs the seed propagation fixed across all simulator creation and clone paths.

T-Rex T-Rex Logs

What T-Rex did

  • Seed propagation from SimulatorConfig(seed=42) was traced through ConfigureNetwork to SimpleDisconnectedNetwork::Configure, RepeatedExecuteOnHost, and QCSimState::Configure("seed").
  • SampleCountsMany was verified to use the seeded rng for multi-shot statevector sampling and for path-integral sampling.
  • The seed=None path was verified to skip seed configuration, leaving the network seed string empty and ensuring RepeatedExecuteOnHost does not reuse seeded state.
  • Each simple_execute call creates a new network, so there is no seed state leakage between calls.
  • QCSimSimulator.Clone() was verified to derive distinct seeds via splitmix64 when a user seed is set.
  • The nanobind constructor was verified to add seed as the last keyword parameter with a None default, maintaining backward compatibility.
  • Runtime validation was blocked because the local build could not find required Boost components.
  • Attempted to install dependencies and build: a pip install -e . failed due to missing Boost components, and an apt-get attempt for libboost-all-dev was not available in the sandbox.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

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)

  1. Network/SimpleDisconnectedNetwork.h, line 591-593 (link)

    P1 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.

    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.
  2. Network/SimpleDisconnectedNetwork.h, line 1900-1903 (link)

    P2 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.

    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());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 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.

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.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant