Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into bp_optimal_sequence…
Browse files Browse the repository at this point in the history
…_finding
  • Loading branch information
JoeyT1994 committed May 6, 2024
2 parents a498736 + 0df8051 commit 4fea5e2
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 33 deletions.
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "ITensorNetworks"
uuid = "2919e153-833c-4bdc-8836-1ea460a35fc7"
authors = ["Matthew Fishman <[email protected]>, Joseph Tindall <[email protected]> and contributors"]
version = "0.10.0"
version = "0.11.0"

[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
Expand Down Expand Up @@ -57,13 +57,13 @@ DocStringExtensions = "0.9"
EinExprs = "0.6.4"
Graphs = "1.8"
GraphsFlows = "0.1.1"
ITensors = "0.4"
ITensors = "0.4, 0.5"
IsApprox = "0.1"
IterTools = "1.4.0"
KrylovKit = "0.6, 0.7"
NamedGraphs = "0.6.0"
NDTensors = "0.3"
Observers = "0.2"
Observers = "0.2.4"
OMEinsumContractionOrders = "0.8.3"
PackageExtensionCompat = "1"
SerializedElementArrays = "0.1"
Expand Down
19 changes: 16 additions & 3 deletions src/solvers/dmrg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,24 @@ using KrylovKit: KrylovKit
"""
Overload of `ITensors.ITensorMPS.dmrg`.
"""

function ITensorMPS.dmrg(
operator, init_state; nsweeps, nsites=2, updater=eigsolve_updater, kwargs...
operator,
init_state;
nsweeps,
nsites=2,
updater=eigsolve_updater,
(region_observer!)=nothing,
kwargs...,
)
return alternating_update(operator, init_state; nsweeps, nsites, updater, kwargs...)
eigvals_ref = Ref{Any}()
region_observer! = compose_observers(
region_observer!, ValuesObserver((; eigvals=eigvals_ref))
)
state = alternating_update(
operator, init_state; nsweeps, nsites, updater, region_observer!, kwargs...
)
eigval = only(eigvals_ref[])
return eigval, state
end

"""
Expand Down
18 changes: 16 additions & 2 deletions src/solvers/dmrg_x.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
function dmrg_x(
operator, init_state::AbstractTTN; nsweeps, nsites=2, updater=dmrg_x_updater, kwargs...
operator,
init_state::AbstractTTN;
nsweeps,
nsites=2,
updater=dmrg_x_updater,
(region_observer!)=nothing,
kwargs...,
)
return alternating_update(operator, init_state; nsweeps, nsites, updater, kwargs...)
eigvals_ref = Ref{Any}()
region_observer! = compose_observers(
region_observer!, ValuesObserver((; eigvals=eigvals_ref))
)
state = alternating_update(
operator, init_state; nsweeps, nsites, updater, region_observer!, kwargs...
)
eigval = only(eigvals_ref[])
return eigval, state
end
5 changes: 2 additions & 3 deletions src/solvers/local_solvers/dmrg_x.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ function dmrg_x_updater(
which_region_update,
internal_kwargs,
)
#ToDo: Implement this via KrylovKit or similar for better scaling
H = contract(projected_operator![], ITensor(true))
D, U = eigen(H; ishermitian=true)
u = uniqueind(U, H)
max_overlap, max_ind = findmax(abs, array(dag(init) * U))
U_max = U * dag(onehot(u => max_ind))
# TODO: improve this to return the energy estimate too
return U_max, (;)
eigvals = [((onehot(u => max_ind)' * D) * dag(onehot(u => max_ind)))[]]
return U_max, (; eigvals)
end
16 changes: 15 additions & 1 deletion src/treetensornetworks/projttns/projttn.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,24 @@ struct ProjTTN{V,Pos<:Union{Indices{V},NamedEdge{V}}} <: AbstractProjTTN{V}
pos::Pos
operator::TTN{V}
environments::Dictionary{NamedEdge{V},ITensor}
global function _ProjTTN(pos, operator::TTN, environments::Dictionary)
return new{vertextype(operator),Indices{vertextype(operator)}}(
Indices{vertextype(operator)}(pos),
operator,
convert(Dictionary{NamedEdge{vertextype(operator)},ITensor}, environments),
)
end
global function _ProjTTN(pos::NamedEdge, operator::TTN, environments::Dictionary)
return new{vertextype(operator),NamedEdge{vertextype(operator)}}(
convert(NamedEdge{vertextype(operator)}, pos),
operator,
convert(Dictionary{NamedEdge{vertextype(operator)},ITensor}, environments),
)
end
end

function ProjTTN(pos, operator::TTN, environments::Dictionary)
return ProjTTN(Indices(pos), operator, environments)
return _ProjTTN(pos, operator, environments)
end

function ProjTTN(operator::TTN)
Expand Down
21 changes: 21 additions & 0 deletions src/update_observer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,24 @@ end
function update_observer!(observer::Nothing; kwargs...)
return nothing
end

struct ComposedObservers{Observers<:Tuple}
observers::Observers
end
compose_observers(observers...) = ComposedObservers(observers)
function update_observer!(observer::ComposedObservers; kwargs...)
for observerᵢ in observer.observers
update_observer!(observerᵢ; kwargs...)
end
return observer
end

struct ValuesObserver{Values<:NamedTuple}
values::Values
end
function update_observer!(observer::ValuesObserver; kwargs...)
for key in keys(observer.values)
observer.values[key][] = kwargs[key]
end
return observer
end
2 changes: 2 additions & 0 deletions test/test_treetensornetworks/Project.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
[deps]
Dictionaries = "85a47980-9c8c-11e8-2b9f-f7ca1fa99fb4"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
ITensorNetworks = "2919e153-833c-4bdc-8836-1ea460a35fc7"
ITensors = "9136182c-28ba-11e9-034c-db9fb085ebd5"
NamedGraphs = "678767b0-92e7-4007-89e4-4527a8725b19"
15 changes: 12 additions & 3 deletions test/test_treetensornetworks/test_position.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
@eval module $(gensym())
using Dictionaries: Dictionary, Indices
using Graphs: vertices
using ITensors: ITensors
using ITensorNetworks: ProjTTN, ttn, environments, position, siteinds
using ITensors: ITensors, ITensor
using ITensorNetworks: ITensorNetwork, ProjTTN, ttn, environments, position, siteinds
using ITensorNetworks.ModelHamiltonians: ModelHamiltonians
using NamedGraphs.NamedGraphGenerators: named_comb_tree
using NamedGraphs: NamedEdge
using NamedGraphs.NamedGraphGenerators: named_comb_tree, named_path_graph
using Test: @test, @testset

@testset "ProjTTN position" begin
Expand Down Expand Up @@ -47,4 +49,11 @@ using Test: @test, @testset
ITensors.disable_auto_fermion()
end
end
@testset "ProjTTN construction regression test" begin
pos = Indices{Tuple{String,Int}}()
g = named_path_graph(2)
operator = ttn(ITensorNetwork{Any}(g))
environments = Dictionary{NamedEdge{Any},ITensor}()
@test ProjTTN(pos, operator, environments) isa ProjTTN{Any,Indices{Any}}
end
end
8 changes: 3 additions & 5 deletions test/test_treetensornetworks/test_solvers/test_contract.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ using Test: @test, @test_broken, @testset
@test inner(psi, Hpsi) inner(psi', H, psi) rtol = 1e-5
# Test variational compression via DMRG
Hfit = ProjOuterProdTTN(psi', H)
Hpsi_via_dmrg = dmrg(Hfit, psi; updater_kwargs=(; which_eigval=:LR,), nsweeps=1)
e, Hpsi_via_dmrg = dmrg(Hfit, psi; updater_kwargs=(; which_eigval=:LR,), nsweeps=1)
@test abs(inner(Hpsi_via_dmrg, Hpsi / norm(Hpsi))) 1 rtol = 1e-4
# Test whether the interface works for ProjTTNSum with factors
Hfit = ProjTTNSum([ProjOuterProdTTN(psi', H), ProjOuterProdTTN(psi', H)], [-0.2, -0.8])
Hpsi_via_dmrg = dmrg(Hfit, psi; nsweeps=1, updater_kwargs=(; which_eigval=:SR,))
e, Hpsi_via_dmrg = dmrg(Hfit, psi; nsweeps=1, updater_kwargs=(; which_eigval=:SR,))
@test abs(inner(Hpsi_via_dmrg, Hpsi / norm(Hpsi))) 1 rtol = 1e-4

# Test basic usage for use with multiple ProjOuterProdTTN with default parameters
Expand All @@ -66,9 +66,7 @@ using Test: @test, @test_broken, @testset
# Test the above via DMRG
# ToDo: Investigate why this is broken
Hfit = ProjTTNSum([ProjOuterProdTTN(psi', H), ProjOuterProdTTN(psi', identity)], [-1, 1])
Hpsi_normalized = ITensorNetworks.dmrg(
Hfit, psi; nsweeps=3, updater_kwargs=(; which_eigval=:SR)
)
e, Hpsi_normalized = dmrg(Hfit, psi; nsweeps=3, updater_kwargs=(; which_eigval=:SR))
@test_broken abs(inner(Hpsi, (Hpsi_normalized) / norm(Hpsi))) 1 rtol = 1e-5

#
Expand Down
21 changes: 12 additions & 9 deletions test/test_treetensornetworks/test_solvers/test_dmrg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,22 +53,24 @@ ITensors.disable_auto_fermion()
psi_mps = ITensorMPS.MPS([psi[v] for v in 1:nv(psi)])
e2, psi2 = dmrg(H_mpo, psi_mps; nsweeps, maxdim, outputlevel=0)

psi = dmrg(
e, psi = dmrg(
H, psi; nsweeps, maxdim, cutoff, nsites, updater_kwargs=(; krylovdim=3, maxiter=1)
)
@test inner(psi', H, psi) e
@test inner(psi', H, psi) inner(psi2', H_mpo, psi2)

# Alias for `ITensorNetworks.dmrg`
psi = eigsolve(
e, psi = eigsolve(
H, psi; nsweeps, maxdim, cutoff, nsites, updater_kwargs=(; krylovdim=3, maxiter=1)
)
@test inner(psi', H, psi) e
@test inner(psi', H, psi) inner(psi2', H_mpo, psi2)

# Test custom sweep regions #BROKEN, ToDo: Make proper custom sweep regions for test
#=
orig_E = inner(psi', H, psi)
sweep_regions = [[1], [2], [3], [3], [2], [1]]
psi = dmrg(H, psi; nsweeps, maxdim, cutoff, sweep_regions)
e, psi = dmrg(H, psi; nsweeps, maxdim, cutoff, sweep_regions)
new_E = inner(psi', H, psi)
@test new_E ≈ orig_E
=#
Expand Down Expand Up @@ -101,13 +103,14 @@ end
energy(; eigvals, kw...) = eigvals[1]
region_observer! = observer(region, sweep, energy)

psi = dmrg(H, psi; nsweeps, maxdim, cutoff, sweep_observer!, region_observer!)
e, psi = dmrg(H, psi; nsweeps, maxdim, cutoff, sweep_observer!, region_observer!)

#
# Test out certain values
#
@test region_observer![9, :region] == [2, 1]
@test region_observer![30, :energy] < -4.25
@test region_observer![30, :energy] e rtol = 1e-6
end

@testset "Cache to Disk" begin
Expand All @@ -126,7 +129,7 @@ end
nsweeps = 4
maxdim = [10, 20, 40, 80]

@test_broken psi = dmrg(
@test_broken e, psi = dmrg(
H,
psi;
nsweeps,
Expand Down Expand Up @@ -160,7 +163,7 @@ end
maxdim = [200, 250, 400, 600, 800, 1200, 2000, 2400, 2600, 3000]
cutoff = [1e-10, 1e-10, 1e-12, 1e-12, 1e-12, 1e-12, 1e-14, 1e-14, 1e-14, 1e-14]

psi = dmrg(H, psi; nsweeps, maxdim, cutoff)
e, psi = dmrg(H, psi; nsweeps, maxdim, cutoff)
end

@testset "Tree DMRG" for nsites in [2]
Expand Down Expand Up @@ -195,7 +198,7 @@ end
nsweeps = 10
maxdim = [10, 20, 40, 100]
@show use_qns
psi = dmrg(
e, psi = dmrg(
H, psi; nsweeps, maxdim, cutoff, nsites, updater_kwargs=(; krylovdim=3, maxiter=1)
)

Expand Down Expand Up @@ -252,7 +255,7 @@ end
end
states = v -> d[v]
psi = ttn(states, s)
psi = dmrg(
e, psi = dmrg(
H, psi; nsweeps, maxdim, cutoff, nsites, updater_kwargs=(; krylovdim=3, maxiter=1)
)

Expand Down Expand Up @@ -280,7 +283,7 @@ end
os = ModelHamiltonians.heisenberg(c)
H = ttn(os, s)
psi = random_ttn(s; link_space=5)
psi = dmrg(H, psi; nsweeps, maxdim, nsites)
e, psi = dmrg(H, psi; nsweeps, maxdim, nsites)

@test all(edge_data(linkdims(psi)) .<= maxdim)
end
Expand Down
13 changes: 9 additions & 4 deletions test/test_treetensornetworks/test_solvers/test_dmrg_x.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ using NamedGraphs.NamedGraphGenerators: named_comb_tree
using Random: Random
using Test: @test, @testset

# TODO: Combine MPS and TTN tests.
@testset "MPS DMRG-X" for conserve_qns in (false, true)
n = 10
s = siteinds("S=1/2", n; conserve_qns)
Expand All @@ -25,14 +26,16 @@ using Test: @test, @testset

dmrg_x_kwargs = (nsweeps=20, normalize=true, maxdim=20, cutoff=1e-10, outputlevel=0)

ϕ = dmrg_x(H, ψ; nsites=2, dmrg_x_kwargs...)
e, ϕ = dmrg_x(H, ψ; nsites=2, dmrg_x_kwargs...)

@test inner', H, ϕ) / inner(ϕ, ϕ) e
@test inner', H, ψ) / inner(ψ, ψ) inner', H, ϕ) / inner(ϕ, ϕ) rtol = 1e-1
@test inner(H, ψ, H, ψ) inner', H, ψ)^2 rtol = 1e-7
@test inner(H, ϕ, H, ϕ) inner', H, ϕ)^2 rtol = 1e-7

ϕ̃ = dmrg_x(H, ϕ; nsites=1, dmrg_x_kwargs...)
e, ϕ̃ = dmrg_x(H, ϕ; nsites=1, dmrg_x_kwargs...)

@test inner(ϕ̃', H, ϕ̃) / inner(ϕ̃, ϕ̃) e
@test inner', H, ψ) / inner(ψ, ψ) inner(ϕ̃', H, ϕ̃) / inner(ϕ̃, ϕ̃) rtol = 1e-1
@test inner(H, ϕ̃, H, ϕ̃) inner(ϕ̃', H, ϕ̃)^2 rtol = 1e-3
# Sometimes broken, sometimes not
Expand All @@ -56,14 +59,16 @@ end

dmrg_x_kwargs = (nsweeps=20, normalize=true, maxdim=20, cutoff=1e-10, outputlevel=0)

ϕ = dmrg_x(H, ψ; nsites=2, dmrg_x_kwargs...)
e, ϕ = dmrg_x(H, ψ; nsites=2, dmrg_x_kwargs...)

@test inner', H, ϕ) / inner(ϕ, ϕ) e
@test inner', H, ψ) / inner(ψ, ψ) inner', H, ϕ) / inner(ϕ, ϕ) rtol = 1e-1
@test inner(H, ψ, H, ψ) inner', H, ψ)^2 rtol = 1e-2
@test inner(H, ϕ, H, ϕ) inner', H, ϕ)^2 rtol = 1e-7

ϕ̃ = dmrg_x(H, ϕ; nsites=1, dmrg_x_kwargs...)
e, ϕ̃ = dmrg_x(H, ϕ; nsites=1, dmrg_x_kwargs...)

@test inner(ϕ̃', H, ϕ̃) / inner(ϕ̃, ϕ̃) e
@test inner', H, ψ) / inner(ψ, ψ) inner(ϕ̃', H, ϕ̃) / inner(ϕ̃, ϕ̃) rtol = 1e-1
@test inner(H, ϕ̃, H, ϕ̃) inner(ϕ̃', H, ϕ̃)^2 rtol = 1e-6
# Sometimes broken, sometimes not
Expand Down

0 comments on commit 4fea5e2

Please sign in to comment.