@@ -30,4 +30,122 @@ function LinearAlgebra.permutedims!(C::Array{T,N}, A::StridedArray{T,N}, perm) w
3030 invoke (permutedims!, Tuple{Any,AbstractArray,Any}, C, A, perm)
3131 end
3232end
33+ ```
34+
35+ ## Examples
36+
37+ Let us use the Petersen graph as an example, we first generate its tensor network contraction tree.
38+ ``` julia
39+ julia> using GraphTensorNetworks, Random, LightGraphs
40+
41+ julia> graph = (Random. seed! (2 ); LightGraphs. smallgraph (:petersen ))
42+ {10 , 15 } undirected simple Int64 graph
43+
44+ julia> problem = Independence (graph; optmethod= :tree , sc_target= 0 , sc_weight= 1.0 , ntrials= 10 , βs= 0.01 : 0.1 : 15.0 , niters= 20 , rw_weight= 0.2 );
45+ ┌ Warning: target space complexity not found, got: 4.0 , with time complexity 7.965784284662087 , read- right complexity 8.661778097771988 .
46+ └ @ OMEinsumContractionOrders ~ / . julia/ dev/ OMEinsumContractionOrders/ src/ treesa. jl: 71
47+ time/ space complexity is (7.965784284662086 , 4.0 )
48+ ```
49+
50+ Here, the ` problem ` is a ` Independence ` instance, it contains the tensor network contraction tree for the target graph.
51+ Here, we choose the ` :tree ` optimizer to optimize the tensor network contraciton tree, it is a local search based algorithm, check [ arXiv: 2108.05665] ( https://arxiv.org/abs/2108.05665 ) . You will see some warnings, do not panic, this is because we set ` sc_target ` (target space complex) to 1 for agressive optimization of space complexity. Type ` ?Independence ` in a Julia REPL for more information about the key word arguments.
52+ Similarly, one can select tensor network structures for solving other problems like ` MaximalIndependence ` , ` MaxCut ` , ` Matching ` , ` Coloring{K} ` and ` set_packing ` .
53+
54+ Then we can solve graph properties
55+ ``` julia
56+ # maximum independent set size
57+ julia> solve (problem, " size max" )
58+ 0 - dimensional Array{TropicalNumbers. TropicalF64, 0 }:
59+ 4.0 ₜ
60+
61+ # all independent sets
62+ julia> solve (problem, " counting sum" )
63+ 0 - dimensional Array{Float64, 0 }:
64+ 76.0
65+
66+ # counting maximum independent sets
67+ julia> solve (problem, " counting max" )
68+ 0 - dimensional Array{TropicalNumbers. CountingTropicalF64, 0 }:
69+ (4.0 , 5.0 )ₜ
70+
71+ # counting independent sets of max two sizes
72+ julia> solve (problem, " counting max2" )
73+ 0 - dimensional Array{Max2Poly{Float64, Float64}, 0 }:
74+ 30.0 * x^ 3 + 5.0 * x^ 4
75+ ```
76+
77+ Here, ` solve ` function returns you a 0-dimensional array.
78+ For open graphs, this output tensor can have higher dimensions. Each entry corresponds to a different boundary condition.
79+
80+ We provide 3 approaches to compute the independence polynomials.
81+
82+ ``` julia
83+ # using `Polynomial` type
84+ julia> solve (problem, " counting all" )
85+ 0 - dimensional Array{Polynomial{Float64, :x }, 0 }:
86+ Polynomial (1.0 + 10.0 * x + 30.0 * x^ 2 + 30.0 * x^ 3 + 5.0 * x^ 4 )
87+
88+ # using the finitefield approach
89+ julia> solve (problem, " counting all (finitefield)" )
90+ 0 - dimensional Array{Polynomial{BigInt, :x }, 0 }:
91+ Polynomial (1 + 10 * x + 30 * x^ 2 + 30 * x^ 3 + 5 * x^ 4 )
92+
93+ # using the fourier approach
94+ julia> solve (problem, " counting all (fft)" , r= 1.0 )
95+ 0 - dimensional Array{Polynomial{ComplexF64, :x }, 0 }:
96+ Polynomial (1.0000000000000029 + 2.664535259100376e-16im + (10.000000000000004 - 1.9512435398857492e-16im )x + (30.0 - 1.9622216671393801e-16im )x^ 2 + (30.0 + 1.1553104311877194e-15im )x^ 3 + (5.0 - 1.030417436395244e-15im )x^ 4 )
97+ ```
98+
99+ The ` finitefield ` approach is the most recommended, because it has no round off error is can be upload to GPU. To upload the computing to GPU,
100+ ``` julia
101+ julia> using CUDA
102+ [ Info: OMEinsum loaded the CUDA module successfully
103+
104+ julia> solve (problem, " counting all (finitefield)" , usecuda= true )
105+ 0 - dimensional Array{Polynomial{BigInt, :x }, 0 }:
106+ Polynomial (1 + 10 * x + 30 * x^ 2 + 30 * x^ 3 + 5 * x^ 4 )
107+ ```
108+
109+ The `fft` approach is fast but with round off errors. Its imaginary part can be regarded as the precision,
110+ keyword argument `r` controls the round off errors in high/low IS size region.
111+
112+ ``` julia
113+ # one of MISs
114+ julia> solve (problem, " config max" )
115+ 0 - dimensional Array{CountingTropical{Float64, ConfigSampler{10 , 1 , 1 }}, 0 }:
116+ (4.0 , ConfigSampler {10, 1, 1} (1010000011 ))ₜ
117+
118+ julia> solve (problem, " config max (bounded)" )
119+ 0 - dimensional Array{CountingTropical{Float64, ConfigSampler{10 , 1 , 1 }}, 0 }:
120+ (4.0 , ConfigSampler {10, 1, 1} (1010000011 ))ₜ
121+
122+ # enumerate all MISs
123+ julia> solve (problem, " configs max" ) # not recommended
124+ 0 - dimensional Array{CountingTropical{Float64, ConfigEnumerator{10 , 1 , 1 }}, 0 }:
125+ (4.0 , {1010000011 , 0100100110 , 1001001100 , 0010111000 , 0101010001 })ₜ
126+
127+ julia> solve (problem, " configs max (bounded)" )
128+ 0 - dimensional Array{CountingTropical{Int64, ConfigEnumerator{10 , 1 , 1 }}, 0 }:
129+ (4 , {1010000011 , 0100100110 , 1001001100 , 0010111000 , 0101010001 })ₜ
130+
131+ # enumerate all MIS and MIS-1 configurations
132+ julia> solve (problem, " configs max2" )
133+ 0 - dimensional Array{Max2Poly{ConfigEnumerator{10 , 1 , 1 }, Float64}, 0 }:
134+ {0010101000 , 0101000001 , 0100100010 , 0010100010 , 0100000011 , 0010000011 , 1001001000 , 1010001000 , 1001000001 , 1010000001 , 1010000010 , 1000000011 , 0100100100 , 0000101100 , 0101000100 , 0001001100 , 0000100110 , 0100000110 , 1001000100 , 1000001100 , 1000000110 , 0100110000 , 0000111000 , 0101010000 , 0001011000 , 0010110000 , 0010011000 , 0001010001 , 0100010001 , 0010010001 }* x^ 3 + {1010000011 , 0100100110 , 1001001100 , 0010111000 , 0101010001 }* x^ 4
135+
136+ # enumerate all IS configurations
137+ julia> solve (problem, " configs all" )
138+ 0 - dimensional Array{Polynomial{ConfigEnumerator{10 , 1 , 1 }, :x }, 0 }:
139+ Polynomial ({0000000000 } + {0010000000 , 0000100000 , 0001000000 , 0100000000 , 0000001000 , 0000000001 , 0000000010 , 1000000000 , 0000000100 , 0000010000 }* x + {1000000010 , 0010100000 , 0010001000 , 0100100000 , 0000101000 , 0101000000 , 0001001000 , 0001000001 , 0100000001 , 0010000001 , 0000100010 , 0100000010 , 0010000010 , 0000000011 , 1001000000 , 1000001000 , 1010000000 , 1000000001 , 0000000110 , 0000100100 , 0001000100 , 0100000100 , 0000001100 , 1000000100 , 0010010000 , 0000110000 , 0001010000 , 0100010000 , 0000011000 , 0000010001 }* x^ 2 + {1010000010 , 1000000011 , 0010101000 , 0101000001 , 0100100010 , 0010100010 , 0100000011 , 0010000011 , 1001001000 , 1010001000 , 1001000001 , 1010000001 , 0000100110 , 0100000110 , 0100100100 , 0000101100 , 0101000100 , 0001001100 , 1001000100 , 1000001100 , 1000000110 , 0010110000 , 0010011000 , 0100110000 , 0000111000 , 0101010000 , 0001011000 , 0001010001 , 0100010001 , 0010010001 }* x^ 3 + {1010000011 , 0100100110 , 1001001100 , 0010111000 , 0101010001 }* x^ 4 )
140+ ```
141+
142+ If you want to enumerate all MISs, we highly recommend using the bounded version to save the computational effort. One can also store the configurations on your disk by typing
143+ ``` julia
144+ julia> cs = solve (problem, " configs max (bounded)" )[1 ]. c # the `c` field is a `ConfigEnumerator`
145+ {1010000011 , 0100100110 , 1001001100 , 0010111000 , 0101010001 }
146+
147+ julia> save_configs (" configs.dat" , cs; format= :text ) # `:text` or `:binary`
148+
149+ julia> load_configs (" configs.dat" ; format= :text )
150+ {1010000011 , 0100100110 , 1001001100 , 0010111000 , 0101010001 }
33151```
0 commit comments