Skip to content

Commit e2cac8f

Browse files
committed
update
1 parent 81cb710 commit e2cac8f

File tree

7 files changed

+148
-23
lines changed

7 files changed

+148
-23
lines changed

src/GraphTensorNetworks.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export GreedyMethod, TreeSA, SABipartite, KaHyParBipartite, MergeVectors, MergeG
1212

1313
project_relative_path(xs...) = normpath(joinpath(dirname(dirname(pathof(@__MODULE__))), xs...))
1414

15+
include("utils.jl")
1516
include("bitvector.jl")
1617
include("arithematics.jl")
1718
include("networks.jl")

src/arithematics.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ for (F,TP) in [(:set_type, :ConfigEnumerator), (:sampler_type, :ConfigSampler)]
201201
function $F(::Type{T}, n::Int, nflavor::Int) where {TV, T<:CountingTropical{TV}}
202202
CountingTropical{TV, $F(n,nflavor)}
203203
end
204+
function $F(::Type{Real}, n::Int, nflavor::Int) where {TV}
205+
$F(n, nflavor)
206+
end
204207
function $F(n::Integer, nflavor::Integer)
205208
s = ceil(Int, log2(nflavor))
206209
c = _nints(n,s)

src/configurations.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ function best_solutions(gp::GraphProblem; all=false, usecuda=false)
1616
syms = symbols(gp)
1717
T = (all ? set_type : sampler_type)(CountingTropical{Int64}, length(syms), bondsize(gp))
1818
vertex_index = Dict([s=>i for (i, s) in enumerate(syms)])
19-
xst = generate_tensors(l->TropicalF64(1.0), gp)
19+
xst = generate_tensors(l->TropicalF64(get_weight(gp, vertex_index[l])), gp)
2020
ymask = trues(fill(2, length(getiyv(gp.code)))...)
2121
if usecuda
2222
xst = CuArray.(xst)
@@ -62,7 +62,7 @@ best2_solutions(gp::GraphProblem; all=true, usecuda=false) = solutions(gp, Max2P
6262
function bestk_solutions(gp::GraphProblem, k::Int)
6363
syms = symbols(gp)
6464
vertex_index = Dict([s=>i for (i, s) in enumerate(syms)])
65-
xst = generate_tensors(l->TropicalF64(1.0), gp)
65+
xst = generate_tensors(l->TropicalF64(get_weight(gp, vertex_index[l])), gp)
6666
ymask = trues(fill(2, length(getiyv(gp.code)))...)
6767
T = set_type(TruncatedPoly{k,Float64,Float64}, length(syms), bondsize(gp))
6868
xs = generate_tensors(l->_onehotv(T, vertex_index[l], 1, get_weight(gp, vertex_index[l])), gp)
@@ -107,6 +107,9 @@ end
107107
function _onehotv(::Type{CountingTropical{TV,BS}}, x, v, w) where {TV,BS}
108108
CountingTropical{TV,BS}(TV(w), onehotv(BS, x, v))
109109
end
110+
function _onehotv(::Type{BS}, x, v, w) where {BS<:ConfigEnumerator}
111+
onehotv(BS, x, v)
112+
end
110113

111114
for GP in [:Independence, :Matching, :MaximalIndependence, :Coloring]
112115
@eval symbols(gp::$GP) = labels(gp.code)

src/interfaces.jl

Lines changed: 109 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,55 +3,146 @@ export solve, SizeMax, CountingAll, CountingMax, GraphPolynomial, SingleConfigMa
33
abstract type AbstractProperty end
44
_support_weight(::AbstractProperty) = false
55

6+
"""
7+
SizeMax <: AbstractProperty
8+
SizeMax()
9+
10+
The maximum independent set size.
11+
12+
* The corresponding tensor element type is [`Tropical`](@ref).
13+
* It is compatible with weighted graph problems.
14+
* BLAS (on CPU) and GPU are supported,
15+
"""
616
struct SizeMax <: AbstractProperty end
717
_support_weight(::SizeMax) = true
818

19+
"""
20+
CountingAll <: AbstractProperty
21+
CountingAll()
22+
23+
Counting the total number of sets. e.g. for [`Independence`](@ref) problem, it counts the independent sets.
24+
25+
* The corresponding tensor element type is [`Base.Real`](@ref).
26+
* The weights on graph does not have effect.
27+
* BLAS (GPU and CPU) and GPU are supported,
28+
"""
929
struct CountingAll <: AbstractProperty end
1030
_support_weight(::CountingAll) = true
1131

32+
"""
33+
CountingMax{K} <: AbstractProperty
34+
CountingMax(K=1)
35+
36+
Counting the number of sets with `K` largest size. e.g. for [`Independence`](@ref) problem,
37+
it counts independent sets of size ``\\alpha(G), \\alpha(G)-1, \\ldots, \\alpha(G)-K+1``.
38+
39+
* The corresponding tensor element type is [`CountingTropical`](@ref) for `K == 1`, and [`TruncatedPoly{K}`](@ref) for `K > 1`.
40+
* Weighted graph problems is only supported for `K == 1`.
41+
* GPU is supported,
42+
"""
1243
struct CountingMax{K} <: AbstractProperty end
1344
CountingMax(K::Int=1) = CountingMax{K}()
1445
max_k(::CountingMax{K}) where K = K
1546
_support_weight(::CountingMax{1}) = true
1647

48+
"""
49+
GraphPolynomial{METHOD} <: AbstractProperty
50+
GraphPolynomial(; method=:finitefield, kwargs...)
51+
52+
Compute the graph polynomial, e.g. for [`Independence`](@ref) problem, it is the independence polynomial.
53+
The `METHOD` type parameter can be one of the following symbols
54+
55+
* `:finitefield`, it uses finite field algebra to fit the polynomial.
56+
* The corresponding tensor element type is [`Mods.Mod`](@ref),
57+
* It does not have round-off error,
58+
* GPU is supported,
59+
* It accepts keyword arguments `maxorder` (optional, e.g. the MIS size in the [`Independence`](@ref) problem).
60+
* `:polynomial`, the program uses polynomial numbers to solve the polynomial directly.
61+
* The corresponding tensor element type is [`Polynomials.Polynomial`](@ref).
62+
* It might have small round-off error depending on the data type for storing the counting.
63+
* It has memory overhead that linear to the graph size.
64+
* `:fft`,
65+
* The corresponding tensor element type is [`Base.Complex`](@ref).
66+
* It has (controllable) round-off error.
67+
* BLAS and GPU are supported.
68+
* It accepts keyword arguments `maxorder` (optional) and `r`,
69+
if `r > 1`, one has better precision for coefficients of large order, if `r < 1`,
70+
one has better precision for coefficients of small order.
71+
72+
Graph polynomials are not defined for weighted graph problems.
73+
"""
1774
struct GraphPolynomial{METHOD} <: AbstractProperty
1875
kwargs
1976
end
2077
GraphPolynomial(; method::Symbol = :finitefield, kwargs...) = GraphPolynomial{method}(kwargs)
2178
graph_polynomial_method(::GraphPolynomial{METHOD}) where METHOD = METHOD
2279

80+
"""
81+
SingleConfigMax{BOUNDED} <: AbstractProperty
82+
SingleConfigMax(; bounded=false)
83+
84+
Finding single best solution, e.g. for [`Independence`](@ref) problem, it is one of the maximum independent sets.
85+
86+
* The corresponding data type is [`CountingTropical{Float64,<:ConfigSampler}`](@ref) if `BOUNDED` is `true`, [`Tropical`](@ref) otherwise.
87+
* Weighted graph problems is supported.
88+
* GPU is supported,
89+
"""
2390
struct SingleConfigMax{BOUNDED} <:AbstractProperty end
2491
SingleConfigMax(; bounded::Bool=false) = SingleConfigMax{bounded}()
2592
_support_weight(::SingleConfigMax) = true
2693

94+
"""
95+
ConfigsAll <:AbstractProperty
96+
ConfigsAll()
97+
98+
Find all valid configurations, e.g. for [`Independence`](@ref) problem, it is finding all independent sets.
99+
100+
* The corresponding data type is [`ConfigEnumerator`](@ref).
101+
* Weights do not take effect.
102+
"""
27103
struct ConfigsAll <:AbstractProperty end
28104
_support_weight(::ConfigsAll) = true
29105

106+
"""
107+
ConfigsMax{K, BOUNDED} <:AbstractProperty
108+
ConfigsMax(K=1; bounded=true)
109+
110+
Find configurations with largest sizes, e.g. for [`Independence`](@ref) problem,
111+
it is finding all independent sets of sizes ``\\alpha(G), \\alpha(G)-1, \\ldots, \\alpha(G)-K+1``.
112+
113+
* The corresponding data type is [`CountingTropical{Float64,<:ConfigEnumerator}`](@ref) for `K == 1` and [`TruncatedPoly{K,<:ConfigEnumerator}`] for `K > 1`.
114+
* Weighted graph problems is only supported for `K == 1`.
115+
"""
30116
struct ConfigsMax{K, BOUNDED} <:AbstractProperty end
31117
ConfigsMax(K::Int=1; bounded::Bool=true) = ConfigsMax{K,bounded}()
32118
max_k(::ConfigsMax{K}) where K = K
33119
_support_weight(::ConfigsMax{1}) = true
34120

35121
"""
36-
solve(problem, task; usecuda=false)
122+
solve(problem, property; usecuda=false, T=Float64)
37123
124+
Solving a certain property of a graph problem.
125+
126+
Positional Arguments
127+
---------------------------
38128
* `problem` is the graph problem with tensor network information,
39-
* `task` is string specifying the task. Using the maximum independent set problem as an example, it can be one of
40-
* "size max", the maximum independent set size,
41-
* "counting sum", total number of independent sets,
42-
* "counting max", the dengeneracy of maximum independent sets (MIS),
43-
* "counting max2", the dengeneracy of MIS and MIS-1,
44-
* "counting all", independence polynomial, the polynomial number approach,
45-
* "counting all (fft)", independence polynomial, the fourier transformation approach,
46-
* "counting all (finitefield)", independence polynomial, the finite field approach,
47-
* "config max", one of the maximum independent set,
48-
* "config max (bounded)", one of the maximum independent set, the bounded version,
49-
* "configs max", all MIS configurations,
50-
* "configs max2", all MIS configurations and MIS-1 configurations,
51-
* "configs all", all IS configurations,
52-
* "configs max (bounded)", all MIS configurations, the bounded approach (much faster),
53-
* "configs max2 (bounded)", all MIS and MIS-1 configurations, the bounded approach (much faster),
54-
* "configs max3 (bounded)", all MIS, MIS-1 and MIS-2 configurations, the bounded approach (much faster),
129+
* `property` is string specifying the task. Using the maximum independent set problem as an example, it can be one of
130+
131+
* [`SizeMax`](@ref) for finding maximum configuration size,
132+
133+
* [`CountingMax`](@ref) for counting configurations with top `K` sizes,
134+
* [`CountingAll`](@ref) for counting all configurations,
135+
* [`GraphPolynomial`](@ref) for evaluating the graph polynomial,
136+
137+
* [`SingleConfigMax`](@ref) for finding one maximum configuration,
138+
* [`ConfigsMax`](@ref) for enumerating configurations with top `K` sizes,
139+
* [`ConfigsAll`](@ref) for enumerating all configurations,
140+
141+
142+
Keyword arguments
143+
-------------------------------------
144+
* `usecuda` is a switch to use CUDA (if possible), user need to call statement `using CUDA` before turning on this switch.
145+
* `T` is the "base" element type, sometimes can be used to reduce the memory cost.
55146
"""
56147
function solve(gp::GraphProblem, property::AbstractProperty; T=Float64, usecuda=false)
57148
if !_support_weight(property) && _has_weight(gp)
@@ -78,7 +169,7 @@ function solve(gp::GraphProblem, property::AbstractProperty; T=Float64, usecuda=
78169
elseif property isa (ConfigsMax{K, false} where K)
79170
return solutions(gp, TruncatedPoly{max_k(property),T,T}; all=true, usecuda=usecuda)
80171
elseif property isa ConfigsAll
81-
return solutions(gp, Polynomial{T,:x}; all=true, usecuda=usecuda)
172+
return solutions(gp, Real; all=true, usecuda=usecuda)
82173
elseif property isa SingleConfigMax{true}
83174
return best_solutions(gp; all=false, usecuda=usecuda)
84175
elseif property isa ConfigsMax{1,true}

src/networks.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ end
208208
_optimize_code(code, size_dict, optimizer::Nothing, simplifier) = code
209209
_optimize_code(code, size_dict, optimizer, simplifier) = optimize_code(code, size_dict, optimizer, simplifier)
210210

211-
# TODO:
211+
# TODOs:
212212
# 1. Dominating set
213213
# \exists x_i,\ldots,x_K \forall y\left[\bigwedge_{i=1}^{K}(y=x_i\wedge \textbf{adj}(y, x_i))\right]
214214
# 2. Polish reading data

src/utils.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export is_independent_set
2+
3+
function is_independent_set(g::SimpleGraph, config)
4+
for e in edges(g)
5+
if config[e.src] == config[e.dst] == 1
6+
return false
7+
end
8+
end
9+
return true
10+
end

test/interfaces.jl

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ using Graphs, Test
3030
@test res6.c.data res7.c.data
3131
@test all(x->sum(x) == 4, res7.c.data)
3232
@test all(x->sum(x) == 3, res8.coeffs[1].data) && all(x->sum(x) == 4, res8.coeffs[2].data) && length(res8.coeffs[1].data) == 30 && length(res8.coeffs[2].data) == 5
33-
@test all(x->all(c->sum(c) == x[1]-1, x[2].data), enumerate(res9.coeffs))
33+
@test length(unique(res9.data)) == 76 && all(c->is_independent_set(g, c), res9.data)
3434
@test res10 res5
3535
@test res11 == res5
3636
@test res12.c.data res13.c.data
@@ -111,7 +111,7 @@ end
111111
@test res6.c.data res7.c.data
112112
@test all(x->sum(x) == 4, res7.c.data)
113113
@test all(x->sum(x) == 3, res8.coeffs[1].data) && all(x->sum(x) == 4, res8.coeffs[2].data) && length(res8.coeffs[1].data) == 30 && length(res8.coeffs[2].data) == 5
114-
@test all(x->all(c->sum(c) == x[1]-1, x[2].data), enumerate(res9.coeffs))
114+
@test length(unique(res9.data)) == 76 && all(c->is_independent_set(g, c), res9.data)
115115
@test res10 res5
116116
@test res11 == res5
117117
@test res12.c.data res13.c.data
@@ -124,3 +124,20 @@ end
124124
length(res17.coeffs[1].data) == 30 && length(res17.coeffs[2].data) == 30 && length(res17.coeffs[3].data) == 5
125125
end
126126

127+
@testset "Weighted" begin
128+
g = Graphs.smallgraph("petersen")
129+
gp = Independence(g; weights=collect(1:10))
130+
res1 = solve(gp, SizeMax())[]
131+
@test res1 == Tropical(24.0)
132+
res2 = solve(gp, CountingMax(1))[]
133+
@test res2 == CountingTropical(24.0, 1.0)
134+
@test_throws ArgumentError solve(gp, CountingMax(2))[]
135+
res3 = solve(gp, SingleConfigMax(; bounded=false))[]
136+
res3b = solve(gp, SingleConfigMax(; bounded=true))[]
137+
@test res3 == res3b
138+
@test sum(collect(res3.c.data) .* (1:10)) == 24.0
139+
res4 = solve(gp, ConfigsMax(1; bounded=false))[]
140+
res4b = solve(gp, ConfigsMax(1; bounded=true))[]
141+
@test res4 == res4b
142+
@test res4.c.data[] == res3.c.data
143+
end

0 commit comments

Comments
 (0)