Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mutation behavior of position #131

Merged
merged 15 commits into from
Jan 31, 2024
38 changes: 34 additions & 4 deletions src/treetensornetworks/projttns/abstractprojttn.jl
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,43 @@ end
function position(
P::AbstractProjTTN{V}, psi::TTN{V}, pos::Union{Vector{<:V},NamedEdge{V}}
) where {V}
# shift position
P = shift_position(P, pos)
# remove internal edges (out of place)
P = invalidate_environments(P)
P = make_environments(P, psi)
return P
end

function position!(
P::AbstractProjTTN{V}, psi::TTN{V}, pos::Union{Vector{<:V},NamedEdge{V}}
) where {V}
P = shift_position(P, pos)
P = invalidate_environments(P)
make_environments!(P, psi, e)
return P
end

function invalidate_environments(P::AbstractProjTTN)
ie = internal_edges(P)
newenvskeys = filter(!in(ie), keys(P.environments))
P = ProjTTN(pos, P.H, getindices(P.environments, newenvskeys))
# make all environments surrounding new position
P = ProjTTN(P.pos, P.H, getindices(P.environments, newenvskeys))
return P
end

function invalidate_environment(P::AbstractProjTTN{V}, e::NamedEdge{V}) where {V}
newenvskeys = filter(isequal(e), keys(P.environments))
P = ProjTTN(P.pos, P.H, getindices(P.environments, newenvskeys))
return P
end

function make_environments(P::AbstractProjTTN{V}, psi::TTN{V}) where {V}
P = copy(P)
for e in incident_edges(P)
set!(P.environments, e, make_environment(P, psi, e))
end
return P
end

function make_environments!(P::AbstractProjTTN{V}, psi::TTN{V}) where {V}
for e in incident_edges(P)
make_environment!(P, psi, e)
end
Expand Down
59 changes: 41 additions & 18 deletions src/treetensornetworks/projttns/projttn.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function ProjTTN(H::TTN)
return ProjTTN(vertices(H), H, Dictionary{edgetype(H),ITensor}())
end

copy(P::ProjTTN) = ProjTTN(P.pos, copy(P.H), copy(P.environments))
copy(P::ProjTTN) = ProjTTN(P.pos, copy(P.H), NamedGraphs.copy_keys_values(P.environments))

# trivial if we choose to specify position as above; only kept to allow using alongside
# ProjMPO
Expand All @@ -30,23 +30,7 @@ function make_environment!(P::ProjTTN{V}, psi::TTN{V}, e::NamedEdge{V})::ITensor
if haskey(P.environments, e)
env = environment(P, e)
else
if is_leaf(underlying_graph(P), src(e))
# leaves are easy
env = psi[src(e)] * P.H[src(e)] * dag(prime(psi[src(e)]))
else
# construct by contracting neighbors
neighbor_envs = ITensor[]
for n in setdiff(neighbors(underlying_graph(P), src(e)), [dst(e)])
push!(neighbor_envs, make_environment!(P, psi, edgetype(P)(n, src(e))))
end
# manually heuristic for contraction order: two environments, site tensors, then
# other environments
frst, scnd, rst = _separate_first_two(neighbor_envs)
itensor_map = vcat(psi[src(e)], frst, scnd, P.H[src(e)], dag(prime(psi[src(e)])), rst)
# TODO: actually use optimal contraction sequence here
env = reduce(*, itensor_map)
end
# cache
env = _compute_environment(P, psi, e)
set!(P.environments, e, env)
end
@assert(
Expand All @@ -55,3 +39,42 @@ function make_environment!(P::ProjTTN{V}, psi::TTN{V}, e::NamedEdge{V})::ITensor
)
return env
end

function make_environment(P::ProjTTN{V}, psi::TTN{V}, e::NamedEdge{V})::ITensor where {V}
# invalidate environment for opposite edge direction if necessary
#P=copy(P)
reverse(e) ∈ incident_edges(P) || (P = invalidate_environment(P, reverse(e)))
# do nothing if valid environment already present
if haskey(P.environments, e)
env = environment(P, e)
else
env = _compute_environment(P, psi, e)
end
@assert(
hascommoninds(env, psi[src(e)]),
"Something went wrong, probably re-orthogonalized this edge in the same direction twice!"
)
return env
end

function _compute_environment(
P::ProjTTN{V}, psi::TTN{V}, e::NamedEdge{V}
)::ITensor where {V}
if is_leaf(underlying_graph(P), src(e))
# leaves are easy
env = psi[src(e)] * P.H[src(e)] * dag(prime(psi[src(e)]))
else
# construct by contracting neighbors
neighbor_envs = ITensor[]
for n in setdiff(neighbors(underlying_graph(P), src(e)), [dst(e)])
push!(neighbor_envs, make_environment!(P, psi, edgetype(P)(n, src(e))))
end
# manually heuristic for contraction order: two environments, site tensors, then
# other environments
frst, scnd, rst = _separate_first_two(neighbor_envs)
itensor_map = vcat(psi[src(e)], frst, scnd, P.H[src(e)], dag(prime(psi[src(e)])), rst)
# TODO: actually use optimal contraction sequence here
env = reduce(*, itensor_map)
end
return env
end
1 change: 1 addition & 0 deletions test/test_treetensornetworks/test_position.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ using Test
ITensors.disable_auto_fermion()
end
end
nothing
Loading