Skip to content
Closed
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
10 changes: 8 additions & 2 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,16 @@ the sampled values for all the global parameters and objects in the scene from t
import os
os.chdir('..')

To make sampling deterministic, seed Scenic's random number generators
before calling `Scenario.generate` using `scenic.setSeed` (the programmatic
equivalent of the :option:`--seed` command-line option):

.. autofunction:: scenic.setSeed

.. testcode::

import random, scenic
random.seed(12345)
import scenic
scenic.setSeed(12345)
scenario = scenic.scenarioFromString('ego = new Object with foo Range(0, 5)')
scene, numIterations = scenario.generate()
print(f'ego has foo = {scene.egoObject.foo}')
Expand Down
2 changes: 2 additions & 0 deletions docs/options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ General Scenario Control
(although :mod:`random` and :mod:`numpy.random` should not be used in place of
Scenic's own sampling constructs in Scenic code).

This option can be configured from the Python API using `scenic.setSeed`.

.. option:: --scenario <scenario>

If the given Scenic file defines multiple scenarios, select which one to run.
Expand Down
23 changes: 23 additions & 0 deletions src/scenic/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,31 @@
"""A compiler and scene generator for the Scenic scenario description language."""

import random as _random

import numpy as _numpy

import scenic.core.errors as _errors
from scenic.core.errors import setDebuggingOptions
from scenic.syntax.translator import scenarioFromFile, scenarioFromString

_errors.showInternalBacktrace = False # see comment in errors module
del _errors


def setSeed(seed):
"""Seed the random number generators Scenic uses for sampling.

Seeds both the Python :mod:`random` module and :mod:`numpy.random`, which
are what Scenic's rejection sampler draws from. After calling this,
subsequent calls into Scenic (e.g. :func:`scenarioFromFile` /
:meth:`Scenario.generate`) will produce deterministic results for the
given seed.

This is the programmatic equivalent of the ``-s``/``--seed``
command-line option; see :option:`--seed`.

Args:
seed (int): Seed value to pass to both RNGs.
"""
_random.seed(seed)
_numpy.random.seed(seed)
6 changes: 1 addition & 5 deletions src/scenic/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@

import argparse
from importlib import metadata
import random
import sys
import time
import warnings

import numpy

import scenic
from scenic.core.distributions import RejectionException
import scenic.core.errors as errors
Expand Down Expand Up @@ -185,8 +182,7 @@
if args.verbosity >= 1:
print(f"Using random seed = {args.seed}")

random.seed(args.seed)
numpy.random.seed(args.seed)
scenic.setSeed(args.seed)

# Load scenario from file
if args.verbosity >= 1:
Expand Down
11 changes: 11 additions & 0 deletions tests/syntax/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,17 @@ def test_verbose():
setDebuggingOptions(verbosity=1)


def test_setSeed():
scenic.setSeed(12345)
p1 = sampleParamPFrom("param p = Range(0, 1)")
scenic.setSeed(12345)
p2 = sampleParamPFrom("param p = Range(0, 1)")
assert p1 == p2
scenic.setSeed(54321)
p3 = sampleParamPFrom("param p = Range(0, 1)")
assert p1 != p3


def test_dump_ast():
scenic.syntax.translator.dumpScenicAST = True
try:
Expand Down