iPEPS¶
Infinite Projected Entangled Pair States (iPEPS) is a variational ansatz for 2D quantum lattice models. Tenax implements the simple update for optimisation and the Corner Transfer Matrix (CTM) method for computing observables.
Background¶
An iPEPS represents a 2D quantum state as a tensor network where each site has a local tensor \(A[u,d,l,r,s]\) with four virtual bonds and one physical index. For translationally invariant states, a single-site unit cell suffices.
Simple update¶
Fast imaginary time evolution:
For each nearest-neighbour bond, apply \(\exp(-\delta\tau\, H_{\text{bond}})\).
SVD to restore tensor-product form; truncate to bond dimension \(D\).
Update diagonal \(\lambda\) matrices that approximate the bond environment.
CTM environment¶
The Corner Transfer Matrix method approximates the infinite environment of a PEPS site using 8 tensors (4 corners + 4 edges):
C1 --- T1 --- C2
| |
T4 [A] T2
| |
C4 --- T3 --- C3
CTM iteratively absorbs rows and columns until the corner singular values
converge. The projectors used to truncate the enlarged corners are built
from an eigendecomposition (eigh) of the half-row/half-column density
matrices. For AD-based optimization, use truncated_svd_ad instead
(see AD-Based iPEPS Excitations).
Configuration¶
from tenax import iPEPSConfig, CTMConfig
ctm_config = CTMConfig(
chi=20, # CTM environment bond dimension
max_iter=100, # maximum CTM iterations
conv_tol=1e-8, # convergence tolerance on corner singular values
renormalize=True,
)
config = iPEPSConfig(
max_bond_dim=2, # PEPS virtual bond dimension D
num_imaginary_steps=100, # imaginary time evolution steps
dt=0.05, # time step size
ctm=ctm_config,
gate_order="sequential",
)
Choosing dt¶
Larger time steps (dt=0.1–0.3) converge faster but can overshoot;
smaller steps (dt=0.01) are safer but need more iterations. A good
strategy is to start with dt=0.1 for quick exploration and reduce it
for final production runs. The 2-site unit cell often benefits from
larger dt because the two independent tensors converge more slowly.
Example – 2D Heisenberg model¶
import jax.numpy as jnp
from tenax import iPEPSConfig, CTMConfig, ipeps
# Heisenberg gate: H = Sz Sz + 0.5 (S+ S- + S- S+)
Sz = 0.5 * jnp.array([[1, 0], [0, -1]], dtype=jnp.float32)
Sp = jnp.array([[0, 1], [0, 0]], dtype=jnp.float32)
Sm = jnp.array([[0, 0], [1, 0]], dtype=jnp.float32)
I2 = jnp.eye(2, dtype=jnp.float32)
H_bond = (
jnp.kron(Sz, Sz)
+ 0.5 * jnp.kron(Sp, Sm)
+ 0.5 * jnp.kron(Sm, Sp)
).reshape(2, 2, 2, 2)
config = iPEPSConfig(
max_bond_dim=2,
num_imaginary_steps=200,
dt=0.01,
ctm=CTMConfig(chi=10, max_iter=50),
)
energy, peps, env = ipeps(H_bond, initial_peps=None, config=config)
print(f"Energy per site: {energy:.6f}")
Result¶
ipeps() returns a 3-tuple:
Element |
Type |
Description |
|---|---|---|
|
|
Energy per site |
|
|
Optimised PEPS (1x1 unit cell) |
|
|
Converged CTM environment tensors |
CTMEnvironment¶
The CTMEnvironment named tuple contains the 8 environment tensors:
Corners (
C1,C2,C3,C4): shape(chi, chi)Edges (
T1,T2,T3,T4): shape(chi, D^2, chi)
Using CTM standalone¶
The ctm() function can be called independently to compute the
environment for an existing PEPS tensor:
from tenax import ctm, CTMConfig
env = ctm(A_tensor, CTMConfig(chi=20, max_iter=100))
2-site checkerboard unit cell¶
A single-site unit cell cannot capture antiferromagnetic (Néel) order
because both sublattices share the same tensor. Setting
unit_cell="2site" in iPEPSConfig uses a 2-site checkerboard unit cell
with independent tensors \(A\) (sublattice 0) and \(B\) (sublattice 1).
On the checkerboard every neighbour of \(A\) is \(B\) and vice versa, which is the minimal unit cell for Néel-ordered states.
ctm_2site() – standalone 2-site CTM¶
Compute CTM environments for an existing 2-site iPEPS:
from tenax import ctm_2site, CTMConfig
env_A, env_B = ctm_2site(A, B, CTMConfig(chi=20, max_iter=100))
Argument |
Type |
Description |
|---|---|---|
|
|
Site tensor for sublattice A, shape |
|
|
Site tensor for sublattice B, shape |
|
|
CTM configuration |
Returns a tuple (env_A, env_B) of CTMEnvironment named tuples.
compute_energy_ctm_2site() – 2-site energy¶
Compute the energy per site for a 2-site checkerboard iPEPS given converged environments:
from tenax import compute_energy_ctm_2site
energy = compute_energy_ctm_2site(A, B, env_A, env_B, H_bond, d=2)
The energy includes one horizontal and one vertical bond per site: \(E/\text{site} = E_h + E_v\).
AD ground-state optimization¶
optimize_gs_ad() uses automatic differentiation through the CTM
fixed-point equation to compute exact gradients of the energy with
respect to the site tensor, then optimises with optax:
from tenax import iPEPSConfig, CTMConfig, optimize_gs_ad
config = iPEPSConfig(
max_bond_dim=2,
ctm=CTMConfig(chi=20, max_iter=100),
gs_optimizer="adam",
gs_learning_rate=1e-3,
gs_num_steps=200,
)
A_opt, env, E_gs = optimize_gs_ad(H_bond, A_init=None, config=config)
Simple update initialization¶
Starting AD optimization from a random tensor can cause large gradients
and slow convergence. Setting su_init=True runs simple update first
(using the num_imaginary_steps and dt already in the config) to
produce a physically reasonable starting point:
config = iPEPSConfig(
max_bond_dim=2,
num_imaginary_steps=200,
dt=0.01,
ctm=CTMConfig(chi=20, max_iter=100),
gs_num_steps=200,
gs_learning_rate=1e-3,
su_init=True,
)
A_opt, env, E_gs = optimize_gs_ad(H_bond, A_init=None, config=config)
When A_init is provided explicitly, su_init is ignored.
For AD-based excitation spectra on top of an optimised iPEPS, see AD-Based iPEPS Excitations.