Source code for qtealeaves.observables.overlap
# This code is part of qtealeaves.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""
Distance observable will measure the distance of the quantum system
to one or more pure states defined within this observable as filenames.
We measure the overlap and return a complex number <phi | psi>.
"""
import logging
from typing import TYPE_CHECKING, Any, Self
from qtealeaves.emulator import ATTN, MPS, TTN, StateVector
from qtealeaves.tooling import QTeaLeavesError
from .tnobase import _TNObsBase
if TYPE_CHECKING:
from qtealeaves.abstracttns.abstract_tn import _AbstractTN
else:
_AbstractTN = Any
__all__ = ["Overlap"]
logger = logging.getLogger(__name__)
[docs]
class Overlap(_TNObsBase):
"""
Distance observable will measure the distance of the quantum system
to one or more pure states defined within this observable as filenames.
We measure the overlap and return a complex number
:math:`\\rangle\\phi | \\psi\\langle`.
**Arguments**
name : str
Define a label under which we can find the observable in the
result dictionary.
path_to_state : str
Filename to the state. The default extension for formatted
Fortran TTNs is ``.ttn`` and for unformatted Fortran TTNs
is ``.ttnbin``. Other file extension might be added.
"""
# mypy triggered because of StateVector
_measurable_ansaetze = (MPS, TTN, ATTN, StateVector) # type: ignore[assignment]
def __init__(self, name: str, path_to_state: str):
super().__init__(name)
self.path_to_state = [path_to_state]
self.check_extension(path_to_state)
[docs]
@classmethod
def empty(cls) -> Self:
"""
Documentation see :func:`_TNObsBase.empty`.
"""
obj = cls("x", "x.ttn")
obj.name = []
obj.path_to_state = []
return obj
def __iadd__(self, other: Any) -> Self:
"""
Documentation see :func:`_TNObsBase.__iadd__`.
"""
if isinstance(other, Overlap):
self.name += other.name
self.path_to_state += other.path_to_state
else:
raise QTeaLeavesError(
f"__iadd__ not defined for types {type(self)} and {type(other)}."
)
return self
[docs]
def measure(
self,
state: _AbstractTN,
operators: Any = None,
**kwargs: Any,
) -> dict[str, Any]:
"""
Measure the overlap between the current state and self.path_to_state,
and save it in the results buffer. Both have to be pure states.
Args:
state : instance of class from :py:mod:`qtealeaves.emulator`
The state to measure the observable on.
operators : instance of :py:class:`qtealeaves.operators.TNOperators`
The operators to be measured. Not used for this observable, therefore set to None.
**kwargs : dict
Additional keyword arguments, see :func:`_TNObsBase.measure`.
"""
# we allow as before only the same ansatz
ansatz_cls = state.__class__
if len(self.name) == 0:
return self.results_buffer
if not self.check_measurable(ansatz_cls):
logger.warning("Observable %s not measurable for %s", self.name, str(state))
return self.results_buffer
for jj, name_jj in enumerate(self.name):
path_jj = self.path_to_state[jj]
psi_tn = ansatz_cls.read(path_jj, tensor_backend=state.tensor_backend)
self.results_buffer[name_jj] = state.dot(psi_tn) # type: ignore[attr-defined]
return self.results_buffer
[docs]
@classmethod
def check_extension(cls, path_to_state: str) -> None:
"""
Check that the file uses a valid file extension at least readable
by some simulation.
"""
if "." not in path_to_state:
raise QTeaLeavesError("No file extension detected.")
file_extension = path_to_state.split(".")[-1]
if not any(
ansatz.extension in file_extension for ansatz in cls._measurable_ansaetze
):
raise QTeaLeavesError(
f"Unknown extension for pure state: {file_extension}."
)