Skip to content
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "ITensorNetworks"
uuid = "2919e153-833c-4bdc-8836-1ea460a35fc7"
version = "0.19.7"
version = "0.20.0"
authors = ["Matthew Fishman <mfishman@flatironinstitute.org>, Joseph Tindall <jtindall@flatironinstitute.org> and contributors"]

[workspace]
Expand Down
2 changes: 1 addition & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ path = ".."
Documenter = "1.10"
Graphs = "1"
ITensorFormatter = "0.2.27"
ITensorNetworks = "0.19"
ITensorNetworks = "0.20"
ITensors = "0.9"
Literate = "2.20.1"
NamedGraphs = "0.11"
Expand Down
68 changes: 0 additions & 68 deletions docs/src/deprecated_methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,6 @@ Suggestions of methods which could be deleted.

#### ITensorNetwork Constructors

* Default constructor (`itensornetwork.jl`).
```julia
ITensorNetwork{V}()
```

* (Only actually deprecate / delete this function if the more generic constructor `ITensorNetwork(tensors)` can also handle this case.)
From a vector of `ITensor`s, with vertex labels auto-assigned to `eachindex(ts)`.
Edges are inferred from shared indices (`itensornetwork.jl`):
```julia
ITensorNetwork(ts::AbstractVector{ITensor})
```

* From a collection of ITensorNetworks. Merges (Kronecker or tensor product) of input networks (`itensornetwork.jl`):
```julia
ITensorNetwork(itns::Vector{ITensorNetwork})
```

* From a named graph, forwards to construction from `IndsNetwork` (`itensornetwork.jl`):
```julia
ITensorNetwork{V}(g::NamedGraph)
Expand All @@ -47,11 +30,6 @@ Suggestions of methods which could be deleted.
ITensorNetwork(itensor_constructor::Function, is::IndsNetwork; link_space = trivial_space(is), kwargs...)
```

* From a single `ITensor`. Wraps the tensor in a single-vertex network (`itensornetwork.jl`):
```julia
ITensorNetwork(t::ITensor)
```

* Construct an `ITensorNetwork` from an `IndsNetwork`. Initializes ITensors with `undef` storage on each vertex
of the `IndsNetwork` with the corresponding indices (`itensornetwork.jl`):
```julia
Expand All @@ -63,58 +41,20 @@ Suggestions of methods which could be deleted.

#### Local Operations on ITensorNetworks

* Versions of `siteinds` taking a `vertex` argument. Each of these is just an alias for `uniqueinds`. Possibly the wrong design / implementation. (`abstractitensornetwork.jl`).
```julia
siteinds(tn::AbstractITensorNetwork, vertex) # abstractitensornetwork.jl:288
siteinds(tn::AbstractITensorNetwork, vertex::Int) # abstractitensornetwork.jl:292
```


* Functions in `apply.jl` which are unused, even inside that file (`apply.jl`):
```julia
_gate_vertices(o::ITensor, ψ)
_gate_vertices(o::AbstractEdge, ψ)
_contract_gate(o::ITensor, ψv1, Λ, ψv2)
_contract_gate(o::AbstractEdge, ψv1, Λ, ψv2)
```

* Collection of tensors neighboring the given vertex (`abstractitensornetwork.jl`):
```julia
neighbor_tensors(tn::AbstractITensorNetwork, vertex)
```

* Iterate over the tensors at the given vertices, default all vertices (`abstractitensornetwork.jl`):
```julia
eachtensor(tn::AbstractITensorNetwork, vertices = vertices(tn))
```

* 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)
```

* Alias for `uniqueinds` (`abstractitensornetwork.jl`):
```julia
siteinds(tn::AbstractITensorNetwork, vertex)
siteinds(tn::AbstractITensorNetwork, vertex::Int)
```

* 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)
```

* Indices on `tn[vertex]` that aren't shared with any neighbor, i.e. the external/site
indices of that vertex (`abstractitensornetwork.jl`).
(Use a set function like `setdiff` instead.)
```julia
uniqueinds(tn::AbstractITensorNetwork, vertex)
```

## Global Operations on ITensorNetworks


Expand All @@ -138,11 +78,3 @@ Suggestions of methods which could be deleted.
```
To be revisited after Jack's work on NamedGraphs.

* Methods in `graphs.jl`.
Just one methods which constructs a `SimpleGraph` from ITensors (`graphs.jl`).
```julia
SimpleGraphs.SimpleGraph(itensors::Vector{ITensor})
```
Not used anywhere in library.

* Methods in `update_observer.jl`. Not used anywhere in library.
11 changes: 0 additions & 11 deletions docs/src/experimental_methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,6 @@ Methods which still need to be discussed, modified, or deprecated.
dst_ind_map::Function = prime)
```

* Collect all site indices (per-vertex) of a network as a flat vector (`abstractitensornetwork.jl`):
```julia
flatten_siteinds(tn::AbstractITensorNetwork)
```

* Collect all link indices (per-edge) of a network as a flat vector (`abstractitensornetwork.jl`):
```julia
flatten_linkinds(tn::AbstractITensorNetwork)
```


## TreeTensorNetwork Types

#### OpSum Constructors
Expand Down
3 changes: 1 addition & 2 deletions docs/src/itensor_networks.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ i, j, k = Index(2, "i"), Index(2, "j"), Index(2, "k")
A, B, C = ITensor(i, j), ITensor(j, k), ITensor(k)

tn = ITensorNetwork([A, B, C]) # integer vertices 1, 2, 3
tn = ITensorNetwork(["A", "B", "C"], [A, B, C]) # named vertices
tn = ITensorNetwork(["A" => A, "B" => B, "C" => C]) # from pairs
tn = ITensorNetwork(Dict("A" => A, "B" => B, "C" => C)) # named vertices via a Dict
```

```@docs; canonical=false
Expand Down
2 changes: 1 addition & 1 deletion examples/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ ITensorNetworks = "2919e153-833c-4bdc-8836-1ea460a35fc7"
path = ".."

[compat]
ITensorNetworks = "0.19"
ITensorNetworks = "0.20"
2 changes: 0 additions & 2 deletions src/ITensorNetworks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ module ITensorNetworks
include("lib/BaseExtensions/src/BaseExtensions.jl")
include("lib/ITensorsExtensions/src/ITensorsExtensions.jl")
include("visualize.jl")
include("graphs.jl")
include("abstractindsnetwork.jl")
include("indextags.jl")
include("indsnetwork.jl")
Expand All @@ -23,7 +22,6 @@ include("formnetworks/bilinearformnetwork.jl")
include("formnetworks/linearformnetwork.jl")
include("formnetworks/quadraticformnetwork.jl")
include("utils.jl")
include("update_observer.jl")

include("treetensornetworks/abstracttreetensornetwork.jl")
include("treetensornetworks/treetensornetwork.jl")
Expand Down
85 changes: 27 additions & 58 deletions src/abstractitensornetwork.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ Base.copy(tn::AbstractITensorNetwork) = not_implemented()
# Iteration
Base.iterate(tn::AbstractITensorNetwork, args...) = iterate(vertex_data(tn), args...)

# Vertex-keyed access: `keys(tn)` returns the vertex set, `tn[v]` returns the
# tensor at vertex `v`. Together with `Base.iterate` above, this lets `tn`
# stand in as a `keys`/`values`-style collection of tensors keyed by vertex.
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::AbstractITensorNetwork) = eltype(vertex_data(tn))
Expand Down Expand Up @@ -167,8 +172,11 @@ end
# TODO: broadcasting

function Base.union(tn1::AbstractITensorNetwork, tn2::AbstractITensorNetwork; kwargs...)
# TODO: Use a different constructor call here?
tn = _ITensorNetwork(union(data_graph(tn1), data_graph(tn2)); kwargs...)
g = union(underlying_graph(tn1), underlying_graph(tn2); kwargs...)
tensors = Dict{vertextype(g), ITensor}(
v => (v in vertices(tn1) ? tn1[v] : tn2[v]) for v in vertices(g)
)
tn = ITensorNetwork(tensors, g)
# Add any new edges that are introduced during the union
for v1 in vertices(tn1)
for v2 in vertices(tn2)
Expand All @@ -181,8 +189,9 @@ function Base.union(tn1::AbstractITensorNetwork, tn2::AbstractITensorNetwork; kw
end

function NamedGraphs.rename_vertices(f::Function, tn::AbstractITensorNetwork)
# TODO: Use a different constructor call here?
return _ITensorNetwork(rename_vertices(f, data_graph(tn)))
new_g = NamedGraphs.rename_vertices(f, underlying_graph(tn))
tensors = Dict{vertextype(new_g), ITensor}(f(v) => tn[v] for v in vertices(tn))
return ITensorNetwork(tensors, new_g)
end

#
Expand All @@ -197,23 +206,16 @@ function ITensors.hascommoninds(tn::AbstractITensorNetwork, edge::AbstractEdge)
return hascommoninds(tn[src(edge)], tn[dst(edge)])
end

# Convenience wrapper
function eachtensor(tn::AbstractITensorNetwork, vertices = vertices(tn))
return map(v -> tn[v], vertices)
end

#
# Promotion and conversion
#

function ITensorsExtensions.promote_indtypeof(tn::AbstractITensorNetwork)
return mapreduce(promote_indtype, eachtensor(tn)) do t
return indtype(t)
end
return mapreduce(v -> indtype(tn[v]), promote_indtype, vertices(tn))
end

function NDTensors.scalartype(tn::AbstractITensorNetwork)
return mapreduce(eltype, promote_type, eachtensor(tn); init = Bool)
return mapreduce(v -> eltype(tn[v]), promote_type, vertices(tn); init = Bool)
end

# TODO: Define `eltype(::AbstractITensorNetwork)` as `ITensor`?
Expand Down Expand Up @@ -249,32 +251,24 @@ end
function IndsNetwork(tn::AbstractITensorNetwork)
is = IndsNetwork(underlying_graph(tn))
for v in vertices(tn)
is[v] = uniqueinds(tn, v)
is[v] = siteinds(tn, v)
end
for e in edges(tn)
is[e] = commoninds(tn, e)
end
return is
end

# Alias
indsnetwork(tn::AbstractITensorNetwork) = IndsNetwork(tn)

# TODO: Output a `VertexDataGraph`? Unfortunately
# `IndsNetwork` doesn't allow iterating over vertex data.
function siteinds(tn::AbstractITensorNetwork)
is = IndsNetwork(underlying_graph(tn))
for v in vertices(tn)
is[v] = uniqueinds(tn, v)
is[v] = siteinds(tn, v)
end
return is
end

function flatten_siteinds(tn::AbstractITensorNetwork)
# `identity.(...)` narrows the type, maybe there is a better way.
return identity.(flatten(map(v -> siteinds(tn, v), vertices(tn))))
end

function linkinds(tn::AbstractITensorNetwork)
is = IndsNetwork(underlying_graph(tn))
for e in edges(tn)
Expand All @@ -283,23 +277,20 @@ function linkinds(tn::AbstractITensorNetwork)
return is
end

function flatten_linkinds(tn::AbstractITensorNetwork)
# `identity.(...)` narrows the type, maybe there is a better way.
return identity.(flatten(map(e -> linkinds(tn, e), edges(tn))))
end

#
# Index access
#

function neighbor_tensors(tn::AbstractITensorNetwork, vertex)
return eachtensor(tn, neighbors(tn, vertex))
end

function ITensors.uniqueinds(tn::AbstractITensorNetwork, vertex)
tn_vertex = [tn[vertex]; collect(neighbor_tensors(tn, vertex))]
return reduce(setdiff, inds.(tn_vertex))
function _siteinds(tn::AbstractITensorNetwork, vertex)
s = inds(tn[vertex])
for v in neighbors(tn, vertex)
s = setdiff(s, inds(tn[v]))
end
return s
end
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)])
Expand All @@ -309,14 +300,6 @@ function ITensors.uniqueinds(tn::AbstractITensorNetwork, edge::Pair)
return uniqueinds(tn, edgetype(tn)(edge))
end

function siteinds(tn::AbstractITensorNetwork, vertex)
return uniqueinds(tn, vertex)
end
# Fix ambiguity error with IndsNetwork constructor.
function siteinds(tn::AbstractITensorNetwork, vertex::Int)
return uniqueinds(tn, vertex)
end

function ITensors.commoninds(tn::AbstractITensorNetwork, edge)
e = edgetype(tn)(edge)
return commoninds(tn[src(e)], tn[dst(e)])
Expand Down Expand Up @@ -843,7 +826,7 @@ function ITensorVisualizationCore.visualize(
vertex_labels = [vertex_labels_prefix * string(v) for v in vertices(tn)]
end
# TODO: Use `tokenize_vertex`.
return visualize(collect(eachtensor(tn)), args...; vertex_labels, kwargs...)
return visualize([tn[v] for v in vertices(tn)], args...; vertex_labels, kwargs...)
end

#
Expand Down Expand Up @@ -877,20 +860,6 @@ function linkdims(tn::AbstractITensorNetwork{V}) where {V}
return ld
end

#
# Site combiners
#

# TODO: will be broken, fix this
function site_combiners(tn::AbstractITensorNetwork{V}) where {V}
Cs = DataGraph{V, ITensor}(copy(underlying_graph(tn)))
for v in vertices(tn)
s = siteinds(tn, v)
Cs[v] = combiner(s; tags = commontags(s))
end
return Cs
end

function insert_linkinds(
tn::AbstractITensorNetwork, edges = edges(tn); link_space = trivial_space(tn)
)
Expand Down
25 changes: 4 additions & 21 deletions src/apply.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ function full_update_bp(
Qᵥ₂, Rᵥ₂ = ITensor(true), copy(ψ[v⃗[2]])
else
Qᵥ₁, Rᵥ₁ = factorize(
ψ[v⃗[1]], uniqueinds(uniqueinds(ψ[v⃗[1]], ψ[v⃗[2]]), uniqueinds(ψ, v⃗[1]))
ψ[v⃗[1]],
setdiff(setdiff(inds(ψ[v⃗[1]]), inds(ψ[v⃗[2]])), siteinds(ψ, v⃗[1]))
)
Qᵥ₂, Rᵥ₂ = factorize(
ψ[v⃗[2]], uniqueinds(uniqueinds(ψ[v⃗[2]], ψ[v⃗[1]]), uniqueinds(ψ, v⃗[2]))
ψ[v⃗[2]],
setdiff(setdiff(inds(ψ[v⃗[2]]), inds(ψ[v⃗[1]])), siteinds(ψ, v⃗[2]))
)
end
extended_envs = vcat(envs, Qᵥ₁, prime(dag(Qᵥ₁)), Qᵥ₂, prime(dag(Qᵥ₂)))
Expand Down Expand Up @@ -286,25 +288,6 @@ function ITensors.apply(
return apply(ITensor(o, siteinds(ψ)), ψ; normalize, ortho, apply_kwargs...)
end

_gate_vertices(o::ITensor, ψ) = neighbor_vertices(ψ, o)
_gate_vertices(o::AbstractEdge, ψ) = [src(o), dst(o)]

function _contract_gate(o::ITensor, ψv1, Λ, ψv2)
indsᵥ₁ = noprime(noncommoninds(ψv1, Λ))
Qᵥ₁, Rᵥ₁ = qr(ψv1, setdiff(uniqueinds(indsᵥ₁, ψv2), commoninds(indsᵥ₁, o)))
Qᵥ₂, Rᵥ₂ = qr(ψv2, setdiff(uniqueinds(ψv2, indsᵥ₁), commoninds(ψv2, o)))
theta = noprime(noprime(Rᵥ₁ * Λ) * Rᵥ₂ * o)
return Qᵥ₁, Rᵥ₁, Qᵥ₂, Rᵥ₂, theta
end

function _contract_gate(o::AbstractEdge, ψv1, Λ, ψv2)
indsᵥ₁ = noprime(noncommoninds(ψv1, Λ))
Qᵥ₁, Rᵥ₁ = qr(ψv1, uniqueinds(indsᵥ₁, ψv2))
Qᵥ₂, Rᵥ₂ = qr(ψv2, uniqueinds(ψv2, indsᵥ₁))
theta = noprime(Rᵥ₁ * Λ) * Rᵥ₂
return Qᵥ₁, Rᵥ₁, Qᵥ₂, Rᵥ₂, theta
end

### Full Update Routines ###

# Calculate the overlap of the gate acting on the previous p and q versus the new p and q in the presence of environments. This is the cost function that optimise_p_q will minimise
Expand Down
Loading
Loading