Source code for ffsim.protocols.apply_unitary_protocol
# (C) Copyright IBM 2023.
#
# 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.
"""Apply unitary protocol."""
from __future__ import annotations
from typing import Any, Protocol
import numpy as np
[docs]
class SupportsApplyUnitary(Protocol):
"""An object that can apply a unitary transformation to a vector."""
[docs]
def _apply_unitary_(
self, vec: np.ndarray, norb: int, nelec: int | tuple[int, int], copy: bool
) -> np.ndarray:
"""Apply a unitary transformation to a vector.
Args:
vec: The vector to apply the unitary transformation to.
norb: The number of spatial orbitals.
nelec: Either a single integer representing the number of fermions for a
spinless system, or a pair of integers storing the numbers of spin alpha
and spin beta fermions.
copy: Whether to copy the vector before operating on it.
- If ``copy=True`` then this function always returns a newly allocated
vector and the original vector is left untouched.
- If ``copy=False`` then this function may still return a newly
allocated vector, but the original vector may have its data
overwritten. It is also possible that the original vector is
returned, modified in-place.
Returns:
The transformed vector.
"""
[docs]
def apply_unitary(
vec: np.ndarray,
obj: Any,
norb: int,
nelec: int | tuple[int, int],
copy: bool = True,
) -> np.ndarray:
"""Apply a unitary transformation to a vector.
Args:
vec: The vector to apply the unitary transformation to.
obj: The object with a unitary effect.
norb: The number of spatial orbitals.
nelec: Either a single integer representing the number of fermions for a
spinless system, or a pair of integers storing the numbers of spin alpha
and spin beta fermions.
copy: Whether to copy the vector before operating on it.
- If ``copy=True`` then this function always returns a newly allocated
vector and the original vector is left untouched.
- If ``copy=False`` then this function may still return a newly allocated
vector, but the original vector may have its data overwritten.
It is also possible that the original vector is returned,
modified in-place.
Returns:
The transformed vector.
"""
method = getattr(obj, "_apply_unitary_", None)
if method is not None:
result = method(vec, norb=norb, nelec=nelec, copy=copy)
if result is not NotImplemented:
return result
raise TypeError(
"ffsim.apply_unitary failed. "
"Object doesn't have a unitary effect.\n"
f"type: {type(obj)}\n"
f"object: {obj!r}\n"
"The object did not have an _apply_unitary_ method that returned "
"a value besides NotImplemented."
)