diff --git a/CHANGELOG.md b/CHANGELOG.md index cb1ef58e0..9aa374f9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,10 +13,15 @@ ### Bug fixes +* Renamed `QiskitDevice.probabilities` to `QiskitDevice.probability` to overload `pennylane.Device.probability`. This fixes a bug that raises `NotImplementedError` when a QNode is used to compute probabilities on a IBMQ device. + [(#80)](https://github.com/XanaduAI/pennylane-qiskit/pull/80) + ### Contributors This release contains contributions from (in alphabetical order): +Rafael Haenel + --- # Release 0.8.2 diff --git a/pennylane_qiskit/qiskit_device.py b/pennylane_qiskit/qiskit_device.py index fdbfc4925..c58deafb8 100644 --- a/pennylane_qiskit/qiskit_device.py +++ b/pennylane_qiskit/qiskit_device.py @@ -340,7 +340,7 @@ def expval(self, observable, wires, par): if self.backend_name in self._state_backends and self.analytic: # exact expectation value eigvals = self.eigvals(observable, wires, par) - prob = np.fromiter(self.probabilities(wires=wires).values(), dtype=np.float64) + prob = np.fromiter(self.probability(wires=wires).values(), dtype=np.float64) return (eigvals @ prob).real if self.analytic: @@ -354,7 +354,7 @@ def var(self, observable, wires, par): if self.backend_name in self._state_backends and self.analytic: # exact variance value eigvals = self.eigvals(observable, wires, par) - prob = np.fromiter(self.probabilities(wires=wires).values(), dtype=np.float64) + prob = np.fromiter(self.probability(wires=wires).values(), dtype=np.float64) return (eigvals ** 2) @ prob - (eigvals @ prob).real ** 2 if self.analytic: @@ -371,7 +371,7 @@ def sample(self, observable, wires, par): if self.backend_name in self._state_backends: # software simulator. Need to sample from probabilities. eigvals = self.eigvals(observable, wires, par) - prob = np.fromiter(self.probabilities(wires=wires).values(), dtype=np.float64) + prob = np.fromiter(self.probability(wires=wires).values(), dtype=np.float64) return np.random.choice(eigvals, self.shots, p=prob) # a hardware simulator @@ -385,7 +385,7 @@ def sample(self, observable, wires, par): else: # Need to convert counts into samples samples = np.vstack( - [np.vstack([s] * int(self.shots * p)) for s, p in self.probabilities().items()] + [np.vstack([s] * int(self.shots * p)) for s, p in self.probability().items()] ) if isinstance(observable, str) and observable in {"PauliX", "PauliY", "PauliZ", "Hadamard"}: @@ -405,7 +405,7 @@ def sample(self, observable, wires, par): def state(self): return self._state - def probabilities(self, wires=None): + def probability(self, wires=None): """Return the (marginal) probability of each computational basis state from the last run of the device. diff --git a/tests/test_apply.py b/tests/test_apply.py index 9e16f9a51..7262b9d5b 100644 --- a/tests/test_apply.py +++ b/tests/test_apply.py @@ -200,7 +200,7 @@ def test_qubit_state_vector(self, init_state, device, tol): dev._obs_queue = [] dev.pre_measure() - res = np.fromiter(dev.probabilities().values(), dtype=np.float64) + res = np.fromiter(dev.probability().values(), dtype=np.float64) expected = np.abs(state) ** 2 assert np.allclose(res, expected, **tol) @@ -224,7 +224,7 @@ def test_single_qubit_no_parameters(self, init_state, device, name, mat, tol): dev._obs_queue = [] dev.pre_measure() - res = np.fromiter(dev.probabilities().values(), dtype=np.float64) + res = np.fromiter(dev.probability().values(), dtype=np.float64) expected = np.abs(mat @ state) ** 2 assert np.allclose(res, expected, **tol) @@ -240,7 +240,7 @@ def test_single_qubit_parameters(self, init_state, device, name, func, theta, to dev._obs_queue = [] dev.pre_measure() - res = np.fromiter(dev.probabilities().values(), dtype=np.float64) + res = np.fromiter(dev.probability().values(), dtype=np.float64) expected = np.abs(func(theta) @ state) ** 2 assert np.allclose(res, expected, **tol) @@ -255,7 +255,7 @@ def test_two_qubit_no_parameters(self, init_state, device, name, mat, tol): dev._obs_queue = [] dev.pre_measure() - res = np.fromiter(dev.probabilities().values(), dtype=np.float64) + res = np.fromiter(dev.probability().values(), dtype=np.float64) expected = np.abs(mat @ state) ** 2 assert np.allclose(res, expected, **tol) @@ -270,7 +270,7 @@ def test_qubit_unitary(self, init_state, device, mat, tol): dev._obs_queue = [] dev.pre_measure() - res = np.fromiter(dev.probabilities().values(), dtype=np.float64) + res = np.fromiter(dev.probability().values(), dtype=np.float64) expected = np.abs(mat @ state) ** 2 assert np.allclose(res, expected, **tol) @@ -293,7 +293,7 @@ def test_three_qubit_no_parameters(self, init_state, device, name, mat, tol): dev._obs_queue = [] dev.pre_measure() - res = np.fromiter(dev.probabilities().values(), dtype=np.float64) + res = np.fromiter(dev.probability().values(), dtype=np.float64) expected = np.abs(mat @ state) ** 2 assert np.allclose(res, expected, **tol) @@ -309,6 +309,6 @@ def test_single_qubit_parameters(self, init_state, device, name, func, theta, to dev._obs_queue = [] dev.pre_measure() - res = np.fromiter(dev.probabilities().values(), dtype=np.float64) + res = np.fromiter(dev.probability().values(), dtype=np.float64) expected = np.abs(func(theta) @ state) ** 2 assert np.allclose(res, expected, **tol) diff --git a/tests/test_qiskit_device.py b/tests/test_qiskit_device.py index 15ca9186a..6cce2eb30 100644 --- a/tests/test_qiskit_device.py +++ b/tests/test_qiskit_device.py @@ -35,7 +35,7 @@ def test_probability_no_results(self): """Test that the probabilities function returns None if no job has yet been run.""" dev = AerDevice(backend="statevector_simulator", wires=1, analytic=True) - assert dev.probabilities() is None + assert dev.probability() is None class TestAnalyticWarningHWSimulator: