Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate path optimization of disconnected components in the network graph #53

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
22 changes: 22 additions & 0 deletions src/EinExpr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ using Base: AbstractVecOrTuple
using DataStructures: DefaultDict
using AbstractTrees
using Compat
using Graphs

Base.@kwdef struct EinExpr{Label}
head::Vector{Label}
Expand Down Expand Up @@ -300,3 +301,24 @@ function sumtraces(path::EinExpr)

EinExpr(path.head, _args)
end

function components(path::EinExpr{L}) where {L}
network = map(head, path.args)
# create adjacency matrix of the network
n = nargs(path)
adjmat = falses(n,n)

for (i,j) in combinations(1:n, 2)
if !isdisjoint(network[i], network[j])
adjmat[i,j] = true
adjmat[j,i] = true
end
end

# find disconneceted subgraphs
subgraphs = connected_components(SimpleGraph(adjmat))

# create subnetworks
indeppaths = [sum(EinExpr.([network[tns] for tns in subnet])) for subnet in subgraphs]
return indeppaths
end
4 changes: 2 additions & 2 deletions src/Optimizers/Greedy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ The implementation uses a binary heaptree to sort candidate pairwise tensor cont
outer::Bool = false
end

function einexpr(config::Greedy, path::EinExpr{L}, sizedict::Dict{L}) where {L}
function einexpr(config::Greedy, sizedict::Dict{L}, path::EinExpr{L}) where {L}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why change the order?

Copy link
Author

@Todorbsc Todorbsc Feb 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of the multiple dispatching: this way, all optimizers' einexpr function are called through Optimizers.einexpr when the function call is like the one suggested in the issue #51:

network = [[:a, :b], [:b, :c], [:A, :B], [:B, :C]]
expr = sum(EinExpr.(network))
optdata = Dict(key => 2 for key in unique(vcat(network...)))
einexpr(Exhaustive(), expr, optdata)

Although I am not really convinced about this fix, it makes possible to call the optimizers with each of the non-interconnected subgraphs at the level of abstraction of the class Optimizers avoiding the need to modify each specific optimizer.

Let me know what are your thoughts on this and whether there's another more-suitable way to implement this.

# remove self-loops
path = sumtraces(path)
metric = config.metric(sizedict)
Expand Down Expand Up @@ -70,4 +70,4 @@ function einexpr(config::Greedy, path::EinExpr{L}, sizedict::Dict{L}) where {L}
return path
end

einexpr(config::Greedy, path::SizedEinExpr) = SizedEinExpr(einexpr(config, path.path, path.size), path.size)
einexpr(config::Greedy, path::SizedEinExpr) = SizedEinExpr(einexpr(config, path.size, path.path), path.size)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above: why change the order?

2 changes: 0 additions & 2 deletions src/Optimizers/Naive.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ using AbstractTrees

struct Naive <: Optimizer end

einexpr(::Naive, path, _) = einexpr(Naive(), path)

function einexpr(::Naive, path)
# remove self-loops
path = sumtraces(path)
Expand Down
2 changes: 1 addition & 1 deletion src/Optimizers/Optimizers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ abstract type Optimizer end
function einexpr end

einexpr(T::Type{<:Optimizer}, args...; kwargs...) = einexpr(T(; kwargs...), args...)
einexpr(config::Optimizer, expr, sizedict) = einexpr(config, SizedEinExpr(expr, sizedict))
einexpr(config::Optimizer, expr, sizedict) = sum(einexpr.((config,), map(exp -> SizedEinExpr(exp, sizedict), components(expr))))

include("Naive.jl")
include("Exhaustive.jl")
Expand Down
Loading