ITensor / ITensorNetworks.jl

A package with general tools for working with higher-dimensional tensor networks based on ITensor.
MIT License
62 stars 13 forks source link

`ITensors.MPS`/`ITensors.MPO` graph interface layer #37

Open mtfishman opened 1 year ago

mtfishman commented 1 year ago

Move the ITensors.MPS/ITensors.MPO graph interface layer from https://github.com/ITensor/ITensorTDVP.jl/pull/43 into this package, once that PR is merged.

An interesting question that hits on some limitations of Julia's subtyping system is that it would be nice for ITensors.MPS/ITensors.MPO to work in the functions defined in these packages, once they adhere to the AbstractDataGraph interface. However, it is awkward to try to make them subtypes of AbstractDataGraph.

It's possible to do that without making ITensors.jl depend on the full DataGraphs.jl package by making an interface package DataGraphsCore.jl in the spirit of StaticArraysCore.jl but that seems a bit overkill. The alternative is to use traits implemented with the SimpleTraits.jl package, and define traits such as IsITensorNetwork or IsDataGraph which are then overloaded for ITensors.MPS/ITensors.MPO, but that also seems a bit overkill as well since then we would need to define all of the functions we currently define through abstract type dispatch with AbstractITensorNetwork or AbstractDataGraph with traits instead.

In the end, it may not matter so much since I think the ITensorNetworks.TreeTensorNetwork type will supersede the ITensors.MPS/ITensors.MPO types but be superior in a variety of ways, so we can just keep some simple interfacing functionality and have conversions from ITensors.MPS/ITensors.MPO to ITensorNetworks.TreeTensorNetwork.

emstoudenmire commented 1 year ago

Yeah this is where I wish Julia dispatch worked more along the lines of "check if a certain set of methods are defined for this type, if so it is a DataGraph" which I think is more how the new concepts system works in C++20.

By the IsDataGraph idea, do you mean something like:

const IsDataGraph = Union{DataGraph,MPS,MPO}

? Then later removing this once MPS and MPO are defined as a kind of graph?

mtfishman commented 1 year ago

We could do it through a union type since we have a finite number of types in mind, but the more general solution is defining them as traits from SimpleTraits.jl since that is more extensible (it would allow someone else to opt-in with their own tensor network or data graph type, without hard-coding it in a union type or with subtyping).

This may be overkill for this case anyway, mostly just bringing up the issue and summarizing the different potential solutions. Eventually I would imagine just deprecating ITensors.MPS and ITensors.MPO, but of course we want to make sure they continue to exist and have the same functionality they have now going into the future so that user code still works. But the general plan may be to just add new functionality for ITensorNetworks.TreeTensorNetwork. Depending on how things develop, ITensorTDVP.jl/ITensorSolvers.jl may be the right time to rip off the band-aid and move fully to ITensorNetworks.TreeTensorNetwork once the functionality catches up to ITensors.AbstractMPS.

mtfishman commented 1 year ago

An interesting perspective is that ITensors.AbstractMPS can be viewed as an implicitly defined graph, as in the graph layout is implicitly defined as a path graph by the type. The interface layer in the file src/tree_patch.jl in Lander's PR just makes that explicit. This is similar to SpecialGraphs.PathGraph.

So we could imagine in the future people devising implicitly defined graphs (i.e. the edges and vertices are implied by the type but not explicitly stored). A concrete example of that is Vector{ITensor}, which implicitly defines a graph by the connectivity of the indices of the ITensors. So it may be nice to make Vector{ITensor} act like a DataGraph through a IsDataGraph trait and the edges are determined on the fly by commoninds, which would be impossible with subtyping and would start to get annoying to handle through a Union type (for example, what about Matrix{ITensor} or NTuple{N,ITensor} or Dict{<:Any,ITensor}?). This may be inefficient for certain workflows and operations since it would be doing O(length(tn)^2) calls to hascommoninds, but it could be nice for making functionality like prime(::Vector{ITensor}) and more sophisticated versions that only prime the link indices "just work" using ITensorNetworks.jl functionality.