Reference
Data structures and interfaces
OMEinsumContractionOrders.AbstractEinsum
— TypeAbstractEinsum
Abstract type for einsum notations.
Required Interfaces
getixsv
: a vector of vectors, each vector represents the labels associated with a input tensor.getiyv
: a vector of labels associated with the output tensor.uniquelabels
: a vector of labels that are unique in the einsum notation.
Derived interfaces
labeltype
: the data type to represent the labels in the einsum notation.
OMEinsumContractionOrders.CodeOptimizer
— TypeCodeOptimizer
Abstract type for code optimizers.
OMEinsumContractionOrders.CodeSlicer
— TypeCodeSlicer
Abstract type for code slicers.
OMEinsumContractionOrders.EinCode
— TypeEinCode{LT} <: AbstractEinsum
EinCode(ixs::Vector{Vector{LT}}, iy::Vector{LT})
Einsum code with input indices ixs
and output index iy
.
Examples
The einsum notation for matrix multiplication is:
julia> code = OMEinsumContractionOrders.EinCode([[1,2], [2, 3]], [1, 3])
1∘2, 2∘3 -> 1∘3
julia> OMEinsumContractionOrders.getixsv(code)
2-element Vector{Vector{Int64}}:
[1, 2]
[2, 3]
julia> OMEinsumContractionOrders.getiyv(code)
2-element Vector{Int64}:
1
3
OMEinsumContractionOrders.NestedEinsum
— TypeNestedEinsum{LT} <: AbstractEinsum
NestedEinsum(args::Vector{NestedEinsum}, eins::EinCode)
The einsum notation with a contraction order specified as a tree data structure. It is automatically generated by the contraction code optimizer with the optimize_code
function.
Fields
args
: the children of the current nodetensorindex
: the index of the input tensor, required only for leaf nodes. For non-leaf nodes, it is-1
.eins
: the einsum notation for the operation at the current node.
OMEinsumContractionOrders.ScoreFunction
— TypeScoreFunction
A function to compute the score of a contraction code:
score = tc_weight * 2^tc + rw_weight * 2^rw + sc_weight * max(0, 2^sc - 2^sc_target)
Fields
tc_weight
: the weight of the time complexity, default is 1.0.sc_weight
: the weight of the space complexity (the size of the largest tensor), default is 1.0.rw_weight
: the weight of the read-write complexity, default is 0.0.sc_target
: the target space complexity, below which thesc_weight
will be set to 0 automatically, default is 0.0.
OMEinsumContractionOrders.SlicedEinsum
— TypeSlicedEinsum{LT,ET<:Union{EinCode{LT},NestedEinsum{LT}}} <: AbstractEinsum
SlicedEinsum(slicing::Vector{LT}, eins::ET)
The einsum notation with sliced indices. The sliced indices are the indices enumerated manually at the top level. By slicing the indices, the space complexity of the einsum notation can be reduced.
Fields
slicing
: the sliced indices.eins
: the einsum notation of the current node, which is aNestedEinsum
object.
OMEinsumContractionOrders.getixsv
— Functiongetixsv(code::AbstractEinsum) -> Vector{Vector{LT}}
Returns the input indices of the einsum notation. Each vector represents the labels associated with a input tensor.
OMEinsumContractionOrders.getiyv
— Functiongetiyv(code::AbstractEinsum) -> Vector{LT}
Returns the output index of the einsum notation.
OMEinsumContractionOrders.labeltype
— Methodlabeltype(code::AbstractEinsum) -> Type
Returns the data type to represent the labels in the einsum notation.
OMEinsumContractionOrders.uniquelabels
— Methoduniquelabels(code::AbstractEinsum) -> Vector{LT}
Returns the unique labels in the einsum notation. The labels are the indices of the tensors.
Time and space complexity
OMEinsumContractionOrders.contraction_complexity
— Methodcontraction_complexity(eincode, size_dict) -> ContractionComplexity
Returns the time, space and read-write complexity of the einsum contraction. The returned ContractionComplexity
object contains 3 fields:
tc
: time complexity defined aslog2(number of element-wise multiplications)
.sc
: space complexity defined aslog2(size of the maximum intermediate tensor)
.rwc
: read-write complexity defined aslog2(the number of read-write operations)
.
OMEinsumContractionOrders.flop
— Methodflop(eincode, size_dict) -> Int
Returns the number of iterations, which is different with the true floating point operations (FLOP) by a factor of 2.
OMEinsumContractionOrders.label_elimination_order
— Methodlabel_elimination_order(code) -> Vector
Returns a vector of labels sorted by the order they are eliminated in the contraction tree. The contraction tree is specified by code
, which e.g. can be a NestedEinsum
instance.
OMEinsumContractionOrders.peak_memory
— Methodpeak_memory(code, size_dict::Dict) -> Int
Estimate peak memory in number of elements.
OMEinsumContractionOrders.uniformsize
— Methoduniformsize(code::AbstractEinsum, size::Int) -> Dict
Returns a dictionary that maps each label to the given size.
Contraction order optimizers
OMEinsumContractionOrders.optimize_code
— Methodoptimize_code(eincode, size_dict, optimizer = GreedyMethod(); slicer=nothing, simplifier=nothing, permute=true) -> optimized_eincode
Optimize the einsum contraction code and reduce the time/space complexity of tensor network contraction. Returns a NestedEinsum
instance. Input arguments are
Arguments
eincode
is an einsum contraction code instance, one ofDynamicEinCode
,StaticEinCode
orNestedEinsum
.size
is a dictionary of "edge label=>edge size" that contains the size information, one can useuniformsize(eincode, 2)
to create a uniform size.optimizer
is aCodeOptimizer
instance, should be one ofGreedyMethod
,Treewidth
,KaHyParBipartite
,SABipartite
orTreeSA
. Check their docstrings for details.
Keyword Arguments
slicer
is for slicing the contraction code to reduce the space complexity, default is nothing. Currently onlyTreeSASlicer
is supported.simplifier
is one ofMergeVectors
orMergeGreedy
. Default is nothing.permute
is a boolean flag to indicate whether to optimize the permutation of the contraction order.
Examples
julia> using OMEinsum
julia> code = ein"ij, jk, kl, il->"
ij, jk, kl, il ->
julia> optimize_code(code, uniformsize(code, 2), TreeSA());
OMEinsumContractionOrders.slice_code
— Methodslice_code(code, size_dict, slicer) -> sliced_code
Slice the einsum contraction code to reduce the space complexity, returns a SlicedEinsum
instance.
Arguments
code
is aNestedEinsum
instance.size_dict
is a dictionary of "edge label=>edge size" that contains the size information, one can useuniformsize(eincode, 2)
to create a uniform size.slicer
is aCodeSlicer
instance, currently onlyTreeSASlicer
is supported.
OMEinsumContractionOrders.GreedyMethod
— TypeGreedyMethod{MT}
GreedyMethod(; α = 0.0, temperature = 0.0)
It may not be optimal, but it is fast.
Fields
α
is the parameter for the loss function, for pairwise interaction, L = size(out) - α * (size(in1) + size(in2))temperature
is the parameter for sampling, if it is zero, the minimum loss is selected; for non-zero, the loss is selected by the Boltzmann distribution, given by p ~ exp(-loss/temperature).
OMEinsumContractionOrders.optimize_greedy
— Methodoptimize_greedy(eincode, size_dict; α, temperature)
Greedy optimizing the contraction order and return a NestedEinsum
object. Check the docstring of tree_greedy
for detailed explaination of other input arguments.
OMEinsumContractionOrders.tree_greedy
— Methodtree_greedy(incidence_list, log2_sizes; α = 0.0, temperature = 0.0)
Compute greedy order, and the time and space complexities, the rows of the incidence_list
are vertices and columns are edges. log2_sizes
are defined on edges. α
is the parameter for the loss function, for pairwise interaction, L = size(out) - α * (size(in1) + size(in2)) temperature
is the parameter for sampling, if it is zero, the minimum loss is selected; for non-zero, the loss is selected by the Boltzmann distribution, given by p ~ exp(-loss/temperature).
OMEinsumContractionOrders.TreeSA
— TypeTreeSA{IT} <: CodeOptimizer
TreeSA(; βs=collect(0.01:0.05:15), ntrials=10, niters=50, initializer=:greedy, score=ScoreFunction())
Optimize the einsum contraction pattern using the simulated annealing on tensor expression tree.
Fields
ntrials
,βs
andniters
are annealing parameters, doingntrials
indepedent annealings, each has inverse tempteratures specified byβs
, in each temperature, doniters
updates of the tree.initializer
specifies how to determine the initial configuration, it can be:greedy
,:random
or:specified
. If the initializer is:specified
, the inputcode
should be aNestedEinsum
object.score
specifies the score function to evaluate the quality of the contraction tree, it is a function of time complexity, space complexity and read-write complexity.
References
Breaking changes:
nslices
is removed, since the slicing part is now separated from the optimization part, seeslice_code
function andTreeSASlicer
.greedy_method
is removed. If you want to have detailed control of the initializer, please pre-optimize the code with another method and then use:specified
to initialize the tree.
OMEinsumContractionOrders.optimize_tree
— Methodoptimize_tree(code, size_dict; βs, ntrials, niters, initializer, score)
Optimize the einsum contraction pattern specified by code
, and edge sizes specified by size_dict
. Check the docstring of TreeSA
for detailed explaination of other input arguments.
OMEinsumContractionOrders.ExactTreewidth
— Typeconst ExactTreewidth = Treewidth{SafeRules{BT, MMW{3}(), MF}}
ExactTreewidth() = Treewidth()
ExactTreewidth
is a specialization of Treewidth
for the SafeRules
preprocessing algorithm with the BT
elimination algorithm. The BT
algorithm is an exact solver for the treewidth problem that implemented in TreeWidthSolver.jl
.
OMEinsumContractionOrders.Treewidth
— Typestruct Treewidth{EL <: EliminationAlgorithm, GM} <: CodeOptimizer
Treewidth(; alg::EL = SafeRules(BT(), MMW{3}(), MF()))
Tree width based solver. The solvers are implemented in CliqueTrees.jl and TreeWidthSolver.jl. They include:
Algorithm | Description | Time Complexity | Space Complexity |
---|---|---|---|
BFS | breadth-first search | O(m + n) | O(n) |
MCS | maximum cardinality search | O(m + n) | O(n) |
LexBFS | lexicographic breadth-first search | O(m + n) | O(m + n) |
RCMMD | reverse Cuthill-Mckee (minimum degree) | O(m + n) | O(m + n) |
RCMGL | reverse Cuthill-Mckee (George-Liu) | O(m + n) | O(m + n) |
MCSM | maximum cardinality search (minimal) | O(mn) | O(n) |
LexM | lexicographic breadth-first search (minimal) | O(mn) | O(n) |
AMF | approximate minimum fill | O(mn) | O(m + n) |
MF | minimum fill | O(mn²) | - |
MMD | multiple minimum degree | O(mn²) | O(m + n) |
Detailed descriptions is available in the CliqueTrees.jl.
Fields
alg::EL
: The algorithm to use for the treewidth calculation. Available elimination algorithms are listed above.
Example
julia> optimizer = Treewidth();
julia> eincode = OMEinsumContractionOrders.EinCode([['a', 'b'], ['a', 'c', 'd'], ['b', 'c', 'e', 'f'], ['e'], ['d', 'f']], ['a'])
ab, acd, bcef, e, df -> a
julia> size_dict = Dict([c=>(1<<i) for (i,c) in enumerate(['a', 'b', 'c', 'd', 'e', 'f'])]...)
Dict{Char, Int64} with 6 entries:
'f' => 64
'a' => 2
'c' => 8
'd' => 16
'e' => 32
'b' => 4
julia> optcode = optimize_code(eincode, size_dict, optimizer)
ba, ab -> a
├─ bcf, fac -> ba
│ ├─ e, bcef -> bcf
│ │ ├─ e
│ │ └─ bcef
│ └─ df, acd -> fac
│ ├─ df
│ └─ acd
└─ ab
OMEinsumContractionOrders.optimize_treewidth
— Methodoptimize_treewidth(optimizer, eincode, size_dict)
Optimizing the contraction order via solve the exact tree width of the line graph corresponding to the eincode and return a NestedEinsum
object. Check the docstring of treewidth_method
for detailed explaination of other input arguments.
OMEinsumContractionOrders.HyperND
— TypeHyperND(;
dis = KaHyParND(),
algs = (MF(), AMF(), MMD()),
level = 6,
width = 120,
imbalances = 130:130,
score = ScoreFunction(),
)
Nested-dissection based optimizer. Recursively partitions a tensor network, then calls a greedy algorithm on the leaves. The optimizer is run a number of times: once for each greedy algorithm in algs
and each imbalance value in imbalances
. The recursion depth is controlled by the parameters level
and width
.
The line graph is partitioned using the algorithm dis
. OMEinsumContractionOrders currently supports two partitioning algorithms, both of which require importing an external library.
type | package |
---|---|
METISND | Metis.jl |
KaHyParND | KayHyPar.jl |
The optimizer is implemented using the tree decomposition library CliqueTrees.jl.
Arguments
dis
: graph partitioning algorithmalgs
: tuple of elimination algorithms.level
: maximum levelwidth
: minimum widthimbalances
: imbalance parametersscore
: a function to evaluate the quality of the contraction tree. Default isScoreFunction()
.
OMEinsumContractionOrders.BipartiteResult
— TypeBipartiteResult{RT}
BipartiteResult(part1, part2, sc, valid)
Result of the bipartite optimization. part1
and part2
are the two parts of the bipartition, sc
is the space complexity of the bipartition, valid
is a boolean indicating whether the bipartition is valid.
OMEinsumContractionOrders.KaHyParBipartite
— TypeKaHyParBipartite{RT,IT,GM}
KaHyParBipartite(; sc_target, imbalances=collect(0.0:0.005:0.8),
max_group_size=40, greedy_config=GreedyMethod())
Optimize the einsum code contraction order using the KaHyPar + Greedy approach. This program first recursively cuts the tensors into several groups using KaHyPar, with maximum group size specifed by max_group_size
and maximum space complexity specified by sc_target
, Then finds the contraction order inside each group with the greedy search algorithm. Other arguments are
Fields
sc_target
is the target space complexity, defined aslog2(number of elements in the largest tensor)
,imbalances
is a KaHyPar parameter that controls the group sizes in hierarchical bipartition,max_group_size
is the maximum size that allowed to used greedy search,sub_optimizer
is the sub-optimizer used to find the contraction order when the group size is small enough.
References
OMEinsumContractionOrders.SABipartite
— TypeSABipartite{RT,BT}
SABipartite(; sc_target=25, ntrials=50, βs=0.1:0.2:15.0, niters=1000
max_group_size=40, greedy_config=GreedyMethod(), initializer=:random)
Optimize the einsum code contraction order using the Simulated Annealing bipartition + Greedy approach. This program first recursively cuts the tensors into several groups using simulated annealing, with maximum group size specifed by max_group_size
and maximum space complexity specified by sc_target
, Then finds the contraction order inside each group with the greedy search algorithm. Other arguments are
Fields
sc_target
is the target space complexity, defined aslog2(number of elements in the largest tensor)
,ntrials
is the number of repetition (with different random seeds),βs
is a list of inverse temperature1/T
,niters
is the number of iteration in each temperature,max_group_size
is the maximum size that allowed to used greedy search,sub_optimizer
is the optimizer for the bipartited sub graphs, one can chooseGreedyMethod()
orTreeSA()
,initializer
is the partition configuration initializer, one can choose:random
or:greedy
(slow but better).
References
OMEinsumContractionOrders.optimize_sa
— Methodoptimize_sa(code, size_dict; sc_target, max_group_size=40, βs=0.1:0.2:15.0, niters=1000, ntrials=50,
sub_optimizer = GreedyMethod(), initializer=:random)
Optimize the einsum code
contraction order using the Simulated Annealing bipartition + Greedy approach. size_dict
is a dictionary that specifies leg dimensions. Check the docstring of SABipartite
for detailed explaination of other input arguments.
References
Slicing
OMEinsumContractionOrders.TreeSASlicer
— TypeTreeSASlicer{IT, LT} <: CodeSlicer
A structure for configuring the Tree Simulated Annealing (TreeSA) slicing algorithm. The goal of slicing is to reach the target space complexity specified by score.sc_target
.
Fields
ntrials
,βs
andniters
are annealing parameters, doingntrials
indepedent annealings, each has inverse tempteratures specified byβs
, in each temperature, doniters
updates of the tree.fixed_slices::Vector{LT}
: A vector of fixed slices that should not be altered. Default is an empty vector.optimization_ratio::Float64
: A constant used for determining the number of iterations for slicing. Default is 2.0. i.e. if the current space complexity is 30, and the target space complexity is 20, then the number of iterations for slicing is (30 - 20) xoptimization_ratio
.score::ScoreFunction
: A function to evaluate the quality of the contraction tree. Default isScoreFunction(sc_target=30.0)
.
References
Preprocessing code
Some optimizers (e.g. TreeSA
) are too costly to run. We provide a preprocessing step to reduce the time of calling optimizers.
OMEinsumContractionOrders.CodeSimplifier
— TypeCodeSimplifier
Abstract type for code simplifiers.
OMEinsumContractionOrders.MergeGreedy
— TypeMergeGreedy <: CodeSimplifier
MergeGreedy(; threshhold=-1e-12)
Contraction code simplifier (in order to reduce the time of calling optimizers) that merges tensors greedily if the space complexity of merged tensors is reduced (difference smaller than the threshhold
).
OMEinsumContractionOrders.MergeVectors
— TypeMergeVectors <: CodeSimplifier
MergeVectors()
Contraction code simplifier (in order to reduce the time of calling optimizers) that merges vectors to closest tensors.
OMEinsumContractionOrders.NetworkSimplifier
— TypeNetworkSimplifier{LT}
A network simplifier that contains a list of operations that can be applied to a tensor network to reduce the number of tensors. It is generated from a proprocessor, such as MergeVectors
or MergeGreedy
.
Fields
operations
: a list ofNestedEinsum
objects.
OMEinsumContractionOrders.embed_simplifier
— Methodembed_simplifier(code::NestedEinsum, simplifier::NetworkSimplifier)
Embed the simplifier into the contraction code. A typical workflow is: (i) generate a simplifier with simplify_code
, (ii) then optimize the simplified code with optimize_code
and (iii) post-process the optimized code with embed_simplifier
to produce correct contraction order for the original code. This is automatically done in optimize_code
given the simplifier
argument is not nothing
.
Arguments
code
: the contraction code to embed the simplifier into.simplifier
: the simplifier to embed, which is aNetworkSimplifier
object.
Returns
- A new
NestedEinsum
object.
OMEinsumContractionOrders.simplify_code
— Methodsimplify_code(code::Union{EinCode, NestedEinsum}, size_dict, method::CodeSimplifier)
Simplify the contraction code by preprocessing the code with a simplifier.
Arguments
code
: the contraction code to simplify.size_dict
: the size dictionary of the contraction code.method
: the simplifier to use, which can beMergeVectors
orMergeGreedy
.
Returns
- A tuple of
(NetworkSimplifier, newcode)
, wherenewcode
is a newEinCode
object.
Dump and load contraction orders
OMEinsumContractionOrders.readjson
— Methodreadjson(filename::AbstractString)
Read the contraction order from a JSON file.
Arguments
filename
: the name of the file to read from.
OMEinsumContractionOrders.writejson
— Methodwritejson(filename::AbstractString, ne::Union{NestedEinsum, SlicedEinsum})
Write the contraction order to a JSON file.
Arguments
filename
: the name of the file to write to.ne
: the contraction order to write. It can be aNestedEinsum
or aSlicedEinsum
object.
Visualization
Requires using LuxorGraphPlot
to load the extension.
OMEinsumContractionOrders.viz_contraction
— Methodviz_contraction(code::Union{NestedEinsum, SlicedEinsum}; locs=StressLayout(), framerate=10, filename=tempname() * ".mp4", show_progress=true)
Visualize the contraction process of a tensor network.
Arguments
code
: The tensor network to visualize.
Keyword Arguments
locs
: The coordinates or layout algorithm to use for positioning the nodes in the graph. Default isStressLayout()
.framerate
: The frame rate of the animation. Default is10
.filename
: The name of the output file, with.gif
or.mp4
extension. Default is a temporary file with.mp4
extension.show_progress
: Whether to show progress information. Default istrue
.
Returns
- the path of the generated file.
OMEinsumContractionOrders.viz_eins
— Methodviz_eins(code::AbstractEinsum; locs=StressLayout(), filename = nothing, kwargs...)
Visualizes an AbstractEinsum
object by creating a tensor network graph and rendering it using GraphViz.
Arguments
code::AbstractEinsum
: TheAbstractEinsum
object to visualize.
Keyword Arguments
locs=StressLayout()
: The coordinates or layout algorithm to use for positioning the nodes in the graph.filename = nothing
: The name of the file to save the visualization to. Ifnothing
, the visualization will be displayed on the screen instead of saving to a file.config = GraphDisplayConfig()
: The configuration for displaying the graph. Please refer to the documentation ofGraphDisplayConfig
for more information.kwargs...
: Additional keyword arguments to be passed to theGraphViz
constructor.