Skip to content

Commit 763c8a4

Browse files
samuelsonricgdalle
andauthored
Chordal coloring algorithm (#202)
* Add chordal coloring. * fix bug * Add ordering algorithm: `PerfectEliminationOrder` * Add tests for ordering algorithm `PerfectEliminationOrder`. * Respond to PR comments. * Add `PerfectEliminationOrder` to api. * Update src/order.jl * Update src/order.jl * Update src/order.jl * Fix docstring * Bump version * Make elimination algorithm parametric * Only substitution --------- Co-authored-by: Guillaume Dalle <22795598+gdalle@users.noreply.github.com>
1 parent 3cdcf96 commit 763c8a4

8 files changed

Lines changed: 81 additions & 1 deletion

File tree

Project.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "SparseMatrixColorings"
22
uuid = "0a514795-09f3-496d-8182-132a7b665d35"
33
authors = ["Guillaume Dalle", "Alexis Montoison"]
4-
version = "0.4.14"
4+
version = "0.4.15"
55

66
[deps]
77
ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
@@ -12,13 +12,16 @@ Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
1212
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1313

1414
[weakdeps]
15+
CliqueTrees = "60701a23-6482-424a-84db-faee86b9b1f8"
1516
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
1617

1718
[extensions]
19+
SparseMatrixColoringsCliqueTreesExt = "CliqueTrees"
1820
SparseMatrixColoringsColorsExt = "Colors"
1921

2022
[compat]
2123
ADTypes = "1.2.1"
24+
CliqueTrees = "0.5.2"
2225
Colors = "0.12.11, 0.13"
2326
DataStructures = "0.18"
2427
DocStringExtensions = "0.8,0.9"

docs/Project.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@ DocumenterInterLinks = "d12716ef-a0f6-4df4-a9f1-a5a34e75c656"
66
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
77
SparseMatrixColorings = "0a514795-09f3-496d-8182-132a7b665d35"
88
StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"
9+
10+
[sources]
11+
SparseMatrixColorings = {path=".."}

docs/src/api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,5 @@ SmallestLast
5353
IncidenceDegree
5454
DynamicLargestFirst
5555
DynamicDegreeBasedOrder
56+
PerfectEliminationOrder
5657
```
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module SparseMatrixColoringsCliqueTreesExt
2+
3+
import CliqueTrees: permutation, EliminationAlgorithm, MCS
4+
import SparseArrays: SparseMatrixCSC, rowvals, nnz
5+
import SparseMatrixColorings:
6+
AdjacencyGraph, BipartiteGraph, PerfectEliminationOrder, pattern, vertices
7+
8+
PerfectEliminationOrder() = PerfectEliminationOrder(MCS())
9+
10+
function vertices(g::AdjacencyGraph{T}, order::PerfectEliminationOrder) where {T}
11+
S = pattern(g)
12+
13+
# construct matrix with sparsity pattern S
14+
M = SparseMatrixCSC{Bool,T}(size(S)..., S.colptr, rowvals(S), ones(Bool, nnz(S)))
15+
16+
# construct a perfect elimination order
17+
# self-loops are ignored
18+
order, _ = permutation(M; alg=order.elimination_algorithm)
19+
20+
return reverse!(order)
21+
end
22+
23+
end # module

src/SparseMatrixColorings.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ include("show_colors.jl")
5757

5858
export NaturalOrder, RandomOrder, LargestFirst
5959
export DynamicDegreeBasedOrder, SmallestLast, IncidenceDegree, DynamicLargestFirst
60+
export PerfectEliminationOrder
6061
export ColoringProblem, GreedyColoringAlgorithm, AbstractColoringResult
6162
export ConstantColoringAlgorithm
6263
export coloring, fast_coloring

src/order.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Depending on how the vertices are ordered, the number of colors necessary may va
1414
- [`IncidenceDegree`](@ref) (experimental)
1515
- [`SmallestLast`](@ref) (experimental)
1616
- [`DynamicLargestFirst`](@ref) (experimental)
17+
- [`PerfectEliminationOrder`](@ref)
1718
"""
1819
abstract type AbstractOrder end
1920

@@ -301,3 +302,24 @@ Instance of [`AbstractOrder`](@ref) which sorts vertices from lowest to highest
301302
- [`DynamicDegreeBasedOrder`](@ref)
302303
"""
303304
const DynamicLargestFirst = DynamicDegreeBasedOrder{:forward,:low2high}
305+
306+
"""
307+
PerfectEliminationOrder(elimination_algorithm=CliqueTrees.MCS())
308+
309+
Instance of [`AbstractOrder`](@ref) which computes a perfect elimination ordering when the underlying graph is [chordal](https://en.wikipedia.org/wiki/Chordal_graph). For non-chordal graphs, it computes a suboptimal ordering.
310+
311+
The `elimination_algorithm` must be an instance of `CliqueTrees.EliminationAlgorithm`.
312+
313+
!!! warning
314+
This order can only be applied for symmetric or bidirectional coloring problems. Furthermore, its theoretical guarantees only hold for decompression by substitution.
315+
316+
!!! danger
317+
This order is implemented as a package extension and requires loading [CliqueTrees.jl](https://github.com/AlgebraicJulia/CliqueTrees.jl).
318+
319+
# References
320+
321+
- [Simple Linear-Time Algorithms to Test Chordality of Graphs, Test Acyclicity of Hypergraphs, and Selectively Reduce Acyclic Hypergraphs](https://epubs.siam.org/doi/10.1137/0213035), Tarjan and Yannakakis (1984)
322+
"""
323+
struct PerfectEliminationOrder{E} <: AbstractOrder
324+
elimination_algorithm::E
325+
end

test/Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
77
BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0"
88
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
99
Chairmarks = "0ca39b1e-fe0b-4e98-acfc-b1656634c4de"
10+
CliqueTrees = "60701a23-6482-424a-84db-faee86b9b1f8"
1011
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
1112
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
1213
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"

test/order.jl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using CliqueTrees: CliqueTrees
2+
using BandedMatrices
13
using LinearAlgebra
24
using SparseArrays
35
using SparseMatrixColorings
@@ -7,6 +9,7 @@ using SparseMatrixColorings:
79
LargestFirst,
810
NaturalOrder,
911
RandomOrder,
12+
PerfectEliminationOrder,
1013
degree_dist2,
1114
nb_vertices,
1215
valid_dynamic_order,
@@ -110,3 +113,26 @@ end;
110113
end
111114
end
112115
end;
116+
117+
@testset "PerfectEliminationOrder" begin
118+
problem = ColoringProblem(; structure=:symmetric, partition=:column)
119+
substitution_algo = GreedyColoringAlgorithm(
120+
PerfectEliminationOrder(); decompression=:substitution
121+
)
122+
123+
# band graphs
124+
for (n, m) in ((800, 80), (400, 40), (200, 20), (100, 10))
125+
perm = randperm(rng, n)
126+
matrix = permute!(sparse(Symmetric(brand(n, n, m, 0), :L)), perm, perm)
127+
π = vertices(AdjacencyGraph(matrix), PerfectEliminationOrder())
128+
@test isperm(π)
129+
@test ncolors(coloring(matrix, problem, substitution_algo)) == m + 1
130+
end
131+
132+
# random graphs
133+
for (n, p) in Iterators.product(20:20:100, 0.0:0.1:0.2)
134+
matrix = sparse(Symmetric(sprand(rng, Bool, n, n, p)))
135+
π = vertices(AdjacencyGraph(matrix), PerfectEliminationOrder())
136+
@test isperm(π)
137+
end
138+
end

0 commit comments

Comments
 (0)