Skip to content

Commit

Permalink
craig review
Browse files Browse the repository at this point in the history
  • Loading branch information
m-mcewen committed Dec 8, 2023
1 parent 73c3d79 commit 4044b76
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 99 deletions.
61 changes: 34 additions & 27 deletions doc/python_api_reference_vDev.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ API references for stable versions are kept on the [stim github wiki](https://gi
- [`stim.ExplainedError.dem_error_terms`](#stim.ExplainedError.dem_error_terms)
- [`stim.FlipSimulator`](#stim.FlipSimulator)
- [`stim.FlipSimulator.__init__`](#stim.FlipSimulator.__init__)
- [`stim.FlipSimulator.apply_pauli_errors`](#stim.FlipSimulator.apply_pauli_errors)
- [`stim.FlipSimulator.batch_size`](#stim.FlipSimulator.batch_size)
- [`stim.FlipSimulator.broadcast_pauli_errors`](#stim.FlipSimulator.broadcast_pauli_errors)
- [`stim.FlipSimulator.do`](#stim.FlipSimulator.do)
- [`stim.FlipSimulator.get_detector_flips`](#stim.FlipSimulator.get_detector_flips)
- [`stim.FlipSimulator.get_measurement_flips`](#stim.FlipSimulator.get_measurement_flips)
Expand Down Expand Up @@ -6132,12 +6132,34 @@ def __init__(
"""
```

<a name="stim.FlipSimulator.apply_pauli_errors"></a>
<a name="stim.FlipSimulator.batch_size"></a>
```python
# stim.FlipSimulator.apply_pauli_errors
# stim.FlipSimulator.batch_size

# (in class stim.FlipSimulator)
def apply_pauli_errors(
@property
def batch_size(
self,
) -> int:
"""Returns the number of instances being simulated by the simulator.
Examples:
>>> import stim
>>> sim = stim.FlipSimulator(batch_size=256)
>>> sim.batch_size
256
>>> sim = stim.FlipSimulator(batch_size=42)
>>> sim.batch_size
42
"""
```

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

# (in class stim.FlipSimulator)
def broadcast_pauli_errors(
self,
*,
pauli: Union[str, int],
Expand All @@ -6149,7 +6171,7 @@ def apply_pauli_errors(
pauli: The pauli, specified as an integer or string.
Uses the convention 0=I, 1=X, 2=Y, 3=Z.
Any value from [0, 1, 2, 3, 'X', 'Y', 'Z', 'I', '_'] is allowed.
mask: a bool array with shape (qubit, simulation_instance)
mask: a np.bool_ array with shape (qubit, simulation_instance)
The pauli error is only applied to qubits q and simulation indices k
where mask[q, k] == True
Expand All @@ -6161,34 +6183,19 @@ def apply_pauli_errors(
... num_qubits=3,
... disable_stabilizer_randomization=True,
... )
>>> sim.apply_pauli_errors(
>>> sim.broadcast_pauli_errors(
... pauli='X',
... mask=np.asarray([[True, False],[False, False],[True, True]]),
... )
>>> sim.peek_pauli_flips()
[stim.PauliString("+X_X"), stim.PauliString("+__X")]
"""
```

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

# (in class stim.FlipSimulator)
@property
def batch_size(
self,
) -> int:
"""Returns the number of instances being simulated by the simulator.
Examples:
>>> import stim
>>> sim = stim.FlipSimulator(batch_size=256)
>>> sim.batch_size
256
>>> sim = stim.FlipSimulator(batch_size=42)
>>> sim.batch_size
42
>>> sim.broadcast_pauli_errors(
... pauli='Z',
... mask=np.asarray([[False, True],[False, False],[True, True]]),
... )
>>> sim.peek_pauli_flips()
[stim.PauliString("+X_Y"), stim.PauliString("+Z_Y")]
"""
```

Expand Down
41 changes: 24 additions & 17 deletions doc/stim.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -4655,7 +4655,22 @@ class FlipSimulator:
>>> import stim
>>> sim = stim.FlipSimulator(batch_size=256)
"""
def apply_pauli_errors(
@property
def batch_size(
self,
) -> int:
"""Returns the number of instances being simulated by the simulator.
Examples:
>>> import stim
>>> sim = stim.FlipSimulator(batch_size=256)
>>> sim.batch_size
256
>>> sim = stim.FlipSimulator(batch_size=42)
>>> sim.batch_size
42
"""
def broadcast_pauli_errors(
self,
*,
pauli: Union[str, int],
Expand All @@ -4667,7 +4682,7 @@ class FlipSimulator:
pauli: The pauli, specified as an integer or string.
Uses the convention 0=I, 1=X, 2=Y, 3=Z.
Any value from [0, 1, 2, 3, 'X', 'Y', 'Z', 'I', '_'] is allowed.
mask: a bool array with shape (qubit, simulation_instance)
mask: a np.bool_ array with shape (qubit, simulation_instance)
The pauli error is only applied to qubits q and simulation indices k
where mask[q, k] == True
Expand All @@ -4679,27 +4694,19 @@ class FlipSimulator:
... num_qubits=3,
... disable_stabilizer_randomization=True,
... )
>>> sim.apply_pauli_errors(
>>> sim.broadcast_pauli_errors(
... pauli='X',
... mask=np.asarray([[True, False],[False, False],[True, True]]),
... )
>>> sim.peek_pauli_flips()
[stim.PauliString("+X_X"), stim.PauliString("+__X")]
"""
@property
def batch_size(
self,
) -> int:
"""Returns the number of instances being simulated by the simulator.
Examples:
>>> import stim
>>> sim = stim.FlipSimulator(batch_size=256)
>>> sim.batch_size
256
>>> sim = stim.FlipSimulator(batch_size=42)
>>> sim.batch_size
42
>>> sim.broadcast_pauli_errors(
... pauli='Z',
... mask=np.asarray([[False, True],[False, False],[True, True]]),
... )
>>> sim.peek_pauli_flips()
[stim.PauliString("+X_Y"), stim.PauliString("+Z_Y")]
"""
def do(
self,
Expand Down
41 changes: 24 additions & 17 deletions glue/python/src/stim/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -4655,7 +4655,22 @@ class FlipSimulator:
>>> import stim
>>> sim = stim.FlipSimulator(batch_size=256)
"""
def apply_pauli_errors(
@property
def batch_size(
self,
) -> int:
"""Returns the number of instances being simulated by the simulator.
Examples:
>>> import stim
>>> sim = stim.FlipSimulator(batch_size=256)
>>> sim.batch_size
256
>>> sim = stim.FlipSimulator(batch_size=42)
>>> sim.batch_size
42
"""
def broadcast_pauli_errors(
self,
*,
pauli: Union[str, int],
Expand All @@ -4667,7 +4682,7 @@ class FlipSimulator:
pauli: The pauli, specified as an integer or string.
Uses the convention 0=I, 1=X, 2=Y, 3=Z.
Any value from [0, 1, 2, 3, 'X', 'Y', 'Z', 'I', '_'] is allowed.
mask: a bool array with shape (qubit, simulation_instance)
mask: a np.bool_ array with shape (qubit, simulation_instance)
The pauli error is only applied to qubits q and simulation indices k
where mask[q, k] == True
Expand All @@ -4679,27 +4694,19 @@ class FlipSimulator:
... num_qubits=3,
... disable_stabilizer_randomization=True,
... )
>>> sim.apply_pauli_errors(
>>> sim.broadcast_pauli_errors(
... pauli='X',
... mask=np.asarray([[True, False],[False, False],[True, True]]),
... )
>>> sim.peek_pauli_flips()
[stim.PauliString("+X_X"), stim.PauliString("+__X")]
"""
@property
def batch_size(
self,
) -> int:
"""Returns the number of instances being simulated by the simulator.
Examples:
>>> import stim
>>> sim = stim.FlipSimulator(batch_size=256)
>>> sim.batch_size
256
>>> sim = stim.FlipSimulator(batch_size=42)
>>> sim.batch_size
42
>>> sim.broadcast_pauli_errors(
... pauli='Z',
... mask=np.asarray([[False, True],[False, False],[True, True]]),
... )
>>> sim.peek_pauli_flips()
[stim.PauliString("+X_Y"), stim.PauliString("+Z_Y")]
"""
def do(
self,
Expand Down
73 changes: 42 additions & 31 deletions src/stim/simulators/frame_simulator.pybind.cc
Original file line number Diff line number Diff line change
Expand Up @@ -772,14 +772,17 @@ void stim_pybind::pybind_frame_simulator_methods(
.data());

c.def(
"apply_pauli_errors",
"broadcast_pauli_errors",
[](FrameSimulator<MAX_BITWORD_WIDTH> &self,
const pybind11::object &pauli,
const pybind11::object &mask
) {
uint8_t p = 255;
try {
p = pybind11::cast<uint8_t>(pauli);
if (p >= 4) {
throw pybind11::cast_error();
}
} catch (const pybind11::cast_error &) {
try {
std::string s = pybind11::cast<std::string>(pauli);
Expand All @@ -791,53 +794,53 @@ void stim_pybind::pybind_frame_simulator_methods(
p = 3;
} else if (s == "I" || s == "_") {
p = 0;
} else {
throw pybind11::cast_error();
}
} catch (const pybind11::cast_error &) {
throw std::invalid_argument(
"broadcast_pauli_errors only accepts pauli arguments in ['I', '_', 'X', 'Y', 'Z', 0,1,2,3]");
}
}

bool flip_z_part = p & 2;
bool flip_x_part = 6 >> p & 1; // 0b0110 >> p & 0b0001

if (pybind11::isinstance<pybind11::array_t<bool>>(mask)) {
// can use pybind11::isinstance<pybind11::array_t<bool, pybind11::array::c_style>>
// to check for dense c_ordered array for copying, if this is too slow for you
const pybind11::array_t<bool> &arr = pybind11::cast<pybind11::array_t<bool>>(mask);
if (arr.ndim() == 2) {
//pybind11::ssize_t???
size_t major = arr.shape(0);
size_t minor = arr.shape(1);
//size_t major_stride = arr.strides(0);
//size_t minor_stride = arr.strides(1);
auto u = arr.unchecked<2>();
for (size_t i = 0; i < major; i++){
for (size_t j = 0; j < minor; j++){
auto b = u.data(i, j);
self.x_table[i][j] ^= *b & flip_x_part;
self.z_table[i][j] ^= *b & flip_z_part;
}
}
} else {
throw std::invalid_argument(
"apply_pauli_errors currently only supports a mask that is a 2D bool numpy array");
}
} else {
throw std::invalid_argument(
"apply_pauli_errors currently only supports a mask that is a 2D bool numpy array");
bool flip_x_part = (0b0110 >> p) & 1; // parity of 2 bit number


if (!pybind11::isinstance<pybind11::array_t<bool>>(mask)) {
throw std::invalid_argument(
"broadcast_pauli_errors can only accept mask that is a 2D array of np.bool_");
}
const pybind11::array_t<bool> &arr = pybind11::cast<pybind11::array_t<bool>>(mask);

if (arr.ndim() != 2) {
throw std::invalid_argument(
"broadcast_pauli_errors can only accept mask that is a 2D array of np.bool_");
}

size_t major = arr.shape(0);
size_t minor = arr.shape(1);
auto u = arr.unchecked<2>();
for (size_t i = 0; i < major; i++){
for (size_t j = 0; j < minor; j++){
auto b = u.data(i, j);
self.x_table[i][j] ^= *b & flip_x_part;
self.z_table[i][j] ^= *b & flip_z_part;
}
}
},
pybind11::kw_only(),
pybind11::arg("pauli"),
pybind11::arg("mask"),
clean_doc_string(R"DOC(
@signature def apply_pauli_errors(self, *, pauli: Union[str, int], mask: np.ndarray) -> None:
@signature def broadcast_pauli_errors(self, *, pauli: Union[str, int], mask: np.ndarray) -> None:
Applies a pauli over all qubits in all simulation indices, filtered by mask.
Args:
pauli: The pauli, specified as an integer or string.
Uses the convention 0=I, 1=X, 2=Y, 3=Z.
Any value from [0, 1, 2, 3, 'X', 'Y', 'Z', 'I', '_'] is allowed.
mask: a bool array with shape (qubit, simulation_instance)
mask: a np.bool_ array with shape (qubit, simulation_instance)
The pauli error is only applied to qubits q and simulation indices k
where mask[q, k] == True
Expand All @@ -849,12 +852,20 @@ void stim_pybind::pybind_frame_simulator_methods(
... num_qubits=3,
... disable_stabilizer_randomization=True,
... )
>>> sim.apply_pauli_errors(
>>> sim.broadcast_pauli_errors(
... pauli='X',
... mask=np.asarray([[True, False],[False, False],[True, True]]),
... )
>>> sim.peek_pauli_flips()
[stim.PauliString("+X_X"), stim.PauliString("+__X")]
>>> sim.broadcast_pauli_errors(
... pauli='Z',
... mask=np.asarray([[False, True],[False, False],[True, True]]),
... )
>>> sim.peek_pauli_flips()
[stim.PauliString("+X_Y"), stim.PauliString("+Z_Y")]
)DOC")
.data());
}
Loading

0 comments on commit 4044b76

Please sign in to comment.