Skip to content

Commit aed47d8

Browse files
committed
update README
1 parent 054e621 commit aed47d8

File tree

4 files changed

+146
-3
lines changed

4 files changed

+146
-3
lines changed

README.md

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
3232
end
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
```

src/cuda.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ using .CUDA
22
using TropicalGEMM: XTranspose, NativeTypes, Tropical, TropicalTypes
33
using LinearAlgebra
44

5+
# patch
6+
Base.ndims(::Base.Broadcast.Broadcasted{CUDA.CuArrayStyle{0}}) = 0
7+
58
function onehotmask(A::CuArray{T}, X::CuArray{T}) where T
69
mask = X .== inv.(A)
710
ci = argmax(mask)
@@ -39,4 +42,4 @@ function LinearAlgebra.permutedims!(dest::AbstractGPUArray, src::AbstractGPUArra
3942
end
4043
gpu_call(permutedims_kernel, dest, src, perm)
4144
return dest
42-
end
45+
end

src/graphs.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ function diagonal_coupled_graph(mask::AbstractMatrix{Bool})
1818
unitdisk_graph(locs, 1.5)
1919
end
2020

21-
function unitdisk_graph(locs::Vector, unit::Real)
21+
function unitdisk_graph(locs::AbstractVector, unit::Real)
2222
n = length(locs)
2323
g = SimpleGraph(n)
2424
for i=1:n, j=i+1:n

src/interfaces.jl

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,26 @@ end
122122

123123
# convert to Matrix
124124
Base.Matrix(ce::ConfigEnumerator) = plain_matrix(ce)
125-
Base.Vector(ce::StaticElementVector) = collect(ce)
125+
Base.Vector(ce::StaticElementVector) = collect(ce)
126+
127+
# some useful API
128+
export mis_compactify!
129+
130+
"""
131+
mis_compactify!(tropicaltensor)
132+
133+
Compactify tropical tensor for maximum independent set problem. It will eliminate
134+
some entries by setting them to zero, by the criteria that even these entries are removed, the MIS size is not changed.
135+
"""
136+
function mis_compactify!(a::AbstractArray{T}) where T <: TropicalTypes
137+
for (ind_a, val_a) in enumerate(a)
138+
for (ind_b, val_b) in enumerate(a)
139+
bs_a = ind_a - 1
140+
bs_b = ind_b - 1
141+
@inbounds if bs_a != bs_b && val_a <= val_b && (bs_b & bs_a) == bs_b
142+
a[ind_a] = zero(T)
143+
end
144+
end
145+
end
146+
return a
147+
end

0 commit comments

Comments
 (0)