Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pauli iter all #598

Closed
wants to merge 11 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 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
140 changes: 140 additions & 0 deletions doc/python_api_reference_vDev.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,17 @@ API references for stable versions are kept on the [stim github wiki](https://gi
- [`stim.PauliString.copy`](#stim.PauliString.copy)
- [`stim.PauliString.from_numpy`](#stim.PauliString.from_numpy)
- [`stim.PauliString.from_unitary_matrix`](#stim.PauliString.from_unitary_matrix)
- [`stim.PauliString.iter_all`](#stim.PauliString.iter_all)
- [`stim.PauliString.random`](#stim.PauliString.random)
- [`stim.PauliString.sign`](#stim.PauliString.sign)
- [`stim.PauliString.to_numpy`](#stim.PauliString.to_numpy)
- [`stim.PauliString.to_tableau`](#stim.PauliString.to_tableau)
- [`stim.PauliString.to_unitary_matrix`](#stim.PauliString.to_unitary_matrix)
- [`stim.PauliStringIterator`](#stim.PauliStringIterator)
- [`stim.PauliStringIterator.__iter__`](#stim.PauliStringIterator.__iter__)
- [`stim.PauliStringIterator.__next__`](#stim.PauliStringIterator.__next__)
- [`stim.PauliStringIterator.next_qubit_permutation`](#stim.PauliStringIterator.next_qubit_permutation)
- [`stim.PauliStringIterator.seed_iterator`](#stim.PauliStringIterator.seed_iterator)
- [`stim.Tableau`](#stim.Tableau)
- [`stim.Tableau.__add__`](#stim.Tableau.__add__)
- [`stim.Tableau.__call__`](#stim.Tableau.__call__)
Expand Down Expand Up @@ -7586,6 +7592,45 @@ def from_unitary_matrix(
"""
```

<a name="stim.PauliString.iter_all"></a>
```python
# stim.PauliString.iter_all

# (in class stim.PauliString)
@staticmethod
def iter_all(
num_qubits: int,
*,
min_weight: Optional[int] = None,
max_weight: Optional[int] = None,
) -> stim.PauliStringIterator:
"""Returns an iterator that iterates over all PauliStrings.

The length of PauliString and its weight (the number of
non-identity terms) are controlled by num_qubits and
min_/max_weight.

Args:
num_qubits: The number of qubits the Pauli string acts on.
min_weight: The minimum weight PauliString to consider. If None
min_weight is set to zero and the identity string is included.
max_weight: The maximum weight PauliString to consider. If None
then max_weight is set to num_qubits.

Returns:
An Iterable[stim.PauliString] that yields the requested PauliStrings.

Examples:
>>> import stim
>>> pauli_iter = stim.PauliString.iter_all(10, min_weight=2, max_weight=3)
>>> n = 0
>>> for pauli_string in pauli_iter:
... n += 1
>>> n
3645
"""
```

<a name="stim.PauliString.random"></a>
```python
# stim.PauliString.random
Expand Down Expand Up @@ -7793,6 +7838,101 @@ def to_unitary_matrix(
"""
```

<a name="stim.PauliStringIterator"></a>
```python
# stim.PauliStringIterator

# (at top-level in the stim module)
class PauliStringIterator:
"""Iterates over all possible pauli_strings of weight specfied by
min_weight and max_weight.

Returns:
An Iterable[stim.PauliString] that yields the requested Pauli
string.

Examples:
>>> import stim
>>> pauli_iter = stim.PauliString.iter_all(10, min_weight=2, max_weight=3)
>>> n = 0
>>> for pauli_string in pauli_iter:
... n += 1
>>> n
3645
"""
```

<a name="stim.PauliStringIterator.__iter__"></a>
```python
# stim.PauliStringIterator.__iter__

# (in class stim.PauliStringIterator)
def __iter__(
self,
) -> stim.PauliStringIterator:
"""Returns an independent copy of the pauli string iterator.
"""
```

<a name="stim.PauliStringIterator.__next__"></a>
```python
# stim.PauliStringIterator.__next__

# (in class stim.PauliStringIterator)
def __next__(
self,
) -> stim.PauliString:
"""Returns the next iterated pauli string.
"""
```

<a name="stim.PauliStringIterator.next_qubit_permutation"></a>
```python
# stim.PauliStringIterator.next_qubit_permutation

# (in class stim.PauliStringIterator)
def next_qubit_permutation(
self,
) -> object:
"""Get the next permutation of qubit labels.

It's alot easier to test more complicated edge cases in python
which largely arise due to the algorithm for generating the next
permutation. The user should probably not interact with this function.

Returns:
next_perm: numpy boolean array which represents the next qubit permutation

Examples:
>>> import stim
>>> pauli_iter = stim.PauliString.iter_all(5, min_weight=3, max_weight=5)
>>> pauli_iter.next_qubit_permutation()
array([ True, True, False, True, False])
"""
```

<a name="stim.PauliStringIterator.seed_iterator"></a>
```python
# stim.PauliStringIterator.seed_iterator

# (in class stim.PauliStringIterator)
def seed_iterator(
self,
arg0: object,
) -> None:
"""Seed the iterator with a given qubit pattern.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not clear to me what this means.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm actually going to remove this function, after closer thought it's not super helpful. The idea was to be able to "seed" the iterator at a specific bit pattern which may be difficult to reach if w was large, but this can be tested on the C++ side more easily, and not sure if it's actually useful on the python side.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually scratch that, I needed it for testing random starting points for long strings with higher weight. I will change the name to something more descriptive

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I renamed this to set_current_permutation.


Examples:
>>> import stim
>>> import numpy as np
>>> pauli_iter = stim.PauliString.iter_all(4, min_weight=2, max_weight=2)
>>> seed = np.array([False, True, True, False])
>>> pauli_iter.seed_iterator(seed)
>>> pauli_iter.next_qubit_permutation()
array([ True, False, False, True])
"""
```

<a name="stim.Tableau"></a>
```python
# stim.Tableau
Expand Down
92 changes: 92 additions & 0 deletions doc/stim.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -5805,6 +5805,38 @@ class PauliString:
stim.PauliString("+XZ")
"""
@staticmethod
def iter_all(
num_qubits: int,
*,
min_weight: Optional[int] = None,
max_weight: Optional[int] = None,
) -> stim.PauliStringIterator:
"""Returns an iterator that iterates over all PauliStrings.

The length of PauliString and its weight (the number of
non-identity terms) are controlled by num_qubits and
min_/max_weight.

Args:
num_qubits: The number of qubits the Pauli string acts on.
min_weight: The minimum weight PauliString to consider. If None
min_weight is set to zero and the identity string is included.
max_weight: The maximum weight PauliString to consider. If None
then max_weight is set to num_qubits.

Returns:
An Iterable[stim.PauliString] that yields the requested PauliStrings.

Examples:
>>> import stim
>>> pauli_iter = stim.PauliString.iter_all(10, min_weight=2, max_weight=3)
>>> n = 0
>>> for pauli_string in pauli_iter:
... n += 1
>>> n
3645
"""
@staticmethod
def random(
num_qubits: int,
*,
Expand Down Expand Up @@ -5976,6 +6008,66 @@ class PauliString:
[0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j],
[0.+0.j, 0.+0.j, 0.+1.j, 0.+0.j]], dtype=complex64)
"""
class PauliStringIterator:
"""Iterates over all possible pauli_strings of weight specfied by
min_weight and max_weight.

Returns:
An Iterable[stim.PauliString] that yields the requested Pauli
string.

Examples:
>>> import stim
>>> pauli_iter = stim.PauliString.iter_all(10, min_weight=2, max_weight=3)
>>> n = 0
>>> for pauli_string in pauli_iter:
... n += 1
>>> n
3645
"""
def __iter__(
self,
) -> stim.PauliStringIterator:
"""Returns an independent copy of the pauli string iterator.
"""
def __next__(
self,
) -> stim.PauliString:
"""Returns the next iterated pauli string.
"""
def next_qubit_permutation(
self,
) -> object:
"""Get the next permutation of qubit labels.

It's alot easier to test more complicated edge cases in python
which largely arise due to the algorithm for generating the next
permutation. The user should probably not interact with this function.

Returns:
next_perm: numpy boolean array which represents the next qubit permutation

Examples:
>>> import stim
>>> pauli_iter = stim.PauliString.iter_all(5, min_weight=3, max_weight=5)
>>> pauli_iter.next_qubit_permutation()
array([ True, True, False, True, False])
"""
def seed_iterator(
self,
arg0: object,
) -> None:
"""Seed the iterator with a given qubit pattern.

Examples:
>>> import stim
>>> import numpy as np
>>> pauli_iter = stim.PauliString.iter_all(4, min_weight=2, max_weight=2)
>>> seed = np.array([False, True, True, False])
>>> pauli_iter.seed_iterator(seed)
>>> pauli_iter.next_qubit_permutation()
array([ True, False, False, True])
"""
class Tableau:
"""A stabilizer tableau.

Expand Down
1 change: 1 addition & 0 deletions file_lists/benchmark_files
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ src/stim/simulators/error_analyzer.perf.cc
src/stim/simulators/frame_simulator.perf.cc
src/stim/simulators/tableau_simulator.perf.cc
src/stim/stabilizers/pauli_string.perf.cc
src/stim/stabilizers/pauli_string_iter.perf.cc
src/stim/stabilizers/tableau.perf.cc
src/stim/stabilizers/tableau_iter.perf.cc
1 change: 1 addition & 0 deletions file_lists/python_api_files
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ src/stim/simulators/matched_error.pybind.cc
src/stim/simulators/measurements_to_detection_events.pybind.cc
src/stim/simulators/tableau_simulator.pybind.cc
src/stim/stabilizers/pauli_string.pybind.cc
src/stim/stabilizers/pauli_string_iter.pybind.cc
src/stim/stabilizers/tableau.pybind.cc
src/stim/stabilizers/tableau_iter.pybind.cc
1 change: 1 addition & 0 deletions file_lists/test_files
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ src/stim/simulators/transform_without_feedback.test.cc
src/stim/simulators/vector_simulator.test.cc
src/stim/stabilizers/conversions.test.cc
src/stim/stabilizers/pauli_string.test.cc
src/stim/stabilizers/pauli_string_iter.test.cc
src/stim/stabilizers/tableau.test.cc
src/stim/stabilizers/tableau_iter.test.cc
src/stim/str_util.test.cc
Expand Down
92 changes: 92 additions & 0 deletions glue/python/src/stim/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -5805,6 +5805,38 @@ class PauliString:
stim.PauliString("+XZ")
"""
@staticmethod
def iter_all(
num_qubits: int,
*,
min_weight: Optional[int] = None,
max_weight: Optional[int] = None,
) -> stim.PauliStringIterator:
"""Returns an iterator that iterates over all PauliStrings.

The length of PauliString and its weight (the number of
non-identity terms) are controlled by num_qubits and
min_/max_weight.

Args:
num_qubits: The number of qubits the Pauli string acts on.
min_weight: The minimum weight PauliString to consider. If None
min_weight is set to zero and the identity string is included.
max_weight: The maximum weight PauliString to consider. If None
then max_weight is set to num_qubits.

Returns:
An Iterable[stim.PauliString] that yields the requested PauliStrings.

Examples:
>>> import stim
>>> pauli_iter = stim.PauliString.iter_all(10, min_weight=2, max_weight=3)
>>> n = 0
>>> for pauli_string in pauli_iter:
... n += 1
>>> n
3645
"""
@staticmethod
def random(
num_qubits: int,
*,
Expand Down Expand Up @@ -5976,6 +6008,66 @@ class PauliString:
[0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j],
[0.+0.j, 0.+0.j, 0.+1.j, 0.+0.j]], dtype=complex64)
"""
class PauliStringIterator:
"""Iterates over all possible pauli_strings of weight specfied by
min_weight and max_weight.

Returns:
An Iterable[stim.PauliString] that yields the requested Pauli
string.

Examples:
>>> import stim
>>> pauli_iter = stim.PauliString.iter_all(10, min_weight=2, max_weight=3)
>>> n = 0
>>> for pauli_string in pauli_iter:
... n += 1
>>> n
3645
"""
def __iter__(
self,
) -> stim.PauliStringIterator:
"""Returns an independent copy of the pauli string iterator.
"""
def __next__(
self,
) -> stim.PauliString:
"""Returns the next iterated pauli string.
"""
def next_qubit_permutation(
self,
) -> object:
"""Get the next permutation of qubit labels.

It's alot easier to test more complicated edge cases in python
which largely arise due to the algorithm for generating the next
permutation. The user should probably not interact with this function.

Returns:
next_perm: numpy boolean array which represents the next qubit permutation

Examples:
>>> import stim
>>> pauli_iter = stim.PauliString.iter_all(5, min_weight=3, max_weight=5)
>>> pauli_iter.next_qubit_permutation()
array([ True, True, False, True, False])
"""
def seed_iterator(
self,
arg0: object,
) -> None:
"""Seed the iterator with a given qubit pattern.

Examples:
>>> import stim
>>> import numpy as np
>>> pauli_iter = stim.PauliString.iter_all(4, min_weight=2, max_weight=2)
>>> seed = np.array([False, True, True, False])
>>> pauli_iter.seed_iterator(seed)
>>> pauli_iter.next_qubit_permutation()
array([ True, False, False, True])
"""
class Tableau:
"""A stabilizer tableau.

Expand Down
Loading