diff --git a/Project.toml b/Project.toml index ee8154ff6..0158933e7 100644 --- a/Project.toml +++ b/Project.toml @@ -7,7 +7,9 @@ version = "0.8.0-DEV" AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c" Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" DeltaArrays = "10b0fc19-5ccc-4427-889b-d75dd6306188" +ECharts_jll = "ffd69456-1935-58d2-abba-ba12e8909167" EinExprs = "b1794770-133b-4de1-afb4-526377e9f4c5" +Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6" KeywordDispatch = "5888135b-5456-5c80-a1b6-c91ef8180460" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" OMEinsum = "ebe7aa44-baf0-506c-a96f-8464559b3922" @@ -25,7 +27,6 @@ ChainRulesTestUtils = "cdddcdb0-9152-4a09-a978-84456f9df70a" Dagger = "d58978e5-989f-55fb-8d15-ea34adc7bf54" FiniteDifferences = "26cc04aa-876d-5657-8c51-4c34ba976000" GraphMakie = "1ecd5474-83a3-4783-bb4f-06765db800d2" -Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6" ITensorNetworks = "2919e153-833c-4bdc-8836-1ea460a35fc7" ITensors = "9136182c-28ba-11e9-034c-db9fb085ebd5" KrylovKit = "0b1a1467-8014-51b9-945f-bf0ae24f4b77" @@ -60,6 +61,7 @@ ChainRulesTestUtils = "1" Combinatorics = "1.0" Dagger = "0.18" DeltaArrays = "0.1.1" +ECharts_jll = "5" EinExprs = "0.5, 0.6" FiniteDifferences = "0.12" GraphMakie = "0.4,0.5" diff --git a/ext/TenetGraphMakieExt.jl b/ext/TenetGraphMakieExt.jl index bd5e974a1..397000328 100644 --- a/ext/TenetGraphMakieExt.jl +++ b/ext/TenetGraphMakieExt.jl @@ -1,9 +1,9 @@ module TenetGraphMakieExt +using Tenet using GraphMakie using Makie -const Graphs = GraphMakie.Graphs -using Tenet +using Graphs using Combinatorics: combinations const NetworkLayout = GraphMakie.NetworkLayout @@ -46,34 +46,7 @@ function GraphMakie.graphplot!(f::Union{Figure,GridPosition}, tn::TensorNetwork; end function GraphMakie.graphplot!(ax::Union{Axis,Axis3}, tn::TensorNetwork; labels=false, kwargs...) - hypermap = Tenet.hyperflatten(tn) - tn = transform(tn, Tenet.HyperFlatten) - - tensormap = IdDict(tensor => i for (i, tensor) in enumerate(tensors(tn))) - - graph = Graphs.SimpleGraph(length(tensors(tn))) - for i in setdiff(inds(tn; set=:inner), inds(tn; set=:hyper)) - edge_tensors = tensors(tn; intersects=i) - - @assert length(edge_tensors) == 2 - a, b = edge_tensors - - Graphs.add_edge!(graph, tensormap[a], tensormap[b]) - end - - # TODO recognise `copytensors` by using `DeltaArray` or `Diagonal` representations - copytensors = findall(tensor -> any(flatinds -> issetequal(inds(tensor), flatinds), keys(hypermap)), tensors(tn)) - ghostnodes = map(inds(tn; set=:open)) do index - # create new ghost node - Graphs.add_vertex!(graph) - node = Graphs.nv(graph) - - # connect ghost node - tensor = only(tn.indexmap[index]) - Graphs.add_edge!(graph, node, tensormap[tensor]) - - return node - end + tn, graph, _, hypermap, copytensors, ghostnodes = graph_representation(tn) # configure graphics # TODO refactor hardcoded values into constants diff --git a/src/Tenet.jl b/src/Tenet.jl index 46e13c920..a4a4e4cf9 100644 --- a/src/Tenet.jl +++ b/src/Tenet.jl @@ -46,6 +46,8 @@ export PEPS, pPEPS, PEPO, pPEPO export evolve!, expect, overlap +include("Visualization.jl") + # reexports from EinExprs export einexpr, inds diff --git a/src/Transformations.jl b/src/Transformations.jl index 779a7eefa..0575b39d1 100644 --- a/src/Transformations.jl +++ b/src/Transformations.jl @@ -46,7 +46,7 @@ See also: [`HyperGroup`](@ref). """ struct HyperFlatten <: Transformation end -function hyperflatten(tn::TensorNetwork) +function hyperflatten(tn::AbstractTensorNetwork) return Dict( map(inds(tn; set=:hyper)) do hyperindex n = length(tensors(tn; intersects=hyperindex)) diff --git a/src/Visualization.jl b/src/Visualization.jl new file mode 100644 index 000000000..d38bc0fdf --- /dev/null +++ b/src/Visualization.jl @@ -0,0 +1,118 @@ +using ECharts_jll +using Graphs: Graphs, vertices, edges + +function graph_representation(tn::AbstractTensorNetwork) + hypermap = Tenet.hyperflatten(tn) + if !isempty(hypermap) + tn = transform(tn, Tenet.HyperFlatten) + end + tensormap = IdDict(tensor => i for (i, tensor) in enumerate(tensors(tn))) + + graph = Graphs.SimpleGraph(length(tensors(tn))) + for i in setdiff(inds(tn; set=:inner), inds(tn; set=:hyper)) + a, b = tensors(tn; intersects=i) + Graphs.add_edge!(graph, tensormap[a], tensormap[b]) + end + + # TODO recognise `copytensors` by using `DeltaArray` or `Diagonal` representations + hypernodes = findall(tensor -> any(flatinds -> issetequal(inds(tensor), flatinds), keys(hypermap)), tensors(tn)) + ghostnodes = map(inds(tn; set=:open)) do index + # create new ghost node + Graphs.add_vertex!(graph) + node = Graphs.nv(graph) + + # connect ghost node + tensor = only(tn.indexmap[index]) + Graphs.add_edge!(graph, node, tensormap[tensor]) + + return node + end + + return tn, graph, tensormap, hypermap, hypernodes, ghostnodes +end + +Base.show(io::IO, ::MIME"text/html", @nospecialize(tn::AbstractTensorNetwork)) = show(io, MIME"juliavscode/html"(), tn) +function Base.show(io::IO, ::MIME"juliavscode/html", @nospecialize(tn::AbstractTensorNetwork)) + tn, graph, tensormap, hypermap, hypernodes, ghostnodes = graph_representation(tn) + hypermap = Dict(Iterators.flatten([[i => v for i in k] for (k, v) in hypermap])) + + appid = gensym("tenet-graph") + return print( + io, + """ + +
+ + """, + ) +end