Skip to content

Commit

Permalink
Add VnEntanglementEntropyMP measurement process (#6270)
Browse files Browse the repository at this point in the history
**Context:**
With the qinfo deprecations in progress, it makes sense to have users
still be able to easily access the VN entanglement entropy.

**Description of the Change:**
Add a `VnEntanglementEntropyMP` and associated
`qml.vn_entanglement_entropy` function

**Benefits:**

**Possible Drawbacks:**

**Related GitHub Issues:**

---------

Co-authored-by: Isaac De Vlugt <isaacdevlugt@gmail.com>
Co-authored-by: Isaac De Vlugt <34751083+isaacdevlugt@users.noreply.github.com>
Co-authored-by: Astral Cai <astral.cai@xanadu.ai>
Co-authored-by: Ahmed Darwish <exclass9.24@gmail.com>
Co-authored-by: Cristian Emiliano Godinez Ramirez <57567043+EmilianoG-byte@users.noreply.github.com>
Co-authored-by: Ali Asadi <10773383+maliasadi@users.noreply.github.com>
Co-authored-by: albi3ro <chrissie.c.l@gmail.com>
Co-authored-by: Christina Lee <christina@xanadu.ai>
Co-authored-by: ringo-but-quantum <github-ringo-but-quantum@xanadu.ai>
Co-authored-by: David Wierichs <david.wierichs@xanadu.ai>
Co-authored-by: Thomas R. Bromley <49409390+trbromley@users.noreply.github.com>
Co-authored-by: Korbinian Kottmann <43949391+Qottmann@users.noreply.github.com>
Co-authored-by: Tonmoy Bhattacharya <ultraton_16@yahoo.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Vincent Michaud-Rioux <vincent.michaud-rioux@xanadu.ai>
Co-authored-by: Matthew Silverman <matthews@xanadu.ai>
Co-authored-by: Guillermo Alonso-Linaje <65235481+KetpuntoG@users.noreply.github.com>
Co-authored-by: Utkarsh <utkarshazad98@gmail.com>
Co-authored-by: soranjh <40344468+soranjh@users.noreply.github.com>
Co-authored-by: Romain Moyard <rmoyard@gmail.com>
Co-authored-by: Diksha Dhawan <40900030+ddhawan11@users.noreply.github.com>
Co-authored-by: soranjh <soran.jahangiri@gmail.com>
Co-authored-by: Jorge J. Martínez de Lejarza <61199780+gmlejarza@users.noreply.github.com>
Co-authored-by: anthayes92 <34694788+anthayes92@users.noreply.github.com>
Co-authored-by: Alex Preciado <alex.preciado@xanadu.ai>
Co-authored-by: Mikhail Andrenkov <mikhail@xanadu.ai>
Co-authored-by: Jack Brown <jack@xanadu.ai>
Co-authored-by: Austin Huang <65315367+austingmhuang@users.noreply.github.com>
Co-authored-by: Pietropaolo Frisoni <pietropaolo.frisoni@xanadu.ai>
Co-authored-by: Justin Pickering <79890410+justinpickering@users.noreply.github.com>
Co-authored-by: lillian542 <38584660+lillian542@users.noreply.github.com>
Co-authored-by: Will <wmaxwell90@gmail.com>
Co-authored-by: Josh Izaac <josh146@gmail.com>
Co-authored-by: Lee James O'Riordan <mlxd@users.noreply.github.com>
Co-authored-by: Pietropaolo Frisoni <pietropfrisoni@gmail.com>
  • Loading branch information
1 parent 8d8bece commit e6fe7ea
Show file tree
Hide file tree
Showing 16 changed files with 775 additions and 22 deletions.
4 changes: 4 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
# Release 0.39.0-dev (development release)

<h3>New features since last release</h3>

* A new `qml.vn_entanglement_entropy` measurement process has been added which measures the
Von Neumann entanglement entropy of a quantum state.
[(#5911)](https://github.com/PennyLaneAI/pennylane/pull/5911)

<h3>Improvements 🛠</h3>

Expand Down
7 changes: 4 additions & 3 deletions pennylane/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
state,
var,
vn_entropy,
vn_entanglement_entropy,
purity,
mutual_info,
classical_shadow,
Expand Down Expand Up @@ -183,23 +184,23 @@ def __getattr__(name):
if name == "QubitDevice":
warn(
"QubitDevice will no longer be accessible top level. Please access "
" the class as pennylane.devices.QubitDevice",
"the class as pennylane.devices.QubitDevice",
PennyLaneDeprecationWarning,
)
return pennylane.devices._qubit_device.QubitDevice # pylint:disable=protected-access

if name == "QutritDevice":
warn(
"QutritDevice will no longer be accessible top level. Please access "
" the class as pennylane.devices.QutritDevice",
"the class as pennylane.devices.QutritDevice",
PennyLaneDeprecationWarning,
)
return pennylane.devices._qutrit_device.QutritDevice # pylint:disable=protected-access

if name == "Device":
warn(
"Device will no longer be accessible top level. Please access "
" the class as pennylane.devices.LegacyDevice",
"the class as pennylane.devices.LegacyDevice",
PennyLaneDeprecationWarning,
)
return pennylane.devices._legacy_device.Device # pylint:disable=protected-access
Expand Down
59 changes: 57 additions & 2 deletions pennylane/devices/_qubit_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
StateMeasurement,
StateMP,
VarianceMP,
VnEntanglementEntropyMP,
VnEntropyMP,
)
from pennylane.operation import Operation, operation_derivative
Expand Down Expand Up @@ -718,6 +719,29 @@ def statistics(
)
result = self.vn_entropy(wires=obs.wires, log_base=obs.log_base)

elif isinstance(m, VnEntanglementEntropyMP):
if self.wires.labels != tuple(range(self.num_wires)):
raise qml.QuantumFunctionError(
"Returning the Von Neumann entanglement entropy is not supported when using custom wire labels"
)

if self._shot_vector is not None:
raise NotImplementedError(
"Returning the Von Neumann entanglement entropy is not supported with shot vectors."
)

if self.shots is not None:
warnings.warn(
"Requested Von Neumann entanglement entropy with finite shots; the returned "
"state information is analytic and is unaffected by sampling. To silence "
"this warning, set shots=None on the device.",
UserWarning,
)
wires0, wires1 = obs.raw_wires
result = self.vn_entanglement_entropy(
wires0=wires0, wires1=wires1, log_base=obs.log_base
)

elif isinstance(m, MutualInfoMP):
if self.wires.labels != tuple(range(self.num_wires)):
raise qml.QuantumFunctionError(
Expand Down Expand Up @@ -777,6 +801,7 @@ def statistics(
VarianceMP,
ProbabilityMP,
VnEntropyMP,
VnEntanglementEntropyMP,
MutualInfoMP,
ShadowExpvalMP,
),
Expand Down Expand Up @@ -1008,14 +1033,44 @@ def vn_entropy(self, wires, log_base):
"""
try:
state = self.density_matrix(wires=self.wires)
except qml.QuantumFunctionError as e: # pragma: no cover
except (qml.QuantumFunctionError, NotImplementedError) as e: # pragma: no cover
raise NotImplementedError(
f"Cannot compute the Von Neumman entropy with device {self.name} that is not capable of returning the "
f"state. "
) from e
wires = wires.tolist()
return qml.math.vn_entropy(state, indices=wires, c_dtype=self.C_DTYPE, base=log_base)

def vn_entanglement_entropy(self, wires0, wires1, log_base):
r"""Returns the Von Neumann entanglement entropy prior to measurement.
.. math::
S(\rho_A) = -\text{Tr}[\rho_A \log \rho_A] = -\text{Tr}[\rho_B \log \rho_B] = S(\rho_B)
Args:
wires0 (Sequence[int] or int): the wires of the first subsystem
wires1 (Sequence[int] or int): the wires of the second subsystem
log_base (float): Base for the logarithm.
Returns:
float: returns the Von Neumann entropy
"""
try:
state = self.density_matrix(wires=self.wires)
except (qml.QuantumFunctionError, NotImplementedError) as e: # pragma: no cover
raise NotImplementedError(
f"Cannot compute the Von Neumman entropy with device {self.name} that is not capable of returning the "
f"state. "
) from e

wires0 = wires0.tolist()
wires1 = wires1.tolist()

return qml.math.vn_entanglement_entropy(
state, indices0=wires0, indices1=wires1, c_dtype=self.C_DTYPE, base=log_base
)

def mutual_info(self, wires0, wires1, log_base):
r"""Returns the mutual information prior to measurement:
Expand All @@ -1035,7 +1090,7 @@ def mutual_info(self, wires0, wires1, log_base):
"""
try:
state = self.density_matrix(wires=self.wires)
except qml.QuantumFunctionError as e: # pragma: no cover
except (qml.QuantumFunctionError, NotImplementedError) as e: # pragma: no cover
raise NotImplementedError(
f"Cannot compute the mutual information with device {self.name} that is not capable of returning the "
f"state. "
Expand Down
22 changes: 22 additions & 0 deletions pennylane/devices/_qutrit_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,28 @@ def vn_entropy(self, wires, log_base):
"Unsupported return type specified for observable Von Neumann entropy"
)

def vn_entanglement_entropy(self, wires0, wires1, log_base):
r"""Returns the Von Neumann entanglement entropy prior to measurement.
.. math::
S(\rho_A) = -\text{Tr}[\rho_A \log \rho_A] = -\text{Tr}[\rho_B \log \rho_B] = S(\rho_B)
Args:
wires0 (Sequence[int] or int): the wires of the first subsystem
wires1 (Sequence[int] or int): the wires of the second subsystem
log_base (float): Base for the logarithm.
Returns:
float: returns the Von Neumann entropy
"""
# TODO: Add support for VnEntanglementEntropy return type. Currently, qml.math is hard coded to calculate this for qubit
# states (see `qml.math.vn_entanglement_entropy()`), so it needs to be updated before VnEntanglementEntropy can be supported for qutrits.
# For now, if a user tries to request this return type, an error will be raised.
raise qml.QuantumFunctionError(
"Unsupported return type specified for observable Von Neumann entanglement entropy"
)

def mutual_info(self, wires0, wires1, log_base):
r"""Returns the mutual information prior to measurement:
Expand Down
10 changes: 7 additions & 3 deletions pennylane/devices/default_mixed.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
SampleMP,
StateMP,
VarianceMP,
VnEntanglementEntropyMP,
VnEntropyMP,
)
from pennylane.operation import Channel
Expand Down Expand Up @@ -637,6 +638,9 @@ def _snapshot_measurements(self, density_matrix, measurement):
density_matrix, indices=map_wires, c_dtype=self.C_DTYPE, base=base
)

elif isinstance(measurement, VnEntanglementEntropyMP):
snap_result = measurement.process_density_matrix(density_matrix, wire_order=self.wires)

elif isinstance(measurement, MutualInfoMP):
base = measurement.log_base
wires0, wires1 = list(map(self.map_wires, measurement.raw_wires))
Expand Down Expand Up @@ -762,9 +766,9 @@ def execute(self, circuit, **kwargs):
# not specified or all wires specified.
self.measured_wires = self.wires
return super().execute(circuit, **kwargs)
if isinstance(m, (VnEntropyMP, MutualInfoMP)):
# VnEntropy, MutualInfo: Computed for the state
# prior to measurement. So, readout error need not be applied to the
if isinstance(m, (VnEntropyMP, VnEntanglementEntropyMP, MutualInfoMP)):
# VnEntropy, VnEntanglementEntropyMP, MutualInfo: Computed for the state
# prior to measurement. So, readout error need not be applied on the
# corresponding device wires.
continue
wires_list.append(m.wires)
Expand Down
2 changes: 2 additions & 0 deletions pennylane/measurements/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ def circuit(x):
StateMeasurement,
Variance,
VnEntropy,
VnEntanglementEntropy,
)
from .mid_measure import MeasurementValue, MidMeasureMP, measure, find_post_processed_mcms
from .mutual_info import MutualInfoMP, mutual_info
Expand All @@ -298,3 +299,4 @@ def circuit(x):
from .state import DensityMatrixMP, StateMP, density_matrix, state
from .var import VarianceMP, var
from .vn_entropy import VnEntropyMP, vn_entropy
from .vn_entanglement_entropy import VnEntanglementEntropyMP, vn_entanglement_entropy
4 changes: 4 additions & 0 deletions pennylane/measurements/measurements.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class ObservableReturnTypes(Enum):
State = "state"
MidMeasure = "measure"
VnEntropy = "vnentropy"
VnEntanglementEntropy = "vnentanglemententropy"
MutualInfo = "mutualinfo"
Shadow = "shadow"
ShadowExpval = "shadowexpval"
Expand Down Expand Up @@ -90,6 +91,9 @@ def __repr__(self):
VnEntropy = ObservableReturnTypes.VnEntropy
"""Enum: An enumeration which represents returning Von Neumann entropy before measurements."""

VnEntanglementEntropy = ObservableReturnTypes.VnEntanglementEntropy
"""Enum: An enumeration which represents returning Von Neumann entanglement entropy before measurements."""

MutualInfo = ObservableReturnTypes.MutualInfo
"""Enum: An enumeration which represents returning the mutual information before measurements."""

Expand Down
Loading

0 comments on commit e6fe7ea

Please sign in to comment.