@@ -3,20 +3,47 @@ using OMEinsum: NestedEinsum, getixs, getiy
33using FFTW
44using LightGraphs
55
6- export contractx, graph_polynomial, optimize_code
6+ export contractx, contractf, graph_polynomial, optimize_code
77export Independence, MaximalIndependence, Matching, Coloring
88const EinTypes = Union{EinCode,NestedEinsum}
99
1010abstract type GraphProblem end
11+ """
12+ Independence{CT<:EinTypes} <: GraphProblem
13+ Independence(graph; kwargs...)
14+
15+ Independent set problem. For `kwargs`, check `optimize_code` API.
16+ """
1117struct Independence{CT<: EinTypes } <: GraphProblem
1218 code:: CT
1319end
20+
21+ """
22+ Independence{CT<:EinTypes} <: GraphProblem
23+ Independence(graph; kwargs...)
24+
25+ Independent set problem. For `kwargs`, check `optimize_code` API.
26+ """
1427struct MaximalIndependence{CT<: EinTypes } <: GraphProblem
1528 code:: CT
1629end
30+
31+ """
32+ Matching{CT<:EinTypes} <: GraphProblem
33+ Matching(graph; kwargs...)
34+
35+ Vertex matching problem. For `kwargs`, check `optimize_code` API.
36+ """
1737struct Matching{CT<: EinTypes } <: GraphProblem
1838 code:: CT
1939end
40+
41+ """
42+ Coloring{K,CT<:EinTypes} <: GraphProblem
43+ Coloring{K}(graph; kwargs...)
44+
45+ K-Coloring problem. For `kwargs`, check `optimize_code` API.
46+ """
2047struct Coloring{K,CT<: EinTypes } <: GraphProblem
2148 code:: CT
2249end
@@ -39,7 +66,31 @@ function labels(code::EinTypes)
3966 return res
4067end
4168
42- function graph_polynomial (gp:: GraphProblem , :: Val{:fft} ; usecuda= false , maxorder= graph_polynomial_maxorder (gp; usecuda= usecuda), r= 1.0 )
69+ """
70+ graph_polynomial(problem, method; usecuda=false, kwargs...)
71+
72+ Computing the graph polynomial for specific problem.
73+
74+ * `problem` can be one of the following instances,
75+ * `Independence` for the independence polynomial,
76+ * `MaximalIndependence` for the maximal independence polynomial,
77+ * `Matching` for the matching polynomial,
78+
79+ * `method` can be one of the following inputs,
80+ * `Val(:finitefield)`, compute exactly with the finite field method.
81+ It consumes additional kwargs [`max_iter`, `maxorder`], where `maxorder` is maximum order of polynomial
82+ and `max_iter` is the maximum number of primes numbers to use in the finitefield algebra.
83+ `max_iter` can be determined automatically in most cases.
84+ * `Val(:polynomial)`, compute directly with `Polynomial` number type,
85+ * `Val(:fft)`, compute with the fast fourier transformation approach, fast but needs to tune the hyperparameter `r`.
86+ It Consumes additional kwargs [`maxorder`, `r`]. The larger `r` is,
87+ the more accurate the factors of high order terms, and the less accurate the factors of low order terms.
88+ * `Val(:fitting)`, compute with the polynomial fitting approach, fast but inaccurate for large graphs.
89+ """
90+ function graph_polynomial end
91+
92+ function graph_polynomial (gp:: GraphProblem , :: Val{:fft} ; usecuda= false ,
93+ maxorder= graph_polynomial_maxorder (gp; usecuda= usecuda), r= 1.0 )
4394 ω = exp (- 2im * π/ (maxorder+ 1 ))
4495 xs = r .* collect (ω .^ (0 : maxorder))
4596 ys = [asscalar (contractx (gp, x; usecuda= usecuda)) for x in xs]
@@ -68,7 +119,8 @@ function _polynomial_single(gp::GraphProblem, ::Type{T}; usecuda, maxorder) wher
68119 A \ T .(ys)
69120end
70121
71- function graph_polynomial (gp:: GraphProblem , :: Val{:finitefield} ; usecuda= false , maxorder= graph_polynomial_maxorder (gp; usecuda= usecuda), max_iter= 100 )
122+ function graph_polynomial (gp:: GraphProblem , :: Val{:finitefield} ; usecuda= false ,
123+ maxorder= graph_polynomial_maxorder (gp; usecuda= usecuda), max_iter= 100 )
72124 TI = Int32 # Int 32 is faster
73125 N = typemax (TI)
74126 YS = []
@@ -93,21 +145,38 @@ function improved_counting(sequences)
93145 map (yi-> Mods. CRT (yi... ), zip (sequences... ))
94146end
95147
96- function optimize_code (code; method= :kahypar , sc_target= 17 , max_group_size= 40 , nrepeat= 10 , imbalances= 0.0 : 0.001 : 0.8 )
148+ """
149+ optimize_code(code; optmethod=:kahypar, sc_target=17, max_group_size=40, nrepeat=10, imbalances=0.0:0.001:0.8)
150+
151+ Optimize the contraction order.
152+
153+ * `optmethod` can be one of
154+ * `:kahypar`, the kahypar + greedy approach, takes kwargs [`sc_target`, `max_group_size`, `imbalances`].
155+ Check `optimize_kahypar` method in package `OMEinsumContractionOrders`.
156+ * `:auto`, also the kahypar + greedy approach, but determines `sc_target` automatically. It is slower!
157+ * `:greedy`, the greedy approach. Check in `optimize_greedy` in package `OMEinsum`.
158+ * `:raw`, do nothing and return the raw EinCode.
159+ """
160+ function optimize_code (code:: EinTypes ; optmethod= :kahypar , sc_target= 17 , max_group_size= 40 , nrepeat= 10 , imbalances= 0.0 : 0.001 : 0.8 )
97161 size_dict = Dict ([s=> 2 for s in labels (code)])
98- optcode = if method == :kahypar
162+ optcode = if optmethod == :kahypar
99163 optimize_kahypar (code, size_dict; sc_target= sc_target, max_group_size= max_group_size, imbalances= imbalances)
100- elseif method == :greedy
164+ elseif optmethod == :greedy
101165 optimize_greedy (code, size_dict; nrepeat= nrepeat)
166+ elseif optmethod == :auto
167+ optimize_kahypar_auto (code, size_dict; max_group_size= max_group_size, effort= 500 )
168+ elseif optmethod == :raw
169+ code
102170 else
103- ArgumentError (" optimizer `$method ` not defined." )
171+ ArgumentError (" optimizer `$optmethod ` not defined." )
104172 end
105173 println (" time/space complexity is $(OMEinsum. timespace_complexity (optcode, size_dict)) " )
106174 return optcode
107175end
108176
109- function contractx (gp:: GraphProblem , x:: T ; usecuda= false ) where T
110- xs = generate_tensors (_-> x, gp)
177+ contractx (gp:: GraphProblem , x; usecuda= false ) = contractf (_-> x, gp; usecuda= usecuda)
178+ function contractf (f, gp:: GraphProblem ; usecuda= false )
179+ xs = generate_tensors (f, gp)
111180 if usecuda
112181 xs = CuArray .(xs)
113182 end
116185
117186# ############## Problem specific implementations ################
118187# ## independent set ###
119- function Independence (g:: SimpleGraph )
120- Independence (EinCode (([(i,) for i in LightGraphs. vertices (g)]. .. , # labels for vertex tensors
121- [minmax (e. src,e. dst) for e in LightGraphs. edges (g)]. .. ), ())) # labels for edge tensors
188+ function Independence (g:: SimpleGraph ; kwargs... )
189+ rawcode = EinCode (([(i,) for i in LightGraphs. vertices (g)]. .. , # labels for vertex tensors
190+ [minmax (e. src,e. dst) for e in LightGraphs. edges (g)]. .. ), ()) # labels for edge tensors
191+ Independence (optimize_code (rawcode; kwargs... ))
122192end
123193
124194function generate_tensors (fx, gp:: Independence )
@@ -136,7 +206,7 @@ misv(val::T) where T = [one(T), val]
136206graph_polynomial_maxorder (gp:: Independence ; usecuda) = Int (sum (contractx (gp, TropicalF64 (1.0 ); usecuda= usecuda)). n)
137207
138208# ## coloring ###
139- Coloring (g:: SimpleGraph ) = Coloring (Independence (g). code)
209+ Coloring (g:: SimpleGraph ; kwargs ... ) = Coloring (Independence (g; kwargs ... ). code)
140210function generate_tensors (fx, c:: Coloring{K} ) where K
141211 ixs = getixs (flatten (code))
142212 T = eltype (fx (ixs[1 ][1 ]))
159229coloringv (vals:: Vector{T} ) where T = vals
160230
161231# ## matching ###
162- function Matching (g:: SimpleGraph )
163- Matching (EinCode (([(minmax (e. src,e. dst),) for e in LightGraphs. edges (g)]. .. , # labels for edge tensors
164- [([minmax (i,j) for j in neighbors (g, i)]. .. ,) for i in LightGraphs. vertices (g)]. .. ,), ())) # labels for vertex tensors
232+ function Matching (g:: SimpleGraph ; kwargs... )
233+ rawcode = EinCode (([(minmax (e. src,e. dst),) for e in LightGraphs. edges (g)]. .. , # labels for edge tensors
234+ [([minmax (i,j) for j in neighbors (g, i)]. .. ,) for i in LightGraphs. vertices (g)]. .. ,), ()) # labels for vertex tensors
235+ Matching (optimize_code (rawcode; kwargs... ))
165236end
166237
167238function generate_tensors (fx, m:: Matching )
193264graph_polynomial_maxorder (m:: Matching ; usecuda) = Int (sum (contractx (m, TropicalF64 (1.0 ); usecuda= usecuda)). n)
194265
195266# ## maximal independent set ###
196- function MaximalIndependence (g:: SimpleGraph )
197- MaximalIndependence (EinCode (([(LightGraphs. neighbors (g, v)... , v) for v in LightGraphs. vertices (g)]. .. ,), ()))
267+ function MaximalIndependence (g:: SimpleGraph ; kwargs... )
268+ rawcode = EinCode (([(LightGraphs. neighbors (g, v)... , v) for v in LightGraphs. vertices (g)]. .. ,), ())
269+ MaximalIndependence (optimize_code (rawcode; kwargs... ))
198270end
199271
200272function generate_tensors (fx, mi:: MaximalIndependence )
@@ -213,8 +285,4 @@ function neighbortensor(x::T, d::Int) where T
213285 return t
214286end
215287
216- graph_polynomial_maxorder (mi:: MaximalIndependence ; usecuda) = Int (sum (contractx (mi, TropicalF64 (1.0 ); usecuda= usecuda)). n)
217-
218- for GP in [:Independence , :MaximalIndependence , :Matching , :Coloring ]
219- @eval optimize_code (gp:: $GP ; kwargs... ) = $ GP (optimize_code (gp. code; kwargs... ))
220- end
288+ graph_polynomial_maxorder (mi:: MaximalIndependence ; usecuda) = Int (sum (contractx (mi, TropicalF64 (1.0 ); usecuda= usecuda)). n)
0 commit comments