Repository: netket/netket

Issue:
OverflowError when using random_state with Fock space
This produces an `OverflowError` on my system:
```python
import netket as nk

hi = nk.hilbert.Fock(N=1)
print(hi) # Fock(n_max=INT_MAX, N=1)

rng = nk.jax.PRNGSeq(0)
hi.random_state(next(seq))
```
```
OverflowError: Python int 9223372036854775808 too large to convert to int64
```

Note that `9223372036854775808` is `hi.n_max + 1` so it appears to be an off-by-one error somewhere.
OverflowError when using random_state with Fock space
This produces an `OverflowError` on my system:
```python
import netket as nk

hi = nk.hilbert.Fock(N=1)
print(hi) # Fock(n_max=INT_MAX, N=1)

rng = nk.jax.PRNGSeq(0)
hi.random_state(next(seq))
```
```
OverflowError: Python int 9223372036854775808 too large to convert to int64
```

Note that `9223372036854775808` is `hi.n_max + 1` so it appears to be an off-by-one error somewhere.


Discussion:
I was trying to fix this but then I realised that this does not play well with our samplers: we need to have integer samples otherwise this will break down...
as well as integer hi.random_state
I was trying to fix this but then I realised that this does not play well with our samplers: we need to have integer samples otherwise this will break down...
as well as integer hi.random_state

Resolving patch:
diff --git a/netket/hilbert/fock.py b/netket/hilbert/fock.py
--- a/netket/hilbert/fock.py
+++ b/netket/hilbert/fock.py
@@ -22,6 +22,13 @@
 from .homogeneous import HomogeneousHilbert
 from ._deprecations import graph_to_N_depwarn
 
+FOCK_MAX = np.iinfo(np.intp).max - 1
+"""
+Maximum number of particles in the fock space.
+It is `maxvalue(np.int64)-1` because we use N+1 in several formulas
+and it would overflow.
+"""
+
 
 @jit(nopython=True)
 def _sum_constraint(x, n_particles):
@@ -90,8 +97,7 @@ def constraints(x):
             # assert self._n_max > 0
             local_states = np.arange(self._n_max + 1)
         else:
-            max_ind = np.iinfo(np.intp).max
-            self._n_max = max_ind
+            self._n_max = FOCK_MAX
             local_states = None
 
         super().__init__(local_states, N, constraints)
@@ -152,7 +158,7 @@ def __repr__(self):
             if self._n_particles is not None
             else ""
         )
-        nmax = self._n_max if self._n_max < np.iinfo(np.intp).max else "INT_MAX"
+        nmax = self._n_max if self._n_max < FOCK_MAX else "FOCK_MAX"
         return "Fock(n_max={}{}, N={})".format(nmax, n_particles, self._size)
 
     @property


Test patch:
diff --git a/test/hilbert/test_hilbert.py b/test/hilbert/test_hilbert.py
--- a/test/hilbert/test_hilbert.py
+++ b/test/hilbert/test_hilbert.py
@@ -175,6 +175,13 @@ def test_random_states_homogeneous(hi: HomogeneousHilbert):
             assert state in local_states
 
 
+def test_random_states_fock_infinite():
+    hi = Fock(N=2)
+    rstate = hi.random_state(jax.random.PRNGKey(14), 20)
+    assert np.all(rstate >= 0)
+    assert rstate.shape == (20, 2)
+
+
 @pytest.mark.parametrize("hi", particle_hilbert_params)
 def test_random_states_particle(hi: Particle):
     assert hi.random_state(jax.random.PRNGKey(13)).shape == (hi.size,)
@@ -241,6 +248,33 @@ def test_flip_state_particle(hi: Particle):
         nk.hilbert.random.flip_state(hi, rng.next(), states, ids)
 
 
+def test_flip_state_fock_infinite():
+    hi = Fock(N=2)
+    rng = nk.jax.PRNGSeq(1)
+    N_batches = 20
+
+    states = hi.random_state(rng.next(), N_batches, dtype=jnp.int64)
+
+    ids = jnp.asarray(
+        jnp.floor(hi.size * jax.random.uniform(rng.next(), shape=(N_batches,))),
+        dtype=int,
+    )
+
+    new_states, old_vals = nk.hilbert.random.flip_state(hi, rng.next(), states, ids)
+
+    assert new_states.shape == states.shape
+
+    assert np.all(states >= 0)
+
+    states_np = np.asarray(states)
+    states_new_np = np.array(new_states)
+
+    for (row, col) in enumerate(ids):
+        states_new_np[row, col] = states_np[row, col]
+
+    np.testing.assert_allclose(states_np, states_new_np)
+
+
 @pytest.mark.parametrize("hi", discrete_hilbert_params)
 def test_hilbert_index_discrete(hi: DiscreteHilbert):
     log_max_states = np.log(nk.hilbert._abstract_hilbert.max_states)