jflows 0.5.3__py3-none-any.whl

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.
jflows/__init__.py ADDED
@@ -0,0 +1,93 @@
1
+ """jflows — JAX normalizing flows for unconditional energy-based sampling.
2
+
3
+ Built on JAX and equinox.
4
+
5
+ Public surface:
6
+
7
+ jflows.flow : Flow, NSF, NCSF, CNF, OTFlow, RealNVP, ComposedTransform
8
+ jflows.potential : Potential, potential_from, Nlog_Uniform, Nlog_Gaussian,
9
+ Nlog_Gaussian_Mixture, linear_combination (+ the operator
10
+ algebra c*U, U+V, U-V, -U, U/c, sum([...]))
11
+ jflows.loss : reverse_KL_F, forward_KL_G, forward_KLX_G,
12
+ forward_X_G
13
+ jflows.train : Monitor and all train_* stage drivers
14
+ jflows.boltzmann : adaptive-staging and fixed-schedule boltzmann_* generators
15
+ jflows.artifacts : save and load medium-level training outputs
16
+ jflows.backend : selected/available JAX backends and accelerator model
17
+ jflows.utils : metrics / optimization / rejuvenation / anneal / quench
18
+
19
+ Internals (`jflows.core.*`) adapt zuko's clean flow and transform design.
20
+ The public computation API uses explicit PRNG keys and takes `Flow` objects
21
+ directly for losses, importance weights, AIS, and training.
22
+ """
23
+
24
+ from importlib.metadata import entry_points
25
+ from importlib.util import find_spec
26
+ import os
27
+ from shutil import which
28
+ import subprocess
29
+
30
+ import equinox
31
+ import jax
32
+
33
+ from . import artifacts, boltzmann, flow, loss, potential, train, utils
34
+ from .version import __version__
35
+
36
+
37
+ def backend():
38
+ """Print the available JAX backends and selected accelerator."""
39
+ plugins = tuple(item.name.lower() for item in entry_points(group="jax_plugins"))
40
+ available = ["CPU"]
41
+ details = ["- CPU — cpu"]
42
+
43
+ cuda_visible = os.environ.get("CUDA_VISIBLE_DEVICES") not in ("", "-1")
44
+ if cuda_visible and any("cuda" in name for name in plugins) and which("nvidia-smi"):
45
+ result = subprocess.run(
46
+ ["nvidia-smi", "--query-gpu=name", "--format=csv,noheader"],
47
+ capture_output=True,
48
+ text=True,
49
+ )
50
+ models = tuple(
51
+ dict.fromkeys(line for line in result.stdout.splitlines() if line)
52
+ )
53
+ if result.returncode == 0 and models:
54
+ available.append("CUDA")
55
+ details.append(f"- CUDA — {', '.join(models)}")
56
+
57
+ rocm_visible = os.environ.get("ROCR_VISIBLE_DEVICES") not in ("", "-1")
58
+ if rocm_visible and any("rocm" in name for name in plugins) and which("rocm-smi"):
59
+ available.append("ROCm")
60
+ details.append("- ROCm")
61
+
62
+ if find_spec("libtpu"):
63
+ available.append("TPU")
64
+ details.append("- TPU")
65
+
66
+ configured = os.environ.get("JAX_PLATFORMS", "").split(",")[0].lower()
67
+ selected = {"cpu": "CPU", "cuda": "CUDA", "rocm": "ROCm", "tpu": "TPU"}.get(
68
+ configured
69
+ )
70
+ if selected not in available:
71
+ selected = next(
72
+ name for name in ("CUDA", "ROCm", "TPU", "CPU") if name in available
73
+ )
74
+
75
+ print(f"JAX {jax.__version__}")
76
+ print(f"Equinox {equinox.__version__}")
77
+ print(f"Selected backend: {selected}")
78
+ print(f"Available backends: {', '.join(available)}")
79
+ for detail in details:
80
+ print(detail)
81
+
82
+
83
+ __all__ = [
84
+ "__version__",
85
+ "artifacts",
86
+ "backend",
87
+ "boltzmann",
88
+ "flow",
89
+ "loss",
90
+ "potential",
91
+ "train",
92
+ "utils",
93
+ ]
jflows/artifacts.py ADDED
@@ -0,0 +1,46 @@
1
+ """Save and load medium-level training outputs."""
2
+
3
+ from pathlib import Path
4
+
5
+ import equinox as eqx
6
+ import numpy as np
7
+
8
+ __all__ = [
9
+ "load_flow",
10
+ "load_history",
11
+ "load_samples",
12
+ "save_flow",
13
+ "save_history",
14
+ "save_samples",
15
+ ]
16
+
17
+
18
+ def save_flow(path, flow) -> None:
19
+ """Save one flow's array leaves."""
20
+ eqx.tree_serialise_leaves(Path(path), flow)
21
+
22
+
23
+ def load_flow(path, template):
24
+ """Load flow leaves into a matching template."""
25
+ return eqx.tree_deserialise_leaves(Path(path), template)
26
+
27
+
28
+ def save_samples(path, samples) -> None:
29
+ """Save one sample array."""
30
+ np.save(Path(path), np.asarray(samples), allow_pickle=False)
31
+
32
+
33
+ def load_samples(path):
34
+ """Load one sample array."""
35
+ return np.load(Path(path), allow_pickle=False)
36
+
37
+
38
+ def save_history(path, **history) -> None:
39
+ """Save named training-history arrays."""
40
+ np.savez(Path(path), **history)
41
+
42
+
43
+ def load_history(path) -> dict:
44
+ """Load named training-history arrays."""
45
+ with np.load(Path(path), allow_pickle=False) as history:
46
+ return {name: history[name].copy() for name in history.files}