Skip to content

Commit 385cc2c

Browse files
committed
Add optional seed parameter to stim.Tableau.random()
Fixes #974
1 parent 79ae4f1 commit 385cc2c

4 files changed

Lines changed: 72 additions & 4 deletions

File tree

glue/python/src/stim/__init__.pyi

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9987,6 +9987,7 @@ class PauliString:
99879987
num_qubits: int,
99889988
*,
99899989
allow_imaginary: bool = False,
9990+
seed: int | None = None,
99909991
) -> stim.PauliString:
99919992
"""Samples a uniformly random Hermitian Pauli string.
99929993

@@ -9995,6 +9996,28 @@ class PauliString:
99959996
allow_imaginary: Defaults to False. If True, the sign of the result may be
99969997
1j or -1j in addition to +1 or -1. In other words, setting this to True
99979998
allows the result to be non-Hermitian.
9999+
seed: PARTIALLY determines the sampled Pauli string by deterministically
10000+
seeding the random number generator.
10001+
10002+
Must be None or an integer in range(2**64).
10003+
10004+
Defaults to None. When None, the prng is seeded from system entropy.
10005+
10006+
When set to an integer, making the exact same series calls on the exact
10007+
same machine with the exact same version of Stim will produce the exact
10008+
same Pauli string.
10009+
10010+
CAUTION: the Pauli string produced by a specific seed *WILL NOT* be
10011+
consistent between versions of Stim. This restriction is present to
10012+
make it possible to have future optimizations to the random sampling,
10013+
and is enforced by introducing intentional differences in the seeding
10014+
strategy from version to version.
10015+
10016+
CAUTION: the Pauli string produced by a specific seed *MAY NOT* be
10017+
consistent across machines that differ in the width of supported SIMD
10018+
instructions. For example, using the same seed on a machine that
10019+
supports AVX instructions and one that only supports SSE instructions
10020+
may produce different Pauli strings.
999810021

999910022
Examples:
1000010023
>>> import stim
@@ -11212,11 +11235,35 @@ class Tableau:
1121211235
@staticmethod
1121311236
def random(
1121411237
num_qubits: int,
11238+
*,
11239+
seed: int | None = None
1121511240
) -> stim.Tableau:
1121611241
"""Samples a uniformly random Clifford operation and returns its tableau.
1121711242

1121811243
Args:
1121911244
num_qubits: The number of qubits the tableau should act on.
11245+
seed: PARTIALLY determines the sampled tableau by deterministically
11246+
seeding the random number generator.
11247+
11248+
Must be None or an integer in range(2**64).
11249+
11250+
Defaults to None. When None, the prng is seeded from system entropy.
11251+
11252+
When set to an integer, making the exact same series calls on the exact
11253+
same machine with the exact same version of Stim will produce the exact
11254+
same tableau.
11255+
11256+
CAUTION: the tableau produced by a specific seed *WILL NOT* be
11257+
consistent between versions of Stim. This restriction is present to
11258+
make it possible to have future optimizations to the random sampling,
11259+
and is enforced by introducing intentional differences in the seeding
11260+
strategy from version to version.
11261+
11262+
CAUTION: the tableau produced by a specific seed *MAY NOT* be
11263+
consistent across machines that differ in the width of supported SIMD
11264+
instructions. For example, using the same seed on a machine that
11265+
supports AVX instructions and one that only supports SSE instructions
11266+
may produce different tableaus.
1122011267

1122111268
Returns:
1122211269
The sampled tableau.

src/stim/stabilizers/pauli_string.pybind.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -635,14 +635,15 @@ void stim_pybind::pybind_pauli_string_methods(pybind11::module &m, pybind11::cla
635635

636636
c.def_static(
637637
"random",
638-
[](size_t num_qubits, bool allow_imaginary) {
639-
auto rng = make_py_seeded_rng(pybind11::none());
638+
[](size_t num_qubits, bool allow_imaginary, pybind11::object seed_obj) {
639+
auto rng = make_py_seeded_rng(seed_obj);
640640
return FlexPauliString(
641641
PauliString<MAX_BITWORD_WIDTH>::random(num_qubits, rng), allow_imaginary ? (rng() & 1) : false);
642642
},
643643
pybind11::arg("num_qubits"),
644644
pybind11::kw_only(),
645645
pybind11::arg("allow_imaginary") = false,
646+
pybind11::arg("seed") = pybind11::none(),
646647
clean_doc_string(R"DOC(
647648
Samples a uniformly random Hermitian Pauli string.
648649
@@ -651,6 +652,7 @@ void stim_pybind::pybind_pauli_string_methods(pybind11::module &m, pybind11::cla
651652
allow_imaginary: Defaults to False. If True, the sign of the result may be
652653
1j or -1j in addition to +1 or -1. In other words, setting this to True
653654
allows the result to be non-Hermitian.
655+
seed: Optional. An integer to seed the random number generator.
654656
655657
Examples:
656658
>>> import stim

src/stim/stabilizers/tableau.pybind.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,16 +180,18 @@ void stim_pybind::pybind_tableau_methods(pybind11::module &m, pybind11::class_<T
180180

181181
c.def_static(
182182
"random",
183-
[](size_t num_qubits) {
184-
auto rng = make_py_seeded_rng(pybind11::none());
183+
[](size_t num_qubits, pybind11::object seed_obj) {
184+
auto rng = make_py_seeded_rng(seed_obj);
185185
return Tableau<MAX_BITWORD_WIDTH>::random(num_qubits, rng);
186186
},
187187
pybind11::arg("num_qubits"),
188+
pybind11::arg("seed") = pybind11::none(),
188189
clean_doc_string(R"DOC(
189190
Samples a uniformly random Clifford operation and returns its tableau.
190191
191192
Args:
192193
num_qubits: The number of qubits the tableau should act on.
194+
seed: Optional. An integer to seed the random number generator.
193195
194196
Returns:
195197
The sampled tableau.

src/stim/stabilizers/tableau_pybind_test.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,23 @@ def test_random():
111111
assert t != stim.Tableau.random(10)
112112

113113

114+
def test_random_seed():
115+
t1 = stim.Tableau.random(4, seed=12345)
116+
t2 = stim.Tableau.random(4, seed=12345)
117+
assert t1 == t2
118+
119+
t3 = stim.Tableau.random(4, seed=54321)
120+
assert t1 != t3
121+
122+
t4 = stim.Tableau.random(4, seed=None)
123+
t5 = stim.Tableau.random(4, seed=None)
124+
assert t4 != t5
125+
126+
t6 = stim.Tableau.random(num_qubits=2, seed=999)
127+
t7 = stim.Tableau.random(num_qubits=2, seed=999)
128+
assert t6 == t7
129+
130+
114131
def test_str():
115132
assert str(stim.Tableau.from_named_gate("cnot")).strip() == """
116133
+-xz-xz-

0 commit comments

Comments
 (0)