Tree Tensor Networks
Overview
A TreeTensorNetwork (alias TTN) is an ITensorNetwork whose underlying graph is a tree (no cycles). This additional structure enables exact, efficient canonical gauges via QR decomposition — a key ingredient in variational algorithms such as DMRG and TDVP.
A TreeTensorNetwork carries an extra piece of metadata: the ortho_region, which records which vertices currently form the orthogonality center of the network. Algorithms update this field as the gauge changes.
MPS (matrix product states) are the special case of a TreeTensorNetwork on a 1D path graph.
Construction
From an OpSum (Hamiltonian)
A common way to obtain a Hamiltonian-shaped TTN is to convert an OpSum over an IndsNetwork of site indices.
ITensorNetworks.TreeTensorNetwork — Method
TreeTensorNetwork(os::OpSum, sites::IndsNetwork{<:Index}; kwargs...)
TreeTensorNetwork(eltype::Type{<:Number}, os::OpSum, sites::IndsNetwork{<:Index}; kwargs...)Convert an OpSum object os to a TreeTensorNetwork, with indices given by sites.
From an existing ITensorNetwork
The TreeTensorNetwork struct wraps an ITensorNetwork and records the current orthogonality region. Use the TreeTensorNetwork constructor to convert a plain ITensorNetwork with tree topology into a TTN, and ITensorNetwork to strip the gauge metadata when you need a plain network again.
using Graphs: edges, vertices
using ITensorNetworks: ITensorNetwork, TreeTensorNetwork, ortho_region, orthogonalize,
siteinds
using ITensors: ITensors, Index, random_itensor
using LinearAlgebra: norm
using NamedGraphs: NamedGraph
using NamedGraphs.GraphsExtensions: incident_edges
using NamedGraphs.NamedGraphGenerators: named_comb_tree
# Comb-tree TTN (a popular tree topology for 2D-like systems)
g = NamedGraph(named_comb_tree((3, 2)))
sites = siteinds("S=1/2", g)
# Build a structured `ITensorNetwork` with shared link indices on each edge
χ = 2
links = Dict(e => Index(χ, "Link") for e in edges(g))
tensors = Dict(map(collect(vertices(g))) do v
site_v = sites[v]
link_v = [haskey(links, e) ? links[e] : links[reverse(e)] for e in incident_edges(g, v)]
return v => random_itensor(site_v..., link_v...)
end)
itn = ITensorNetwork(tensors)
psi = TreeTensorNetwork(itn)ITensorNetworks.TreeTensorNetwork{Tuple{Int64, Int64}} with 6 vertices:
6-element NamedGraphs.OrderedDictionaries.OrderedIndices{Tuple{Int64, Int64}}:
(3, 2)
(1, 2)
(3, 1)
(1, 1)
(2, 2)
(2, 1)
and 5 edge(s):
(3, 2) => (3, 1)
(1, 2) => (1, 1)
(3, 1) => (2, 1)
(1, 1) => (2, 1)
(2, 2) => (2, 1)
with vertex data:
6-element Dictionaries.Dictionary{Tuple{Int64, Int64}, Any}:
(3, 2) │ ((dim=2|id=990|"S=1/2,Site,n=3×2"), (dim=2|id=848|"Link"))
(1, 2) │ ((dim=2|id=1|"S=1/2,Site,n=1×2"), (dim=2|id=62|"Link"))
(3, 1) │ ((dim=2|id=464|"S=1/2,Site,n=3×1"), (dim=2|id=872|"Link"), (dim=2|id=…
(1, 1) │ ((dim=2|id=794|"S=1/2,Site,n=1×1"), (dim=2|id=260|"Link"), (dim=2|id=…
(2, 2) │ ((dim=2|id=994|"S=1/2,Site,n=2×2"), (dim=2|id=596|"Link"))
(2, 1) │ ((dim=2|id=92|"S=1/2,Site,n=2×1"), (dim=2|id=260|"Link"), (dim=2|id=8…To strip the gauge metadata back to a plain ITensorNetwork:
itn_again = ITensorNetwork(psi) # TTN → ITensorNetworkITensorNetworks.ITensorNetwork{Tuple{Int64, Int64}} with 6 vertices:
6-element NamedGraphs.OrderedDictionaries.OrderedIndices{Tuple{Int64, Int64}}:
(3, 2)
(1, 2)
(3, 1)
(1, 1)
(2, 2)
(2, 1)
and 5 edge(s):
(3, 2) => (3, 1)
(1, 2) => (1, 1)
(3, 1) => (2, 1)
(1, 1) => (2, 1)
(2, 2) => (2, 1)
with vertex data:
6-element Dictionaries.Dictionary{Tuple{Int64, Int64}, Any}:
(3, 2) │ ((dim=2|id=990|"S=1/2,Site,n=3×2"), (dim=2|id=848|"Link"))
(1, 2) │ ((dim=2|id=1|"S=1/2,Site,n=1×2"), (dim=2|id=62|"Link"))
(3, 1) │ ((dim=2|id=464|"S=1/2,Site,n=3×1"), (dim=2|id=872|"Link"), (dim=2|id=…
(1, 1) │ ((dim=2|id=794|"S=1/2,Site,n=1×1"), (dim=2|id=260|"Link"), (dim=2|id=…
(2, 2) │ ((dim=2|id=994|"S=1/2,Site,n=2×2"), (dim=2|id=596|"Link"))
(2, 1) │ ((dim=2|id=92|"S=1/2,Site,n=2×1"), (dim=2|id=260|"Link"), (dim=2|id=8…ITensorNetworks.TreeTensorNetwork — Type
TreeTensorNetwork{V} <: AbstractTreeTensorNetwork{V}A tensor network whose underlying graph is a tree. Storage mirrors ITensorNetwork — graph, vertex_data, and ind_to_vertices — plus an ortho_region tracking the orthogonality center.
TTN is an alias for TreeTensorNetwork.
Use the TreeTensorNetwork constructors to build instances, and orthogonalize to bring the network into a canonical gauge.
See also: ITensorNetwork.
Orthogonal Gauge
One of the most powerful features of tree tensor networks is the ability to bring the network into an orthogonal gauge in linear time. When the network is in a gauge centered on vertex v, all tensors away from v are isometric with respect to the bond pointing toward v. This makes computing local observables, inner products, and eigenvalue problems numerically efficient and stable.
The current orthogonality center is tracked by the ortho_region field.
v = collect(vertices(psi))[1]
v1 = collect(vertices(psi))[1]
v2 = collect(vertices(psi))[2]
vs = [v]
psi = orthogonalize(psi, v) # QR-sweep to put ortho center at vertex v
psi = orthogonalize(psi, [v1, v2]) # two-site center (for nsites=2 sweeps)
ortho_region(psi) # query current ortho region (returns an index set)2-element Dictionaries.Indices{Tuple{Int64, Int64}}:
(3, 2)
(1, 2)ITensorNetworks.orthogonalize — Function
orthogonalize(ttn::AbstractTreeTensorNetwork, region) -> TreeTensorNetworkBring ttn into an orthogonal gauge with orthogonality center at region. region may be a single vertex or a vector of vertices.
QR decompositions are applied along the unique tree path from the current ortho_region to region, so that all tensors outside region are left- or right-orthogonal with respect to that path.
See also: ortho_region, truncate.
ITensorNetworks.ortho_region — Function
ortho_region(tn::TreeTensorNetwork) -> IndicesReturn the set of vertices that currently form the orthogonality center of tn.
See also: orthogonalize.
Bond Truncation
After algorithms that grow the bond dimension (e.g. addition, subspace expansion), use truncate to recompress the network. For TreeTensorNetwork there are two forms:
- Whole-network recompression (TTN-specific):
truncate(ttn; kwargs...)sweeps from the leaves to the root, orthogonalising and truncating every bond in sequence. This is the preferred form after addition or DMRG expansion. - Single-bond truncation (available for any
ITensorNetwork):truncate(tn, edge; kwargs...)truncates one bond by SVD — see the ITensor Networks page.
psi = truncate(psi; cutoff = 1e-10, maxdim = 50)ITensorNetworks.TreeTensorNetwork{Tuple{Int64, Int64}} with 6 vertices:
6-element NamedGraphs.OrderedDictionaries.OrderedIndices{Tuple{Int64, Int64}}:
(3, 2)
(1, 2)
(3, 1)
(1, 1)
(2, 2)
(2, 1)
and 5 edge(s):
(3, 2) => (3, 1)
(1, 2) => (1, 1)
(3, 1) => (2, 1)
(1, 1) => (2, 1)
(2, 2) => (2, 1)
with vertex data:
6-element Dictionaries.Dictionary{Tuple{Int64, Int64}, Any}:
(3, 2) │ ((dim=2|id=990|"S=1/2,Site,n=3×2"), (dim=2|id=743|"3×1,3×2"))
(1, 2) │ ((dim=2|id=1|"S=1/2,Site,n=1×2"), (dim=2|id=59|"1×1,1×2"))
(3, 1) │ ((dim=2|id=464|"S=1/2,Site,n=3×1"), (dim=2|id=419|"2×1,3×1"), (dim=2|…
(1, 1) │ ((dim=2|id=794|"S=1/2,Site,n=1×1"), (dim=2|id=59|"1×1,1×2"), (dim=2|i…
(2, 2) │ ((dim=2|id=994|"S=1/2,Site,n=2×2"), (dim=2|id=145|"2×1,2×2"))
(2, 1) │ ((dim=2|id=92|"S=1/2,Site,n=2×1"), (dim=2|id=877|"1×1,2×1"), (dim=2|i…The sweep-based form orthogonalises each bond before truncating it, so truncation errors are controlled. All keyword arguments accepted by ITensors.svd (e.g. cutoff, maxdim, mindim) are forwarded.
Base.truncate — Method
truncate(tn::AbstractTreeTensorNetwork; root_vertex=..., kwargs...) -> TreeTensorNetworkTruncate the bond dimensions of tn by sweeping from the leaves toward root_vertex and performing an SVD-based truncation on each bond.
Before truncating each bond the relevant subtree is first orthogonalized (controlled truncation), ensuring that discarded singular values correspond to actual truncation error. Truncation parameters are passed through kwargs.
Keyword Arguments
root_vertex: Root of the DFS traversal. Defaults todefault_root_vertex(tn).cutoff: Drop singular values smaller than this threshold (relative or absolute).maxdim: Maximum number of singular values to retain on each bond.
See also: orthogonalize.
Addition and Arithmetic
Two TTNs with the same graph and site indices can be summed. The result has bond dimension equal to the sum of the two inputs, and can be recompressed with truncate.
psi1, psi2 = psi, psi
psi3 = psi1 + psi2 # or add(psi1, psi2)
psi3 = truncate(psi3; cutoff = 1e-10, maxdim = 50)
2 * psi # scalar multiplication
psi / norm(psi) # manual normalisationITensorNetworks.TreeTensorNetwork{Tuple{Int64, Int64}} with 6 vertices:
6-element NamedGraphs.OrderedDictionaries.OrderedIndices{Tuple{Int64, Int64}}:
(3, 2)
(1, 2)
(3, 1)
(1, 1)
(2, 2)
(2, 1)
and 5 edge(s):
(3, 2) => (3, 1)
(1, 2) => (1, 1)
(3, 1) => (2, 1)
(1, 1) => (2, 1)
(2, 2) => (2, 1)
with vertex data:
6-element Dictionaries.Dictionary{Tuple{Int64, Int64}, Any}:
(3, 2) │ ((dim=2|id=990|"S=1/2,Site,n=3×2"), (dim=2|id=743|"3×1,3×2"))
(1, 2) │ ((dim=2|id=1|"S=1/2,Site,n=1×2"), (dim=2|id=59|"1×1,1×2"))
(3, 1) │ ((dim=2|id=464|"S=1/2,Site,n=3×1"), (dim=2|id=419|"2×1,3×1"), (dim=2|…
(1, 1) │ ((dim=2|id=794|"S=1/2,Site,n=1×1"), (dim=2|id=59|"1×1,1×2"), (dim=2|i…
(2, 2) │ ((dim=2|id=994|"S=1/2,Site,n=2×2"), (dim=2|id=145|"2×1,2×2"))
(2, 1) │ ((dim=2|id=92|"S=1/2,Site,n=2×1"), (dim=2|id=877|"1×1,2×1"), (dim=2|i…ITensorNetworks.add — Method
add(tn1::AbstractITensorNetwork, tn2::AbstractITensorNetwork) -> ITensorNetworkAdd two ITensorNetworks together by taking their direct sum (growing the bond dimension). The result represents the state tn1 + tn2, with bond dimension on each edge equal to the sum of the bond dimensions of tn1 and tn2.
Both networks must have the same vertex set and matching site indices at each vertex.
Use truncate on the result to compress back to a lower bond dimension.
See also: Base.:+ for TreeTensorNetwork, truncate.
add(tns::AbstractTreeTensorNetwork...; kwargs...) -> TreeTensorNetworkAdd tree tensor networks together by growing the bond dimension. Equivalent to +(tns...).
Base.:+ — Method
+(tn1::AbstractTreeTensorNetwork, tn2::AbstractTreeTensorNetwork; alg="directsum", kwargs...) -> TreeTensorNetworkAdd two tree tensor networks by growing the bond dimension, returning a network that represents the state tn1 + tn2. The bond dimension of the result is the sum of the bond dimensions of the two inputs.
Use truncate afterward to compress the resulting network.
Keyword Arguments
alg="directsum": Algorithm for combining the networks. Currently only"directsum"is supported for trees.
Both networks must share the same graph structure and site indices.