Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compute expectation value #4484

Merged
merged 48 commits into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
8c9868d
added expectation_value function
ludmilaasb Aug 14, 2023
16ba2df
Merge remote-tracking branch 'origin/master' into compute_expectation…
ludmilaasb Aug 14, 2023
1f5f7b0
added tests
ludmilaasb Aug 15, 2023
c27d6f0
Use local PRNG in `spsa_grad` (#4165)
frederikwilde Aug 15, 2023
0070333
Reverse factor 1/2 in transmon_interaction (#4478)
Qottmann Aug 15, 2023
89b6f5f
passing tests
ludmilaasb Aug 15, 2023
b15147c
Merge branch 'PennyLaneAI:master' into compute_expectation_value
ludmilaasb Aug 15, 2023
7777b4e
up
ludmilaasb Aug 15, 2023
69534d6
Merge branch 'compute_expectation_value' of github.com:ludmilaasb/pen…
ludmilaasb Aug 15, 2023
20746d4
small fix
ludmilaasb Aug 16, 2023
775ca0e
Apply suggestions from code review
ludmilaasb Aug 17, 2023
2e4a79d
Update pennylane/math/quantum.py
ludmilaasb Aug 17, 2023
ecdb5d4
Apply suggestions from code review
ludmilaasb Aug 17, 2023
cdcecc0
added more random states to test
ludmilaasb Aug 22, 2023
924a9aa
fix import
ludmilaasb Aug 23, 2023
4383aa4
changed test decorator
ludmilaasb Aug 23, 2023
4ce9666
up
ludmilaasb Aug 23, 2023
8e378f1
Merge branch 'master' into compute_expectation_value
ludmilaasb Sep 19, 2023
a68290e
Merge branch 'PennyLaneAI:master' into compute_expectation_value
ludmilaasb Jan 29, 2024
6ee3a32
changed examples and added more tests
ludmilaasb Jan 29, 2024
4d66ef9
Apply suggestions from code review
ludmilaasb Feb 5, 2024
2b4df2a
Merge branch 'PennyLaneAI:master' into compute_expectation_value
ludmilaasb Feb 5, 2024
f3a309c
updated changelog
ludmilaasb Feb 5, 2024
99d3f5a
added more tests
ludmilaasb Feb 6, 2024
eded14d
list to array fix
ludmilaasb Feb 7, 2024
8ada9dc
Merge branch 'master' into compute_expectation_value
ludmilaasb Feb 7, 2024
4613f1e
Merge branch 'PennyLaneAI:master' into compute_expectation_value
ludmilaasb Feb 8, 2024
65f53ca
Merge branch 'PennyLaneAI:master' into compute_expectation_value
ludmilaasb Feb 9, 2024
68ce1e7
added more tests
ludmilaasb Feb 9, 2024
72d89b3
tf einsum fix
ludmilaasb Feb 9, 2024
f99f67b
up
ludmilaasb Feb 9, 2024
03da70d
fixed allclose issue and torch tensor problem with type
ludmilaasb Feb 13, 2024
5d9c75e
small fix
ludmilaasb Feb 13, 2024
a452fa2
Merge branch 'master' into compute_expectation_value
ludmilaasb Feb 13, 2024
0689ebe
added more tests
ludmilaasb Feb 13, 2024
89c8d2e
fix hermitian test
ludmilaasb Feb 13, 2024
16e31b7
Merge branch 'master' into compute_expectation_value
astralcai May 9, 2024
ef8e2c9
Fix imports
astralcai May 9, 2024
643b382
Update changelog-dev.md
astralcai May 23, 2024
83c8b32
Merge branch 'master' into compute_expectation_value
astralcai May 23, 2024
68c7a25
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
astralcai Jun 14, 2024
22d8184
minor updates
astralcai Jun 14, 2024
21845fd
Merge branch 'master' into compute_expectation_value
astralcai Jun 14, 2024
c26e2eb
update test
astralcai Jun 14, 2024
0384e00
update docstring
astralcai Jun 17, 2024
0277aa6
Merge branch 'master' of https://github.com/PennyLaneAI/pennylane int…
astralcai Jun 17, 2024
d82ca50
apply suggestions from code review
astralcai Jun 17, 2024
3d2210c
Merge branch 'master' into compute_expectation_value
astralcai Jun 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@
[1 1 0]
```

* `expectation_value` was added to `qml.math` to calculate the expectation value of a matrix for pure states.
[(#4484)](https://github.com/PennyLaneAI/pennylane/pull/4484)

```pycon
>>> state_vector = [1/np.sqrt(2), 0, 1/np.sqrt(2), 0]
>>> operator_matrix = qml.matrix(qml.PauliZ(0), wire_order=[0,1])
>>> qml.math.expectation_value(operator_matrix, state_vector)
tensor(-2.23711432e-17+0.j, requires_grad=True)
```

* The `default.tensor` device is introduced to perform tensor network simulations of quantum circuits using the `mps` (Matrix Product State) method.
[(#5699)](https://github.com/PennyLaneAI/pennylane/pull/5699)

Expand Down Expand Up @@ -470,6 +480,7 @@ Tarun Kumar Allamsetty,
Guillermo Alonso-Linaje,
Utkarsh Azad,
Lillian M. A. Frederiksen,
Ludmila Botelho,
Gabriel Bottrill,
Astral Cai,
Ahmed Darwish,
Expand Down
2 changes: 2 additions & 0 deletions pennylane/math/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
from .quantum import (
cov_matrix,
dm_from_state_vector,
expectation_value,
ludmilaasb marked this conversation as resolved.
Show resolved Hide resolved
marginal_prob,
mutual_info,
partial_trace,
Expand Down Expand Up @@ -151,6 +152,7 @@ def __getattr__(name):
"dot",
"einsum",
"expand_matrix",
"expectation_value",
"eye",
"fidelity",
"fidelity_statevector",
Expand Down
144 changes: 135 additions & 9 deletions pennylane/math/quantum.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,10 @@ def reduce_statevector(state, indices, check_state=False, c_dtype="complex128"):
[ABC[i + 1] for i in sorted(indices)] + [ABC[num_wires + i + 1] for i in sorted(indices)]
)
density_matrix = einsum(
f"a{indices1},a{indices2}->a{target}", state, np.conj(state), optimize="greedy"
f"a{indices1},a{indices2}->a{target}",
state,
np.conj(state),
optimize="greedy",
)

# Return the reduced density matrix by using numpy tensor product
Expand Down Expand Up @@ -514,7 +517,10 @@ def dm_from_state_vector(state, check_state=False, c_dtype="complex128"):
"""
num_wires = int(np.log2(np.shape(state)[-1]))
return reduce_statevector(
state, indices=list(range(num_wires)), check_state=check_state, c_dtype=c_dtype
state,
indices=list(range(num_wires)),
check_state=check_state,
c_dtype=c_dtype,
)


Expand Down Expand Up @@ -663,7 +669,14 @@ def _compute_vn_entropy(density_matrix, base=None):


# pylint: disable=too-many-arguments
def mutual_info(state, indices0, indices1, base=None, check_state=False, c_dtype="complex128"):
def mutual_info(
state,
indices0,
indices1,
base=None,
check_state=False,
c_dtype="complex128",
):
r"""Compute the mutual information between two subsystems given a state:

.. math::
Expand Down Expand Up @@ -719,29 +732,139 @@ def mutual_info(state, indices0, indices1, base=None, check_state=False, c_dtype
raise ValueError("Subsystems for computing mutual information must not overlap.")

return _compute_mutual_info(
state, indices0, indices1, base=base, check_state=check_state, c_dtype=c_dtype
state,
indices0,
indices1,
base=base,
check_state=check_state,
c_dtype=c_dtype,
)


# pylint: disable=too-many-arguments
def _compute_mutual_info(
state, indices0, indices1, base=None, check_state=False, c_dtype="complex128"
state,
indices0,
indices1,
base=None,
check_state=False,
c_dtype="complex128",
):
"""Compute the mutual information between the subsystems."""
all_indices = sorted([*indices0, *indices1])
vn_entropy_1 = vn_entropy(
state, indices=indices0, base=base, check_state=check_state, c_dtype=c_dtype
state,
indices=indices0,
base=base,
check_state=check_state,
c_dtype=c_dtype,
)
vn_entropy_2 = vn_entropy(
state, indices=indices1, base=base, check_state=check_state, c_dtype=c_dtype
state,
indices=indices1,
base=base,
check_state=check_state,
c_dtype=c_dtype,
)
vn_entropy_12 = vn_entropy(
state, indices=all_indices, base=base, check_state=check_state, c_dtype=c_dtype
state,
indices=all_indices,
base=base,
check_state=check_state,
c_dtype=c_dtype,
)

return vn_entropy_1 + vn_entropy_2 - vn_entropy_12


def _check_hermitian_operator(operators):
"""Check the shape, and if the matrix is hermitian."""
dim = operators.shape[-1]

if (
len(operators.shape) not in (2, 3)
or operators.shape[-2] != dim
or not np.log2(dim).is_integer()
):
raise ValueError(
"Operator matrix must be of shape (2**wires,2**wires) "
"or (batch_dim, 2**wires, 2**wires)."
)

if len(operators.shape) == 2:
operators = qml.math.stack([operators])

if not is_abstract(operators):
for ops in operators:
conj_trans = np.transpose(np.conj(ops))
if not allclose(ops, conj_trans):
raise ValueError("The matrix is not Hermitian.")


def expectation_value(
operator_matrix, state_vector, check_state=False, check_operator=False, c_dtype="complex128"
):
r"""Compute the expectation value of an operator with respect to a pure state.

The expectation value is the probabilistic expected result of an experiment.
Given a pure state, i.e., a state which can be represented as a single
vector :math:`\ket{\psi}` in the Hilbert space, the expectation value of an
operator :math:`A` can computed as

.. math::
\langle A \rangle_\psi = \bra{\psi} A \ket{\psi}


Args:
operator_matrix (tensor_like): operator matrix with shape ``(2**N, 2**N)`` or ``(batch_dim, 2**N, 2**N)``.
state_vector (tensor_like): state vector with shape ``(2**N)`` or ``(batch_dim, 2**N)``.
check_state (bool): if True, the function will check the validity of the state vector
via its shape and the norm.
check_operator (bool): if True, the function will check the validity of the operator
via its shape and whether it is hermitian.
c_dtype (str): complex floating point precision type.

Returns:
float: Expectation value of the operator for the state vector.
ludmilaasb marked this conversation as resolved.
Show resolved Hide resolved

**Example**

The expectation value for any operator can obtained by passing their matrix representation as an argument.
For example, for a 2 qubit state, we can compute the expectation value of the operator :math:`Z \otimes I` as


>>> state_vector = [1/np.sqrt(2), 0, 1/np.sqrt(2), 0]
>>> operator_matrix = qml.matrix(qml.PauliZ(0), wire_order=[0,1])
>>> qml.math.expectation_value(operator_matrix, state_vector)
tensor(-2.23711432e-17+0.j, requires_grad=True)

.. seealso:: :func:`pennylane.math.fidelity`
dwierichs marked this conversation as resolved.
Show resolved Hide resolved

"""
state_vector = cast(state_vector, dtype=c_dtype)
operator_matrix = cast(operator_matrix, dtype=c_dtype)

if check_state:
_check_state_vector(state_vector)

if check_operator:
_check_hermitian_operator(operator_matrix)

if qml.math.shape(operator_matrix)[-1] != qml.math.shape(state_vector)[-1]:
raise qml.QuantumFunctionError(
"The operator and the state vector must have the same number of wires."
)

# The overlap <psi|A|psi>
expval = qml.math.einsum(
"...i,...i->...",
qml.math.conj(state_vector),
qml.math.einsum("...ji,...i->...j", operator_matrix, state_vector, optimize="greedy"),
optimize="greedy",
)
return expval


# pylint: disable=too-many-arguments
def vn_entanglement_entropy(
state, indices0, indices1, base=None, check_state=False, c_dtype="complex128"
Expand Down Expand Up @@ -884,7 +1007,10 @@ def _compute_relative_entropy(rho, sigma, base=None):
# the matrix of inner products between eigenvectors of rho and eigenvectors
# of sigma; this is a doubly stochastic matrix
rel = qml.math.einsum(
f"{indices_rho},{indices_sig}->{target}", np.conj(u_rho), u_sig, optimize="greedy"
f"{indices_rho},{indices_sig}->{target}",
np.conj(u_rho),
u_sig,
optimize="greedy",
)
rel = np.abs(rel) ** 2

Expand Down
Loading
Loading