Skip to content

Commit 4a85e5e

Browse files
authored
Belief Propagation
2 parents 119089f + bab1b36 commit 4a85e5e

File tree

10 files changed

+620
-15
lines changed

10 files changed

+620
-15
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using ITensors
2+
using ITensorNetworks
3+
using ITensorNetworks:
4+
delta_network,
5+
formsubgraphs,
6+
partition,
7+
flatten_thicken_bonds,
8+
flattened_inner_network,
9+
construct_initial_mts,
10+
update_all_mts,
11+
get_single_site_expec,
12+
iterate_single_site_expec,
13+
contract_boundary_mps
14+
using KaHyPar
15+
using Compat
16+
17+
#nxn GRID
18+
n = 4
19+
g = named_grid((n, n))
20+
s = siteinds("S=1/2", g)
21+
chi = 3
22+
23+
#Random Tensor Network, Flatten it too
24+
psi = randomITensorNetwork(s; link_space=chi)
25+
psiflat, combiners = flatten_thicken_bonds(deepcopy(psi))
26+
27+
v = (1, 1)
28+
29+
#Apply Sz to site v and flatten that
30+
psiflatO = flatten_thicken_bonds(psi; ops=["Sz"], vops=[v], s=s, combiners=combiners)
31+
32+
#Get the value of sz on v via exact contraction
33+
actual_sz = ITensors.contract(psiflatO)[1] / ITensors.contract(psiflat)[1]
34+
35+
println("Actual value of Sz on site " * string(v) * " is " * string(actual_sz))
36+
37+
nsites = 1
38+
println("First " * string(nsites) * " sites form a subgraph")
39+
dg_subgraphs = formsubgraphs(g, Int(n * n / nsites))
40+
mts = construct_initial_mts(psiflat, dg_subgraphs; init=(I...) -> allequal(I) ? 1 : 0)
41+
niters = 5
42+
43+
iterate_single_site_expec(psiflat, psiflatO, mts, dg_subgraphs, niters, v)
44+
45+
nsites = 4
46+
println("Now " * string(nsites) * " sites form a subgraph")
47+
dg_subgraphs = formsubgraphs(g, Int(n * n / nsites))
48+
mts = construct_initial_mts(psiflat, dg_subgraphs; init=(I...) -> allequal(I) ? 1 : 0)
49+
50+
iterate_single_site_expec(psiflat, psiflatO, mts, dg_subgraphs, niters, v)

src/ITensorNetworks.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ include("expect.jl")
125125
include("models.jl")
126126
include("tebd.jl")
127127
include("itensornetwork.jl")
128+
include("specialitensornetworks.jl")
129+
include("renameitensornetwork.jl")
130+
include("boundarymps.jl")
131+
include("subgraphs.jl")
132+
include("beliefpropagation.jl")
128133
include(joinpath("treetensornetwork", "treetensornetwork.jl"))
129134

130135
include("exports.jl")

src/abstractitensornetwork.jl

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,80 @@ end
450450
# TODO: rename `sqnorm` to match https://github.com/JuliaStats/Distances.jl?
451451
norm2::AbstractITensorNetwork; sequence) = contract_inner(ψ, ψ; sequence)
452452

453+
#Run over all edges of an ITENSORNETWORK and combine any duplicated indices into one
454+
#Can take pre-existing combiners as an argument
455+
function combine_link_indices(psi::AbstractITensorNetwork; combiners=nothing)
456+
if (combiners == nothing)
457+
outcombiners = Dict{NamedDimEdge{Tuple},ITensor}()
458+
end
459+
es = edges(psi)
460+
new_psi = deepcopy(psi)
461+
462+
for e in es
463+
v1, v2 = src(e), dst(e)
464+
if (combiners == nothing)
465+
is = commoninds(psi, e)
466+
C = combiner(is; tags=tags(is[1]))
467+
else
468+
C = combiners[e]
469+
end
470+
new_psi[v1] = new_psi[v1] * C
471+
new_psi[v2] = new_psi[v2] * C
472+
if (combiners == nothing)
473+
outcombiners[e] = C
474+
end
475+
end
476+
477+
if (combiners == nothing)
478+
return new_psi, outcombiners
479+
else
480+
return new_psi
481+
end
482+
end
483+
484+
#Run over all edges of an ITENSORNETWORK and uncombine any indices which were previously combined
485+
#Can take pre-existing combiners as an argument
486+
function uncombine_link_indices(
487+
psi::AbstractITensorNetwork, combiners=Dict{NamedDimEdge{Tuple},ITensor}()
488+
)
489+
es = edges(psi)
490+
new_psi = deepcopy(psi)
491+
492+
for e in es
493+
v1, v2 = src(e), dst(e)
494+
if (haskey(combiners, e))
495+
C = combiners[e]
496+
new_psi[v1] = new_psi[v1] * C
497+
new_psi[v2] = new_psi[v2] * C
498+
end
499+
end
500+
501+
return new_psi
502+
end
503+
504+
#GIVEN AN ITENSOR NETWORK WITH DANGLING (PHYSICAL) BONDS, CONTRACT IT ONTO ITS CONJUGATE AND COMBINE ALL
505+
#DOUBLE INDICES. RETURN THE COMBINERS USED ON THE LINK INDICES
506+
#CAN APPLY LOCAL OPS ALONG THE PHYSICAL INDICES OF THE ITENSORNETWORK BEFORE CONTRACTION (ops is a list of strings, vops is a list of vertices, s is the indsnetwork)
507+
#CAN ALSO PASS COMBINERS FROM BEFORE TO ENSURE THE INDICES ARE CONSISTENT BETWEEN DIFFERENT APPLICATIONS OF THIS FUNCTION
508+
function flatten_thicken_bonds(
509+
psi::AbstractITensorNetwork; ops=nothing, vops=nothing, s=nothing, combiners=nothing
510+
)
511+
psiin = deepcopy(psi)
512+
outcombiners = Dict{NamedDimEdge{Tuple},ITensor}()
513+
514+
if (ops != nothing)
515+
for (op, v) in zip(ops, vops)
516+
O = ITensor(Op(op, v), s)
517+
psiin[v] = noprime!(O * psiin[v])
518+
end
519+
end
520+
521+
flatpsi = flattened_inner_network(psiin, psi)
522+
flatpsi = rename_vertices_itn(flatpsi, Dictionary(vertices(flatpsi), vertices(psi)))
523+
524+
return combine_link_indices(flatpsi; combiners=combiners)
525+
end
526+
453527
#
454528
# Printing
455529
#

0 commit comments

Comments
 (0)