Skip to content

Commit

Permalink
modify the implementation for extracting values from ObsTree
Browse files Browse the repository at this point in the history
  • Loading branch information
qyli committed Apr 20, 2024
1 parent b289d88 commit e4d6848
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 91 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "FiniteMPS"
uuid = "6b572690-f317-4dad-a5fe-5fe73a0b7d42"
authors = ["qyli <[email protected]>"]
version = "1.3.0"
version = "1.4.0"

[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ end
calObs!(Tree, Ψ)
# collect the results from Tree
Obs = convert(Dict, Tree, [(:Sz, :Sz), (:Sz,)])
Obs = convert(NamedTuple, Tree)
```

Now you can obtain the spin correlation $\langle S_i^z S_j^z\rangle$ via `Obs.SzSz[(i,j)]` and local moment $\langle S_i^z \rangle$ via `Obs.Sz[(i,)]` (should be zero up to a noise due to the $SU_2$ symmetry of the Heisenberg model).
Expand Down
4 changes: 2 additions & 2 deletions example/Heisenberg_DMRG/main.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ Obs = let
@time calObs!(Tree, Ψ; GCspacing=1000, verbose=verbose, showtimes=10)

if Sym == :U₁
convert(Dict, Tree, [(:Sz, :Sz), (:Su, :Sd),])
convert(Dict, Tree)
elseif Sym == :SU₂
convert(Dict, Tree, [(:S, :S),])
convert(Dict, Tree)
end
end

2 changes: 1 addition & 1 deletion example/Hubbard_DMRG/main.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,6 @@ Obs = let

@time calObs!(Tree, Ψ; GCspacing=1000, verbose=verbose, showtimes=10)

convert(Dict, Tree, [(:n,), (:S, :S), (:n, :n), (:Fdag, :F), (:Fdag, :FdagS, :FS, :F), (:Fdag, :FdagT, :FT, :F)])
convert(Dict, Tree)
end

15 changes: 15 additions & 0 deletions src/IntrTree/Node.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ mutable struct InteractionTreeNode{T}
value::Union{Nothing, T}
parent::Union{Nothing,InteractionTreeNode}
children::Vector{InteractionTreeNode}
function InteractionTreeNode{T}(Op::Union{Nothing,AbstractLocalOperator},
value::T,
parent::Union{Nothing,InteractionTreeNode} = nothing,
children::Vector{InteractionTreeNode} = InteractionTreeNode[]) where T
return new{T}(Op, value, parent, children)
end
function InteractionTreeNode(Op::Union{Nothing,AbstractLocalOperator},
value::T,
parent::Union{Nothing,InteractionTreeNode},
Expand Down Expand Up @@ -74,6 +80,15 @@ function addchild!(node::InteractionTreeNode, Op::AbstractLocalOperator, value)
child = InteractionTreeNode(Op, value, node)
return addchild!(node, child)
end
# for Obs tree
function addchild!(node::InteractionTreeNode{T}, Op::AbstractLocalOperator, ::Nothing) where T <: Tuple{String, Vararg{Int64}}
# convert nothing to the required type
return addchild!(node, Op, ("",))
end
function addchild!(node::InteractionTreeNode{T}, Op::AbstractLocalOperator, value::Tuple{String, Vararg{Int64}} = ("",)) where T <: Tuple{String, Vararg{Int64}}
child = InteractionTreeNode{Tuple{String, Vararg{Int64}}}(Op, value, node)
return addchild!(node, child)
end

"""
struct InteractionTree{N, T}
Expand Down
3 changes: 3 additions & 0 deletions src/IntrTree/addIntr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ Generic function to add an N-site interaction via `addIntr1!`, `addIntr2!` and `
name::NTuple{N,Union{Symbol,String}}
Detailed usage of kwargs see `addIntr1!`, `addIntr2!` and `addIntr4!`.
Obs::Bool = false
`Obs == true` means this interaction is used for calculating observables, and thus the `name` and `si` information will be stored in the last node additionally.
"""
function addIntr!(Root::InteractionTreeNode,
Op::NTuple{1,AbstractTensorMap},
Expand Down
23 changes: 17 additions & 6 deletions src/IntrTree/addIntr1.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,36 @@
Op::AbstractTensorMap,
si::Int64,
strength::Number;
Obs::Bool = false,
name::Union{Symbol,String} = :O) -> nothing
addIntr1!(Tree::InteractionTree, args...) = addIntr1!(Tree.Root.children[1], args...)
Add an on-site term `Op` at site `si` to a given interaction tree.
addIntr1!(Root::InteractionTreeNode, O::LocalOperator, strength::Number) -> nothing
addIntr1!(Root::InteractionTreeNode,
O::LocalOperator,
strength::Number;
value = nothing) -> nothing
Expert version, each method finally reduces to this one.
Expert version, each method finally reduces to this one. The `value` will be stored in the last node.
"""
function addIntr1!(Root::InteractionTreeNode, Op::AbstractTensorMap, si::Int64, strength::Number;
Obs::Bool=false,
name::Union{Symbol,String}=:O)
# add on-site term
# convert to string
name = string(name)

strength == 0 && return nothing
O = LocalOperator(Op, name, si)
return addIntr1!(Root, O, strength)

return addIntr1!(Root, O, strength; value = Obs ? (name, si) : nothing)


end
addIntr1!(Tree::InteractionTree, args...; kwargs...) = addIntr1!(Tree.Root.children[1], args...; kwargs...)

function addIntr1!(Root::InteractionTreeNode, O::LocalOperator, strength::Number)
function addIntr1!(Root::InteractionTreeNode, O::LocalOperator, strength::Number; value=nothing)
current_node = Root
si = 1
pspace = getPhysSpace(O)
Expand All @@ -44,9 +52,12 @@ function addIntr1!(Root::InteractionTreeNode, O::LocalOperator, strength::Number

idx = findfirst(x -> x.Op == O, current_node.children)
if isnothing(idx)
addchild!(current_node, O)
addchild!(current_node, O, value)
current_node.children[end].Op.strength = strength
else
if !isnothing(value)
current_node.children[idx].value = value
end
_update_strength!(current_node.children[idx], strength) && deleteat!(current_node.children, idx)
end

Expand Down
33 changes: 22 additions & 11 deletions src/IntrTree/addIntr2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Op::NTuple{2,AbstractTensorMap},
si::NTuple{2,Int64},
strength::Number;
Obs::Bool = false,
Z::Union{Nothing,AbstractTensorMap} = nothing,
name::NTuple{2,Union{Symbol,String}} = (:A, :B)) -> nothing
Expand All @@ -14,44 +15,51 @@ Add a two-site interaction `Op` at site `si` (2tuple) to a given interaction tre
OL::LocalOperator,
OR::LocalOperator,
strength::Number,
Z::Union{Nothing,AbstractTensorMap}) -> nothing
Z::Union{Nothing,AbstractTensorMap};
value = nothing) -> nothing
Expert version, each method finally reduces to this one.
Expert version, each method finally reduces to this one. The `value` will be stored in the last node.
Note if `OL.si == OR.si`, it will recurse to `addIntr1!` automatically.
"""
function addIntr2!(Root::InteractionTreeNode, Op::NTuple{2,AbstractTensorMap}, si::NTuple{2,Int64}, strength::Number;
Obs::Bool=false,
Z::Union{Nothing,AbstractTensorMap}=nothing,
name::NTuple{2,Union{Symbol,String}}=(:A, :B))
# add two site interaction term

# convert to string
name = string.(name)

strength == 0 && return nothing
value = Obs ? (prod(name), si...) : nothing

if si[1] == si[2]
OL = LocalOperator(Op[1], name[1], si[1])
OR = LocalOperator(Op[2], name[2], si[2])
return addIntr1!(Root, OL*OR, strength)
return addIntr1!(Root, OL * OR, strength; value=value)
end

if si[1] < si[2]
OL = LocalOperator(Op[1], name[1], si[1])
OR = LocalOperator(Op[2], name[2], si[2])
!isnothing(Z) && _addZ!(OR, Z)
else
OL = LocalOperator(Op[2], name[2], si[2]; swap = true)
OR = LocalOperator(Op[1], name[1], si[1]; swap = true)
OL = LocalOperator(Op[2], name[2], si[2]; swap=true)
OR = LocalOperator(Op[1], name[1], si[1]; swap=true)
if !isnothing(Z)
_addZ!(OR, Z)
strength = - strength # note ZFZ = -F
strength = -strength # note ZFZ = -F
end
end
return addIntr2!(Root, OL, OR, strength, Z)
return addIntr2!(Root, OL, OR, strength, Z; value=value)

end
addIntr2!(Tree::InteractionTree, args...) = addIntr2!(Tree.Root.children[1], args...)

function addIntr2!(Root::InteractionTreeNode, OL::LocalOperator, OR::LocalOperator,
strength::Number, Z::Union{Nothing,AbstractTensorMap})
function addIntr2!(Root::InteractionTreeNode,
OL::LocalOperator, OR::LocalOperator,
strength::Number, Z::Union{Nothing,AbstractTensorMap};
value=nothing)
@assert OL.si < OR.si

current_node = Root
Expand Down Expand Up @@ -79,9 +87,12 @@ function addIntr2!(Root::InteractionTreeNode, OL::LocalOperator, OR::LocalOperat

idx = findfirst(x -> x.Op == OR, current_node.children)
if isnothing(idx)
addchild!(current_node, OR)
addchild!(current_node, OR, value)
current_node.children[end].Op.strength = strength
else
if !isnothing(value)
current_node.children[idx].value = value
end
_update_strength!(current_node.children[idx], strength) && deleteat!(current_node.children, idx)
end

Expand Down
43 changes: 28 additions & 15 deletions src/IntrTree/addIntr4.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Op::NTuple{4,AbstractTensorMap},
si::NTuple{4,Int64},
strength::Number;
Obs::Bool = false,
Z::Union{Nothing,AbstractTensorMap} = nothing,
name::NTuple{4,Union{Symbol,String}} = (:A, :B, :C, :D)) -> nothing
Expand All @@ -16,16 +17,24 @@ Add a 4-site interaction `Op` at site `si` (4tuple) to a given interaction tree.
C::LocalOperator,
D::LocalOperator,
strength::Number,
Z::Union{Nothing,AbstractTensorMap}) -> nothing
Z::Union{Nothing,AbstractTensorMap};
value = nothing) -> nothing
Expert version, each method finally reduces to this one.
Note if there exist repeated si, it will recurse to `addIntr2!` or `addIntr3!`(TODO) automatically.
"""
function addIntr4!(Root::InteractionTreeNode, O::NTuple{4,AbstractTensorMap}, si::NTuple{4,Int64}, strength::Number;
Obs::Bool=false,
Z::Union{Nothing,AbstractTensorMap}=nothing,
name::NTuple{4,Union{Symbol,String}}=(:A, :B, :C, :D))

# convert to string
name = string.(name)

strength == 0 && return nothing
value = Obs ? (prod(name), si...) : nothing

(A, B, C, D) = map(1:4) do i
LocalOperator(O[i], name[i], si[i])
end
Expand All @@ -49,7 +58,7 @@ function addIntr4!(Root::InteractionTreeNode, O::NTuple{4,AbstractTensorMap}, si
# B --> AC
# A Z Z Z Z
!isnothing(Z) && (strength = -strength)
return addIntr2!(Root, _leftOp(A * C), _rightOp(B * D), strength)
return addIntr2!(Root, _leftOp(A * C), _rightOp(B * D), strength, nothing; value = value)
end
# ============ reduce to 3-site term ===========
if A.si == C.si
Expand All @@ -59,21 +68,21 @@ function addIntr4!(Root::InteractionTreeNode, O::NTuple{4,AbstractTensorMap}, si
# B --> AC -B Z Z
# A Z Z
!isnothing(Z) && (strength = -strength)
return addIntr3!(Root, _leftOp(A * C), B, D, strength, Z; fermionic=(false, true, true))
return addIntr3!(Root, _leftOp(A * C), B, D, strength, Z; fermionic=(false, true, true), value = value)
else
# D
# C Z Z B
# B --> AC D Z Z
# A Z Z Z Z
return addIntr3!(Root, _leftOp(A * C), D, _rightOp(B), strength, Z; fermionic=(false, true, true))
return addIntr3!(Root, _leftOp(A * C), D, _rightOp(B), strength, Z; fermionic=(false, true, true), value = value)
end
end
if B.si == C.si
# D
# C Z Z BC D
# B --> A Z Z Z Z
# A Z Z
return addIntr3!(Root, A, B * C, D, strength, Z; fermionic=(true, false, false))
return addIntr3!(Root, A, B * C, D, strength, Z; fermionic=(true, false, false), value = value)
end
if B.si == D.si
if A.si < C.si
Expand All @@ -82,14 +91,14 @@ function addIntr4!(Root::InteractionTreeNode, O::NTuple{4,AbstractTensorMap}, si
# B --> A Z Z
# A Z Z Z Z
!isnothing(Z) && (strength = -strength)
return addIntr3!(Root, A, _leftOp(C), _rightOp(B * D), strength, Z; fermionic=(true, true, false))
return addIntr3!(Root, A, _leftOp(C), _rightOp(B * D), strength, Z; fermionic=(true, true, false), value = value)
else
# note AZ = -ZA
# D
# C Z Z Z Z -A -BD A BD
# B --> C Z Z --> C Z Z
# A Z Z
return addIntr3!(Root, _leftOp(C), A, _rightOp(B * D), strength, Z; fermionic=(true, true, false))
return addIntr3!(Root, _leftOp(C), A, _rightOp(B * D), strength, Z; fermionic=(true, true, false), value = value)
end
end
# ----------------------------------------------
Expand All @@ -98,7 +107,7 @@ function addIntr4!(Root::InteractionTreeNode, O::NTuple{4,AbstractTensorMap}, si
# C Z Z
# B
# A Z Z
return addIntr4!(Root, A, B, C, D, strength, Z)
return addIntr4!(Root, A, B, C, D, strength, Z; value = value)
else
if A.si < C.si
if B.si < D.si
Expand All @@ -107,36 +116,36 @@ function addIntr4!(Root::InteractionTreeNode, O::NTuple{4,AbstractTensorMap}, si
# B --> C
# A Z Z Z Z A Z Z
!isnothing(Z) && (strength = -strength)
return addIntr4!(Root, A, _leftOp(C), _rightOp(B), D, strength, Z)
return addIntr4!(Root, A, _leftOp(C), _rightOp(B), D, strength, Z; value = value)
else
A.si < C.si && B.si > D.si
# D B
# C Z Z D Z Z
# B --> C
# A Z Z Z Z Z Z A Z Z
return addIntr4!(Root, A, _leftOp(C), D, _rightOp(B), strength, Z)
return addIntr4!(Root, A, _leftOp(C), D, _rightOp(B), strength, Z; value = value)
end
elseif A.si < D.si
if B.si < D.si
# D
# C Z Z Z Z Z Z D D
# B --> -A -B Z Z --> A B Z Z
# A Z Z C Z Z C Z Z
return addIntr4!(Root, _leftOp(C), A, _rightOp(B), D, strength, Z)
return addIntr4!(Root, _leftOp(C), A, _rightOp(B), D, strength, Z; value = value)
else
# D
# C Z Z Z Z B
# B --> -A D Z Z
# A Z Z Z Z C Z Z
!isnothing(Z) && (strength = -strength)
return addIntr4!(Root, _leftOp(C), A, D, _rightOp(B), strength, Z)
return addIntr4!(Root, _leftOp(C), A, D, _rightOp(B), strength, Z; value = value)
end
else
# D
# C Z Z
# B
# A Z Z
return addIntr4!(Root, _leftOp(C), D, A, _rightOp(B), strength, Z)
return addIntr4!(Root, _leftOp(C), D, A, _rightOp(B), strength, Z; value = value)
end
end

Expand All @@ -145,7 +154,8 @@ function addIntr4!(Root::InteractionTreeNode, O::NTuple{4,AbstractTensorMap}, si
end

function addIntr4!(Root::InteractionTreeNode, A::LocalOperator, B::LocalOperator, C::LocalOperator, D::LocalOperator,
strength::Number, Z::Union{Nothing,AbstractTensorMap})
strength::Number, Z::Union{Nothing,AbstractTensorMap};
value = nothing)
@assert A.si < B.si < C.si < D.si

# D
Expand Down Expand Up @@ -192,9 +202,12 @@ function addIntr4!(Root::InteractionTreeNode, A::LocalOperator, B::LocalOperator

idx = findfirst(x -> x.Op == D, current_node.children)
if isnothing(idx)
addchild!(current_node, D)
addchild!(current_node, D, value)
current_node.children[end].Op.strength = strength
else
if !isnothing(value)
current_node.children[idx].value = value
end
_update_strength!(current_node.children[idx], strength) && deleteat!(current_node.children, idx)
end

Expand Down
Loading

2 comments on commit e4d6848

@Qiaoyi-Li
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register

Release notes:

  • fix the bug in ObservableTree which may give an incorrect sign for some 4-site fermionic correlations.
  • note the type parameter of the tree nodes in ObservableTree is different from old versions.
  • rewrite the implementation (method convert) for extracting the values stored in ObservableTree. The usage changes from
convert(Type, Tree::ObservableTree, name::NTuple{N, String})

to

convert(Type, Tree::ObservableTree)

where the supported Type contains Dict and NamedTuple. Passing in the name that corresponds to the correlation is no long needed.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/105299

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.4.0 -m "<description of version>" e4d6848ab0de859fe93210021986731d8ede3fa6
git push origin v1.4.0

Please sign in to comment.