Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 18 additions & 1 deletion selene-sim/python/selene_sim/instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ def run_shots(
shot_increment: int = 1,
n_processes: int = 1,
parse_results: bool = True,
seed_mode: str = "default",
) -> Iterator[Iterator[TaggedResult]]:
"""
Run the compiled program through multiple selene shots.
Expand All @@ -186,7 +187,8 @@ def run_shots(
results_logfile: The file to write the results to (if any)
random_seed: The random seed to use for the simulator, error model,
and runtime if they have not been set explicitly. On
each shot, the random seed will be incremented by 1.
each shot, the random seed will be updated according to
to `seed_mode`.
parse_results:
Whether to interpret tags in the result stream.
If True (default), tags will be stripped, interpreted,
Expand All @@ -207,6 +209,10 @@ def run_shots(
Setting to True provides the high level Selene interface, and
using False allows for Selene to be used as an intermediate
component for use with an external result stream handler.
seed_mode: The mode for handling random seeds.

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.

Worth considering using an enum for this instead of a string?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It could be. Though it will necessitate an extra import e.g.:

from selene_sim import SeedMode

run_shots(..., seed_mode=SeedMode.legacy)

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.

Yes, perhaps not worth it.

- "default" uses `random_seed` as a seed for an RNG that
itself generates the seeds on all shots.
- "legacy" increments the seed by 1 on each shot.
"""

self._check_health()
Expand All @@ -219,12 +225,18 @@ def run_shots(
library_search_dirs = self.library_search_dirs.copy()
for component in (simulator, error_model, runtime):
library_search_dirs.extend(component.library_search_dirs)

assert seed_mode in ("default", "legacy"), (
f"Invalid seed_mode: {seed_mode}, must be one of 'default' or 'legacy'"
)

global_configuration = {
"event_hooks": {flag: True for flag in event_hook.get_selene_flags()},
"n_qubits": n_qubits,
"simulator": self._get_component_config(simulator, random_seed),
"error_model": self._get_component_config(error_model, random_seed),
"runtime": self._get_component_config(runtime, random_seed),
"seed_mode": seed_mode,
}
with TCPStream(
timeout=timeout,
Expand Down Expand Up @@ -292,6 +304,7 @@ def run(
random_seed: int | None = None,
shot_offset: int = 0,
parse_results: bool = True,
seed_mode: str = "default",
) -> Iterator[TaggedResult]:
"""
Run the compiled program through a single selene shot.
Expand All @@ -309,6 +322,9 @@ def run(
results_logfile: The file to write the results to (if any)
random_seed: The random seed to use for the simulator, error model,
and runtime if they have not been set explicitly
seed_mode: The mode for handling random seeds. If "legacy", the
random_seed is used as-is. If "default", it first goes
through RNG, reproducing the behaviour of run_shots.
"""
shot_generator = self.run_shots(
simulator=simulator,
Expand All @@ -323,6 +339,7 @@ def run(
random_seed=random_seed,
shot_offset=shot_offset,
parse_results=parse_results,
seed_mode=seed_mode,
)
# We cannot simply yield from the shot generator, as this can
# cause lifetime issues with the run_shots generator.
Expand Down
6 changes: 4 additions & 2 deletions selene-sim/python/selene_sim/interactive/full_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ def __init__(
error_model: ErrorModel | None = None,
event_hook: EventHook | None = None,
random_seed: int | None = None,
seed_mode: str = "default",
):
self._lib = self.load_library()
self._instance = SeleneInstancePtr()
Expand Down Expand Up @@ -350,8 +351,7 @@ def __init__(
for component in (self.simulator, self.error_model, self.runtime)
]
config_data = self._build_configuration(
n_qubits=n_qubits,
random_seed=random_seed,
n_qubits=n_qubits, random_seed=random_seed, seed_mode=seed_mode
)
config_data["shots"] = {
"count": self._shot_spec.count,
Expand Down Expand Up @@ -390,12 +390,14 @@ def _build_configuration(
self,
n_qubits: int,
random_seed: int | None,
seed_mode: str = "default",
) -> dict:
return {
"n_qubits": int(n_qubits),
"simulator": _component_config(self.simulator, random_seed),
"error_model": _component_config(self.error_model, random_seed),
"runtime": _component_config(self.runtime, random_seed),
"seed_mode": seed_mode,
}

def _teardown_environment(self):
Expand Down
Loading