diff --git a/Project.toml b/Project.toml index bd5f615c..27703289 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "ITensorNetworksNext" uuid = "302f2e75-49f0-4526-aef7-d8ba550cb06c" -version = "0.6.1" +version = "0.7.0" authors = ["ITensor developers and contributors"] [workspace] @@ -30,7 +30,7 @@ Combinatorics = "1" DataGraphs = "0.4" Dictionaries = "0.4.5" Graphs = "1.13.1" -ITensorBase = "0.6.3" +ITensorBase = "0.7" LinearAlgebra = "1.10" MacroTools = "0.5.16" MatrixAlgebraKit = "0.6" @@ -38,5 +38,5 @@ NamedGraphs = "0.11" Random = "1.10" SimpleTraits = "0.9.5" SplitApplyCombine = "1.2.3" -TensorAlgebra = "0.9.7" +TensorAlgebra = "0.10" julia = "1.10" diff --git a/docs/Project.toml b/docs/Project.toml index 1d282003..f01c94b8 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -10,5 +10,5 @@ path = ".." [compat] Documenter = "1" ITensorFormatter = "0.2.27" -ITensorNetworksNext = "0.6" +ITensorNetworksNext = "0.7" Literate = "2" diff --git a/docs/src/reference.md b/docs/src/reference.md index e61d6719..4b4c04c0 100644 --- a/docs/src/reference.md +++ b/docs/src/reference.md @@ -1,5 +1,5 @@ # Reference ```@autodocs -Modules = [ITensorNetworksNext, ITensorNetworksNext.TensorNetworkGenerators] +Modules = [ITensorNetworksNext, ITensorNetworksNext.ITensorNetworkGenerators] ``` diff --git a/examples/Project.toml b/examples/Project.toml index 9a198288..ad5bc0be 100644 --- a/examples/Project.toml +++ b/examples/Project.toml @@ -5,4 +5,4 @@ ITensorNetworksNext = "302f2e75-49f0-4526-aef7-d8ba550cb06c" path = ".." [compat] -ITensorNetworksNext = "0.6" +ITensorNetworksNext = "0.7" diff --git a/src/TensorNetworkGenerators/TensorNetworkGenerators.jl b/src/ITensorNetworkGenerators/ITensorNetworkGenerators.jl similarity index 75% rename from src/TensorNetworkGenerators/TensorNetworkGenerators.jl rename to src/ITensorNetworkGenerators/ITensorNetworkGenerators.jl index 96dae416..3fdc851a 100644 --- a/src/TensorNetworkGenerators/TensorNetworkGenerators.jl +++ b/src/ITensorNetworkGenerators/ITensorNetworkGenerators.jl @@ -1,4 +1,4 @@ -module TensorNetworkGenerators +module ITensorNetworkGenerators export delta_network, ising_network diff --git a/src/TensorNetworkGenerators/delta_network.jl b/src/ITensorNetworkGenerators/delta_network.jl similarity index 76% rename from src/TensorNetworkGenerators/delta_network.jl rename to src/ITensorNetworkGenerators/delta_network.jl index 3af29120..7b1370a9 100644 --- a/src/TensorNetworkGenerators/delta_network.jl +++ b/src/ITensorNetworkGenerators/delta_network.jl @@ -1,6 +1,6 @@ -using ..ITensorNetworksNext: TensorNetwork +using ..ITensorNetworksNext: ITensorNetwork using Graphs: AbstractGraph -using ITensorBase: NamedUnitRange, denamed, name, nameddims +using ITensorBase: NamedUnitRange, name, nameddims, unnamed using NamedGraphs.GraphsExtensions: incident_edges diaglength(a::AbstractArray) = minimum(size(a)) @@ -29,20 +29,20 @@ function diagonaltensor( diag::AbstractVector, is::Tuple{NamedUnitRange, Vararg{NamedUnitRange}} ) - return nameddims(diagonaltensor(diag, denamed.(is)), name.(is)) + return nameddims(diagonaltensor(diag, unnamed.(is)), name.(is)) end -delta(elt::Type, is) = diagonaltensor(ones(elt, minimum(length ∘ denamed, is)), is) +delta(elt::Type, is) = diagonaltensor(ones(elt, minimum(length, is)), is) """ delta_network(f, elt::Type = Float64, g::AbstractGraph) -Construct a TensorNetwork on the graph `g` with element type `elt` that has delta tensors +Construct a ITensorNetwork on the graph `g` with element type `elt` that has delta tensors on each vertex. Link dimensions are defined using the function `f(e)` that should take an edge `e` as an input and should output the link index on that edge. """ function delta_network(f, elt::Type, g::AbstractGraph) - return tn = TensorNetwork(g) do v + return tn = ITensorNetwork(g) do v is = Tuple(f.(incident_edges(g, v))) return delta(elt, is) end diff --git a/src/TensorNetworkGenerators/ising_network.jl b/src/ITensorNetworkGenerators/ising_network.jl similarity index 94% rename from src/TensorNetworkGenerators/ising_network.jl rename to src/ITensorNetworkGenerators/ising_network.jl index 86c66aa1..3cdf9a26 100644 --- a/src/TensorNetworkGenerators/ising_network.jl +++ b/src/ITensorNetworkGenerators/ising_network.jl @@ -18,7 +18,7 @@ end """ ising_network(f, β::Number, g::AbstractGraph) -Construct a TensorNetwork on the graph `g` with inverse temperature `β` that has Ising +Construct a ITensorNetwork on the graph `g` with inverse temperature `β` that has Ising partition function tensors on each vertex. Link dimensions are defined using the function `f(e)` that should take an edge `e` as an input and should output the link index on that edge. diff --git a/src/ITensorNetworksNext.jl b/src/ITensorNetworksNext.jl index 50f3970e..92a541f1 100644 --- a/src/ITensorNetworksNext.jl +++ b/src/ITensorNetworksNext.jl @@ -12,7 +12,7 @@ include("select_algorithm.jl") include("AlgorithmsInterfaceExtensions/AlgorithmsInterfaceExtensions.jl") include("abstracttensornetwork.jl") include("tensornetwork.jl") -include("TensorNetworkGenerators/TensorNetworkGenerators.jl") +include("ITensorNetworkGenerators/ITensorNetworkGenerators.jl") include("contract_network.jl") include("beliefpropagation/messagecache.jl") diff --git a/src/abstracttensornetwork.jl b/src/abstracttensornetwork.jl index 809f9e4f..664a224b 100644 --- a/src/abstracttensornetwork.jl +++ b/src/abstracttensornetwork.jl @@ -11,13 +11,13 @@ using NamedGraphs.GraphsExtensions: directed_graph, incident_edges, rem_edges!, using NamedGraphs.OrdinalIndexing: OrdinalSuffixedInteger using NamedGraphs: NamedGraphs, NamedGraph, not_implemented, similar_graph -abstract type AbstractTensorNetwork{V, VD} <: AbstractDataGraph{V, VD, Nothing} end +abstract type AbstractITensorNetwork{V, VD} <: AbstractDataGraph{V, VD, Nothing} end # Need to be careful about removing edges from tensor networks in case there is a bond -Graphs.rem_edge!(::AbstractTensorNetwork, edge) = not_implemented() +Graphs.rem_edge!(::AbstractITensorNetwork, edge) = not_implemented() # Graphs.jl overloads -function Graphs.weights(graph::AbstractTensorNetwork) +function Graphs.weights(graph::AbstractITensorNetwork) V = vertextype(graph) es = Tuple.(edges(graph)) ws = Dictionary{Tuple{V, V}, Float64}(es, undef) @@ -29,28 +29,28 @@ function Graphs.weights(graph::AbstractTensorNetwork) end # Copy -Base.copy(::AbstractTensorNetwork) = not_implemented() +Base.copy(::AbstractITensorNetwork) = not_implemented() # Iteration -Base.iterate(tn::AbstractTensorNetwork, args...) = iterate(vertex_data(tn), args...) -Base.keys(tn::AbstractTensorNetwork) = vertices(tn) +Base.iterate(tn::AbstractITensorNetwork, args...) = iterate(vertex_data(tn), args...) +Base.keys(tn::AbstractITensorNetwork) = vertices(tn) # TODO: This contrasts with the `DataGraphs.AbstractDataGraph` definition, # where it is defined as the `vertextype`. Does that cause problems or should it be changed? -Base.eltype(tn::AbstractTensorNetwork) = eltype(vertex_data(tn)) +Base.eltype(tn::AbstractITensorNetwork) = eltype(vertex_data(tn)) # Overload if needed -Graphs.is_directed(::Type{<:AbstractTensorNetwork}) = false +Graphs.is_directed(::Type{<:AbstractITensorNetwork}) = false -DataGraphs.underlying_graph(::AbstractTensorNetwork) = not_implemented() -function NamedGraphs.vertex_positions(tn::AbstractTensorNetwork) +DataGraphs.underlying_graph(::AbstractITensorNetwork) = not_implemented() +function NamedGraphs.vertex_positions(tn::AbstractITensorNetwork) return NamedGraphs.vertex_positions(underlying_graph(tn)) end -function NamedGraphs.ordered_vertices(tn::AbstractTensorNetwork) +function NamedGraphs.ordered_vertices(tn::AbstractITensorNetwork) return NamedGraphs.ordered_vertices(underlying_graph(tn)) end -function Adapt.adapt_structure(to, tn::AbstractTensorNetwork) +function Adapt.adapt_structure(to, tn::AbstractITensorNetwork) # TODO: Define and use: # # @preserve_graph map_vertex_data(adapt(to), tn) @@ -135,14 +135,14 @@ macro preserve_graph(expr) return :(setindex_preserve_graph!($(esc(array)), $(esc(value)), $(esc.(indices)...))) end -# Update the graph of the TensorNetwork `tn` to include +# Update the graph of the ITensorNetwork `tn` to include # edges that should exist based on the tensor connectivity. function add_missing_edges!(tn::AbstractGraph) foreach(v -> add_missing_edges!(tn, v), vertices(tn)) return tn end -# Update the graph of the TensorNetwork `tn` to include +# Update the graph of the ITensorNetwork `tn` to include # edges that should be incident to the vertex `v` # based on the tensor connectivity. function add_missing_edges!(tn::AbstractGraph, v) @@ -157,13 +157,13 @@ function add_missing_edges!(tn::AbstractGraph, v) return tn end -# Fix the edges of the TensorNetwork `tn` to match +# Fix the edges of the ITensorNetwork `tn` to match # the tensor connectivity. function fix_edges!(tn::AbstractGraph) foreach(v -> fix_edges!(tn, v), vertices(tn)) return tn end -# Fix the edges of the TensorNetwork `tn` to match +# Fix the edges of the ITensorNetwork `tn` to match # the tensor connectivity at vertex `v`. function fix_edges!(tn::AbstractGraph, v) for e in incident_edges(tn, v) @@ -176,12 +176,12 @@ function fix_edges!(tn::AbstractGraph, v) return tn end -using ITensorBase: denamedtype, named, nametype, uniquename +using ITensorBase: named, nametype, uniquename, unnamedtype using TensorAlgebra: trivialrange function insertlink!(tn, e) add_edge!(tn, e) T = eltype(inds(tn[src(e)])) - l = named(trivialrange(denamedtype(T)), uniquename(nametype(T))) + l = named(trivialrange(unnamedtype(T)), uniquename(nametype(T))) x = fill!(similar(tn[src(e)], (l,)), one(eltype(tn[src(e)]))) @preserve_graph tn[src(e)] = tn[src(e)] * x @preserve_graph tn[dst(e)] = tn[dst(e)] * conj(x) @@ -202,28 +202,32 @@ function randlinknames(tn) return new_tn end -function Base.setindex!(tn::AbstractTensorNetwork, value, v) +function Base.setindex!(tn::AbstractITensorNetwork, value, v) @preserve_graph tn[v] = value fix_edges!(tn, v) return tn end # Fix ambiguity error. -function Base.setindex!(graph::AbstractTensorNetwork, value, vertex::OrdinalSuffixedInteger) +function Base.setindex!( + graph::AbstractITensorNetwork, + value, + vertex::OrdinalSuffixedInteger + ) graph[vertices(graph)[vertex]] = value return graph end -Base.setindex!(tn::AbstractTensorNetwork, value, edge::AbstractEdge) = not_implemented() -Base.setindex!(tn::AbstractTensorNetwork, value, edge::Pair) = not_implemented() +Base.setindex!(tn::AbstractITensorNetwork, value, edge::AbstractEdge) = not_implemented() +Base.setindex!(tn::AbstractITensorNetwork, value, edge::Pair) = not_implemented() # Fix ambiguity error. function Base.setindex!( - tn::AbstractTensorNetwork, + tn::AbstractITensorNetwork, value, edge::Pair{<:OrdinalSuffixedInteger, <:OrdinalSuffixedInteger} ) return not_implemented() end -function Base.show(io::IO, mime::MIME"text/plain", graph::AbstractTensorNetwork) +function Base.show(io::IO, mime::MIME"text/plain", graph::AbstractITensorNetwork) println(io, "$(typeof(graph)) with $(nv(graph)) vertices:") show(io, mime, vertices(graph)) println(io, "\n") @@ -238,4 +242,4 @@ function Base.show(io::IO, mime::MIME"text/plain", graph::AbstractTensorNetwork) return nothing end -Base.show(io::IO, graph::AbstractTensorNetwork) = show(io, MIME"text/plain"(), graph) +Base.show(io::IO, graph::AbstractITensorNetwork) = show(io, MIME"text/plain"(), graph) diff --git a/src/apply/apply_operators.jl b/src/apply/apply_operators.jl index a9413c1f..74836b8e 100644 --- a/src/apply/apply_operators.jl +++ b/src/apply/apply_operators.jl @@ -5,8 +5,9 @@ using Graphs: dst, src, vertices using ITensorBase: ITensorBase as ITB, AbstractITensor, dimnames, domainnames, operator, replacedimnames using LinearAlgebra: norm +using MatrixAlgebraKit: qr_compact, svd_trunc using NamedGraphs.GraphsExtensions: all_edges, boundary_edges -using TensorAlgebra: TensorAlgebra as TA, gram_eigh_full, gram_eigh_full_with_pinv +using TensorAlgebra.MatrixAlgebra: gram_eigh_full, gram_eigh_full_with_pinv # === Top-level user entry point === @@ -15,7 +16,7 @@ using TensorAlgebra: TensorAlgebra as TA, gram_eigh_full, gram_eigh_full_with_pi Apply each operator in `operators` (a sequence of single-tensor or two-tensor operators) to `state` in turn, updating `env` to reflect each application. -`state` is an `AbstractTensorNetwork`, `env` is a per-edge environment cache +`state` is an `AbstractITensorNetwork`, `env` is a per-edge environment cache (typically built by `identity_norm_message_env(state)` or one of the related `*_norm_message_env` constructors), and the returned `(state, env)` pair has the operators applied. `kwargs` are forwarded to the per-operator algorithm @@ -205,8 +206,8 @@ end # === BP simple-update implementation === function apply_gate_bp!( - dest::AbstractTensorNetwork, op::AbstractITensor, - state::AbstractTensorNetwork, env; kwargs... + dest::AbstractITensorNetwork, op::AbstractITensor, + state::AbstractITensorNetwork, env; kwargs... ) op_in = domainnames(op) vs = [v for v in vertices(state) if !isempty(intersect(op_in, sitenames(state, v)))] @@ -217,15 +218,15 @@ function apply_gate_bp!( end function apply_gate_bp_nsite!( - ::Val{N}, dest::AbstractTensorNetwork, op::AbstractITensor, - state::AbstractTensorNetwork, env, vs; kwargs... + ::Val{N}, dest::AbstractITensorNetwork, op::AbstractITensor, + state::AbstractITensorNetwork, env, vs; kwargs... ) where {N} return throw(ArgumentError("$N-site gate decomposition not implemented")) end function apply_gate_bp_nsite!( - ::Val{1}, dest::AbstractTensorNetwork, op::AbstractITensor, - state::AbstractTensorNetwork, env, vs; + ::Val{1}, dest::AbstractITensorNetwork, op::AbstractITensor, + state::AbstractITensorNetwork, env, vs; normalize, kwargs... ) v = only(vs) @@ -242,8 +243,8 @@ function apply_gate_bp_nsite!( end function apply_gate_bp_nsite!( - ::Val{2}, dest::AbstractTensorNetwork, op::AbstractITensor, - state::AbstractTensorNetwork, env, vs; + ::Val{2}, dest::AbstractITensorNetwork, op::AbstractITensor, + state::AbstractITensorNetwork, env, vs; trunc, normalize ) v1, v2 = vs @@ -258,10 +259,10 @@ function apply_gate_bp_nsite!( ψ_v1 = prod([[state[v1]]; gauges_v1]) ψ_v2 = prod([[state[v2]]; gauges_v2]) - Q_v1, R_v1 = TA.qr(ψ_v1, setdiff(dimnames(ψ_v1), dimnames(ψ_v2), dimnames(op))) - Q_v2, R_v2 = TA.qr(ψ_v2, setdiff(dimnames(ψ_v2), dimnames(ψ_v1), dimnames(op))) + Q_v1, R_v1 = qr_compact(ψ_v1, setdiff(dimnames(ψ_v1), dimnames(ψ_v2), dimnames(op))) + Q_v2, R_v2 = qr_compact(ψ_v2, setdiff(dimnames(ψ_v2), dimnames(ψ_v1), dimnames(op))) op_R_v1v2 = ITB.apply(op, R_v1 * R_v2) - U_v1, S, U_v2 = TA.svd(op_R_v1v2, setdiff(dimnames(R_v1), dimnames(R_v2)); trunc) + U_v1, S, U_v2 = svd_trunc(op_R_v1v2, setdiff(dimnames(R_v1), dimnames(R_v2)); trunc) if normalize S = S / norm(S) end diff --git a/src/beliefpropagation/normnetwork.jl b/src/beliefpropagation/normnetwork.jl index 50b6c71a..60ef064f 100644 --- a/src/beliefpropagation/normnetwork.jl +++ b/src/beliefpropagation/normnetwork.jl @@ -1,7 +1,7 @@ using DataGraphs: underlying_graph using Graphs: dst, edges, edgetype, src -using ITensorBase: codomainnames, denamed, domainnames, name, operator, replacedimnames, - similar_operator, state, uniquename +using ITensorBase: codomainnames, domainnames, name, operator, replacedimnames, + similar_operator, state, uniquename, unnamed using NamedGraphs.GraphsExtensions: all_edges, incident_edges using Random: Random, rand!, randn! @@ -38,7 +38,7 @@ function similar_norm_message_env(tn) v1, v2 = src(e), dst(e) ket_axes = linkinds(tn, e) ket_names = name.(ket_axes) - unnamed_axes = denamed.(ket_axes) + unnamed_axes = unnamed.(ket_axes) bra_names = uniquename.(ket_names) # Message axes are dual to the link they contract against in the factor. push!( @@ -146,7 +146,7 @@ function normnetwork(tn) for e in edges(tn) ) merge!(linknames_map, Dict(reverse(e) => m for (e, m) in linknames_map)) - norm_tn = TensorNetwork(underlying_graph(tn)) do v + norm_tn = ITensorNetwork(underlying_graph(tn)) do v t = tn[v] ket_to_bra = Dict(p for e in incident_edges(tn, v) for p in linknames_map[e]) return t * replacedimnames(n -> get(ket_to_bra, n, n), conj(t)) diff --git a/src/tensornetwork.jl b/src/tensornetwork.jl index 3c6aa471..996075ed 100644 --- a/src/tensornetwork.jl +++ b/src/tensornetwork.jl @@ -16,8 +16,13 @@ using NamedGraphs: function _TensorNetwork end -struct TensorNetwork{V, VD, UG <: AbstractGraph{V}, Tensors <: AbstractDictionary{V, VD}} <: - AbstractTensorNetwork{V, VD} +struct ITensorNetwork{ + V, + VD, + UG <: AbstractGraph{V}, + Tensors <: AbstractDictionary{V, VD}, + } <: + AbstractITensorNetwork{V, VD} underlying_graph::UG tensors::Tensors global @inline function _TensorNetwork( @@ -28,22 +33,22 @@ struct TensorNetwork{V, VD, UG <: AbstractGraph{V}, Tensors <: AbstractDictionar end end # This assumes the tensor connectivity matches the graph structure. -function TensorNetwork(graph::AbstractGraph, tensors) - return TensorNetwork(graph, Dictionary(keys(tensors), values(tensors))) +function ITensorNetwork(graph::AbstractGraph, tensors) + return ITensorNetwork(graph, Dictionary(keys(tensors), values(tensors))) end -function TensorNetwork(graph::AbstractGraph, tensors::AbstractDictionary) +function ITensorNetwork(graph::AbstractGraph, tensors::AbstractDictionary) tn = _TensorNetwork(graph, tensors) fix_links!(tn) return tn end -function TensorNetwork{V, VD, UG, Tensors}( +function ITensorNetwork{V, VD, UG, Tensors}( graph::UG ) where {V, VD, UG <: AbstractGraph{V}, Tensors} return _TensorNetwork(graph, Tensors()) end -function Graphs.rem_vertex!(tn::TensorNetwork, v) +function Graphs.rem_vertex!(tn::ITensorNetwork, v) delete!(tn.tensors, v) rem_vertex!(tn.underlying_graph, v) return tn @@ -51,16 +56,16 @@ end # DataGraphs interface -DataGraphs.underlying_graph(tn::TensorNetwork) = tn.underlying_graph +DataGraphs.underlying_graph(tn::ITensorNetwork) = tn.underlying_graph -DataGraphs.is_vertex_assigned(tn::TensorNetwork, v) = haskey(tn.tensors, v) -DataGraphs.is_edge_assigned(tn::TensorNetwork, e) = false +DataGraphs.is_vertex_assigned(tn::ITensorNetwork, v) = haskey(tn.tensors, v) +DataGraphs.is_edge_assigned(tn::ITensorNetwork, e) = false -DataGraphs.get_vertex_data(tn::TensorNetwork, v) = tn.tensors[v] +DataGraphs.get_vertex_data(tn::ITensorNetwork, v) = tn.tensors[v] -DataGraphs.set_vertex_data!(tn::TensorNetwork, val, v) = set!(tn.tensors, v, val) +DataGraphs.set_vertex_data!(tn::ITensorNetwork, val, v) = set!(tn.tensors, v, val) -function DataGraphs.underlying_graph_type(type::Type{<:TensorNetwork}) +function DataGraphs.underlying_graph_type(type::Type{<:ITensorNetwork}) return fieldtype(type, :underlying_graph) end @@ -82,13 +87,13 @@ function tensornetwork_edges(edgetype::Type, tensors) end tensornetwork_edges(tensors) = tensornetwork_edges(NamedEdge, tensors) -function TensorNetwork(f::Base.Callable, graph::AbstractGraph) - return TensorNetwork(graph, Dictionary(map(f, vertices(graph)))) +function ITensorNetwork(f::Base.Callable, graph::AbstractGraph) + return ITensorNetwork(graph, Dictionary(map(f, vertices(graph)))) end # Insert trivial links for missing edges, and also check # the vertices and edges are consistent between the graph and tensors. -function fix_links!(tn::AbstractTensorNetwork) +function fix_links!(tn::AbstractITensorNetwork) graph = underlying_graph(tn) tensors = vertex_data(tn) @assert issetequal(vertices(graph), keys(tensors)) "Graph vertices and tensor keys must match." @@ -102,27 +107,27 @@ function fix_links!(tn::AbstractTensorNetwork) end # Determine the graph structure from the tensors. -function TensorNetwork(tensors) +function ITensorNetwork(tensors) graph = NamedGraph(keys(tensors)) add_edges!(graph, tensornetwork_edges(tensors)) return _TensorNetwork(graph, tensors) end -function Base.copy(tn::TensorNetwork) - return TensorNetwork(copy(underlying_graph(tn)), copy(vertex_data(tn))) +function Base.copy(tn::ITensorNetwork) + return ITensorNetwork(copy(underlying_graph(tn)), copy(vertex_data(tn))) end -TensorNetwork(tn::TensorNetwork) = copy(tn) -TensorNetwork{V}(tn::TensorNetwork{V}) where {V} = copy(tn) -function TensorNetwork{V}(tn::TensorNetwork) where {V} +ITensorNetwork(tn::ITensorNetwork) = copy(tn) +ITensorNetwork{V}(tn::ITensorNetwork{V}) where {V} = copy(tn) +function ITensorNetwork{V}(tn::ITensorNetwork) where {V} g = convert_vertextype(V, underlying_graph(tn)) d = dictionary(V(k) => tn[k] for k in vertices(tn)) - return TensorNetwork(g, d) + return ITensorNetwork(g, d) end -NamedGraphs.convert_vertextype(::Type{V}, tn::TensorNetwork{V}) where {V} = tn -NamedGraphs.convert_vertextype(V::Type, tn::TensorNetwork) = TensorNetwork{V}(tn) +NamedGraphs.convert_vertextype(::Type{V}, tn::ITensorNetwork{V}) where {V} = tn +NamedGraphs.convert_vertextype(V::Type, tn::ITensorNetwork) = ITensorNetwork{V}(tn) -function Graphs.rem_edge!(tn::TensorNetwork, e) +function Graphs.rem_edge!(tn::ITensorNetwork, e) if !has_edge(underlying_graph(tn), e) return false end @@ -138,7 +143,7 @@ function Graphs.rem_edge!(tn::TensorNetwork, e) end function NamedGraphs.similar_graph( - type::Type{<:TensorNetwork}, + type::Type{<:ITensorNetwork}, vertices = vertextype(type)[] ) DT = fieldtype(type, :tensors) @@ -149,7 +154,7 @@ function NamedGraphs.similar_graph( return _TensorNetwork(underlying_graph, empty_dict) end function NamedGraphs.similar_graph( - graph::TensorNetwork, + graph::ITensorNetwork, VD::Type, ::Type{<:Nothing}, vertices @@ -162,7 +167,7 @@ function NamedGraphs.similar_graph( return _TensorNetwork(new_underlying_graph, empty_dict) end -function NamedGraphs.induced_subgraph_from_vertices(graph::TensorNetwork, subvertices) +function NamedGraphs.induced_subgraph_from_vertices(graph::ITensorNetwork, subvertices) return induced_subgraph_tensornetwork(graph, subvertices) end @@ -170,7 +175,7 @@ function induced_subgraph_tensornetwork(graph, subvertices) underlying_subgraph, vlist = Graphs.induced_subgraph(underlying_graph(graph), subvertices) - subgraph = TensorNetwork(underlying_subgraph) do vertex + subgraph = ITensorNetwork(underlying_subgraph) do vertex return graph[vertex] end @@ -178,52 +183,52 @@ function induced_subgraph_tensornetwork(graph, subvertices) end ## PartitionedGraphs -function PartitionedGraphs.partitioned_vertices(tn::TensorNetwork) +function PartitionedGraphs.partitioned_vertices(tn::ITensorNetwork) return partitioned_vertices(tn.underlying_graph) end -function PartitionedGraphs.quotient_graph(tn::TensorNetwork) +function PartitionedGraphs.quotient_graph(tn::ITensorNetwork) ug = quotient_graph(underlying_graph(tn)) inds = Indices(parent_graph_indices(QuotientVertices(tn))) data = map(v -> tn[QuotientVertex(v)], inds) - return TensorNetwork(ug, data) + return ITensorNetwork(ug, data) end # TODO: This method should not be required with a better interface with a better # DataGraphsPartitionedGraphsExt interface. -function PartitionedGraphs.quotient_graph_type(type::Type{<:TensorNetwork}) +function PartitionedGraphs.quotient_graph_type(type::Type{<:ITensorNetwork}) UG = quotient_graph_type(underlying_graph_type(type)) VD = Vector{vertex_data_type(type)} V = vertextype(UG) - return TensorNetwork{V, VD, UG, Dictionary{V, VD}} + return ITensorNetwork{V, VD, UG, Dictionary{V, VD}} end # Partition the underlying graph of the tensor network; does not affect the data. -function PartitionedGraphs.partitionedgraph(tn::TensorNetwork, parts) +function PartitionedGraphs.partitionedgraph(tn::ITensorNetwork, parts) pg = partitionedgraph(underlying_graph(tn), parts) - return TensorNetwork(pg, copy(vertex_data(tn))) + return ITensorNetwork(pg, copy(vertex_data(tn))) end -PartitionedGraphs.departition(tn::TensorNetwork) = tn +PartitionedGraphs.departition(tn::ITensorNetwork) = tn function PartitionedGraphs.departition( - tn::TensorNetwork{<:Any, <:Any, <:AbstractPartitionedGraph} + tn::ITensorNetwork{<:Any, <:Any, <:AbstractPartitionedGraph} ) - return TensorNetwork(departition(underlying_graph(tn)), vertex_data(tn)) + return ITensorNetwork(departition(underlying_graph(tn)), vertex_data(tn)) end -NamedGraphs.to_graph_index(::TensorNetwork, vertex::QuotientVertex) = vertex +NamedGraphs.to_graph_index(::ITensorNetwork, vertex::QuotientVertex) = vertex # When getting data according the quotient vertices, take a lazy contraction. -function DataGraphs.get_index_data(tn::TensorNetwork, vertex::QuotientVertex) +function DataGraphs.get_index_data(tn::ITensorNetwork, vertex::QuotientVertex) data = collect(map(v -> tn[v], vertices(tn, vertex))) return mapreduce(lazy, *, data) end -function DataGraphs.is_graph_index_assigned(tn::TensorNetwork, vertex::QuotientVertex) +function DataGraphs.is_graph_index_assigned(tn::ITensorNetwork, vertex::QuotientVertex) return isassigned(tn, Vertices(vertices(tn, vertex))) end -function PartitionedGraphs.quotientview(tn::TensorNetwork) +function PartitionedGraphs.quotientview(tn::ITensorNetwork) qview = QuotientView(underlying_graph(tn)) tensors = map(qv -> vertex_data(tn)[Indices(qv)], Indices(quotientvertices(tn))) - return TensorNetwork(qview, tensors) + return ITensorNetwork(qview, tensors) end diff --git a/test/Project.toml b/test/Project.toml index ac2e5885..9369470a 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -28,10 +28,10 @@ AlgorithmsInterface = "0.1" Aqua = "0.8.14" DataGraphs = "0.4" Dictionaries = "0.4.5" -GradedArrays = "0.9.4" +GradedArrays = "0.10" Graphs = "1.13.1" -ITensorBase = "0.6.3" -ITensorNetworksNext = "0.6" +ITensorBase = "0.7" +ITensorNetworksNext = "0.7" ITensorPkgSkeleton = "0.3.42" MatrixAlgebraKit = "0.6" NamedGraphs = "0.11.5" @@ -40,6 +40,6 @@ Random = "1.10" SafeTestsets = "0.1" StableRNGs = "1" Suppressor = "0.2.8" -TensorAlgebra = "0.9.7" +TensorAlgebra = "0.10" TensorOperations = "5.3.1" Test = "1.10" diff --git a/test/test_algorithmsinterfaceextensions.jl b/test/test_algorithmsinterfaceextensions.jl index f5808266..290ebb8a 100644 --- a/test/test_algorithmsinterfaceextensions.jl +++ b/test/test_algorithmsinterfaceextensions.jl @@ -1,5 +1,6 @@ -import AlgorithmsInterface as AI -import ITensorNetworksNext.AlgorithmsInterfaceExtensions as AIE +using AlgorithmsInterface: AlgorithmsInterface as AI +using ITensorNetworksNext.AlgorithmsInterfaceExtensions: + AlgorithmsInterfaceExtensions as AIE using Test: @test, @test_throws, @testset # Concrete `NestedAlgorithm` subtype: holds a flat list of child algorithms diff --git a/test/test_apply_operator.jl b/test/test_apply_operator.jl index 554aadb2..21dd9142 100644 --- a/test/test_apply_operator.jl +++ b/test/test_apply_operator.jl @@ -1,12 +1,10 @@ -import ITensorBase as ITB -import TensorAlgebra as TA using GradedArrays: U1, gradedrange using Graphs: dst, edges, src, vertices -using ITensorBase: Index, name, operator, setname, uniquename -using ITensorNetworksNext: TensorNetwork, apply_operator, apply_operators, +using ITensorBase: ITensorBase as ITB, Index, name, operator, setname, uniquename +using ITensorNetworksNext: ITensorNetwork, apply_operator, apply_operators, beliefpropagation_normnetwork, identity_norm_message_env, insertlink!, ones_norm_message_env -using MatrixAlgebraKit: truncrank +using MatrixAlgebraKit: svd_trunc, truncrank using NamedGraphs.NamedGraphGenerators: named_cycle_graph, named_path_graph using NamedGraphs: NamedGraph using Random: AbstractRNG @@ -24,7 +22,7 @@ function randn_operator(rng::AbstractRNG, elt::Type, domain_namedaxes) end function random_state(rng::AbstractRNG, elt::Type, g, site_axes; nlayers, trunc) - state = TensorNetwork(NamedGraph(collect(vertices(g)))) do v + state = ITensorNetwork(NamedGraph(collect(vertices(g)))) do v return randn(rng, elt, (site_axes[v],)) end for e in edges(g) @@ -75,7 +73,7 @@ end gate = randn_operator(rng, T, (site_axes[2], site_axes[3])) gated_full = ITB.apply(gate, prod(state)) left = [name(site_axes[v]) for v in 1:2] - U, S, Vt = TA.svd(gated_full, left; trunc = truncrank(k)) + U, S, Vt = svd_trunc(gated_full, left; trunc = truncrank(k)) gated, _ = apply_operator(gate, state, env; trunc = truncrank(k)) @test prod(gated) ≈ U * S * Vt rtol = eps(real(T))^(1 / 3) end diff --git a/test/test_basics.jl b/test/test_basics.jl index 9b0197c3..64636f07 100644 --- a/test/test_basics.jl +++ b/test/test_basics.jl @@ -1,17 +1,17 @@ using Dictionaries: Indices using Graphs: dst, edges, has_edge, ne, nv, src, vertices using ITensorBase: Index, dimnames -using ITensorNetworksNext: TensorNetwork, linkinds, siteinds +using ITensorNetworksNext: ITensorNetwork, linkinds, siteinds using NamedGraphs.GraphsExtensions: arranged_edges, incident_edges using NamedGraphs.NamedGraphGenerators: named_grid using Test: @test, @testset @testset "ITensorNetworksNext" begin - @testset "Construct TensorNetwork product state" begin + @testset "Construct ITensorNetwork product state" begin dims = (3, 3) g = named_grid(dims) s = Dict(v => Index(2) for v in vertices(g)) - tn = TensorNetwork(g) do v + tn = ITensorNetwork(g) do v return randn(s[v]) end @test nv(tn) == 9 @@ -32,12 +32,12 @@ using Test: @test, @testset @test isone(length(only(linkinds(tn, e)))) end end - @testset "Construct TensorNetwork partition function" begin + @testset "Construct ITensorNetwork partition function" begin dims = (3, 3) g = named_grid(dims) l = Dict(e => Index(2) for e in edges(g)) l = merge(l, Dict(reverse(e) => l[e] for e in edges(g))) - tn = TensorNetwork(g) do v + tn = ITensorNetwork(g) do v is = map(e -> l[e], incident_edges(g, v)) return randn(Tuple(is)) end diff --git a/test/test_beliefpropagation.jl b/test/test_beliefpropagation.jl index 29979e16..8b548d01 100644 --- a/test/test_beliefpropagation.jl +++ b/test/test_beliefpropagation.jl @@ -1,10 +1,10 @@ -import AlgorithmsInterface as AI +using AlgorithmsInterface: AlgorithmsInterface as AI using DataGraphs: edge_data, edge_data_type using Dictionaries: Dictionary, dictionary, set! using Graphs: AbstractGraph, dst, edges, has_edge, src, vertices using ITensorBase: ITensor, Index, inds, name, noprime, prime -using ITensorNetworksNext: ITensorNetworksNext, MessageCache, StopWhenConverged, - TensorNetwork, bethe_free_energy, edge_scalar, incoming_messages, linkinds, +using ITensorNetworksNext: ITensorNetworksNext, ITensorNetwork, MessageCache, + StopWhenConverged, bethe_free_energy, edge_scalar, incoming_messages, linkinds, messagecache, region_scalar, subgraph, vertex_scalar, vertex_scalars using LinearAlgebra: LinearAlgebra using NamedGraphs.GraphsExtensions: all_edges, arranged_edges, incident_edges, vertextype @@ -34,7 +34,7 @@ function spin_ice_tensornetwork(g) t = t_data[linkinds...] set!(ts, v, t) end - return TensorNetwork(g, ts) + return ITensorNetwork(g, ts) end @testset "Belief propagation" begin @@ -45,7 +45,7 @@ end l = Dict(e => Index(2) for e in edges(g)) l = merge(l, Dict(reverse(e) => l[e] for e in edges(g))) - tn = TensorNetwork(g) do v + tn = ITensorNetwork(g) do v is = map(e -> l[e], incident_edges(g, v)) return randn(Tuple(is)) end @@ -85,7 +85,7 @@ end g = named_path_graph(3) l = Dict(e => Index(2) for e in edges(g)) l = merge(l, Dict(reverse(e) => l[e] for e in edges(g))) - tn = TensorNetwork(g) do v + tn = ITensorNetwork(g) do v is = map(e -> l[e], incident_edges(g, v)) return randn(ComplexF32, Tuple(is)) end @@ -118,7 +118,7 @@ end g = named_grid((3,)) l = Dict(e => Index(2) for e in edges(g)) l = merge(l, Dict(reverse(e) => l[e] for e in edges(g))) - tn = TensorNetwork(g) do v + tn = ITensorNetwork(g) do v is = map(e -> l[e], incident_edges(g, v)) return randn(Tuple(is)) end @@ -134,7 +134,7 @@ end g = named_grid((2,)) l = Dict(e => Index(2) for e in edges(g)) l = merge(l, Dict(reverse(e) => l[e] for e in edges(g))) - tn = TensorNetwork(g) do v + tn = ITensorNetwork(g) do v is = map(e -> l[e], incident_edges(g, v)) return randn(Tuple(is)) end @@ -158,7 +158,7 @@ end l = Dict(e => Index(2) for e in edges(g)) l = merge(l, Dict(reverse(e) => l[e] for e in edges(g))) - tn = TensorNetwork(g) do v + tn = ITensorNetwork(g) do v is = map(e -> l[e], incident_edges(g, v)) return randn(rng, T, Tuple(is)) end @@ -179,7 +179,7 @@ end g = named_comb_tree(dims) l = Dict(e => Index(3) for e in edges(g)) l = merge(l, Dict(reverse(e) => l[e] for e in edges(g))) - tn = TensorNetwork(g) do v + tn = ITensorNetwork(g) do v is = map(e -> l[e], incident_edges(g, v)) return randn(rng, T, Tuple(is)) end diff --git a/test/test_contract_network.jl b/test/test_contract_network.jl index 6525764a..b5383efb 100644 --- a/test/test_contract_network.jl +++ b/test/test_contract_network.jl @@ -1,7 +1,7 @@ using Graphs: edges using ITensorBase: Greedy, Index, Optimal using ITensorNetworksNext: - Exact, LeftAssociative, TensorNetwork, contract_network, linkinds, siteinds + Exact, ITensorNetwork, LeftAssociative, contract_network, linkinds, siteinds using NamedGraphs.GraphsExtensions: arranged_edges, incident_edges using NamedGraphs.NamedGraphGenerators: named_grid using TensorOperations: TensorOperations @@ -28,7 +28,7 @@ using Test: @test, @testset g = named_grid(dims) l = Dict(e => Index(2) for e in edges(g)) l = merge(l, Dict(reverse(e) => l[e] for e in edges(g))) - tn = TensorNetwork(g) do v + tn = ITensorNetwork(g) do v is = map(e -> l[e], incident_edges(g, v)) return randn(Tuple(is)) end diff --git a/test/test_tensornetworkgenerators.jl b/test/test_itensornetworkgenerators.jl similarity index 95% rename from test/test_tensornetworkgenerators.jl rename to test/test_itensornetworkgenerators.jl index e8198dfc..3656ca61 100644 --- a/test/test_tensornetworkgenerators.jl +++ b/test/test_itensornetworkgenerators.jl @@ -1,6 +1,6 @@ using Graphs: edges, ne, nv, vertices using ITensorBase: Index, inds -using ITensorNetworksNext.TensorNetworkGenerators: delta, delta_network, ising_network +using ITensorNetworksNext.ITensorNetworkGenerators: delta, delta_network, ising_network using ITensorNetworksNext: contract_network using NamedGraphs.GraphsExtensions: arranged_edges, incident_edges using NamedGraphs.NamedGraphGenerators: named_grid @@ -8,7 +8,7 @@ using Test: @test, @testset !@isdefined(TestUtils) && include("utils.jl") -@testset "TensorNetworkGenerators" begin +@testset "ITensorNetworkGenerators" begin @testset "Delta Network" begin dims = (3, 3) g = named_grid(dims) diff --git a/test/test_tensornetwork.jl b/test/test_tensornetwork.jl index 3f3cbd15..4efe4cb0 100644 --- a/test/test_tensornetwork.jl +++ b/test/test_tensornetwork.jl @@ -3,7 +3,7 @@ using Graphs: add_edge!, add_vertex!, dst, edges, edgetype, has_edge, has_vertex is_directed, ne, nv, rem_vertex!, src, vertices using ITensorBase: Index, LazyITensor using ITensorNetworksNext: - TensorNetwork, fix_edges!, linkaxes, linkinds, linknames, siteaxes, siteinds, sitenames + ITensorNetwork, fix_edges!, linkaxes, linkinds, linknames, siteaxes, siteinds, sitenames using NamedGraphs.GraphsExtensions: incident_edges, subgraph, vertextype using NamedGraphs.NamedGraphGenerators: named_grid, named_path_graph using NamedGraphs.PartitionedGraphs: AbstractPartitionedGraph, QuotientVertex, departition, @@ -12,11 +12,11 @@ using NamedGraphs.PartitionedGraphs: AbstractPartitionedGraph, QuotientVertex, d using NamedGraphs: convert_vertextype, similar_graph using Test: @test, @test_throws, @testset -@testset "`TensorNetwork`" begin +@testset "`ITensorNetwork`" begin @testset "Basics" begin g = named_grid((2, 2)) s = Dict(v => Index(2) for v in vertices(g)) - tn = TensorNetwork(g) do v + tn = ITensorNetwork(g) do v return randn(s[v]) end @@ -26,7 +26,7 @@ using Test: @test, @test_throws, @testset @test issetequal(keys(tn), vertices(tn)) # `eltype` matches the eltype of the vertex data. @test eltype(tn) === eltype(vertex_data(tn)) - # `is_directed` is `false` for AbstractTensorNetwork. + # `is_directed` is `false` for AbstractITensorNetwork. @test !is_directed(typeof(tn)) # `show` MIME and default both succeed and mention vertices/edges. @@ -60,7 +60,7 @@ using Test: @test, @test_throws, @testset l = Dict(e => Index(2) for e in edges(g)) l = merge(l, Dict(reverse(e) => l[e] for e in edges(g))) s = Dict(v => Index(2) for v in vertices(g)) - tn = TensorNetwork(g) do v + tn = ITensorNetwork(g) do v is = map(e -> l[e], incident_edges(g, v)) return randn((s[v], is...)) end @@ -84,14 +84,14 @@ using Test: @test, @test_throws, @testset g = named_grid((3,)) l = Dict(e => Index(2) for e in edges(g)) l = merge(l, Dict(reverse(e) => l[e] for e in edges(g))) - tn = TensorNetwork(g) do v + tn = ITensorNetwork(g) do v is = map(e -> l[e], incident_edges(g, v)) return randn(Tuple(is)) end sub_vs = [(1,), (2,)] subtn = subgraph(tn, sub_vs) - @test subtn isa TensorNetwork + @test subtn isa ITensorNetwork @test issetequal(vertices(subtn), sub_vs) @test has_edge(subtn, (1,) => (2,)) end @@ -100,12 +100,12 @@ using Test: @test, @test_throws, @testset dims = (3, 3) g = named_grid(dims) s = Dict(v => Index(2) for v in vertices(g)) - tn = TensorNetwork(g) do v + tn = ITensorNetwork(g) do v return randn(s[v]) end stn = similar_graph(tn) - @test stn isa TensorNetwork + @test stn isa ITensorNetwork @test vertices(stn) == vertices(tn) @test edges(stn) == edges(tn) @test isempty(assigned_vertex_data(stn)) @@ -127,7 +127,7 @@ using Test: @test, @test_throws, @testset @test stn isa typeof(tn) ctn = convert_vertextype(Tuple{Float64, Float64}, tn) - @test ctn isa TensorNetwork + @test ctn isa ITensorNetwork @test vertextype(ctn) == Tuple{Float64, Float64} @test collect(vertex_data(ctn)) == collect(vertex_data(tn)) end @@ -136,7 +136,7 @@ using Test: @test, @test_throws, @testset dims = (3, 3) g = named_grid(dims) s = Dict(v => Index(2) for v in vertices(g)) - tn = TensorNetwork(g) do v + tn = ITensorNetwork(g) do v return randn(s[v]) end @@ -164,7 +164,7 @@ using Test: @test, @test_throws, @testset @testset "`quotient_graph` (default partitioning)" begin qtn = quotient_graph(tn) - @test qtn isa TensorNetwork + @test qtn isa ITensorNetwork @test nv(qtn) == 1 @test ne(qtn) == 0 v = only(collect(vertices(qtn))) @@ -173,14 +173,14 @@ using Test: @test, @test_throws, @testset @testset "`quotient_graph_type`" begin QT = quotient_graph_type(typeof(tn)) - @test QT <: TensorNetwork + @test QT <: ITensorNetwork qtn = quotient_graph(tn) @test vertextype(qtn) === vertextype(QT) end @testset "`partitionedgraph(tn, parts)`" begin ptn = partitionedgraph(tn, row_parts) - @test ptn isa TensorNetwork + @test ptn isa ITensorNetwork # The set of underlying vertices/edges is preserved. @test issetequal(vertices(ptn), vertices(tn)) @test issetequal(edges(ptn), edges(tn)) @@ -211,7 +211,7 @@ using Test: @test, @test_throws, @testset @testset "`quotient_graph` of partitioned tn" begin ptn = partitionedgraph(tn, row_parts) qtn = quotient_graph(ptn) - @test qtn isa TensorNetwork + @test qtn isa ITensorNetwork @test nv(qtn) == dims[2] # The row-partitioned grid quotients to a path graph of length `dims[2]`. @test ne(qtn) == dims[2] - 1 @@ -227,7 +227,7 @@ using Test: @test, @test_throws, @testset # `departition` on a partitioned tn unwraps one layer of partitioning. ptn = partitionedgraph(tn, row_parts) dtn = departition(ptn) - @test dtn isa TensorNetwork + @test dtn isa ITensorNetwork @test issetequal(vertices(dtn), vertices(tn)) @test issetequal(edges(dtn), edges(tn)) end