Source code for ffsim.protocols.linear_operator_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.
"""Linear operator protocol."""
from __future__ import annotations
from typing import Any, Protocol
from scipy.sparse.linalg import LinearOperator
from ffsim.operators import FermionOperator
from ffsim.operators.fermion_operator import _fermion_operator_to_linear_operator
[docs]
class SupportsLinearOperator(Protocol):
"""An object that can be converted to a SciPy LinearOperator."""
[docs]
def _linear_operator_(
self, norb: int, nelec: int | tuple[int, int]
) -> LinearOperator:
"""Return a SciPy LinearOperator representing the object.
Args:
norb: The number of spatial orbitals.
nelec: The number of alpha and beta electrons.
Returns:
A Scipy LinearOperator representing the object.
"""
[docs]
def linear_operator(
obj: Any, norb: int, nelec: int | tuple[int, int]
) -> LinearOperator:
"""Return a SciPy LinearOperator representing the object.
Args:
obj: The object to convert to a LinearOperator.
norb: The number of spatial orbitals.
nelec: The number of alpha and beta electrons.
Returns:
A Scipy LinearOperator representing the object.
"""
if isinstance(obj, FermionOperator):
return _fermion_operator_to_linear_operator(obj, norb=norb, nelec=nelec)
method = getattr(obj, "_linear_operator_", None)
if method is not None:
return method(norb=norb, nelec=nelec)
raise TypeError(f"Object of type {type(obj)} has no _linear_operator_ method.")