Skip to content

Commit

Permalink
Fixes mitigate_depolarizing_noise to not raise a warning for `true_…
Browse files Browse the repository at this point in the history
…divide` (#1417)

* fix division issues that might arise with the split version of depolarizing noise mitigation

* Add test

* format

* update to raise error; test too

* formatting

* allow =<; error when non-specified method; add tests

* adjust checks; format

* adjust message; test

* adjust message; format

* test case for average; format

* Update pennylane/kernels/postprocessing.py

Co-authored-by: Johannes Jakob Meyer <46889760+johannesjmeyer@users.noreply.github.com>

* Update pennylane/kernels/postprocessing.py

* Update tests/kernels/test_kernels.py

Co-authored-by: Johannes Jakob Meyer <46889760+johannesjmeyer@users.noreply.github.com>
  • Loading branch information
antalszava and johannesjmeyer authored Jun 21, 2021
1 parent dbef6aa commit 88b1bc2
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 0 deletions.
27 changes: 27 additions & 0 deletions pennylane/kernels/postprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,27 +274,54 @@ def mitigate_depolarizing_noise(K, num_wires, method, use_entries=None):
if method == "single":
if use_entries is None:
use_entries = (0,)

if K[use_entries[0], use_entries[0]] <= (1 / dim):
raise ValueError(
"The single noise mitigation method cannot be applied "
"as the single diagonal element specified is too small."
)

diagonal_element = K[use_entries[0], use_entries[0]]
noise_rate = (1 - diagonal_element) * dim / (dim - 1)
mitigated_matrix = (K - noise_rate / dim) / (1 - noise_rate)

elif method == "average":

if use_entries is None:
diagonal_elements = np.diag(K)
else:
diagonal_elements = np.diag(K)[np.array(use_entries)]

if np.mean(diagonal_elements) <= 1 / dim:
raise ValueError(
"The average noise mitigation method cannot be applied "
"as the average of the used diagonal terms is too small."
)

noise_rates = (1 - diagonal_elements) * dim / (dim - 1)
mean_noise_rate = np.mean(noise_rates)
mitigated_matrix = (K - mean_noise_rate / dim) / (1 - mean_noise_rate)

elif method == "split_channel":
if np.any(np.diag(K) <= 1 / dim):
raise ValueError(
"The split channel noise mitigation method cannot be applied "
"to the input matrix as its diagonal terms are too small."
)

eff_noise_rates = np.clip((1 - np.diag(K)) * dim / (dim - 1), 0.0, 1.0)
noise_rates = 1 - np.sqrt(1 - eff_noise_rates)
inverse_noise = (
-np.outer(noise_rates, noise_rates)
+ noise_rates.reshape((1, len(K)))
+ noise_rates.reshape((len(K), 1))
)

mitigated_matrix = (K - inverse_noise / dim) / (1 - inverse_noise)
else:
raise ValueError(
"Incorrect noise depolarization mitigation method specified. "
"Accepted strategies are: 'single', 'average' and 'split_channel'."
)

return mitigated_matrix
88 changes: 88 additions & 0 deletions tests/kernels/test_kernels.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,3 +494,91 @@ def test_mitigate_depolarizing_noise_split_channel(self, input, expected_output)
noise rates per datapoint."""
output = kern.mitigate_depolarizing_noise(input, self.num_wires, "split_channel")
assert np.allclose(output, expected_output)


class TestErrorForNonRealistic:
"""Tests that the noise mitigation techniques raise an error whenever the
used quantities are too small."""

def test_mitigate_depolarizing_noise_wrong_method(self, recwarn):
"""Test that an error is raised when specifying an incorrect method."""
with pytest.raises(
ValueError, match="Incorrect noise depolarization mitigation method specified"
):
qml.kernels.mitigate_depolarizing_noise(np.array([0]), 4, method="some_dummy_strat")

def test_mitigate_depolarizing_noise_average_method_error(self, recwarn):
"""Test that an error is raised when using the average method for the
mitigation of depolarizing noise with a matrix that has too small diagonal
entries."""
num_wires = 6
wires = range(num_wires)

dev = qml.device("default.qubit", wires=num_wires)

@qml.qnode(dev)
def kernel_circuit(x1, x2):
qml.templates.AngleEmbedding(x1, wires=wires)
qml.adjoint(qml.templates.AngleEmbedding)(x2, wires=wires)
return qml.probs(wires)

kernel = lambda x1, x2: kernel_circuit(x1, x2)[0]

# "Training feature vectors"
X_train = qml.numpy.tensor(
[[0.73096199, 0.19012506, 0.57223395], [0.78126872, 0.53535039, 0.31160784]],
requires_grad=True,
)

# Create symmetric square kernel matrix (for training)
K = qml.kernels.square_kernel_matrix(X_train, kernel)

# Add some (symmetric) Gaussian noise to the kernel matrix.
N = qml.numpy.tensor(
[[-2.33010045, -2.22195441], [-0.40680862, 0.21785961]], requires_grad=True
)
K += (N + N.T) / 2
with pytest.raises(
ValueError, match="The average noise mitigation method cannot be applied"
):
qml.kernels.mitigate_depolarizing_noise(K, num_wires, method="average")

@pytest.mark.parametrize(
"msg, method", [("single", "single"), ("split channel", "split_channel")]
)
def test_mitigate_depolarizing_noise_error(self, msg, method):
"""Test that an error is raised for the mitigation of depolarizing
noise with a matrix that has too small specified entries for the
single and the split channel strategies."""
num_wires = 6
wires = range(num_wires)

dev = qml.device("default.qubit", wires=num_wires)

@qml.qnode(dev)
def kernel_circuit(x1, x2):
qml.templates.AngleEmbedding(x1, wires=wires)
qml.adjoint(qml.templates.AngleEmbedding)(x2, wires=wires)
return qml.probs(wires)

kernel = lambda x1, x2: kernel_circuit(x1, x2)[0]

# "Training feature vectors"
X_train = qml.numpy.tensor(
[[0.39375865, 0.50895605, 0.30720779], [0.34389837, 0.7043728, 0.40067889]],
requires_grad=True,
)

# Create symmetric square kernel matrix (for training)
K = qml.kernels.square_kernel_matrix(X_train, kernel)

# Add some (symmetric) Gaussian noise to the kernel matrix.
N = qml.numpy.tensor(
[[-1.15035284, 0.36726945], [0.26436627, -0.59287149]], requires_grad=True
)
K += (N + N.T) / 2

with pytest.raises(
ValueError, match=f"The {msg} noise mitigation method cannot be applied"
):
qml.kernels.mitigate_depolarizing_noise(K, num_wires, method=method)

0 comments on commit 88b1bc2

Please sign in to comment.