You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Here the main function [`solve`](@ref) takes three input arguments, the problem instance of type [`IndependentSet`](@ref), the property instance of type [`GraphPolynomial`](@ref) and an optional key word argument `usecuda` to decide use GPU or not.
47
-
If one wants to use GPU to accelerate the computation, the `using CUDA` statement must uncommented.
42
+
If one wants to use GPU to accelerate the computation, the `, CUDA` should be uncommented.
43
+
44
+
An [`IndependentSet`](@ref) instance takes two positional arguments to initialize, the graph instance that one wants to solve and the weights for each vertex. Here, we use a random regular graph with 20 vertices and degree 3, and the default uniform weight 1.
48
45
49
-
The problem instance takes four arguments to initialize, the only positional argument is the graph instance that one wants to solve, the key word argument `optimizer` is for specifying the tensor network optimization algorithm, the key word argument `weights` is for specifying the weights of vertices as either a vector or `NoWeight()`.
46
+
The [`GenericTensorNetwork`](@ref) function is a constructor for the problem instance, which takes the problem instance as the first argument and optional key word arguments. The key word argument `optimizer` is for specifying the tensor network optimization algorithm.
50
47
The keyword argument `openvertices` is a tuple of labels for specifying the degrees of freedom not summed over, and `fixedvertices` is a label-value dictionary for specifying the fixed values of the degree of freedoms.
51
-
Here, we use [`TreeSA`](@ref) method as the tensor network optimizer, and leave `weights` and `openvertices` the default values.
48
+
Here, we use [`TreeSA`](@ref) method as the tensor network optimizer, and leave `openvertices` the default values.
52
49
The [`TreeSA`](@ref) method finds the best contraction order in most of our applications, while the default [`GreedyMethod`](@ref) runs the fastest.
53
50
54
51
The first execution of this function will be a bit slow due to Julia's just in time compiling.
The [`IndependentSet`](@ref) constructor maps an independent set problem to a tensor network with optimized contraction order.
13
+
The [`GenericTensorNetwork`](@ref) constructor maps an independent set problem to a tensor network with optimized contraction order.
16
14
The key word argument `optimizer` specifies the contraction order optimizer of the tensor network.
17
15
Here, we choose the local search based [`TreeSA`](@ref) algorithm, which often finds the smallest time/space complexity and supports slicing.
18
16
One can type `?TreeSA` in a Julia REPL for more information about how to configure the hyper-parameters of the [`TreeSA`](@ref) method,
@@ -22,46 +20,32 @@ Alternative tensor network contraction order optimizers include
22
20
*[`KaHyParBipartite`](@ref)
23
21
*[`SABipartite`](@ref)
24
22
25
-
The keyword argument `simplifier` specifies the preprocessor to improve the searching speed of the contraction order finding.
26
23
For example, the `MergeGreedy()` here "contracts" tensors greedily whenever the contraction result has a smaller space complexity.
27
24
It can remove all vertex tensors (vectors) before entering the contraction order optimization algorithm.
28
25
29
26
The returned object `problem` contains a field `code` that specifies the tensor network with optimized contraction order.
30
27
For an independent set problem, the optimal contraction time/space complexity is ``\sim 2^{{\rm tw}(G)}``, where ``{\rm tw(G)}`` is the [tree-width](https://en.wikipedia.org/wiki/Treewidth) of ``G``.
31
28
One can check the time, space and read-write complexity with the [`contraction_complexity`](@ref) function.
32
29
33
-
```julia
34
-
julia>contraction_complexity(problem)
35
-
Time complexity (number of element-wise multiplications) =2^20.568850503058382
36
-
Space complexity (number of elements in the largest intermediate tensor) =2^16.0
37
-
Read-write complexity (number of element-wise read and write) =2^18.70474460304404
30
+
```@repl performancetips
31
+
contraction_complexity(problem)
38
32
```
39
33
40
34
The return values are `log2` values of the number of multiplications, the number elements in the largest tensor during contraction and the number of read-write operations to tensor elements.
41
35
In this example, the number `*` operations is ``\sim 2^{21.9}``, the number of read-write operations are ``\sim 2^{20}``, and the largest tensor size is ``2^{17}``.
42
36
One can check the element size by typing
43
-
```julia
44
-
julia>sizeof(TropicalF64)
45
-
8
46
-
47
-
julia>sizeof(TropicalF32)
48
-
4
49
-
50
-
julia>sizeof(StaticBitVector{200,4})
51
-
32
52
-
53
-
julia>sizeof(TruncatedPoly{5,Float64,Float64})
54
-
48
37
+
```@repl performancetips
38
+
sizeof(TropicalF64)
39
+
sizeof(TropicalF32)
40
+
sizeof(StaticBitVector{200,4})
41
+
sizeof(TruncatedPoly{5,Float64,Float64})
55
42
```
56
43
57
44
One can use [`estimate_memory`](@ref) to get a good estimation of peak memory in bytes.
58
45
For example, to compute the graph polynomial, the peak memory can be estimated as follows.
The finite field approach only requires 298 KB memory, while using the [`Polynomial`](https://juliamath.github.io/Polynomials.jl/stable/polynomials/polynomial/#Polynomial-2) number type requires 71 MB memory.
67
51
@@ -75,25 +59,11 @@ For large scale applications, it is also possible to slice over certain degrees
75
59
loop and accumulate over certain degrees of freedom so that one can have a smaller tensor network inside the loop due to the removal of these degrees of freedom.
76
60
In the [`TreeSA`](@ref) optimizer, one can set `nslices` to a value larger than zero to turn on this feature.
77
61
78
-
```julia
79
-
julia>using GenericTensorNetworks, Graphs, Random
80
-
81
-
julia> graph =random_regular_graph(120, 3)
82
-
{120, 180} undirected simple Int64 graph
83
-
84
-
julia> problem =IndependentSet(graph; optimizer=TreeSA(βs=0.01:0.1:25.0, ntrials=10, niters=10));
85
-
86
-
julia>contraction_complexity(problem)
87
-
Time complexity (number of element-wise multiplications) =2^20.53277253647484
88
-
Space complexity (number of elements in the largest intermediate tensor) =2^16.0
89
-
Read-write complexity (number of element-wise read and write) =2^19.34699193791874
90
-
91
-
julia> problem =IndependentSet(graph; optimizer=TreeSA(βs=0.01:0.1:25.0, ntrials=10, niters=10, nslices=5));
92
-
93
-
julia>contraction_complexity(problem)
94
-
Time complexity (number of element-wise multiplications) =2^21.117277836449578
95
-
Space complexity (number of elements in the largest intermediate tensor) =2^11.0
96
-
Read-write complexity (number of element-wise read and write) =2^19.854965754099602
62
+
```@repl performancetips
63
+
problem = GenericTensorNetwork(iset; optimizer=TreeSA(βs=0.01:0.1:25.0, ntrials=10, niters=10));
64
+
contraction_complexity(problem)
65
+
problem = GenericTensorNetwork(iset; optimizer=TreeSA(βs=0.01:0.1:25.0, ntrials=10, niters=10, nslices=5));
66
+
contraction_complexity(problem)
97
67
```
98
68
99
69
In the second `IndependentSet` constructor, we slice over 5 degrees of freedom, which can reduce the space complexity by at most 5.
@@ -103,7 +73,7 @@ i.e. the peak memory usage is reduced by a factor ``32``, while the (theoretical
103
73
## GEMM for Tropical numbers
104
74
One can speed up the Tropical number matrix multiplication when computing the solution space property [`SizeMax`](@ref)`()` by using the Tropical GEMM routines implemented in package [`TropicalGEMM`](https://github.com/TensorBFS/TropicalGEMM.jl/).
105
75
106
-
```julia
76
+
```julia-repl
107
77
julia> using BenchmarkTools
108
78
109
79
julia> @btime solve(problem, SizeMax())
@@ -139,7 +109,7 @@ results = multiprocess_run(collect(1:10)) do seed
139
109
n =10
140
110
@info"Graph size $n x $n, seed= $seed"
141
111
g =random_diagonal_coupled_graph(n, n, 0.8)
142
-
gp =Independence(g; optimizer=TreeSA(), simplifier=MergeGreedy())
112
+
gp =GenericTensorNetwork(IndependentSet(g); optimizer=TreeSA())
143
113
res =solve(gp, GraphPolynomial())[]
144
114
return res
145
115
end
@@ -165,7 +135,7 @@ You will see a vector of polynomials printed out.
165
135
166
136
## Make use of GPUs
167
137
To upload the computation to GPU, you just add `using CUDA` before calling the `solve` function, and set the keyword argument `usecuda` to `true`.
168
-
```julia
138
+
```julia-repl
169
139
julia> using CUDA
170
140
[ Info: OMEinsum loaded the CUDA module successfully
Copy file name to clipboardExpand all lines: docs/src/sumproduct.md
+9-31Lines changed: 9 additions & 31 deletions
Original file line number
Diff line number
Diff line change
@@ -3,45 +3,23 @@
3
3
It is a sum-product expression tree to store [`ConfigEnumerator`](@ref) in a lazy style, where configurations can be extracted by depth first searching the tree with the `Base.collect` method.
4
4
Although it is space efficient, it is in general not easy to extract information from it due to the exponential large configuration space.
5
5
Directed sampling is one of its most important operations, with which one can get some statistic properties from it with an intermediate effort. For example, if we want to check some property of an intermediate scale graph, one can type
6
-
```julia
7
-
julia> graph =random_regular_graph(70, 3)
8
-
9
-
julia> problem =IndependentSet(graph; optimizer=TreeSA());
10
-
11
-
julia> tree =solve(problem, ConfigsAll(; tree_storage=true))[];
12
-
16633909006371
6
+
```@repl sumproduct
7
+
graph = random_regular_graph(70, 3)
8
+
problem = GenericTensorNetwork(IndependentSet(graph); optimizer=TreeSA());
9
+
tree = solve(problem, ConfigsAll(; tree_storage=true))[]
13
10
```
14
11
If one wants to store these configurations, he will need a hard disk of size 256 TB!
15
12
However, this sum-product binary tree structure supports efficient and unbiased direct sampling.
16
13
17
-
```julia
18
-
samples =generate_samples(tree, 1000);
14
+
```@repl sumproduct
15
+
samples = generate_samples(tree, 1000)
19
16
```
20
17
21
18
With these samples, one can already compute useful properties like Hamming distance (see [`hamming_distribution`](@ref)) distribution.
0 commit comments