Skip to content

Commit

Permalink
Ensure bounded values for numpy binomial (PennyLaneAI#5447)
Browse files Browse the repository at this point in the history
### Before submitting

Please complete the following checklist when submitting a PR:

- [x] All new features must include a unit test.
If you've fixed a bug or added code that should be tested, add a test to
the
      test directory!

- [x] All new functions and code must be clearly commented and
documented.
If you do make documentation changes, make sure that the docs build and
      render correctly by running `make docs`.

- [x] Ensure that the test suite passes, by running `make test`.

- [x] Add a new entry to the `doc/releases/changelog-dev.md` file,
summarizing the
      change, and including a link back to the PR.

- [x] The PennyLane source code conforms to
      [PEP8 standards](https://www.python.org/dev/peps/pep-0008/).
We check all of our code against [Pylint](https://www.pylint.org/).
      To lint modified files, simply `pip install pylint`, and then
      run `pylint pennylane/path/to/file.py`.

When all the above are checked, delete everything above the dashed
line and fill in the pull request template.


------------------------------------------------------------------------------------------------------------

**Context:** A
[user](https://discuss.pennylane.ai/t/multiple-resets-crash-spsaoptimizer-in-ver-0-35/4322/7)
reports errors when running MCM circuits, which fail due to
numpy-defined bounds checks in `qml.random.binomial` which should be
`0<= x <=1`. This error is due to the input data to `binomial` being
supplied with 1.0000000000000002 from another numpy layer, which
triggers this bounds check. This PR rounds towards 1.0 if an associated
ValueError is thrown.

**Description of the Change:** Adds a try-except block to catch and
round if the boundary check fails.

**Benefits:** Ensures continued use of MCM circuits.

**Possible Drawbacks:** Depending on the occurrence frequency of
boundary failures, replacing the try-except block may be better handled
by pre-validation against differences between unity and unity+macheps.

**Related GitHub Issues:**
  • Loading branch information
mlxd committed Apr 3, 2024
1 parent 12e0035 commit 3b0c1b6
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 1 deletion.
3 changes: 3 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,9 @@

<h3>Bug fixes 🐛</h3>

* Avoid bounded value failures due to numerical noise with calls to `np.random.binomial`.
[(#5447)](https://github.com/PennyLaneAI/pennylane/pull/5447)

* Using `@` with legacy Hamiltonian instances now properly de-queues the previously existing operations.
[(#5454)](https://github.com/PennyLaneAI/pennylane/pull/5455)

Expand Down
10 changes: 9 additions & 1 deletion pennylane/devices/qubit/apply_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,15 @@ def apply_mid_measure(
return np.zeros_like(state)
wire = op.wires
probs = qml.devices.qubit.measure(qml.probs(wire), state)
sample = np.random.binomial(1, probs[1])

try: # pragma: no cover
sample = np.random.binomial(1, probs[1])
except ValueError as e: # pragma: no cover
if probs[1] > 1: # MachEps error, safe to catch
sample = np.random.binomial(1, np.round(probs[1], 15))
else: # Other general error, continue to fail
raise e

mid_measurements[op] = sample
if op.postselect is not None and sample != op.postselect:
return np.zeros_like(state)
Expand Down

0 comments on commit 3b0c1b6

Please sign in to comment.