Repository: netket/netket

Issue:
Add identity to operator.spin/boson/fermion
Many people don-t realise that those are shorthands for `LocalOperator`so they use weird hacks to create the identity. Let's just add an identity operator in there.


Discussion:

Resolving patch:
diff --git a/netket/experimental/operator/fermion.py b/netket/experimental/operator/fermion.py
--- a/netket/experimental/operator/fermion.py
+++ b/netket/experimental/operator/fermion.py
@@ -19,13 +19,14 @@
 
 def destroy(hilbert: _AbstractHilbert, site: int, sz: int = None, dtype: _DType = None):
     """
-    Builds the fermion destruction operator :math:`\\hat{a}` acting on the `site`-th of
-    the Hilbert space `hilbert`.
+    Builds the fermion destruction operator :math:`\\hat{a}` acting
+    on the `site`-th of the Hilbert space `hilbert`.
 
     Args:
-        hilbert: The hilbert space
-        site (int): the site on which this operator acts
-        sz (int): spin projection quantum number (e.g. sz=-0.5 for a spin-1/2 down)
+        hilbert: The hilbert space.
+        site: the site on which this operator acts.
+        sz: spin projection quantum number (e.g. sz=-0.5 for a spin-1/2 down)
+        dtype: The datatype to use for the matrix elements.
 
     Returns:
         The resulting FermionOperator2nd
@@ -36,13 +37,14 @@ def destroy(hilbert: _AbstractHilbert, site: int, sz: int = None, dtype: _DType
 
 def create(hilbert: _AbstractHilbert, site: int, sz: int = None, dtype: _DType = None):
     """
-    Builds the fermion creation operator :math:`\\hat{a}^\\dagger` acting on the `site`-th of
-    the Hilbert space `hilbert`.
+    Builds the fermion creation operator :math:`\\hat{a}^\\dagger` acting
+    on the `site`-th of the Hilbert space `hilbert`.
 
     Args:
         hilbert: The hilbert space
-        site (int): the site on which this operator acts
-        sz (int): spin projection quantum number (e.g. sz=-0.5 for a spin-1/2 down)
+        site: the site on which this operator acts
+        sz: spin projection quantum number (e.g. sz=-0.5 for a spin-1/2 down)
+        dtype: The datatype to use for the matrix elements.
 
     Returns:
         The resulting FermionOperator2nd
@@ -59,8 +61,9 @@ def number(hilbert: _AbstractHilbert, site: int, sz: int = None, dtype: _DType =
     Args:
         hilbert: The hilbert space
         site: the site on which this operator acts
-        site (int): the site on which this operator acts
-        sz (int): spin projection quantum number (e.g. sz=-0.5 for a spin-1/2 fermion with spin down)
+        site: the site on which this operator acts
+        sz: spin projection quantum number (e.g. sz=-0.5 for a spin-1/2 fermion with spin down)
+        dtype: The datatype to use for the matrix elements.
 
     Returns:
         The resulting FermionOperator2nd
@@ -93,10 +96,29 @@ def _get_index(hilbert: _AbstractHilbert, site: int, sz: float = None):
 
 
 def identity(hilbert: _AbstractHilbert, dtype: _DType = None):
-    """identity operator"""
+    """
+    Builds the :math:`\\mathbb{I}` identity operator.
+
+    Args:
+        hilbert: The hilbert space.
+        dtype: The datatype to use for the matrix elements.
+
+    Returns:
+        An instance of {class}`nk.operator.LocalOperator`.
+    """
     return _FermionOperator2nd(hilbert, [], [], constant=1.0, dtype=dtype)
 
 
 def zero(hilbert: _AbstractHilbert, dtype: _DType = None):
-    """returns an object that has no contribution, meaning a constant of 0"""
+    """
+    Builds the :math:`0` operator, which has no connected components.
+
+    Why we provide this is a mistery, as you could just multiply by 0.
+
+    Args:
+        hilbert: The hilbert space.
+        dtype: The datatype to use for the matrix elements.
+
+    Returns:
+        An instance of {class}`nk.operator.LocalOperator`."""
     return _FermionOperator2nd(hilbert, [], [], constant=0.0, dtype=dtype)
diff --git a/netket/operator/boson.py b/netket/operator/boson.py
--- a/netket/operator/boson.py
+++ b/netket/operator/boson.py
@@ -16,13 +16,16 @@
 
 from netket.utils.types import DType as _DType
 
-from netket.hilbert import AbstractHilbert as _AbstractHilbert
+from netket.hilbert import DiscreteHilbert as _DiscreteHilbert
 
 from ._local_operator import LocalOperator as _LocalOperator
 
+# export identity from here as well
+from .spin import identity  # noqa: F401
+
 
 def destroy(
-    hilbert: _AbstractHilbert, site: int, dtype: _DType = float
+    hilbert: _DiscreteHilbert, site: int, dtype: _DType = None
 ) -> _LocalOperator:
     """
     Builds the boson destruction operator :math:`\\hat{a}` acting on the `site`-th of
@@ -32,11 +35,12 @@ def destroy(
     as a bosonic space of local dimension M.
 
     Args:
-        hilbert: The hilbert space
-        site: the site on which this operator acts
+        hilbert: The hilbert space.
+        site: The site on which this operator acts.
+        dtype: The datatype to use for the matrix elements.
 
     Returns:
-        The resulting Local Operator
+        An instance of {class}`nk.operator.LocalOperator`.
     """
     import numpy as np
 
@@ -49,7 +53,7 @@ def destroy(
 
 
 def create(
-    hilbert: _AbstractHilbert, site: int, dtype: _DType = float
+    hilbert: _DiscreteHilbert, site: int, dtype: _DType = float
 ) -> _LocalOperator:
     """
     Builds the boson creation operator :math:`\\hat{a}^\\dagger` acting on the `site`-th
@@ -59,11 +63,12 @@ def create(
     as a bosonic space of local dimension M.
 
     Args:
-        hilbert: The hilbert space
-        site: the site on which this operator acts
+        hilbert: The hilbert space.
+        site: The site on which this operator acts.
+        dtype: The datatype to use for the matrix elements.
 
     Returns:
-        The resulting Local Operator
+        An instance of {class}`nk.operator.LocalOperator`.
     """
     import numpy as np
 
@@ -76,7 +81,7 @@ def create(
 
 
 def number(
-    hilbert: _AbstractHilbert, site: int, dtype: _DType = float
+    hilbert: _DiscreteHilbert, site: int, dtype: _DType = float
 ) -> _LocalOperator:
     """
     Builds the number operator :math:`\\hat{a}^\\dagger\\hat{a}`  acting on the
@@ -86,11 +91,12 @@ def number(
     as a bosonic space of local dimension M.
 
     Args:
-        hilbert: The hilbert space
-        site: the site on which this operator acts
+        hilbert: The hilbert space.
+        site: The site on which this operator acts.
+        dtype: The datatype to use for the matrix elements.
 
     Returns:
-        The resulting Local Operator
+        An instance of {class}`nk.operator.LocalOperator`.
     """
     import numpy as np
 
@@ -103,7 +109,7 @@ def number(
 
 
 def proj(
-    hilbert: _AbstractHilbert, site: int, n: int, dtype: _DType = float
+    hilbert: _DiscreteHilbert, site: int, n: int, dtype: _DType = float
 ) -> _LocalOperator:
     """
     Builds the projector operator :math:`|n\\rangle\\langle n |` acting on the
@@ -114,12 +120,12 @@ def proj(
     as a bosonic space of local dimension M.
 
     Args:
-        hilbert: The hilbert space
-        site: the site on which this operator acts
-        n: the state on which to project
+        hilbert: The hilbert space.
+        site: The site on which this operator acts.
+        dtype: The datatype to use for the matrix elements.
 
     Returns:
-        the resulting operator
+        An instance of {class}`nk.operator.LocalOperator`.
     """
     import numpy as np
 
diff --git a/netket/operator/spin.py b/netket/operator/spin.py
--- a/netket/operator/spin.py
+++ b/netket/operator/spin.py
@@ -16,13 +16,27 @@
 
 from netket.utils.types import DType as _DType
 
-from netket.hilbert import AbstractHilbert as _AbstractHilbert
+from netket.hilbert import DiscreteHilbert as _DiscreteHilbert
 
 from ._local_operator import LocalOperator as _LocalOperator
 
 
+def identity(hilbert: _DiscreteHilbert, dtype: _DType = None) -> _LocalOperator:
+    """
+    Builds the :math:`\\mathbb{I}` identity operator.
+
+    Args:
+        hilbert: The hilbert space.
+        dtype: The datatype to use for the matrix elements.
+
+    Returns:
+        An instance of {class}`nk.operator.LocalOperator`.
+    """
+    return _LocalOperator(hilbert, constant=1.0, dtype=dtype)
+
+
 def sigmax(
-    hilbert: _AbstractHilbert, site: int, dtype: _DType = float
+    hilbert: _DiscreteHilbert, site: int, dtype: _DType = None
 ) -> _LocalOperator:
     """
     Builds the :math:`\\sigma^x` operator acting on the `site`-th of the Hilbert
@@ -31,9 +45,13 @@ def sigmax(
     If `hilbert` is a non-Spin space of local dimension M, it is considered
     as a (M-1)/2 - spin space.
 
-    :param hilbert: The hilbert space
-    :param site: the site on which this operator acts
-    :return: a nk.operator.LocalOperator
+    Args:
+        hilbert: The hilbert space.
+        site: The site on which this operator acts.
+        dtype: The datatype to use for the matrix elements.
+
+    Returns:
+        An instance of {class}`nk.operator.LocalOperator`.
     """
     import numpy as np
 
@@ -47,7 +65,7 @@ def sigmax(
 
 
 def sigmay(
-    hilbert: _AbstractHilbert, site: int, dtype: _DType = complex
+    hilbert: _DiscreteHilbert, site: int, dtype: _DType = None
 ) -> _LocalOperator:
     """
     Builds the :math:`\\sigma^y` operator acting on the `site`-th of the Hilbert
@@ -56,9 +74,13 @@ def sigmay(
     If `hilbert` is a non-Spin space of local dimension M, it is considered
     as a (M-1)/2 - spin space.
 
-    :param hilbert: The hilbert space
-    :param site: the site on which this operator acts
-    :return: a nk.operator.LocalOperator
+    Args:
+        hilbert: The hilbert space.
+        site: The site on which this operator acts.
+        dtype: The datatype to use for the matrix elements.
+
+    Returns:
+        An instance of {class}`nk.operator.LocalOperator`.
     """
     import numpy as np
     import netket.jax as nkjax
@@ -87,7 +109,7 @@ def sigmay(
 
 
 def sigmaz(
-    hilbert: _AbstractHilbert, site: int, dtype: _DType = float
+    hilbert: _DiscreteHilbert, site: int, dtype: _DType = None
 ) -> _LocalOperator:
     """
     Builds the :math:`\\sigma^z` operator acting on the `site`-th of the Hilbert
@@ -96,9 +118,13 @@ def sigmaz(
     If `hilbert` is a non-Spin space of local dimension M, it is considered
     as a (M-1)/2 - spin space.
 
-    :param hilbert: The hilbert space
-    :param site: the site on which this operator acts
-    :return: a nk.operator.LocalOperator
+    Args:
+        hilbert: The hilbert space.
+        site: The site on which this operator acts.
+        dtype: The datatype to use for the matrix elements.
+
+    Returns:
+        An instance of {class}`nk.operator.LocalOperator`.
     """
     import numpy as np
 
@@ -112,7 +138,7 @@ def sigmaz(
 
 
 def sigmam(
-    hilbert: _AbstractHilbert, site: int, dtype: _DType = float
+    hilbert: _DiscreteHilbert, site: int, dtype: _DType = None
 ) -> _LocalOperator:
     """
     Builds the :math:`\\sigma^{-} = \\frac{1}{2}(\\sigma^x - i \\sigma^y)` operator acting on the
@@ -121,9 +147,13 @@ def sigmam(
     If `hilbert` is a non-Spin space of local dimension M, it is considered
     as a (M-1)/2 - spin space.
 
-    :param hilbert: The hilbert space
-    :param site: the site on which this operator acts
-    :return: a nk.operator.LocalOperator
+    Args:
+        hilbert: The hilbert space.
+        site: The site on which this operator acts.
+        dtype: The datatype to use for the matrix elements.
+
+    Returns:
+        An instance of {class}`nk.operator.LocalOperator`.
     """
     import numpy as np
 
@@ -138,7 +168,7 @@ def sigmam(
 
 
 def sigmap(
-    hilbert: _AbstractHilbert, site: int, dtype: _DType = float
+    hilbert: _DiscreteHilbert, site: int, dtype: _DType = None
 ) -> _LocalOperator:
     """
     Builds the :math:`\\sigma^{+} = \\frac{1}{2}(\\sigma^x + i \\sigma^y)` operator acting on the
@@ -147,9 +177,13 @@ def sigmap(
     If `hilbert` is a non-Spin space of local dimension M, it is considered
     as a (M-1)/2 - spin space.
 
-    :param hilbert: The hilbert space
-    :param site: the site on which this operator acts
-    :return: a nk.operator.LocalOperator
+    Args:
+        hilbert: The hilbert space.
+        site: The site on which this operator acts.
+        dtype: The datatype to use for the matrix elements.
+
+    Returns:
+        An instance of {class}`nk.operator.LocalOperator`.
     """
     import numpy as np
 


Test patch: