diff --git a/guppylang/pyproject.toml b/guppylang/pyproject.toml index a4e139cbe..9cf26e9a3 100644 --- a/guppylang/pyproject.toml +++ b/guppylang/pyproject.toml @@ -34,9 +34,9 @@ classifiers = [ dependencies = [ "guppylang-internals ~= 0.24.0", - "selene-sim~=0.2.3", - "selene-hugr-qis-compiler~=0.2.8", "numpy~=2.0", + "selene-hugr-qis-compiler~=0.2.8", + "selene-sim~=0.2.3", "tqdm>=4.67.1", "types-tqdm>=4.67.0.20250809", ] diff --git a/guppylang/src/guppylang/std/qsystem/random.py b/guppylang/src/guppylang/std/qsystem/random.py index 218db2697..2e6ba2a8f 100644 --- a/guppylang/src/guppylang/std/qsystem/random.py +++ b/guppylang/src/guppylang/std/qsystem/random.py @@ -73,6 +73,16 @@ def random_int_bounded(self: "RNG", bound: int) -> int: bound: The upper bound of the range, needs to less than 2^31. """ + @hugr_op(external_op("RandomAdvance", [], ext=QSYSTEM_RANDOM_EXTENSION)) + @no_type_check + def random_advance(self: "RNG", delta: int) -> None: + """Advance or backtrack the RNG state by a given number of steps. + + Args: + delta: Number of steps to move the RNG state forward (if positive) + or backward (if negative). + """ + @guppy @no_type_check def shuffle(self: "RNG", array: array[SHUFFLE_T, SHUFFLE_N]) -> None: diff --git a/pyproject.toml b/pyproject.toml index 4c296406c..1fd75bcac 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,6 @@ miette-py = { workspace = true } # Uncomment these to test the latest dependency version during development # hugr = { git = "https://github.com/CQCL/hugr", subdirectory = "hugr-py", rev = "50a2bac" } -# tket = { git = "https://github.com/CQCL/tket2", subdirectory = "tket-py", rev = "e704c19" } [build-system] requires = ["hatchling"] diff --git a/tests/integration/test_qsystem.py b/tests/integration/test_qsystem.py index 4ead52912..a88e8b3ac 100644 --- a/tests/integration/test_qsystem.py +++ b/tests/integration/test_qsystem.py @@ -60,6 +60,24 @@ def test() -> tuple[int, float, int, int, angle, angle]: validate(test.compile_function()) +def test_random_advance(validate, run_int_fn): # type: ignore[no-untyped-def] + """Validate behavior of random_advance from qsystem random extension.""" + + @guppy + def test() -> int: + rng = RNG(42) + rint_bnd1 = rng.random_int_bounded(100) + rng.random_advance(-1) + rint_bnd2 = rng.random_int_bounded(100) + same = rint_bnd1 == rint_bnd2 + rng.discard() + + return int(same) + + validate(test.compile_function()) + run_int_fn(test, 1) + + def test_measure_leaked(validate): # type: ignore[no-untyped-def] """Compile the measure_leaked operation."""