Skip to content

Commit

Permalink
trivial_space cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
mtfishman committed Apr 10, 2024
1 parent a3e69dd commit 59292f4
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 130 deletions.
36 changes: 18 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,13 @@ and 4 edge(s):

with vertex data:
4-element Dictionaries.Dictionary{Tuple{Int64, Int64}, Any}
(1, 1) │ ((dim=2|id=712|"1×1,2×1"), (dim=2|id=598|"1×1,1×2"))
(2, 1) │ ((dim=2|id=712|"1×1,2×1"), (dim=2|id=457|"2×1,2×2"))
(1, 2) │ ((dim=2|id=598|"1×1,1×2"), (dim=2|id=683|"1×2,2×2"))
(2, 2) │ ((dim=2|id=457|"2×1,2×2"), (dim=2|id=683|"1×2,2×2"))
(1, 1) │ ((dim=2|id=74|"1×1,2×1"), (dim=2|id=723|"1×1,1×2"))
(2, 1) │ ((dim=2|id=74|"1×1,2×1"), (dim=2|id=823|"2×1,2×2"))
(1, 2) │ ((dim=2|id=723|"1×1,1×2"), (dim=2|id=712|"1×2,2×2"))
(2, 2) │ ((dim=2|id=823|"2×1,2×2"), (dim=2|id=712|"1×2,2×2"))

julia> tn[1, 1]
ITensor ord=2 (dim=2|id=712|"1×1,2×1") (dim=2|id=598|"1×1,1×2")
ITensor ord=2 (dim=2|id=74|"1×1,2×1") (dim=2|id=723|"1×1,1×2")
NDTensors.EmptyStorage{NDTensors.EmptyNumber, NDTensors.Dense{NDTensors.EmptyNumber, Vector{NDTensors.EmptyNumber}}}

julia> neighbors(tn, (1, 1))
Expand All @@ -135,8 +135,8 @@ and 1 edge(s):

with vertex data:
2-element Dictionaries.Dictionary{Tuple{Int64, Int64}, Any}
(1, 1) │ ((dim=2|id=712|"1×1,2×1"), (dim=2|id=598|"1×1,1×2"))
(1, 2) │ ((dim=2|id=598|"1×1,1×2"), (dim=2|id=683|"1×2,2×2"))
(1, 1) │ ((dim=2|id=74|"1×1,2×1"), (dim=2|id=723|"1×1,1×2"))
(1, 2) │ ((dim=2|id=723|"1×1,1×2"), (dim=2|id=712|"1×2,2×2"))

julia> tn_2 = subgraph(v -> v[1] == 2, tn)
ITensorNetworks.ITensorNetwork{Tuple{Int64, Int64}} with 2 vertices:
Expand All @@ -149,8 +149,8 @@ and 1 edge(s):

with vertex data:
2-element Dictionaries.Dictionary{Tuple{Int64, Int64}, Any}
(2, 1) │ ((dim=2|id=712|"1×1,2×1"), (dim=2|id=457|"2×1,2×2"))
(2, 2) │ ((dim=2|id=457|"2×1,2×2"), (dim=2|id=683|"1×2,2×2"))
(2, 1) │ ((dim=2|id=74|"1×1,2×1"), (dim=2|id=823|"2×1,2×2"))
(2, 2) │ ((dim=2|id=823|"2×1,2×2"), (dim=2|id=712|"1×2,2×2"))
```


Expand All @@ -176,9 +176,9 @@ and 2 edge(s):

with vertex data:
3-element Dictionaries.Dictionary{Int64, Vector{ITensors.Index}}
1 │ ITensors.Index[(dim=2|id=830|"S=1/2,Site,n=1")]
2 │ ITensors.Index[(dim=2|id=369|"S=1/2,Site,n=2")]
3 │ ITensors.Index[(dim=2|id=558|"S=1/2,Site,n=3")]
1 │ ITensors.Index[(dim=2|id=683|"S=1/2,Site,n=1")]
2 │ ITensors.Index[(dim=2|id=123|"S=1/2,Site,n=2")]
3 │ ITensors.Index[(dim=2|id=656|"S=1/2,Site,n=3")]

and edge data:
0-element Dictionaries.Dictionary{NamedGraphs.NamedEdge{Int64}, Vector{ITensors.Index}}
Expand All @@ -196,9 +196,9 @@ and 2 edge(s):

with vertex data:
3-element Dictionaries.Dictionary{Int64, Any}
1 │ ((dim=2|id=830|"S=1/2,Site,n=1"), (dim=2|id=186|"1,2"))
2 │ ((dim=2|id=369|"S=1/2,Site,n=2"), (dim=2|id=186|"1,2"), (dim=2|id=430|"2,3…
3 │ ((dim=2|id=558|"S=1/2,Site,n=3"), (dim=2|id=430|"2,3"))
1 │ ((dim=2|id=683|"S=1/2,Site,n=1"), (dim=2|id=382|"1,2"))
2 │ ((dim=2|id=123|"S=1/2,Site,n=2"), (dim=2|id=382|"1,2"), (dim=2|id=190|"2,3…
3 │ ((dim=2|id=656|"S=1/2,Site,n=3"), (dim=2|id=190|"2,3"))
julia> tn2 = ITensorNetwork(s; link_space=2)
ITensorNetworks.ITensorNetwork{Int64} with 3 vertices:
Expand All @@ -213,9 +213,9 @@ and 2 edge(s):
with vertex data:
3-element Dictionaries.Dictionary{Int64, Any}
1 │ ((dim=2|id=830|"S=1/2,Site,n=1"), (dim=2|id=994|"1,2"))
2 │ ((dim=2|id=369|"S=1/2,Site,n=2"), (dim=2|id=994|"1,2"), (dim=2|id=978|"2,3
3 │ ((dim=2|id=558|"S=1/2,Site,n=3"), (dim=2|id=978|"2,3"))
1 │ ((dim=2|id=683|"S=1/2,Site,n=1"), (dim=2|id=934|"1,2"))
2 │ ((dim=2|id=123|"S=1/2,Site,n=2"), (dim=2|id=934|"1,2"), (dim=2|id=614|"2,3
3 │ ((dim=2|id=656|"S=1/2,Site,n=3"), (dim=2|id=614|"2,3"))

julia> @visualize tn1;
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Expand Down
4 changes: 2 additions & 2 deletions src/ModelNetworks/ModelNetworks.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module ModelNetworks
using Graphs: degree, dst, edges, src
using ..ITensorNetworks: IndsNetwork, delta_network, insert_missing_internal_inds, itensor
using ..ITensorNetworks: IndsNetwork, delta_network, insert_linkinds, itensor
using ITensors: commoninds, diagITensor, inds, noprime
using LinearAlgebra: Diagonal, eigen
using NamedGraphs: NamedGraph
Expand All @@ -17,7 +17,7 @@ OPTIONAL ARGUMENT:
function ising_network(
eltype::Type, s::IndsNetwork, beta::Number; h::Number=0.0, szverts=nothing
)
s = insert_missing_internal_inds(s, edges(s); internal_inds_space=2)
s = insert_linkinds(s; link_space=2)
tn = delta_network(eltype, s)
if (szverts != nothing)
for v in szverts
Expand Down
67 changes: 62 additions & 5 deletions src/abstractindsnetwork.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,47 @@ end
# TODO: Define a generic fallback for `AbstractDataGraph`?
DataGraphs.edge_data_type(::Type{<:AbstractIndsNetwork{V,I}}) where {V,I} = Vector{I}

function indsnetwork_getindex(is::AbstractIndsNetwork, index)
return get(data_graph(is), index, indtype(is)[])
end

function Base.getindex(is::AbstractIndsNetwork, index)
return indsnetwork_getindex(is, index)
end

function Base.getindex(is::AbstractIndsNetwork, index::Pair)
return indsnetwork_getindex(is, index)
end

function Base.getindex(is::AbstractIndsNetwork, index::AbstractEdge)
return indsnetwork_getindex(is, index)
end

function indsnetwork_setindex!(is::AbstractIndsNetwork, value, index)
data_graph(is)[index] = value
return is
end

function Base.setindex!(is::AbstractIndsNetwork, value, index)
indsnetwork_setindex!(is, value, index)
return is
end

function Base.setindex!(is::AbstractIndsNetwork, value, index::Pair)
indsnetwork_setindex!(is, value, index)
return is
end

function Base.setindex!(is::AbstractIndsNetwork, value, index::AbstractEdge)
indsnetwork_setindex!(is, value, index)
return is
end

function Base.setindex!(is::AbstractIndsNetwork, value::Index, index)
indsnetwork_setindex!(is, value, index)
return is
end

#
# Index access
#
Expand All @@ -39,8 +80,8 @@ function ITensors.uniqueinds(is::AbstractIndsNetwork, edge::Pair)
return uniqueinds(is, edgetype(is)(edge))
end

function Base.union(tn1::AbstractIndsNetwork, tn2::AbstractIndsNetwork; kwargs...)
return IndsNetwork(union(data_graph(tn1), data_graph(tn2); kwargs...))
function Base.union(is1::AbstractIndsNetwork, is2::AbstractIndsNetwork; kwargs...)
return IndsNetwork(union(data_graph(is1), data_graph(is2); kwargs...))
end

function NamedGraphs.rename_vertices(f::Function, tn::AbstractIndsNetwork)
Expand All @@ -51,31 +92,47 @@ end
# Convenience functions
#

function promote_indtypeof(is::AbstractIndsNetwork)
sitetype = mapreduce(promote_indtype, vertices(is); init=Index{Int}) do v
return mapreduce(typeof, promote_indtype, is[v]; init=Index{Int})
end
linktype = mapreduce(promote_indtype, edges(is); init=Index{Int}) do e
return mapreduce(typeof, promote_indtype, is[e]; init=Index{Int})
end
return promote_indtype(sitetype, linktype)
end

function union_all_inds(is_in::AbstractIndsNetwork...)
@assert all(map(ug -> ug == underlying_graph(is_in[1]), underlying_graph.(is_in)))
is_out = IndsNetwork(underlying_graph(is_in[1]))
for v in vertices(is_out)
# TODO: Remove this check.
if any(isassigned(is, v) for is in is_in)
# TODO: Change `get` to `getindex`.
is_out[v] = unioninds([get(is, v, Index[]) for is in is_in]...)
end
end
for e in edges(is_out)
# TODO: Remove this check.
if any(isassigned(is, e) for is in is_in)
# TODO: Change `get` to `getindex`.
is_out[e] = unioninds([get(is, e, Index[]) for is in is_in]...)
end
end
return is_out
end

function insert_missing_internal_inds(
function insert_linkinds(
indsnetwork::AbstractIndsNetwork,
edges=edges(indsnetwork);
internal_inds_space=trivial_space(indsnetwork),
link_space=trivial_space(indsnetwork),
)
indsnetwork = copy(indsnetwork)
for e in edges
# TODO: Change to check if it is empty.
if !isassigned(indsnetwork, e)
iₑ = Index(internal_inds_space, edge_tag(e))
iₑ = Index(link_space, edge_tag(e))
# TODO: Allow setting with just `Index`.
indsnetwork[e] = [iₑ]
end
end
Expand Down
31 changes: 14 additions & 17 deletions src/abstractitensornetwork.jl
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ function Base.union(tn1::AbstractITensorNetwork, tn2::AbstractITensorNetwork; kw
# Add any new edges that are introduced during the union
for v1 in vertices(tn1)
for v2 in vertices(tn2)
if hascommoninds(tn[v1], tn[v2])
if hascommoninds(tn, v1 => v2)
add_edge!(tn, v1 => v2)
end
end
Expand Down Expand Up @@ -174,6 +174,8 @@ function Base.Vector{ITensor}(tn::AbstractITensorNetwork)
end

# Convenience wrapper
# TODO: Delete this and just use `Vector{ITensor}`, or maybe
# it should output a dictionary or be called `eachtensor`?
itensors(tn::AbstractITensorNetwork) = Vector{ITensor}(tn)

#
Expand All @@ -184,10 +186,13 @@ function LinearAlgebra.promote_leaf_eltypes(tn::AbstractITensorNetwork)
return LinearAlgebra.promote_leaf_eltypes(itensors(tn))
end

function trivial_space(tn::AbstractITensorNetwork)
return trivial_space(tn[first(vertices(tn))])
function promote_indtypeof(tn::AbstractITensorNetwork)
return mapreduce(promote_indtype, vertices(tn)) do v
return indtype(tn[v])
end
end

# TODO: Delete in favor of `scalartype`.
function ITensors.promote_itensor_eltype(tn::AbstractITensorNetwork)
return LinearAlgebra.promote_leaf_eltypes(tn)
end
Expand Down Expand Up @@ -871,14 +876,13 @@ function site_combiners(tn::AbstractITensorNetwork{V}) where {V}
return Cs
end

# TODO: Combine with `insert_links`.
function insert_missing_internal_inds(
tn::AbstractITensorNetwork, edges; internal_inds_space=trivial_space(tn)
function insert_linkinds(
tn::AbstractITensorNetwork, edges=edges(tn); link_space=trivial_space(tn)
)
tn = copy(tn)
for e in edges
if !hascommoninds(tn[src(e)], tn[dst(e)])
iₑ = Index(internal_inds_space, edge_tag(e))
if !hascommoninds(tn, e)
iₑ = Index(link_space, edge_tag(e))
X = onehot(iₑ => 1)
tn[src(e)] *= X
tn[dst(e)] *= dag(X)
Expand All @@ -887,13 +891,6 @@ function insert_missing_internal_inds(
return tn
end

# TODO: Combine with `insert_links`.
function insert_missing_internal_inds(
tn::AbstractITensorNetwork; internal_inds_space=trivial_space(tn)
)
return insert_internal_inds(tn, edges(tn); internal_inds_space)
end

# TODO: What to output? Could be an `IndsNetwork`. Or maybe
# that would be a different function `commonindsnetwork`.
# Even in that case, this could output a `Dictionary`
Expand Down Expand Up @@ -923,8 +920,8 @@ function ITensorMPS.add(tn1::AbstractITensorNetwork, tn2::AbstractITensorNetwork

if !issetequal(edges_tn1, edges_tn2)
new_edges = union(edges_tn1, edges_tn2)
tn1 = insert_missing_internal_inds(tn1, new_edges)
tn2 = insert_missing_internal_inds(tn2, new_edges)
tn1 = insert_linkinds(tn1, new_edges)
tn2 = insert_linkinds(tn2, new_edges)
end

edges_tn1, edges_tn2 = edges(tn1), edges(tn2)
Expand Down
66 changes: 22 additions & 44 deletions src/itensornetwork.jl
Original file line number Diff line number Diff line change
Expand Up @@ -126,28 +126,26 @@ end
# Construction from IndsNetwork
#

function ITensorNetwork(
eltype::Type, undef::UndefInitializer, inds_network::IndsNetwork; kwargs...
)
return ITensorNetwork(inds_network; kwargs...) do v
function ITensorNetwork(eltype::Type, undef::UndefInitializer, is::IndsNetwork; kwargs...)
return ITensorNetwork(is; kwargs...) do v
return (inds...) -> ITensor(eltype, undef, inds...)
end
end

function ITensorNetwork(eltype::Type, inds_network::IndsNetwork; kwargs...)
return ITensorNetwork(inds_network; kwargs...) do v
function ITensorNetwork(eltype::Type, is::IndsNetwork; kwargs...)
return ITensorNetwork(is; kwargs...) do v
return (inds...) -> ITensor(eltype, inds...)
end
end

function ITensorNetwork(undef::UndefInitializer, inds_network::IndsNetwork; kwargs...)
return ITensorNetwork(inds_network; kwargs...) do v
function ITensorNetwork(undef::UndefInitializer, is::IndsNetwork; kwargs...)
return ITensorNetwork(is; kwargs...) do v
return (inds...) -> ITensor(undef, inds...)
end
end

function ITensorNetwork(inds_network::IndsNetwork; kwargs...)
return ITensorNetwork(inds_network; kwargs...) do v
function ITensorNetwork(is::IndsNetwork; kwargs...)
return ITensorNetwork(is; kwargs...) do v
return (inds...) -> ITensor(inds...)
end
end
Expand Down Expand Up @@ -191,12 +189,14 @@ function to_callable(value::AbstractArray{<:Any,N}) where {N}
end
to_callable(value) = Returns(value)

function ITensorNetwork(value, inds_network::IndsNetwork; kwargs...)
return ITensorNetwork(to_callable(value), inds_network; kwargs...)
function ITensorNetwork(value, is::IndsNetwork; kwargs...)
return ITensorNetwork(to_callable(value), is; kwargs...)
end

function ITensorNetwork(elt::Type, f, inds_network::IndsNetwork; link_space=1, kwargs...)
tn = ITensorNetwork(f, inds_network; kwargs...)
function ITensorNetwork(
elt::Type, f, is::IndsNetwork; link_space=trivial_space(is), kwargs...
)
tn = ITensorNetwork(f, is; kwargs...)
for v in vertices(tn)
# TODO: Ideally we would use broadcasting, i.e. `elt.(tn[v])`,
# but that doesn't work right now on ITensors.
Expand All @@ -206,48 +206,26 @@ function ITensorNetwork(elt::Type, f, inds_network::IndsNetwork; link_space=1, k
end

function ITensorNetwork(
itensor_constructor::Function, inds_network::IndsNetwork; link_space=1, kwargs...
itensor_constructor::Function, is::IndsNetwork; link_space=trivial_space(is), kwargs...
)
if isnothing(link_space)
# Make sure the link space is set
link_space = 1
end
# Graphs.jl uses `zero` to create a graph of the same type
# without any vertices or edges.
inds_network_merge = typeof(inds_network)(
underlying_graph(inds_network); link_space, kwargs...
)
inds_network = union(inds_network_merge, inds_network)
tn = ITensorNetwork{vertextype(inds_network)}()
for v in vertices(inds_network)
is = insert_linkinds(is; link_space)
tn = ITensorNetwork{vertextype(is)}()
for v in vertices(is)
add_vertex!(tn, v)
end
for e in edges(inds_network)
for e in edges(is)
add_edge!(tn, e)
end
for v in vertices(tn)
siteinds = get(inds_network, v, indtype(inds_network)[])
edges = [edgetype(inds_network)(v, nv) for nv in neighbors(inds_network, v)]
linkinds = map(e -> get(inds_network, e, indtype(inds_network)[]), Indices(edges))
siteinds = is[v]
edges = [edgetype(is)(v, nv) for nv in neighbors(is, v)]
linkinds = map(e -> is[e], Indices(edges))
tensor_v = generic_state(itensor_constructor(v), (; siteinds, linkinds))
setindex_preserve_graph!(tn, tensor_v, v)
end
return tn
end

# TODO: Remove this in favor of `insert_missing_internal_inds`
# or call it a different name, such as `factorize_edges`.
function insert_links::ITensorNetwork, edges::Vector=edges(ψ); cutoff=1e-15)
for e in edges
# Define this to work?
# ψ = factorize(ψ, e; cutoff)
ψᵥ₁, ψᵥ₂ = factorize(ψ[src(e)] * ψ[dst(e)], inds(ψ[src(e)]); cutoff, tags=edge_tag(e))
ψ[src(e)] = ψᵥ₁
ψ[dst(e)] = ψᵥ₂
end
return ψ
end

ITensorNetwork(itns::Vector{ITensorNetwork}) = reduce(, itns)

function Base.Vector{ITensor}::ITensorNetwork)
Expand Down
Loading

0 comments on commit 59292f4

Please sign in to comment.