Cluster 8 Ising Normalizing Flow

A generative neural network (a normalizing flow) that learns to sample plausible spin configurations of a small 2D magnet (the Ising model), at any coupling strength between neighboring spins. Trained as part of the 9-cluster Scientific AI Cluster Orchestration Framework, which pairs this network with an exact symbolic ("Symetria") critical- temperature formula and two safety checks under LangGraph supervision.

Unlike most of the other clusters in this series, which train a network to predict a single value (a temperature, a velocity, a pressure), this one trains a network to generate samples from an entire probability distribution β€” the same kind of technique used in modern physics simulation tools called "Boltzmann generators."

Architecture

Type Normalizing flow (RealNVP-style), 4 stacked blocks
Lattice 4Γ—4 grid of spins (16 total), wraparound edges
Input Random noise (16 numbers) + coupling strength J
Output 16 transformed values, one per spin
Parameters ~35,000

A normalizing flow works by repeatedly stretching and squeezing a simple starting distribution (random noise) until it resembles a more complex target one. Each of the 4 blocks only transforms half its inputs at a time, using the other (untouched) half plus the coupling strength J to decide how β€” a standard trick (called "coupling layers") that keeps the transformation easy to invert and its effect on probability density easy to compute exactly.

Quickstart

import torch
from huggingface_hub import hf_hub_download
from modeling import ParallelNormalizingFlow, normalize_coupling

ckpt_path = hf_hub_download("dave1368/cluster-08-ising-flow", "normalizing_flow.pt")
# weights_only=False: the checkpoint is a dict with metadata (model_state_dict
# plus training info), not a bare tensor, so torch's default-safe loader can't
# be used as-is. Only do this for checkpoints you trust the source of.
checkpoint = torch.load(ckpt_path, map_location="cpu", weights_only=False)

model = ParallelNormalizingFlow(lattice_dim=16)
model.load_state_dict(checkpoint["model_state_dict"])  # checkpoint also carries training-time loss history, see training_metrics.json
model.eval()

# J = coupling strength (try values between 0.1 and 5.0)
j_norm = normalize_coupling(torch.tensor(1.0)).expand(1, 1)
noise = torch.randn(1, 16)
z, log_det = model(noise, j_norm)
soft_spins = torch.tanh(z)  # 16 values, each between -1 and 1
print(soft_spins)

Training data

No fixed dataset β€” training data is generated fresh every step: random noise plus a randomly chosen coupling strength J. There's no single "correct answer" to fit here, unlike Clusters 1-7's field predictions; the network instead learns by minimizing a physics-based objective (variational free energy β€” a standard method from the Boltzmann-generator literature, e.g. Wu, Wang & Zhang 2019) computed fresh from its own current samples at each step:

  • 4,000 training steps, batch size 2,048
  • Coupling strength range: J ∈ [0.1, 5.0]
  • Simulated at one fixed reference temperature, not each J's own critical temperature (see Design notes below for why)
  • Final training loss: βˆ’81.62 Β· Final validation loss: βˆ’81.89 (lower is better here β€” it's a free-energy estimate, not an error, so negative values are expected)

Design notes

Every layer of the flow is conditioned on the coupling strength J directly, so a single trained model covers the full slider range rather than being valid at only one coupling value.

Training and evaluation both use one fixed reference temperature, rather than each J's own critical temperature β€” a deliberate choice, not an oversight. Evaluating each J at its own critical point would actually erase J from the math entirely: at exactly the critical point, the physics has a genuine symmetry (a "universality" property well known in this field) that makes the quantity being minimized come out identical regardless of J. That would give the network nothing J-dependent to learn, defeating the point of conditioning on J at all. The fixed reference temperature is chosen so the low and high ends of the J slider land on opposite sides of the phase transition (ordered vs. disordered), so the coupling strength genuinely matters.

Validated against classical sources (post-deployment finding)

Cross-checked against Ising (1925), Bose & Einstein (1924), and Metropolis et al. (1953) β€” the papers cited in this cluster's Master Specification. Full data tables in the Space README.

Check Result
Exact critical-temperature formula vs. independent recomputation Exact match at every tested coupling strength
Historical note: this formula is Onsager's (1944), not Ising's own (1925) result Documented β€” Ising's 1925 paper found no transition in 1D and (incorrectly) guessed the same held in higher dimensions
Network's own "change in probability density" formula vs. an independent slower calculation Match to floating-point precision
Does the coupling strength J actually change the output? Yes β€” average sample energy scales roughly with J across the tested range
Does training actually improve the free-energy estimate? Yes β€” trained model's estimate is lower (tighter) than an untrained copy's, at every tested coupling strength
"Maxwell relation" safety check β€” can it actually fail? No β€” it's a basic calculus identity true for any smooth function, confirmed against random, deliberately-broken, and even physics-free models

Limitations

  • The "Maxwell relation" safety check downstream of this model can't actually distinguish a good model from a broken one β€” see the finding above. It confirms the surrounding code's calculus is implemented correctly, nothing more.
  • The related "subadditivity" check also passed in every test we tried, including deliberately broken models β€” treat it as unproven-but- untested-to-fail, not confirmed reliable the way some other clusters' safety checks are.
  • This network models soft spins (any value between βˆ’1 and 1), not the literal discrete Ising model (where spins are exactly βˆ’1 or +1) β€” a standard relaxation for training a smooth neural network, but it means outputs should be read as an approximation of the real system, not a literal sample from it.

Related

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support