quantax 0.2.1__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {quantax-0.2.1/quantax.egg-info → quantax-0.3.0}/PKG-INFO +13 -7
- {quantax-0.2.1 → quantax-0.3.0}/README.md +14 -2
- {quantax-0.2.1 → quantax-0.3.0}/pyproject.toml +23 -7
- {quantax-0.2.1 → quantax-0.3.0}/quantax/__init__.py +7 -0
- {quantax-0.2.1 → quantax-0.3.0}/quantax/global_defs.py +14 -13
- {quantax-0.2.1 → quantax-0.3.0}/quantax/model/__init__.py +1 -2
- {quantax-0.2.1 → quantax-0.3.0}/quantax/model/backflow.py +120 -43
- {quantax-0.2.1 → quantax-0.3.0}/quantax/model/conv_nets.py +162 -129
- {quantax-0.2.1 → quantax-0.3.0}/quantax/model/fermion_mf.py +259 -135
- quantax-0.3.0/quantax/model/jastrow.py +363 -0
- quantax-0.3.0/quantax/model/shallow_nets.py +183 -0
- quantax-0.3.0/quantax/model/triangular_nets.py +253 -0
- {quantax-0.2.1 → quantax-0.3.0}/quantax/nn/__init__.py +2 -1
- {quantax-0.2.1 → quantax-0.3.0}/quantax/nn/activation.py +17 -14
- {quantax-0.2.1 → quantax-0.3.0}/quantax/nn/conv.py +81 -28
- quantax-0.3.0/quantax/nn/embedding.py +96 -0
- {quantax-0.2.1 → quantax-0.3.0}/quantax/nn/fermion.py +23 -24
- {quantax-0.2.1 → quantax-0.3.0}/quantax/nn/initializers.py +44 -26
- quantax-0.3.0/quantax/nn/modules.py +172 -0
- quantax-0.3.0/quantax/nn/sign.py +100 -0
- {quantax-0.2.1 → quantax-0.3.0}/quantax/operator/__init__.py +2 -1
- {quantax-0.2.1 → quantax-0.3.0}/quantax/operator/common_operators.py +48 -41
- quantax-0.3.0/quantax/operator/operator.py +819 -0
- {quantax-0.2.1 → quantax-0.3.0}/quantax/operator/site_operator.py +105 -8
- quantax-0.3.0/quantax/operator/update_mode_filters.py +51 -0
- quantax-0.3.0/quantax/optimizer/__init__.py +21 -0
- quantax-0.3.0/quantax/optimizer/gradient.py +149 -0
- quantax-0.3.0/quantax/optimizer/qngd.py +337 -0
- quantax-0.3.0/quantax/optimizer/solver.py +798 -0
- quantax-0.3.0/quantax/optimizer/sr.py +234 -0
- quantax-0.3.0/quantax/optimizer/supervised.py +124 -0
- {quantax-0.2.1 → quantax-0.3.0}/quantax/optimizer/time_evol.py +57 -26
- quantax-0.3.0/quantax/optimizer/updater.py +197 -0
- {quantax-0.2.1 → quantax-0.3.0}/quantax/sampler/common_samplers.py +47 -49
- {quantax-0.2.1 → quantax-0.3.0}/quantax/sampler/metropolis.py +213 -115
- {quantax-0.2.1 → quantax-0.3.0}/quantax/sampler/sampler.py +9 -8
- {quantax-0.2.1 → quantax-0.3.0}/quantax/sampler/samples.py +15 -12
- {quantax-0.2.1 → quantax-0.3.0}/quantax/sites/__init__.py +0 -2
- quantax-0.3.0/quantax/sites/common_lattices.py +168 -0
- {quantax-0.2.1 → quantax-0.3.0}/quantax/sites/lattice.py +116 -95
- {quantax-0.2.1 → quantax-0.3.0}/quantax/sites/sites.py +99 -56
- {quantax-0.2.1 → quantax-0.3.0}/quantax/state/__init__.py +0 -1
- {quantax-0.2.1 → quantax-0.3.0}/quantax/state/fermion_mf.py +139 -130
- {quantax-0.2.1 → quantax-0.3.0}/quantax/state/state.py +129 -37
- {quantax-0.2.1 → quantax-0.3.0}/quantax/state/variational.py +260 -195
- {quantax-0.2.1 → quantax-0.3.0}/quantax/symmetry/common_symmetries.py +29 -25
- {quantax-0.2.1 → quantax-0.3.0}/quantax/symmetry/symmetry.py +64 -22
- {quantax-0.2.1 → quantax-0.3.0}/quantax/symmetry/translation.py +13 -6
- {quantax-0.2.1 → quantax-0.3.0}/quantax/utils/__init__.py +9 -8
- quantax-0.3.0/quantax/utils/array.py +167 -0
- {quantax-0.2.1 → quantax-0.3.0}/quantax/utils/basis.py +17 -14
- {quantax-0.2.1 → quantax-0.3.0}/quantax/utils/big_array.py +230 -170
- {quantax-0.2.1 → quantax-0.3.0}/quantax/utils/data.py +50 -38
- quantax-0.3.0/quantax/utils/function.py +267 -0
- quantax-0.3.0/quantax/utils/sharding.py +73 -0
- {quantax-0.2.1 → quantax-0.3.0}/quantax/utils/tree.py +4 -48
- {quantax-0.2.1 → quantax-0.3.0/quantax.egg-info}/PKG-INFO +13 -7
- {quantax-0.2.1 → quantax-0.3.0}/quantax.egg-info/SOURCES.txt +5 -5
- quantax-0.3.0/quantax.egg-info/requires.txt +21 -0
- quantax-0.2.1/docs/source/conf.py +0 -51
- quantax-0.2.1/quantax/model/jastrow.py +0 -197
- quantax-0.2.1/quantax/model/shallow_nets.py +0 -190
- quantax-0.2.1/quantax/model/transformer.py +0 -156
- quantax-0.2.1/quantax/model/triangular_nets.py +0 -196
- quantax-0.2.1/quantax/nn/modules.py +0 -132
- quantax-0.2.1/quantax/nn/sign.py +0 -74
- quantax-0.2.1/quantax/operator/operator.py +0 -595
- quantax-0.2.1/quantax/optimizer/__init__.py +0 -18
- quantax-0.2.1/quantax/optimizer/driver.py +0 -102
- quantax-0.2.1/quantax/optimizer/solver.py +0 -302
- quantax-0.2.1/quantax/optimizer/sr.py +0 -513
- quantax-0.2.1/quantax/optimizer/supervised.py +0 -78
- quantax-0.2.1/quantax/sites/cluster.py +0 -74
- quantax-0.2.1/quantax/sites/common_lattices.py +0 -138
- quantax-0.2.1/quantax/state/lanczos.py +0 -52
- quantax-0.2.1/quantax/utils/array.py +0 -152
- quantax-0.2.1/quantax/utils/function.py +0 -245
- quantax-0.2.1/quantax/utils/sharding.py +0 -22
- quantax-0.2.1/quantax.egg-info/requires.txt +0 -14
- {quantax-0.2.1 → quantax-0.3.0}/LICENSE +0 -0
- {quantax-0.2.1 → quantax-0.3.0}/quantax/sampler/__init__.py +0 -0
- {quantax-0.2.1 → quantax-0.3.0}/quantax/symmetry/__init__.py +0 -0
- {quantax-0.2.1 → quantax-0.3.0}/quantax.egg-info/dependency_links.txt +0 -0
- {quantax-0.2.1 → quantax-0.3.0}/quantax.egg-info/top_level.txt +0 -0
- {quantax-0.2.1 → quantax-0.3.0}/setup.cfg +0 -0
|
@@ -1,22 +1,28 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: quantax
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Flexible neural quantum states based on JAX
|
|
5
5
|
Author: Christopher Roth
|
|
6
6
|
Author-email: Ao Chen <chenao.phys@gmail.com>
|
|
7
|
-
Requires-Python:
|
|
7
|
+
Requires-Python: <3.14,>=3.11
|
|
8
8
|
License-File: LICENSE
|
|
9
|
-
Requires-Dist: numpy>=
|
|
10
|
-
Requires-Dist: scipy>=1.
|
|
11
|
-
Requires-Dist: jax>=0.
|
|
9
|
+
Requires-Dist: numpy>=2.0.0
|
|
10
|
+
Requires-Dist: scipy>=1.14.0
|
|
11
|
+
Requires-Dist: jax>=0.8.0
|
|
12
12
|
Requires-Dist: equinox>=0.11.4
|
|
13
13
|
Requires-Dist: lrux>=0.1.0
|
|
14
14
|
Provides-Extra: full
|
|
15
15
|
Requires-Dist: numpy>=2.0.0; extra == "full"
|
|
16
|
-
Requires-Dist: scipy>=1.
|
|
16
|
+
Requires-Dist: scipy>=1.14.0; extra == "full"
|
|
17
17
|
Requires-Dist: matplotlib>=3.8.0; extra == "full"
|
|
18
18
|
Requires-Dist: quspin>=1.0.0; extra == "full"
|
|
19
|
-
Requires-Dist: jax>=0.
|
|
19
|
+
Requires-Dist: jax>=0.8.0; extra == "full"
|
|
20
20
|
Requires-Dist: equinox>=0.11.4; extra == "full"
|
|
21
|
+
Requires-Dist: lineax>=0.1.0; extra == "full"
|
|
21
22
|
Requires-Dist: lrux>=0.1.0; extra == "full"
|
|
23
|
+
Requires-Dist: jaxmg>=0.0.6; extra == "full"
|
|
24
|
+
Provides-Extra: docs
|
|
25
|
+
Requires-Dist: sphinx; extra == "docs"
|
|
26
|
+
Requires-Dist: myst-nb; extra == "docs"
|
|
27
|
+
Requires-Dist: pydata-sphinx-theme; extra == "docs"
|
|
22
28
|
Dynamic: license-file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<h1 align='center'>Quantax</h1>
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
|
-
<strong>Flexible and scalable neural quantum states
|
|
4
|
+
<strong>Flexible and scalable neural quantum states in JAX</strong>
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
@@ -22,7 +22,7 @@ Quantax is a research-oriented Python package for quantum many-body physics, wit
|
|
|
22
22
|
|
|
23
23
|
## ⚙️Installation
|
|
24
24
|
|
|
25
|
-
Requires Python 3.
|
|
25
|
+
Requires Python 3.11+, JAX 0.8.0+
|
|
26
26
|
|
|
27
27
|
First, ensure that a correct JAX version is installed. For details, check [JAX Installation](https://docs.jax.dev/en/latest/installation.html).
|
|
28
28
|
|
|
@@ -75,3 +75,15 @@ energy_data.plot(baseline=E)
|
|
|
75
75
|
plt.show()
|
|
76
76
|
```
|
|
77
77
|

|
|
78
|
+
|
|
79
|
+
## 📚Citation
|
|
80
|
+
|
|
81
|
+
```bibtex
|
|
82
|
+
@software{quantax,
|
|
83
|
+
author = {Chen, Ao and Roth, Christopher},
|
|
84
|
+
title = {Quantax: Flexible neural quantum states in JAX},
|
|
85
|
+
year = {2024},
|
|
86
|
+
url = {https://github.com/ChenAo-Phys/quantax},
|
|
87
|
+
version = {0.3.0}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
@@ -4,17 +4,17 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "quantax"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.0"
|
|
8
8
|
description = "Flexible neural quantum states based on JAX"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Ao Chen", email = "chenao.phys@gmail.com" },
|
|
11
11
|
{ name = "Christopher Roth" }
|
|
12
12
|
]
|
|
13
|
-
requires-python = ">=3.
|
|
13
|
+
requires-python = ">=3.11,<3.14"
|
|
14
14
|
dependencies = [
|
|
15
|
-
"numpy>=
|
|
16
|
-
"scipy>=1.
|
|
17
|
-
"jax>=0.
|
|
15
|
+
"numpy>=2.0.0",
|
|
16
|
+
"scipy>=1.14.0",
|
|
17
|
+
"jax>=0.8.0",
|
|
18
18
|
"equinox>=0.11.4",
|
|
19
19
|
"lrux>=0.1.0",
|
|
20
20
|
]
|
|
@@ -22,14 +22,30 @@ dependencies = [
|
|
|
22
22
|
[project.optional-dependencies]
|
|
23
23
|
full = [
|
|
24
24
|
"numpy>=2.0.0",
|
|
25
|
-
"scipy>=1.
|
|
25
|
+
"scipy>=1.14.0",
|
|
26
26
|
"matplotlib>=3.8.0",
|
|
27
27
|
"quspin>=1.0.0",
|
|
28
|
-
"jax>=0.
|
|
28
|
+
"jax>=0.8.0",
|
|
29
29
|
"equinox>=0.11.4",
|
|
30
|
+
"lineax>=0.1.0",
|
|
30
31
|
"lrux>=0.1.0",
|
|
32
|
+
"jaxmg>=0.0.6",
|
|
33
|
+
]
|
|
34
|
+
docs = [
|
|
35
|
+
"sphinx",
|
|
36
|
+
"myst-nb",
|
|
37
|
+
"pydata-sphinx-theme",
|
|
31
38
|
]
|
|
32
39
|
|
|
33
40
|
[tool.setuptools.packages.find]
|
|
34
41
|
where = ["."]
|
|
35
42
|
include = ["quantax*"]
|
|
43
|
+
|
|
44
|
+
[tool.black]
|
|
45
|
+
target-version = ["py311", "py312", "py313"]
|
|
46
|
+
|
|
47
|
+
[tool.pyright]
|
|
48
|
+
include = ["quantax"]
|
|
49
|
+
pythonVersion = "3.12"
|
|
50
|
+
typeCheckingMode = "standard"
|
|
51
|
+
|
|
@@ -1,31 +1,32 @@
|
|
|
1
|
-
from typing import Optional, Tuple
|
|
2
1
|
from functools import partial
|
|
3
2
|
from enum import Enum
|
|
4
3
|
import jax
|
|
5
4
|
import jax.numpy as jnp
|
|
6
5
|
import jax.random as jr
|
|
6
|
+
from jax.typing import DTypeLike
|
|
7
7
|
|
|
8
|
+
DTYPE = jnp.dtype(jnp.float32)
|
|
8
9
|
|
|
9
|
-
jax.config.update("jax_enable_x64", True)
|
|
10
|
-
jax.config.update("jax_default_matmul_precision", "float32")
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
DTYPE = jnp.float64
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def set_default_dtype(dtype: jnp.dtype) -> None:
|
|
11
|
+
def set_default_dtype(dtype: DTypeLike) -> None:
|
|
17
12
|
"""
|
|
18
13
|
Set the default data type in Quantax.
|
|
19
|
-
Recommended to be ``jnp.
|
|
14
|
+
Recommended to be ``jnp.float32`` or ``jnp.complex64``. Default to ``jnp.float32``.
|
|
20
15
|
|
|
21
16
|
.. note::
|
|
22
17
|
This doesn't alter the computation inside ``quantax.model``.
|
|
23
18
|
"""
|
|
19
|
+
dtype = jnp.dtype(dtype)
|
|
20
|
+
|
|
24
21
|
if not (
|
|
25
22
|
jnp.issubdtype(dtype, jnp.floating)
|
|
26
23
|
or jnp.issubdtype(dtype, jnp.complexfloating)
|
|
27
24
|
):
|
|
28
25
|
raise ValueError("'dtype' should be float or complex types")
|
|
26
|
+
|
|
27
|
+
if dtype == jnp.float64 or dtype == jnp.complex128:
|
|
28
|
+
jax.config.update("jax_enable_x64", True)
|
|
29
|
+
|
|
29
30
|
global DTYPE
|
|
30
31
|
DTYPE = dtype
|
|
31
32
|
|
|
@@ -58,13 +59,13 @@ def set_random_seed(seed: int) -> None:
|
|
|
58
59
|
global KEY
|
|
59
60
|
KEY = jr.key(seed)
|
|
60
61
|
|
|
61
|
-
from .utils import
|
|
62
|
+
from .utils import local_to_replicated
|
|
62
63
|
|
|
63
|
-
KEY =
|
|
64
|
+
KEY = local_to_replicated(KEY)
|
|
64
65
|
|
|
65
66
|
|
|
66
67
|
@partial(jax.jit, static_argnums=1)
|
|
67
|
-
def _gen_keys(key, num:
|
|
68
|
+
def _gen_keys(key, num: int | None = None) -> tuple[jax.Array, jax.Array]:
|
|
68
69
|
nkeys = 2 if num is None else num + 1
|
|
69
70
|
new_keys = jr.split(key, nkeys)
|
|
70
71
|
key = new_keys[0]
|
|
@@ -72,7 +73,7 @@ def _gen_keys(key, num: Optional[int] = None) -> Tuple[jax.Array, jax.Array]:
|
|
|
72
73
|
return key, new_keys
|
|
73
74
|
|
|
74
75
|
|
|
75
|
-
def get_subkeys(num:
|
|
76
|
+
def get_subkeys(num: int | None = None) -> jax.Array:
|
|
76
77
|
"""
|
|
77
78
|
Get jax keys stored in Quantax. The keys are replicated across all devices.
|
|
78
79
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import Any, Callable, overload, Literal
|
|
2
2
|
import jax
|
|
3
3
|
import jax.numpy as jnp
|
|
4
4
|
import jax.random as jr
|
|
5
|
-
|
|
5
|
+
from jax.typing import DTypeLike
|
|
6
6
|
import lrux
|
|
7
7
|
from .fermion_mf import GeneralDet, MF_Internal, _init_spinless_orbs
|
|
8
8
|
from ..global_defs import get_sites, get_subkeys
|
|
@@ -18,23 +18,23 @@ from ..utils import LogArray
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class DetBackflow(RefModel):
|
|
21
|
-
net: eqx.Module
|
|
22
|
-
U0: jax.Array
|
|
23
|
-
W: jax.Array
|
|
24
|
-
dtype: jnp.dtype
|
|
25
|
-
|
|
26
21
|
r"""
|
|
27
22
|
Determinant backflow model.
|
|
28
23
|
:math:`\psi(n) = \mathrm{det}(n \star (U_0 + U_1(n)))`,
|
|
29
24
|
where :math:`\star` denotes the operation slicing the rows of the matrix.
|
|
30
25
|
"""
|
|
31
26
|
|
|
27
|
+
net: Callable[[jax.Array], jax.Array]
|
|
28
|
+
U0: jax.Array
|
|
29
|
+
W: jax.Array
|
|
30
|
+
dtype: DTypeLike
|
|
31
|
+
|
|
32
32
|
def __init__(
|
|
33
33
|
self,
|
|
34
|
-
net:
|
|
34
|
+
net: Callable[[jax.Array], jax.Array],
|
|
35
35
|
d: int,
|
|
36
|
-
U0:
|
|
37
|
-
dtype:
|
|
36
|
+
U0: jax.Array | None = None,
|
|
37
|
+
dtype: DTypeLike = jnp.float64,
|
|
38
38
|
):
|
|
39
39
|
r"""
|
|
40
40
|
Initialize the determinant backflow model.
|
|
@@ -71,8 +71,8 @@ class DetBackflow(RefModel):
|
|
|
71
71
|
d //= 2
|
|
72
72
|
self.W = lecun_normal(get_subkeys(), (sites.Ntotal, d), dtype=dtype) / 10
|
|
73
73
|
|
|
74
|
-
def __call__(self, s: jax.Array) ->
|
|
75
|
-
x = self.net(s)
|
|
74
|
+
def __call__(self, s: jax.Array) -> LogArray:
|
|
75
|
+
x = jnp.asarray(self.net(s))
|
|
76
76
|
|
|
77
77
|
idx = fermion_idx(s)
|
|
78
78
|
x = x.reshape(-1, get_sites().Nfmodes).astype(self.dtype)
|
|
@@ -89,43 +89,78 @@ class DetBackflow(RefModel):
|
|
|
89
89
|
backflow correction is larger than the total number of particles.
|
|
90
90
|
"""
|
|
91
91
|
Ntotal = get_sites().Ntotal
|
|
92
|
+
if Ntotal is None:
|
|
93
|
+
raise ValueError
|
|
92
94
|
rank = self.W.shape[1]
|
|
93
95
|
return rank < Ntotal
|
|
94
96
|
|
|
95
|
-
def init_internal(self, s) ->
|
|
97
|
+
def init_internal(self, s: jax.Array) -> tuple[LogArray, MF_Internal | None]:
|
|
96
98
|
"""
|
|
97
|
-
|
|
99
|
+
Return wavefunction and internal values for given input configurations.
|
|
98
100
|
See `~quantax.nn.RefModel` for details.
|
|
99
101
|
"""
|
|
100
102
|
if not self.use_ref:
|
|
101
|
-
return None
|
|
103
|
+
return self(s), None
|
|
102
104
|
|
|
103
105
|
idx = fermion_idx(s)
|
|
104
106
|
orbs = self.U0[idx, :]
|
|
105
107
|
inv = jnp.linalg.inv(orbs)
|
|
106
108
|
sign, logabs = jnp.linalg.slogdet(orbs)
|
|
107
109
|
psi = LogArray(sign, logabs) * fermion_inverse_sign(s)
|
|
108
|
-
return MF_Internal(idx, inv, psi)
|
|
110
|
+
return psi, MF_Internal(idx, inv, psi)
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def required_update_modes(self) -> tuple[str, ...]:
|
|
114
|
+
"""
|
|
115
|
+
The required update modes for accelerated ref_forward pass.
|
|
116
|
+
"""
|
|
117
|
+
return ("nflips",)
|
|
118
|
+
|
|
119
|
+
@overload
|
|
120
|
+
def ref_forward(
|
|
121
|
+
self,
|
|
122
|
+
s: jax.Array,
|
|
123
|
+
s_old: jax.Array,
|
|
124
|
+
update_mode: dict[str, Any],
|
|
125
|
+
internal: MF_Internal | None,
|
|
126
|
+
return_update: Literal[False] = False,
|
|
127
|
+
) -> LogArray: ...
|
|
128
|
+
|
|
129
|
+
@overload
|
|
130
|
+
def ref_forward(
|
|
131
|
+
self,
|
|
132
|
+
s: jax.Array,
|
|
133
|
+
s_old: jax.Array,
|
|
134
|
+
update_mode: dict[str, Any],
|
|
135
|
+
internal: MF_Internal | None,
|
|
136
|
+
return_update: Literal[True],
|
|
137
|
+
) -> tuple[LogArray, MF_Internal | None]: ...
|
|
109
138
|
|
|
110
139
|
def ref_forward(
|
|
111
140
|
self,
|
|
112
141
|
s: jax.Array,
|
|
113
142
|
s_old: jax.Array,
|
|
114
|
-
|
|
115
|
-
internal:
|
|
143
|
+
update_mode: dict[str, Any],
|
|
144
|
+
internal: MF_Internal | None,
|
|
116
145
|
return_update: bool = False,
|
|
117
|
-
) ->
|
|
146
|
+
) -> LogArray | tuple[LogArray, MF_Internal | None]:
|
|
118
147
|
"""
|
|
119
148
|
Accelerated forward pass through local updates and internal quantities.
|
|
120
149
|
See `~quantax.nn.RefModel` for details.
|
|
121
150
|
"""
|
|
122
|
-
if not self.use_ref:
|
|
151
|
+
if (not self.use_ref) or (internal is None):
|
|
123
152
|
psi = self(s)
|
|
124
153
|
if return_update:
|
|
125
154
|
return psi, internal
|
|
126
155
|
else:
|
|
127
156
|
return psi
|
|
128
157
|
|
|
158
|
+
if not isinstance(internal.idx, jax.Array):
|
|
159
|
+
raise ValueError
|
|
160
|
+
if not isinstance(internal.inv, jax.Array):
|
|
161
|
+
raise ValueError
|
|
162
|
+
|
|
163
|
+
nflips = update_mode["nflips"]
|
|
129
164
|
nhops = nflips // 2
|
|
130
165
|
idx_annihilate, idx_create = changed_inds(s, s_old, nhops)
|
|
131
166
|
idx = internal.idx
|
|
@@ -135,7 +170,7 @@ class DetBackflow(RefModel):
|
|
|
135
170
|
new_idx = idx.at[row_update_idx].set(idx_create)
|
|
136
171
|
row_update = self.U0[idx_create] - self.U0[idx_annihilate]
|
|
137
172
|
|
|
138
|
-
x = self.net(s)
|
|
173
|
+
x = jnp.asarray(self.net(s))
|
|
139
174
|
x = x.reshape(-1, get_sites().Nfmodes).astype(self.dtype)
|
|
140
175
|
x = x.T[new_idx]
|
|
141
176
|
|
|
@@ -156,25 +191,25 @@ class DetBackflow(RefModel):
|
|
|
156
191
|
|
|
157
192
|
|
|
158
193
|
class PfBackflow(RefModel):
|
|
159
|
-
net: eqx.Module
|
|
160
|
-
U0: jax.Array
|
|
161
|
-
J0: jax.Array
|
|
162
|
-
W: jax.Array
|
|
163
|
-
dtype: jnp.dtype
|
|
164
|
-
|
|
165
194
|
r"""
|
|
166
195
|
Pfaffian backflow model.
|
|
167
196
|
:math:`\psi(n) = \mathrm{pf}(n \star (U_0 + U_1(n)) J_0 (U_0 + U_1(n))^T)`,
|
|
168
197
|
where :math:`\star` denotes the operation slicing the rows and columns of the matrix.
|
|
169
198
|
"""
|
|
170
199
|
|
|
200
|
+
net: Callable[[jax.Array], jax.Array]
|
|
201
|
+
U0: jax.Array
|
|
202
|
+
J0: jax.Array
|
|
203
|
+
W: jax.Array
|
|
204
|
+
dtype: DTypeLike
|
|
205
|
+
|
|
171
206
|
def __init__(
|
|
172
207
|
self,
|
|
173
|
-
net:
|
|
208
|
+
net: Callable[[jax.Array], jax.Array],
|
|
174
209
|
d: int,
|
|
175
|
-
U0:
|
|
176
|
-
J0:
|
|
177
|
-
dtype:
|
|
210
|
+
U0: jax.Array | None = None,
|
|
211
|
+
J0: jax.Array | None = None,
|
|
212
|
+
dtype: DTypeLike = jnp.float64,
|
|
178
213
|
):
|
|
179
214
|
r"""
|
|
180
215
|
Initialize the Pfaffian backflow model.
|
|
@@ -206,6 +241,9 @@ class PfBackflow(RefModel):
|
|
|
206
241
|
U1 = U0.conj() if jnp.issubdtype(dtype, jnp.complexfloating) else U0
|
|
207
242
|
O = jnp.zeros_like(U0)
|
|
208
243
|
U0 = jnp.block([[U0, O], [O, U1]])
|
|
244
|
+
# Break the degeneracy of the clean Fermi sea, otherwise the spinful
|
|
245
|
+
# block structure makes the mean-field Pfaffian U0 J0 U0^T singular.
|
|
246
|
+
U0 += jr.normal(get_subkeys(), U0.shape, U0.dtype) * jnp.std(U0) * 0.1
|
|
209
247
|
elif U0.shape != (M, M):
|
|
210
248
|
raise ValueError(f"U0 must have shape {(M, M)}, got {U0.shape}")
|
|
211
249
|
U0 /= jnp.std(U0)
|
|
@@ -213,7 +251,7 @@ class PfBackflow(RefModel):
|
|
|
213
251
|
|
|
214
252
|
if J0 is None:
|
|
215
253
|
if sites.is_spinful:
|
|
216
|
-
J0 = lrux.skew_eye(M // 2, dtype)
|
|
254
|
+
J0 = lrux.skew_eye(M // 2, dtype) # type: ignore
|
|
217
255
|
else:
|
|
218
256
|
J0 = jr.normal(get_subkeys(), (M, M), dtype=dtype)
|
|
219
257
|
J0 = (J0 - J0.T) / 2
|
|
@@ -227,6 +265,10 @@ class PfBackflow(RefModel):
|
|
|
227
265
|
|
|
228
266
|
@property
|
|
229
267
|
def J0_full(self) -> jax.Array:
|
|
268
|
+
"""
|
|
269
|
+
Returns the full antisymmetric mean-field pairing matrix J0, reconstructed
|
|
270
|
+
from its stored upper-triangular entries.
|
|
271
|
+
"""
|
|
230
272
|
M = self.U0.shape[0]
|
|
231
273
|
J_full = jnp.zeros((M, M), dtype=self.dtype)
|
|
232
274
|
triu_indices = jnp.triu_indices(M, k=1)
|
|
@@ -234,8 +276,8 @@ class PfBackflow(RefModel):
|
|
|
234
276
|
J_full = J_full - J_full.T
|
|
235
277
|
return J_full
|
|
236
278
|
|
|
237
|
-
def __call__(self, s: jax.Array) ->
|
|
238
|
-
x = self.net(s)
|
|
279
|
+
def __call__(self, s: jax.Array) -> LogArray:
|
|
280
|
+
x = jnp.asarray(self.net(s))
|
|
239
281
|
|
|
240
282
|
idx = fermion_idx(s)
|
|
241
283
|
x = x.reshape(-1, get_sites().Nfmodes).astype(self.dtype)
|
|
@@ -253,16 +295,18 @@ class PfBackflow(RefModel):
|
|
|
253
295
|
backflow correction is larger than the total number of particles.
|
|
254
296
|
"""
|
|
255
297
|
Ntotal = get_sites().Ntotal
|
|
298
|
+
if Ntotal is None:
|
|
299
|
+
raise ValueError
|
|
256
300
|
rank = self.W.shape[1] * 2
|
|
257
301
|
return rank < Ntotal
|
|
258
302
|
|
|
259
|
-
def init_internal(self, s) ->
|
|
303
|
+
def init_internal(self, s: jax.Array) -> tuple[LogArray, MF_Internal | None]:
|
|
260
304
|
"""
|
|
261
|
-
|
|
305
|
+
Return wavefunction and internal values for given input configurations.
|
|
262
306
|
See `~quantax.nn.RefModel` for details.
|
|
263
307
|
"""
|
|
264
308
|
if not self.use_ref:
|
|
265
|
-
return None
|
|
309
|
+
return self(s), None
|
|
266
310
|
|
|
267
311
|
idx = fermion_idx(s)
|
|
268
312
|
U = self.U0[idx, :]
|
|
@@ -270,27 +314,60 @@ class PfBackflow(RefModel):
|
|
|
270
314
|
inv = jnp.linalg.inv(F)
|
|
271
315
|
sign, logabs = lrux.slogpf(F)
|
|
272
316
|
psi = LogArray(sign, logabs) * fermion_inverse_sign(s)
|
|
273
|
-
return MF_Internal(idx, inv, psi)
|
|
317
|
+
return psi, MF_Internal(idx, inv, psi)
|
|
318
|
+
|
|
319
|
+
@property
|
|
320
|
+
def required_update_modes(self) -> tuple[str, ...]:
|
|
321
|
+
"""
|
|
322
|
+
The required update modes for accelerated ref_forward pass.
|
|
323
|
+
"""
|
|
324
|
+
return ("nflips",)
|
|
274
325
|
|
|
326
|
+
@overload
|
|
275
327
|
def ref_forward(
|
|
276
328
|
self,
|
|
277
329
|
s: jax.Array,
|
|
278
330
|
s_old: jax.Array,
|
|
279
|
-
|
|
280
|
-
internal:
|
|
331
|
+
update_mode: dict[str, Any],
|
|
332
|
+
internal: MF_Internal | None,
|
|
333
|
+
return_update: Literal[False] = False,
|
|
334
|
+
) -> LogArray: ...
|
|
335
|
+
|
|
336
|
+
@overload
|
|
337
|
+
def ref_forward(
|
|
338
|
+
self,
|
|
339
|
+
s: jax.Array,
|
|
340
|
+
s_old: jax.Array,
|
|
341
|
+
update_mode: dict[str, Any],
|
|
342
|
+
internal: MF_Internal | None,
|
|
343
|
+
return_update: Literal[True],
|
|
344
|
+
) -> tuple[LogArray, MF_Internal | None]: ...
|
|
345
|
+
|
|
346
|
+
def ref_forward(
|
|
347
|
+
self,
|
|
348
|
+
s: jax.Array,
|
|
349
|
+
s_old: jax.Array,
|
|
350
|
+
update_mode: dict[str, Any],
|
|
351
|
+
internal: MF_Internal | None,
|
|
281
352
|
return_update: bool = False,
|
|
282
|
-
) ->
|
|
353
|
+
) -> LogArray | tuple[LogArray, MF_Internal | None]:
|
|
283
354
|
"""
|
|
284
355
|
Accelerated forward pass through local updates and internal quantities.
|
|
285
356
|
See `~quantax.nn.RefModel` for details.
|
|
286
357
|
"""
|
|
287
|
-
if not self.use_ref:
|
|
358
|
+
if (not self.use_ref) or (internal is None):
|
|
288
359
|
psi = self(s)
|
|
289
360
|
if return_update:
|
|
290
361
|
return psi, internal
|
|
291
362
|
else:
|
|
292
363
|
return psi
|
|
293
364
|
|
|
365
|
+
if not isinstance(internal.idx, jax.Array):
|
|
366
|
+
raise ValueError
|
|
367
|
+
if not isinstance(internal.inv, jax.Array):
|
|
368
|
+
raise ValueError
|
|
369
|
+
|
|
370
|
+
nflips = update_mode["nflips"]
|
|
294
371
|
nhops = nflips // 2
|
|
295
372
|
idx_annihilate, idx_create = changed_inds(s, s_old, nhops)
|
|
296
373
|
idx = internal.idx
|
|
@@ -305,7 +382,7 @@ class PfBackflow(RefModel):
|
|
|
305
382
|
U_mean = (U0[new_idx, :] + U0[idx, :]) / 2
|
|
306
383
|
x = jnp.einsum("im,mn,jn->ij", U_diff, J0, U_mean).T
|
|
307
384
|
|
|
308
|
-
U1 = self.net(s)
|
|
385
|
+
U1 = jnp.asarray(self.net(s))
|
|
309
386
|
U1 = U1.reshape(-1, get_sites().Nfmodes).astype(self.dtype)
|
|
310
387
|
U1 = U1.T[new_idx, :]
|
|
311
388
|
W = self.W
|