diff --git a/Project.toml b/Project.toml index 40f38a19..0d38933e 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "ITensorNetworks" uuid = "2919e153-833c-4bdc-8836-1ea460a35fc7" -version = "0.20.0" +version = "0.21.0" authors = ["Matthew Fishman , Joseph Tindall and contributors"] [workspace] diff --git a/docs/Project.toml b/docs/Project.toml index 36834ba9..35064770 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -16,7 +16,7 @@ path = ".." Documenter = "1.10" Graphs = "1" ITensorFormatter = "0.2.27" -ITensorNetworks = "0.20" +ITensorNetworks = "0.21" ITensors = "0.9" Literate = "2.20.1" NamedGraphs = "0.11" diff --git a/docs/src/deprecated_methods.md b/docs/src/deprecated_methods.md index 9892974b..48dd64bc 100644 --- a/docs/src/deprecated_methods.md +++ b/docs/src/deprecated_methods.md @@ -39,37 +39,9 @@ Suggestions of methods which could be deleted. ITensorNetwork(is::IndsNetwork; kwargs...) ``` -#### Local Operations on ITensorNetworks - -* Indices on the source tensor of `edge` that are not shared with the destination tensor. - (`abstractitensornetwork.jl`): - ```julia - uniqueinds(tn::AbstractITensorNetwork, edge::AbstractEdge) - uniqueinds(tn::AbstractITensorNetwork, edge::Pair) - ``` - -* Indices common to the ITensors on the vertices connected by the edge (`abstractitensornetwork.jl`): - (Use a set function like `intersection` instead.) - ```julia - commoninds(tn::AbstractITensorNetwork, edge) - linkinds(tn::AbstractITensorNetwork, edge) - ``` - ## Global Operations on ITensorNetworks -## TreeTensorNetwork Constructors - -* From `Op` and related types (`opsum_to_ttn.jl`): - ```julia - ttn(o::Op, s::IndsNetwork; kws...) - ttn(o::Scaled{C, Op}, s::IndsNetwork; kws...) - ttn(o::Sum{Op}, s::IndsNetwork; kws...) - ttn(o::Prod{Op}, s::IndsNetwork; kws...) - ttn(o::Scaled{C, Prod{Op}}, s::IndsNetwork; kws...) - ttn(o::Sum{Scaled{C, Op}}, s::IndsNetwork; kws...) - ``` - ## Miscellaneous Methods * Methods in `partitioneditensornetwork.jl`. diff --git a/docs/src/experimental_methods.md b/docs/src/experimental_methods.md index 6f447ce5..14d28373 100644 --- a/docs/src/experimental_methods.md +++ b/docs/src/experimental_methods.md @@ -218,13 +218,6 @@ Methods which still need to be discussed, modified, or deprecated. edge_data_eltype(::Type{<:AbstractIndsNetwork{V, I}}) where {V, I} ``` -* Indices "unique" to one side of an edge — for `edge`, returns the indices on - `src(edge)` together with all of its other incident-edge link indices (`abstractindsnetwork.jl`): - ```julia - uniqueinds(is::AbstractIndsNetwork, edge::AbstractEdge) - uniqueinds(is::AbstractIndsNetwork, edge::Pair) - ``` - * Merge two `AbstractIndsNetwork`s, returning an `IndsNetwork` over the merged graph (`abstractindsnetwork.jl`): ```julia union(is1::AbstractIndsNetwork, is2::AbstractIndsNetwork; kwargs...) diff --git a/docs/src/interface_methods.md b/docs/src/interface_methods.md index c0e40c0e..2c40c497 100644 --- a/docs/src/interface_methods.md +++ b/docs/src/interface_methods.md @@ -72,12 +72,12 @@ These ITensorNetwork constructor interfaces are foundational to other constructo ## Global Operations on ITensorNetworks -* Scale tensors at chosen vertices by per-vertex weights, either out-of-place or in-place (`abstractitensornetwork.jl`). Comment: should probably be renamed to `scale_tensors`. +* Scale tensors at chosen vertices by per-vertex weights, either out-of-place or in-place (`abstractitensornetwork.jl`). ```julia - scale(tn::AbstractITensorNetwork, vertices_weights::Dictionary; kwargs...) - scale(weight_function::Function, tn; kwargs...) - scale!(tn::AbstractITensorNetwork, vertices_weights::Dictionary) - scale!(weight_function::Function, tn::AbstractITensorNetwork; kwargs...) + scale_tensors(tn::AbstractITensorNetwork, vertices_weights::Dictionary; kwargs...) + scale_tensors(weight_function::Function, tn; kwargs...) + scale_tensors!(tn::AbstractITensorNetwork, vertices_weights::Dictionary) + scale_tensors!(weight_function::Function, tn::AbstractITensorNetwork; kwargs...) ``` * Tensor product (disjoint union) of two ITensorNetworks (`abstractitensornetwork.jl`): diff --git a/examples/Project.toml b/examples/Project.toml index f6685060..3a9411e4 100644 --- a/examples/Project.toml +++ b/examples/Project.toml @@ -5,4 +5,4 @@ ITensorNetworks = "2919e153-833c-4bdc-8836-1ea460a35fc7" path = ".." [compat] -ITensorNetworks = "0.20" +ITensorNetworks = "0.21" diff --git a/src/abstractindsnetwork.jl b/src/abstractindsnetwork.jl index 9c15af5b..a5799703 100644 --- a/src/abstractindsnetwork.jl +++ b/src/abstractindsnetwork.jl @@ -3,7 +3,7 @@ using DataGraphs: DataGraphs, AbstractDataGraph, DataGraph, IsUnderlyingGraph, e get_edge_data, get_vertex_data, is_edge_assigned, is_vertex_assigned, map_data, set_edge_data!, set_vertex_data!, underlying_graph_type, vertex_data using Graphs: Graphs, AbstractEdge -using ITensors: ITensors, IndexSet, unioninds, uniqueinds +using ITensors: ITensors, unioninds using NamedGraphs.GraphsExtensions: GraphsExtensions, directed_graph, incident_edges, rename_vertices using NamedGraphs: NamedGraphs @@ -50,20 +50,6 @@ end # Index access # -function ITensors.uniqueinds(is::AbstractIndsNetwork, edge::AbstractEdge) - # TODO: Replace with `is[v]` once `getindex(::IndsNetwork, ...)` is smarter. - inds = IndexSet(get(is, src(edge), Index[])) - for ei in setdiff(incident_edges(is, src(edge)), [edge]) - # TODO: Replace with `is[v]` once `getindex(::IndsNetwork, ...)` is smarter. - inds = unioninds(inds, get(is, ei, Index[])) - end - return inds -end - -function ITensors.uniqueinds(is::AbstractIndsNetwork, edge::Pair) - return uniqueinds(is, edgetype(is)(edge)) -end - function Base.union(is1::AbstractIndsNetwork, is2::AbstractIndsNetwork; kwargs...) return IndsNetwork(union(data_graph(is1), data_graph(is2); kwargs...)) end diff --git a/src/abstractitensornetwork.jl b/src/abstractitensornetwork.jl index 8204820b..11f91c96 100644 --- a/src/abstractitensornetwork.jl +++ b/src/abstractitensornetwork.jl @@ -6,8 +6,8 @@ using Dictionaries: Dictionary using Graphs: Graphs, Graph, add_edge!, add_vertex!, bfs_tree, center, dst, edges, edgetype, ne, neighbors, rem_edge!, src, vertices using ITensors: ITensors, @Algorithm_str, ITensor, addtags, combiner, commoninds, - commontags, contract, dag, hascommoninds, inds, noprime, onehot, prime, replaceprime, - replacetags, setprime, settags, sim, swaptags, tags, unioninds, uniqueinds + commontags, contract, dag, inds, noprime, onehot, prime, replaceprime, replacetags, + setprime, settags, sim, swaptags, tags using LinearAlgebra: LinearAlgebra, factorize using MacroTools: @capture using NDTensors: NDTensors, Algorithm, dim, scalartype @@ -31,7 +31,7 @@ function Graphs.weights(graph::AbstractITensorNetwork) es = Tuple.(edges(graph)) ws = Dictionary{Tuple{V, V}, Float64}(es, undef) for e in edges(graph) - w = log2(dim(commoninds(graph, e))) + w = log2(dim(linkinds(graph, e))) ws[(src(e), dst(e))] = w end return ws @@ -135,7 +135,7 @@ function fix_edges!(tn::AbstractITensorNetwork, v) for vertex in vertices(tn) if v ≠ vertex edge = v => vertex - if hascommoninds(tn, edge) + if !isempty(linkinds(tn, edge)) add_edge!(tn, edge) end end @@ -180,7 +180,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 => v2) + if !isempty(linkinds(tn, v1 => v2)) add_edge!(tn, v1 => v2) end end @@ -198,14 +198,6 @@ end # Data modification # -function ITensors.hascommoninds(tn::AbstractITensorNetwork, edge::Pair) - return hascommoninds(tn, edgetype(tn)(edge)) -end - -function ITensors.hascommoninds(tn::AbstractITensorNetwork, edge::AbstractEdge) - return hascommoninds(tn[src(edge)], tn[dst(edge)]) -end - # # Promotion and conversion # @@ -254,7 +246,7 @@ function IndsNetwork(tn::AbstractITensorNetwork) is[v] = siteinds(tn, v) end for e in edges(tn) - is[e] = commoninds(tn, e) + is[e] = linkinds(tn, e) end return is end @@ -272,7 +264,7 @@ end function linkinds(tn::AbstractITensorNetwork) is = IndsNetwork(underlying_graph(tn)) for e in edges(tn) - is[e] = commoninds(tn, e) + is[e] = linkinds(tn, e) end return is end @@ -292,21 +284,9 @@ siteinds(tn::AbstractITensorNetwork, vertex) = _siteinds(tn, vertex) # Fix ambiguity with `siteinds(::Type, ::Int)` from `sitetype.jl`. siteinds(tn::AbstractITensorNetwork, vertex::Int) = _siteinds(tn, vertex) -function ITensors.uniqueinds(tn::AbstractITensorNetwork, edge::AbstractEdge) - return uniqueinds(tn[src(edge)], tn[dst(edge)]) -end - -function ITensors.uniqueinds(tn::AbstractITensorNetwork, edge::Pair) - return uniqueinds(tn, edgetype(tn)(edge)) -end - -function ITensors.commoninds(tn::AbstractITensorNetwork, edge) - e = edgetype(tn)(edge) - return commoninds(tn[src(e)], tn[dst(e)]) -end - function linkinds(tn::AbstractITensorNetwork, edge) - return commoninds(tn, edge) + e = edgetype(tn)(edge) + return intersect(inds(tn[src(e)]), inds(tn[dst(e)])) end # Priming and tagging (changing Index identifiers) @@ -520,7 +500,7 @@ function LinearAlgebra.svd( kwargs... ) tn = copy(tn) - left_inds = uniqueinds(tn, edge) + left_inds = setdiff(inds(tn[src(edge)]), inds(tn[dst(edge)])) U, S, V = svd(tn[src(edge)], left_inds; lefttags = u_tags, righttags = v_tags, kwargs...) @@ -546,7 +526,7 @@ function LinearAlgebra.qr( kwargs... ) tn = copy(tn) - left_inds = uniqueinds(tn, edge) + left_inds = setdiff(inds(tn[src(edge)]), inds(tn[dst(edge)])) Q, R = factorize(tn[src(edge)], left_inds; tags, kwargs...) rem_vertex!(tn, src(edge)) @@ -574,7 +554,7 @@ function LinearAlgebra.factorize( tn = ITensorNetwork{V}(copy(tn)) neighbors_X = setdiff(neighbors(tn, src(edge)), [dst(edge)]) - left_inds = uniqueinds(tn, edge) + left_inds = setdiff(inds(tn[src(edge)]), inds(tn[dst(edge)])) X, Y = factorize(tn[src(edge)], left_inds; tags, kwargs...) rem_vertex!(tn, src(edge)) @@ -605,7 +585,7 @@ function gauge_edge( # return contract(tn, new_vertex => dst(edge)) !has_edge(tn, edge) && throw(ArgumentError("Edge not in graph.")) tn = copy(tn) - left_inds = uniqueinds(tn, edge) + left_inds = setdiff(inds(tn[src(edge)]), inds(tn[dst(edge)])) ltags = tags(tn, edge) X, Y = factorize(tn[src(edge)], left_inds; tags = ltags, ortho = "left", kwargs...) @preserve_graph tn[src(edge)] = X @@ -680,7 +660,7 @@ end function _truncate_edge(tn::AbstractITensorNetwork, edge::AbstractEdge; kwargs...) !has_edge(tn, edge) && throw(ArgumentError("Edge not in graph.")) tn = copy(tn) - left_inds = uniqueinds(tn, edge) + left_inds = setdiff(inds(tn[src(edge)]), inds(tn[dst(edge)])) ltags = tags(tn, edge) U, S, V = svd(tn[src(edge)], left_inds; lefttags = ltags, kwargs...) @preserve_graph tn[src(edge)] = U @@ -865,7 +845,7 @@ function insert_linkinds( ) tn = copy(tn) for e in edges - if !hascommoninds(tn, e) + if isempty(linkinds(tn, e)) iₑ = Index(link_space, edge_tag(e)) X = onehot(iₑ => 1) tn[src(e)] *= X @@ -962,7 +942,7 @@ function add(tn1::AbstractITensorNetwork, tn2::AbstractITensorNetwork) end # Scale each tensor of the network via a function vertex -> Number -function scale!( +function scale_tensors!( weight_function::Function, tn::AbstractITensorNetwork; vertices = collect(Graphs.vertices(tn)) @@ -971,18 +951,18 @@ function scale!( end # Scale each tensor of the network by a scale factor for each vertex in the keys of the dictionary -function scale!(tn::AbstractITensorNetwork, vertices_weights::Dictionary) - return scale!(v -> vertices_weights[v], tn; vertices = keys(vertices_weights)) +function scale_tensors!(tn::AbstractITensorNetwork, vertices_weights::Dictionary) + return scale_tensors!(v -> vertices_weights[v], tn; vertices = keys(vertices_weights)) end -function scale(weight_function::Function, tn; kwargs...) +function scale_tensors(weight_function::Function, tn; kwargs...) tn = copy(tn) - return scale!(weight_function, tn; kwargs...) + return scale_tensors!(weight_function, tn; kwargs...) end -function scale(tn::AbstractITensorNetwork, vertices_weights::Dictionary; kwargs...) +function scale_tensors(tn::AbstractITensorNetwork, vertices_weights::Dictionary; kwargs...) tn = copy(tn) - return scale!(tn, vertices_weights; kwargs...) + return scale_tensors!(tn, vertices_weights; kwargs...) end Base.:+(tn1::AbstractITensorNetwork, tn2::AbstractITensorNetwork) = add(tn1, tn2) diff --git a/src/apply.jl b/src/apply.jl index 6e66066c..f2a3ecc2 100644 --- a/src/apply.jl +++ b/src/apply.jl @@ -2,8 +2,8 @@ using .BaseExtensions: maybe_real using Graphs: has_edge using ITensors.NDTensors: scalartype using ITensors: ITensors, ITensor, Index, Ops, apply, commonind, commoninds, contract, dag, - denseblocks, factorize, factorize_svd, hasqns, isdiag, noncommoninds, noprime, prime, - replaceind, replaceinds, tags, unioninds, uniqueinds + denseblocks, factorize, factorize_svd, hascommoninds, hasqns, isdiag, noncommoninds, + noprime, prime, replaceind, replaceinds, tags, unioninds, uniqueinds using KrylovKit: linsolve using LinearAlgebra: eigen, norm, qr, svd using NamedGraphs: NamedEdge, has_edge diff --git a/src/caches/abstractbeliefpropagationcache.jl b/src/caches/abstractbeliefpropagationcache.jl index 593d1fee..6f5dc05f 100644 --- a/src/caches/abstractbeliefpropagationcache.jl +++ b/src/caches/abstractbeliefpropagationcache.jl @@ -369,7 +369,7 @@ function rescale_partitions( bpc = copy(bpc) tn = tensornetwork(bpc) norms = map(v -> inv(norm(tn[v])), verts) - scale!(bpc, Dictionary(verts, norms)) + scale_tensors!(bpc, Dictionary(verts, norms)) vertices_weights = Dictionary() for pv in partitions @@ -385,7 +385,7 @@ function rescale_partitions( end end - scale!(bpc, vertices_weights) + scale_tensors!(bpc, vertices_weights) return bpc end diff --git a/src/normalize.jl b/src/normalize.jl index 34201b47..44f6573d 100644 --- a/src/normalize.jl +++ b/src/normalize.jl @@ -9,7 +9,7 @@ function rescale(alg::Algorithm"exact", tn::AbstractITensorNetwork; kwargs...) vs = collect(vertices(tn)) c = inv(exp(logn / length(vs))) vertices_weights = Dictionary(vs, [c for v in vs]) - return scale(tn, vertices_weights) + return scale_tensors(tn, vertices_weights) end function rescale( @@ -61,7 +61,7 @@ function LinearAlgebra.normalize( vs = collect(vertices(tn)) c = inv(exp(logn / (2 * length(vs)))) vertices_weights = Dictionary(vs, [c for v in vs]) - return scale(tn, vertices_weights) + return scale_tensors(tn, vertices_weights) end function LinearAlgebra.normalize( diff --git a/src/solvers/applyexp.jl b/src/solvers/applyexp.jl index 1f1be0af..b8cd3a83 100644 --- a/src/solvers/applyexp.jl +++ b/src/solvers/applyexp.jl @@ -1,3 +1,4 @@ +using ITensors: uniqueinds using Printf: @printf @kwdef mutable struct ApplyExpProblem{State} <: AbstractProblem diff --git a/src/solvers/subspace/densitymatrix.jl b/src/solvers/subspace/densitymatrix.jl index 506b1918..558efdf6 100644 --- a/src/solvers/subspace/densitymatrix.jl +++ b/src/solvers/subspace/densitymatrix.jl @@ -1,3 +1,4 @@ +using ITensors: hascommoninds, uniqueinds using NamedGraphs.GraphsExtensions: incident_edges using Printf: @printf diff --git a/src/treetensornetworks/opsum_to_ttn/opsum_to_ttn.jl b/src/treetensornetworks/opsum_to_ttn/opsum_to_ttn.jl index 3ccb1af3..2f530858 100644 --- a/src/treetensornetworks/opsum_to_ttn/opsum_to_ttn.jl +++ b/src/treetensornetworks/opsum_to_ttn/opsum_to_ttn.jl @@ -661,31 +661,6 @@ function mpo(os::OpSum, s::IndsNetwork; kwargs...) return ttn(os, s; kwargs...) end -# Conversion from other formats -function ttn(o::Op, s::IndsNetwork; kwargs...) - return ttn(OpSum{Float64}() + o, s; kwargs...) -end - -function ttn(o::Scaled{C, Op}, s::IndsNetwork; kwargs...) where {C} - return ttn(OpSum{C}() + o, s; kwargs...) -end - -function ttn(o::Sum{Op}, s::IndsNetwork; kwargs...) - return ttn(OpSum{Float64}() + o, s; kwargs...) -end - -function ttn(o::Prod{Op}, s::IndsNetwork; kwargs...) - return ttn(OpSum{Float64}() + o, s; kwargs...) -end - -function ttn(o::Scaled{C, Prod{Op}}, s::IndsNetwork; kwargs...) where {C} - return ttn(OpSum{C}() + o, s; kwargs...) -end - -function ttn(o::Sum{Scaled{C, Op}}, s::IndsNetwork; kwargs...) where {C} - return ttn(OpSum{C}() + o, s; kwargs...) -end - # Catch-all for leaf eltype specification function ttn(eltype::Type{<:Number}, os, sites::IndsNetwork; kwargs...) return NDTensors.convert_scalartype(eltype, ttn(os, sites; kwargs...)) diff --git a/src/treetensornetworks/projttns/projouterprodttn.jl b/src/treetensornetworks/projttns/projouterprodttn.jl index 62fef386..cfd4db63 100644 --- a/src/treetensornetworks/projttns/projouterprodttn.jl +++ b/src/treetensornetworks/projttns/projouterprodttn.jl @@ -1,6 +1,6 @@ using DataGraphs: DataGraphs using Dictionaries: set! -using ITensors: ITensor +using ITensors: ITensor, hascommoninds using NamedGraphs.GraphsExtensions: incident_edges, is_leaf_vertex struct ProjOuterProdTTN{V} <: AbstractProjTTN{V} diff --git a/src/treetensornetworks/projttns/projttn.jl b/src/treetensornetworks/projttns/projttn.jl index 19d0ebe3..09f2ed34 100644 --- a/src/treetensornetworks/projttns/projttn.jl +++ b/src/treetensornetworks/projttns/projttn.jl @@ -1,7 +1,7 @@ using DataGraphs: DataGraphs, underlying_graph using Dictionaries: Dictionary, Indices using Graphs: edgetype, vertices -using ITensors: ITensor +using ITensors: ITensor, hascommoninds using NamedGraphs.GraphsExtensions: incident_edges, is_leaf_vertex using NamedGraphs: NamedEdge diff --git a/src/treetensornetworks/treetensornetwork.jl b/src/treetensornetworks/treetensornetwork.jl index 75d74dd1..48103384 100644 --- a/src/treetensornetworks/treetensornetwork.jl +++ b/src/treetensornetworks/treetensornetwork.jl @@ -230,7 +230,7 @@ function ttn( tn = ITensorNetwork(is) ortho_center = first(ortho_region) for e in post_order_dfs_edges(tn, ortho_center) - left_inds = uniqueinds(is, e) + left_inds = setdiff(inds(a), inds(tn[dst(e)])) a_l, a_r = factorize(a, left_inds; tags = edge_tag(e), ortho = "left", kwargs...) tn[src(e)] = a_l is[e] = commoninds(a_l, a_r) diff --git a/test/Project.toml b/test/Project.toml index cf361b40..c861b038 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -46,7 +46,7 @@ Glob = "1.3.1" Graphs = "1.12" GraphsFlows = "0.1.1" ITensorMPS = "0.3.6, 0.4" -ITensorNetworks = "0.20" +ITensorNetworks = "0.21" ITensorPkgSkeleton = "0.3.42" ITensors = "0.7, 0.8, 0.9" KrylovKit = "0.8, 0.9, 0.10" diff --git a/test/test_belief_propagation.jl b/test/test_belief_propagation.jl index 192573ea..ca22e679 100644 --- a/test/test_belief_propagation.jl +++ b/test/test_belief_propagation.jl @@ -1,9 +1,9 @@ using Compat: Compat using Graphs: vertices -using ITensorNetworks: ITensorNetworks, @preserve_graph, BeliefPropagationCache, - combine_linkinds, contract, contraction_sequence, environment, inner_network, - linkinds_combiners, message, message_diff, partitioned_tensornetwork, scalar, siteinds, - split_index, tensornetwork, update, update_factor, updated_message, ⊗ +using ITensorNetworks: ITensorNetworks, @preserve_graph, BeliefPropagationCache, contract, + contraction_sequence, environment, inner_network, message, message_diff, + partitioned_tensornetwork, scalar, siteinds, split_index, tensornetwork, update, + update_factor, updated_message, ⊗ include("utils.jl") using ITensors.NDTensors: array using ITensors: diff --git a/test/test_itensornetwork.jl b/test/test_itensornetwork.jl index f13b98c5..7f1b6926 100644 --- a/test/test_itensornetwork.jl +++ b/test/test_itensornetwork.jl @@ -7,9 +7,8 @@ using ITensorNetworks: ITensorNetworks, ITensorNetwork, IndsNetwork, contraction inner_network, linkinds, norm_sqr, norm_sqr_network, orthogonalize, siteinds, tree_orthogonalize, ttn, ⊗ using ITensors.NDTensors: NDTensors, dim -using ITensors: ITensors, ITensor, Index, Op, commonind, commoninds, contract, dag, - hascommoninds, hasinds, inds, inner, itensor, onehot, order, prime, random_itensor, - scalartype, sim, uniqueinds +using ITensors: ITensors, ITensor, Index, Op, commonind, commoninds, contract, dag, hasinds, + inds, inner, itensor, onehot, order, prime, random_itensor, scalartype, sim using LinearAlgebra: factorize using NDTensors: NDTensors, dim using NamedGraphs.GraphsExtensions: disjoint_union, incident_edges @@ -290,13 +289,13 @@ const elts = (Float32, Float64, Complex{Float32}, Complex{Float64}) ψ = ITensorNetwork(s; link_space = 2) e = (1, 1) => (2, 1) - uie = uniqueinds(ψ, e) + uie = setdiff(inds(ψ[1, 1]), inds(ψ[2, 1])) @test isempty(commoninds(uie, inds(ψ[2, 1]))) @test issetequal(uie, union(commoninds(ψ[1, 1], ψ[1, 2]), siteinds(ψ, (1, 1)))) @test siteinds(ψ, (1, 1)) == s[1, 1] - cie = commoninds(ψ, e) + cie = linkinds(ψ, e) @test hasinds(ψ[1, 1], cie) && hasinds(ψ[2, 1], cie) @test isempty(commoninds(uie, cie))