Repository: PennyLaneAI/pennylane
Pull request #1680 (2021-09-23 06:50:27)

Fixes bug in default.mixed where probabilities could be non-negative
**Context:** Due to numerical error, it is possible for the `default.mixed` density matrix in to accumulate elements that are not negative by essentially zero, e.g., `-5e-17`. If occurring on the diagonal, this can result in negative probabilities being returned.

**Description of the Change:** Before returning the probabilities, `default.mixed` takes the absolute value of the diagonal.

**Benefits:** Fixes edge cases where negative probabilities can be returned (see #1677).

**Possible Drawbacks:** n/a

**Related GitHub Issues:** n/a


codecov[bot]: # [Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1680?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
> Merging [#1680](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1680?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (a372289) into [master](https://codecov.io/gh/PennyLaneAI/pennylane/commit/16aac9ff7092a94324b27d6b0dfae6f4af43a092?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) (16aac9f) will **not change** coverage.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1680/graphs/tree.svg?width=650&height=150&src=pr&token=9S3YzlUgGk&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1680?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)

```diff
@@           Coverage Diff           @@
##           master    #1680   +/-   ##
=======================================
  Coverage   99.19%   99.19%           
=======================================
  Files         199      199           
  Lines       14857    14857           
=======================================
  Hits        14737    14737           
  Misses        120      120           
```


| [Impacted Files](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1680?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) | Coverage Δ | |
|---|---|---|
| [pennylane/devices/default\_mixed.py](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1680/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL2RldmljZXMvZGVmYXVsdF9taXhlZC5weQ==) | `100.00% <100.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1680?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1680?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI). Last update [16aac9f...a372289](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1680?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).


Patch:
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index 50a7bd7af..aa4aeeaa7 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -219,6 +219,9 @@
   to compute the variance of a QNode with ragged output.
   [(#1646)](https://github.com/PennyLaneAI/pennylane/pull/1646)
 
+* Fixes a bug in `default.mixed`, to ensure that returned probabilities are always non-negative.
+  [(#1680)](https://github.com/PennyLaneAI/pennylane/pull/1680)
+
 <h3>Documentation</h3>
 
 * Adds a link to https://pennylane.ai/qml/demonstrations.html in the navbar.
diff --git a/pennylane/devices/default_mixed.py b/pennylane/devices/default_mixed.py
index 2b83220e3..434d0123f 100644
--- a/pennylane/devices/default_mixed.py
+++ b/pennylane/devices/default_mixed.py
@@ -193,7 +193,7 @@ class DefaultMixed(QubitDevice):
         probs = self.marginal_prob(self._diag(rho), wires)
 
         # take the real part so probabilities are not shown as complex numbers
-        return self._real(probs)
+        return self._abs(self._real(probs))
 
     def _get_kraus(self, operation):  # pylint: disable=no-self-use
         """Return the Kraus operators representing the operation.


Test patch:
diff --git a/tests/devices/test_default_mixed.py b/tests/devices/test_default_mixed.py
index 1fc43d484..33a684129 100644
--- a/tests/devices/test_default_mixed.py
+++ b/tests/devices/test_default_mixed.py
@@ -235,6 +235,15 @@ class TestAnalyticProb:
 
         assert dev.analytic_probability() is None
 
+    def test_probability_not_negative(self, nr_wires):
+        """Test that probabilities are always real"""
+        dev = qml.device("default.mixed", wires=nr_wires)
+        dev._state = np.zeros([2 ** nr_wires, 2 ** nr_wires])
+        dev._state[0, 0] = 1
+        dev._state[1, 1] = -5e-17
+
+        assert np.all(dev.analytic_probability() >= 0)
+
 
 class TestKrausOps:
     """Unit tests for the method `_get_kraus_ops()`"""