Skip to content

Commit

Permalink
Merge branch 'v0.16.0-rc0' of https://github.com/PennyLaneAI/pennylane
Browse files Browse the repository at this point in the history
…into v0.16.0-rc0
  • Loading branch information
Olivia Di Matteo committed Jun 21, 2021
2 parents 860ed97 + 88b1bc2 commit ffaa057
Show file tree
Hide file tree
Showing 29 changed files with 777 additions and 76 deletions.
22 changes: 18 additions & 4 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ random_mat2 = rng.standard_normal(3, requires_grad=False)
```

```pycon
>>> tape = tape.expand(depth=2)
>>> tape = tape.expand(depth=1)
>>> print(tape.draw(wire_order=Wires(all_wires)))
c0: ──────────────╭C──────────────────────╭C──────────┤
c1: ──────────────├C──────────────────────├C──────────┤
Expand Down Expand Up @@ -577,6 +577,19 @@ random_mat2 = rng.standard_normal(3, requires_grad=False)

<h3>Bug fixes</h3>

* Fixes a bug with `qml.math.cast` where the `MottonenStatePreparation` operation expected
a float type instead of double.
[(#1400)](https://github.com/XanaduAI/pennylane/pull/1400)

* Fixes a bug where a copy of `qml.ControlledQubitUnitary` was non-functional as it did not have all the necessary information.
[(#1411)](https://github.com/PennyLaneAI/pennylane/pull/1411)

* Warns when adjoint or reversible differentiation specified or called on a device with finite shots.
[(#1406)](https://github.com/PennyLaneAI/pennylane/pull/1406)

* Fixes the differentiability of the operations `IsingXX` and `IsingZZ` for Autograd, Jax and Tensorflow.
[(#1390)](https://github.com/PennyLaneAI/pennylane/pull/1390)

* Fixes a bug where multiple identical Hamiltonian terms will produce a
different result with ``optimize=True`` using ``ExpvalCost``.
[(#1405)](https://github.com/XanaduAI/pennylane/pull/1405)
Expand All @@ -586,7 +599,7 @@ random_mat2 = rng.standard_normal(3, requires_grad=False)
[(#1392)](https://github.com/XanaduAI/pennylane/pull/1392)

* Fixes floating point errors with `diff_method="finite-diff"` and `order=1` when parameters are `float32`.
[(#1381)](https://github.com/PennyLaneAI/pennylane/pull/1381)
[(#1381)](https://github.com/PennyLaneAI/pennylane/pull/1381)

* Fixes a bug where `qml.ctrl` would fail to transform gates that had no
control defined and no decomposition defined.
Expand Down Expand Up @@ -647,9 +660,10 @@ random_mat2 = rng.standard_normal(3, requires_grad=False)
This release contains contributions from (in alphabetical order):

Marius Aglitoiu, Vishnu Ajith, Thomas Bromley, Jack Ceroni, Alaric Cheng, Miruna Daian, Olivia Di Matteo,

Tanya Garg, Christian Gogolin, Diego Guala, Anthony Hayes, Ryan Hill, Josh Izaac, Pavan Jayasinha, Nathan Killoran,
Christina Lee, Ryan Levy, Nahum Sá, Maria Schuld, Johannes Jakob Meyer, Brian Shi, Antal Száva, David Wierichs,
Vincent Wong, Alberto Maldonado, Ashish Panigrahi.
Christina Lee, Ryan Levy, Johannes Jakob Meyer, Romain Moyard, Nahum Sá, Maria Schuld, Brian Shi, Antal Száva,
David Wierichs, Vincent Wong, Alberto Maldonado, Ashish Panigrahi.


# Release 0.15.1 (current release)
Expand Down
1 change: 1 addition & 0 deletions pennylane/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
qfunc_transform,
single_tape_transform,
quantum_monte_carlo,
apply_controlled_Q,
)
from pennylane.utils import inv
from pennylane.vqe import ExpvalCost, Hamiltonian, VQECost
Expand Down
7 changes: 7 additions & 0 deletions pennylane/_qubit_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,13 @@ def adjoint_jacobian(self, tape, starting_state=None, use_device_state=False):
if not hasattr(m.obs, "base_name"):
m.obs.base_name = None # This is needed for when the observable is a tensor product

if self.shots is not None:
warnings.warn(
"Requested adjoint differentiation to be computed with finite shots."
" The derivative is always exact when using the adjoint differentiation method.",
UserWarning,
)

# Initialization of state
if starting_state is not None:
ket = self._reshape(starting_state, [2] * self.num_wires)
Expand Down
4 changes: 2 additions & 2 deletions pennylane/circuit_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def _list_at_index_or_none(ls, idx):
return None


def is_returned_observable(op):
def _is_returned_observable(op):
"""Helper for the condition of having an observable or
measurement process in the return statement.
Expand Down Expand Up @@ -523,7 +523,7 @@ def greedy_layers(self, wire_order=None, show_all_wires=False):
observables[wire] = [None] * self.max_simultaneous_measurements

for op in self._grid[wire]:
if is_returned_observable(op):
if _is_returned_observable(op):
obs_idx = mp_map[op]
observables[wire][obs_idx] = op

Expand Down
39 changes: 39 additions & 0 deletions pennylane/devices/autograd_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

II = np.eye(4, dtype=C_DTYPE)
ZZ = np.array(kron(Z, Z), dtype=C_DTYPE)
XX = np.array(kron(X, X), dtype=C_DTYPE)

IX = np.array(kron(I, X), dtype=C_DTYPE)
IY = np.array(kron(I, Y), dtype=C_DTYPE)
Expand Down Expand Up @@ -182,6 +183,44 @@ def MultiRZ(theta, n):
return np.exp(-1j * theta / 2 * pauli_eigs(n))


def IsingXX(phi):
r"""Ising XX coupling gate
.. math:: XX(\phi) = \begin{bmatrix}
\cos(\phi / 2) & 0 & 0 & -i \sin(\phi / 2) \\
0 & \cos(\phi / 2) & -i \sin(\phi / 2) & 0 \\
0 & -i \sin(\phi / 2) & \cos(\phi / 2) & 0 \\
-i \sin(\phi / 2) & 0 & 0 & \cos(\phi / 2)
\end{bmatrix}.
Args:
phi (float): rotation angle :math:`\phi`
Returns:
array[complex]: unitary 4x4 rotation matrix
"""
return np.cos(phi / 2) * II - 1j * np.sin(phi / 2) * XX


def IsingZZ(phi):
r"""Ising ZZ coupling gate
.. math:: ZZ(\phi) = \begin{bmatrix}
e^{-i \phi / 2} & 0 & 0 & 0 \\
0 & e^{i \phi / 2} & 0 & 0 \\
0 & 0 & e^{i \phi / 2} & 0 \\
0 & 0 & 0 & e^{-i \phi / 2}
\end{bmatrix}.
Args:
phi (float): rotation angle :math:`\phi`
Returns:
array[complex]: unitary 4x4 rotation matrix
"""
e_m = np.exp(-1j * phi / 2)
e = np.exp(1j * phi / 2)
return np.array([[e_m, 0, 0, 0], [0, e, 0, 0], [0, 0, e, 0], [0, 0, 0, e_m]])


def SingleExcitation(phi):
r"""Single excitation rotation.
Expand Down
2 changes: 2 additions & 0 deletions pennylane/devices/default_qubit_autograd.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ class DefaultQubitAutograd(DefaultQubit):
"CRZ": autograd_ops.CRZ,
"CRot": autograd_ops.CRot,
"MultiRZ": autograd_ops.MultiRZ,
"IsingXX": autograd_ops.IsingXX,
"IsingZZ": autograd_ops.IsingZZ,
"SingleExcitation": autograd_ops.SingleExcitation,
"SingleExcitationPlus": autograd_ops.SingleExcitationPlus,
"SingleExcitationMinus": autograd_ops.SingleExcitationMinus,
Expand Down
2 changes: 2 additions & 0 deletions pennylane/devices/default_qubit_jax.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ def circuit():
"CRZ": jax_ops.CRZ,
"CRot": jax_ops.CRot,
"MultiRZ": jax_ops.MultiRZ,
"IsingXX": jax_ops.IsingXX,
"IsingZZ": jax_ops.IsingZZ,
"SingleExcitation": jax_ops.SingleExcitation,
"SingleExcitationPlus": jax_ops.SingleExcitationPlus,
"SingleExcitationMinus": jax_ops.SingleExcitationMinus,
Expand Down
2 changes: 2 additions & 0 deletions pennylane/devices/default_qubit_tf.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ class DefaultQubitTF(DefaultQubit):
"CRY": tf_ops.CRY,
"CRZ": tf_ops.CRZ,
"CRot": tf_ops.CRot,
"IsingXX": tf_ops.IsingXX,
"IsingZZ": tf_ops.IsingZZ,
"SingleExcitation": tf_ops.SingleExcitation,
"SingleExcitationPlus": tf_ops.SingleExcitationPlus,
"SingleExcitationMinus": tf_ops.SingleExcitationMinus,
Expand Down
39 changes: 39 additions & 0 deletions pennylane/devices/jax_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

II = jnp.eye(4, dtype=C_DTYPE)
ZZ = jnp.array(jnp.kron(Z, Z), dtype=C_DTYPE)
XX = jnp.array(jnp.kron(X, X), dtype=C_DTYPE)

IX = jnp.array(jnp.kron(I, X), dtype=C_DTYPE)
IY = jnp.array(jnp.kron(I, Y), dtype=C_DTYPE)
Expand Down Expand Up @@ -182,6 +183,44 @@ def MultiRZ(theta, n):
return jnp.exp(-1j * theta / 2 * pauli_eigs(n))


def IsingXX(phi):
r"""Ising XX coupling gate.
.. math:: XX(\phi) = \begin{bmatrix}
\cos(\phi / 2) & 0 & 0 & -i \sin(\phi / 2) \\
0 & \cos(\phi / 2) & -i \sin(\phi / 2) & 0 \\
0 & -i \sin(\phi / 2) & \cos(\phi / 2) & 0 \\
-i \sin(\phi / 2) & 0 & 0 & \cos(\phi / 2)
\end{bmatrix}.
Args:
phi (float): rotation angle :math:`\phi`
Returns:
array[complex]: unitary 4x4 rotation matrix
"""
return jnp.cos(phi / 2) * II - 1j * jnp.sin(phi / 2) * XX


def IsingZZ(phi):
r"""Ising ZZ coupling gate
.. math:: ZZ(\phi) = \begin{bmatrix}
e^{-i \phi / 2} & 0 & 0 & 0 \\
0 & e^{i \phi / 2} & 0 & 0 \\
0 & 0 & e^{i \phi / 2} & 0 \\
0 & 0 & 0 & e^{-i \phi / 2}
\end{bmatrix}.
Args:
phi (float): rotation angle :math:`\phi`
Returns:
array[complex]: unitary 4x4 rotation matrix
"""
e_m = jnp.exp(-1j * phi / 2)
e = jnp.exp(1j * phi / 2)
return jnp.array([[e_m, 0, 0, 0], [0, e, 0, 0], [0, 0, e, 0], [0, 0, 0, e_m]])


def SingleExcitation(phi):
r"""Single excitation rotation.
Expand Down
4 changes: 2 additions & 2 deletions pennylane/devices/tests/test_measurements.py
Original file line number Diff line number Diff line change
Expand Up @@ -816,8 +816,8 @@ def test_projector(self, device, tol, skip_if):

skip_if(dev, {"supports_tensor_observables": False})

theta = 0.432
phi = 0.123
theta = 1.432
phi = 1.123
varphi = -0.543

@qml.qnode(dev)
Expand Down
41 changes: 41 additions & 0 deletions pennylane/devices/tf_ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

II = tf.eye(4, dtype=C_DTYPE)
ZZ = tf.constant(kron(Z, Z), dtype=C_DTYPE)
XX = tf.constant(kron(X, X), dtype=C_DTYPE)

IX = tf.constant(kron(I, X), dtype=C_DTYPE)
IY = tf.constant(kron(I, Y), dtype=C_DTYPE)
Expand Down Expand Up @@ -193,6 +194,46 @@ def CRot(a, b, c):
return tf.linalg.diag(CRZ(c)) @ (CRY(b) @ tf.linalg.diag(CRZ(a)))


def IsingXX(phi):
r"""Ising XX coupling gate
.. math:: XX(\phi) = \begin{bmatrix}
\cos(\phi / 2) & 0 & 0 & -i \sin(\phi / 2) \\
0 & \cos(\phi / 2) & -i \sin(\phi / 2) & 0 \\
0 & -i \sin(\phi / 2) & \cos(\phi / 2) & 0 \\
-i \sin(\phi / 2) & 0 & 0 & \cos(\phi / 2)
\end{bmatrix}.
Args:
phi (float): rotation angle :math:`\phi`
Returns:
tf.Tensor[complex]: unitary 4x4 rotation matrix
"""
phi = tf.cast(phi, dtype=C_DTYPE)
return tf.cos(phi / 2) * II - 1j * tf.sin(phi / 2) * XX


def IsingZZ(phi):
r"""Ising ZZ coupling gate
.. math:: ZZ(\phi) = \begin{bmatrix}
e^{-i \phi / 2} & 0 & 0 & 0 \\
0 & e^{i \phi / 2} & 0 & 0 \\
0 & 0 & e^{i \phi / 2} & 0 \\
0 & 0 & 0 & e^{-i \phi / 2}
\end{bmatrix}.
Args:
phi (float): rotation :math:`\phi`
Returns:
tf.Tensor[complex]: unitary 4x4 rotation matrix
"""
phi = tf.cast(phi, dtype=C_DTYPE)
e_m = tf.exp(-1j * phi / 2)
e = tf.exp(1j * phi / 2)
return tf.convert_to_tensor([[e_m, 0, 0, 0], [0, e, 0, 0], [0, 0, e, 0], [0, 0, 0, e_m]])


def SingleExcitation(phi):
r"""Single excitation rotation.
Expand Down
6 changes: 3 additions & 3 deletions pennylane/fourier/coefficients.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ def coefficients(f, n_inputs, degree, lowpass_filter=False, filter_threshold=Non
@qml.qnode(dev)
def circuit(weights, inpt):
qml.RX(inpt[0], wires='a')
qml.Rot(0.1, 0.2, 0.3, wires='a')
qml.Rot(*weights[0], wires='a')
qml.RY(inpt[1], wires='a')
qml.Rot(-4.1, 3.2, 1.3, wires='a')
qml.Rot(*weights[1], wires='a')
return qml.expval(qml.PauliZ(wires='a'))
Expand All @@ -94,7 +94,7 @@ def circuit(weights, inpt):
``weights``:
>>> from functools import partial
>>> weights = np.array([0.5, 0.2])
>>> weights = np.array([[0.1, 0.2, 0.3], [-4.1, 3.2, 1.3]])
>>> partial_circuit = partial(circuit, weights)
Now we must specify the number of inputs, and the maximum desired
Expand Down
29 changes: 28 additions & 1 deletion pennylane/kernels/postprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,34 +267,61 @@ def mitigate_depolarizing_noise(K, num_wires, method, use_entries=None):
**Example:**
For an example usage of ``mitigate_depolarizing_noise`` please refer to the
`PennyLane demo on the kernel module <https://github.com/PennyLaneAI/qml/tree/master/demonstrations/tutorial_kernel_module.py>`_ or `the postprocessing demo for arXiv:2105.02276 <https://github.com/thubregtsen/qhack/blob/master/paper/post_processing_demo.py>`_.
`PennyLane demo on the kernel module <https://github.com/PennyLaneAI/qml/tree/master/demonstrations/tutorial_kernel_based_training.py>`_ or `the postprocessing demo for arXiv:2105.02276 <https://github.com/thubregtsen/qhack/blob/master/paper/post_processing_demo.py>`_.
"""
dim = 2 ** num_wires

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
Loading

0 comments on commit ffaa057

Please sign in to comment.