Skip to content

Commit 09d16e4

Browse files
Quantum 1+1D Ising chain (#189)
* Quantum 1+1D Ising chain * Fix variable name * Docs on quantum partition function construction * Improve docs * Mention translation symmetry in docs [skip ci] * Rename to `quantum_ising_chain` [skip ci] --------- Co-authored-by: Victor Vanthilt <73738005+VictorVanthilt@users.noreply.github.com>
1 parent 14cc46a commit 09d16e4

6 files changed

Lines changed: 176 additions & 0 deletions

File tree

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
2020
StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"
2121
TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec"
2222
TensorKitSectors = "13a9c161-d5da-41f0-bcbd-e1a08ae0647f"
23+
TensorKitTensors = "41b62e7d-e9d1-4e23-942c-79a97adf954b"
2324
Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f"
2425

2526
[compat]
@@ -37,6 +38,7 @@ SpecialFunctions = "2.6.1"
3738
StableRNGs = "1.0.4"
3839
TensorKit = "0.16.2"
3940
TensorKitSectors = "0.3.7"
41+
TensorKitTensors = "0.2.5"
4042
Zygote = "0.7.7"
4143
julia = "1.11"
4244

docs/make.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ makedocs(;
1010
pages = [
1111
"Home" => "index.md"
1212
"Library" => "lib/lib.md"
13+
"Quantum 1+1D" => "quantum_1D.md"
1314
"CFT Data" => "cft.md"
1415
"Finalizers" => "finalizers.md"
1516
"References" => "references.md"

docs/src/quantum_1D.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# 1+1D Quantum Models
2+
3+
TNRKit provides tools to construct partition function tensors for $(1+1)$-dimensional quantum lattice models with translation symmetry (currently only nearest-neighbor Hamiltonians are supported). These tensors can then be studied with any of the 2D tensor network renormalization schemes (TRG, HOTRG, LoopTNR, etc.).
4+
5+
## Quantum Partition Functions
6+
7+
A $(1+1)$D quantum system at inverse temperature $\beta$ has partition function
8+
9+
```math
10+
\mathcal{Z} = \mathrm{Tr}\, e^{-\beta H}
11+
```
12+
13+
where $H$ is the Hamiltonian. By discretizing the imaginary-time direction into $N$ steps of size $\delta\tau = \beta / N$ and applying a Trotter–Suzuki decomposition, the partition function becomes a contraction of a 2D tensor network. Each time step is represented by a Trotter gate acting on nearest-neighbor pairs.
14+
15+
## Tensor Network Representation of $\mathcal{Z}$
16+
17+
When $H = \sum_i h_{i,i+1}$, where $h_{i,i+1} = h$ (due to translation symmetry) is a nearest-neighbor term, the Trotter gate network naturally forms a square lattice. Each Trotter gate $g = \exp(-\delta\tau \, h)$ connects two spatial sites (horizontal direction in the gate diagram) and advances by one imaginary-time step $\delta\tau$ (vertical direction in the gate diagram). However, the gate network is **rotated by 45 degrees** relative to the standard upright orientation.
18+
19+
`gate_to_tensor` transforms the rotated gate network into an **upright** square tensor network. The resulting tensor $T$ is the elementary cell of this upright network, and follows the standard TNRKit leg convention:
20+
21+
```
22+
3
23+
24+
1 ← T ← 4
25+
26+
2
27+
```
28+
29+
The horizontal direction (legs 1 ↔ 4) corresponds to the spatial dimension of the quantum chain, and the vertical direction (legs 2 ↔ 3) corresponds to imaginary time. The imaginary-time step represented by one $T$ tensor is the **same** $\delta\tau$ as one Trotter gate — the transformation does not coarse-grain in time. In the spatial direction, however, the transformation does renormalize: each $T$ represents **two** original lattice sites.
30+
31+
## Vertical Stacking
32+
33+
To build up the imaginary-time direction, multiple copies of $T$ are stacked vertically. As the stack grows, the bond dimension in the spatial direction would grow exponentially if left unchecked. TNRKit provides two stacking strategies that use HOTRG-style compression to keep the bond dimension under control.
34+
35+
- `vertical_stack_exp` stacks $2^{\text{nfold}}$ copies of $T$ by repeatedly doubling the current stack. Each iteration takes the current stack (representing $2^k$ Trotter steps) and compresses it on top of itself, yielding a stack of $2^{k+1}$ steps. After `nfold` iterations, the result represents $2^{\text{nfold}}$ Trotter steps. This is expected to be the more accurate approach, since only $m$ iterations are needed to reach $2^m$ steps.
36+
37+
- `vertical_stack_linear` stacks exactly $n$ copies of $T$ linearly (as opposed to a power of 2). Each iteration adds one more copy of the original tensor $T$ on top of the current stack. This is useful when you need a specific number of Trotter steps rather than a power of 2.
38+
39+
## Implementing Custom Quantum Models
40+
41+
To construct the partition function of a custom $(1+1)$D quantum Hamiltonian with nearest-neighbor interactions, follow this recipe:
42+
43+
1. **Construct the Trotter gate**: Build a 4-leg tensor representing $\exp(-\delta\tau \, h_{i,i+1})$ where $h_{i,i+1}$ is the nearest-neighbor Hamiltonian term. The gate should live in $V \otimes V \leftarrow V \otimes V$, where $V$ is the local Hilbert space.
44+
45+
2. **Convert to partition function tensor**: Call `gate_to_tensor(gate; trunc=...)` to obtain the elementary tensor $T$.
46+
47+
3. **Stack in the time direction**: Use `vertical_stack_exp` or `vertical_stack_linear` to build up the desired number of Trotter steps.
48+
49+
Now you are ready to feed the resulting 2D tensor network into any of TNRKit's 2D schemes (TRG, HOTRG, LoopTNR, etc.).

src/TNRKit.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ using Roots
1414
using NonlinearSolve
1515
using Base.Threads
1616
using Combinatorics: permutations
17+
import TensorKitTensors.SpinOperators as SO
1718

1819
# stop criteria
1920
include("utility/stopping.jl")
@@ -122,6 +123,10 @@ export phi4_real, phi4_real_imp1, phi4_real_imp2
122123
include("models/phi4_complex.jl")
123124
export phi4_complex, phi4_complex_impϕ, phi4_complex_impϕdag, phi4_complex_impϕabs, phi4_complex_impϕ2, phi4_complex_all
124125

126+
include("models/quantum_1D.jl")
127+
export gate_to_tensor, vertical_stack_exp, vertical_stack_linear
128+
export quantum_ising_chain
129+
125130
# utility functions
126131
include("utility/free_energy.jl")
127132
export free_energy

src/models/quantum_1D.jl

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
"""
2+
Construct partition function tensor from nearest neighbor
3+
Trotter gate of (1 + 1)D quantum models with translation symmetry.
4+
```
5+
2 3
6+
↘ ↙
7+
S4
8+
3 4 2 3 ↓
9+
↘︎ ↙︎ ↘ ↙ 1
10+
gate = S1 ← 3 1 ← S3 or
11+
↙︎ ↘︎ ↙ ↘ 3
12+
1 2 1 2 ↓
13+
S2
14+
↙ ↘
15+
1 2
16+
```
17+
The partition function tensor is
18+
```
19+
3'
20+
21+
S2
22+
↙ ↘
23+
b c 3'
24+
↙ ↘ ↓
25+
1'← S3 S1 ← 4' ---> 1'← T ← 4'
26+
↘ ↙ ↓
27+
a d 2'
28+
↘ ↙
29+
S4
30+
31+
2'
32+
```
33+
"""
34+
function gate_to_tensor(
35+
gate::AbstractTensorMap{E, S, 2, 2}; trunc = truncerror(; rtol = 1.0e-8)
36+
) where {E, S}
37+
s1, s3 = SVD12(permute(gate, ((1, 3), (2, 4))), trunc)
38+
s2, s4 = SVD12(gate, trunc)
39+
@tensor T[-1 -2; -3 -4] := s3[-1 a b] * s4[-2 a d] * s2[b c -3] * s1[d c -4]
40+
return T
41+
end
42+
43+
"""
44+
Exponentially stack `2^nfold` copies of `T` in vertical direction using HOTRG.
45+
"""
46+
function vertical_stack_exp(
47+
T::AbstractTensorMap{E, S, 2, 2}, nfold::Integer, trunc::TruncationStrategy
48+
) where {E, S}
49+
@assert nfold >= 1
50+
T2 = copy(T)
51+
for _ in 1:nfold
52+
Ux, = _get_hotrg_xproj(T2, T2, trunc)
53+
T2 = _step_hotrg_y(T2, T2, Ux)
54+
end
55+
return T2
56+
end
57+
58+
"""
59+
Linearly stack `n` copies of `T` in vertical direction using HOTRG.
60+
"""
61+
function vertical_stack_linear(
62+
T::AbstractTensorMap{E, S, 2, 2}, n::Integer, trunc::TruncationStrategy
63+
) where {E, S}
64+
@assert n >= 1
65+
T2 = copy(T)
66+
for _ in 1:(n - 1)
67+
Ux, = _get_hotrg_xproj(T, T2, trunc)
68+
T2 = _step_hotrg_y(T, T2, Ux)
69+
end
70+
return T2
71+
end
72+
73+
# Nearest neighbor (1+1)D quantum Hamiltonian gates
74+
# =================================================
75+
76+
"""
77+
Partition function tensor for 1D transverse field Ising chain
78+
```
79+
H(PBC) = -J ∑_i (σz_i σz_{i+1} + g σx_i)
80+
```
81+
Allowed `symm`: Trivial, Z2Irrep.
82+
"""
83+
function quantum_ising_chain(
84+
elt::Type{<:Number}, symm::Type{<:Sector}, dt::Float64;
85+
J::Float64 = 1.0, g::Float64 = 0.0
86+
)
87+
ZZ = 4 * SO.S_z_S_z(elt, symm)
88+
X = SO.σˣ(elt, symm)
89+
unit = TensorKit.id(codomain(X))
90+
gate = ZZ + (g / 2) * (X unit + unit X)
91+
gate = exp(dt * J * gate)
92+
return gate_to_tensor(gate)
93+
end
94+
quantum_ising_chain(elt::Type{<:Number}, dt::Float64; kwargs...) =
95+
quantum_ising_chain(elt, Trivial, dt; kwargs...)
96+
quantum_ising_chain(symm::Type{<:Sector}, dt::Float64; kwargs...) =
97+
quantum_ising_chain(ComplexF64, symm, dt; kwargs...)

test/models/models.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,25 @@ end
175175
order_para = data[end][4] / data[end][1]
176176
@test order_para 0.0 atol = 1.0e-3
177177
end
178+
179+
# (1 + 1)D quantum chains
180+
@testset "Quantum Ising chain: $stack_alg stacking" for stack_alg in (:exponential, :linear)
181+
trunc_stack = truncerror(; rtol = 1.0e-9) & truncrank(16)
182+
if stack_alg == :exponential
183+
nfold = 7
184+
dt = 1 / (2^nfold)
185+
T = quantum_ising_chain(Float64, Z2Irrep, dt; J = 1.0, g = 1.0)
186+
T = vertical_stack_exp(T, nfold, trunc_stack)
187+
else
188+
n = 100
189+
dt = 1 / n
190+
T = quantum_ising_chain(Float64, Z2Irrep, dt; J = 1.0, g = 1.0)
191+
T = vertical_stack_linear(T, n, trunc_stack)
192+
end
193+
scheme = LoopTNR(T)
194+
data = run!(scheme, truncrank(16), maxiter(16))
195+
cft = CFTData(scheme)
196+
central_charge = cft.central_charge
197+
@test central_charge 0.5 atol = 1.0e-2
198+
@info "Obtained central charge:\n$central_charge."
199+
end

0 commit comments

Comments
 (0)