Skip to content
This repository has been archived by the owner on Oct 8, 2021. It is now read-only.

Commit

Permalink
Add greedy_color for Graph Coloring (#844)
Browse files Browse the repository at this point in the history
* Add greedy_color for Graph Coloring

* Improve Kruskal's MST by optimizing Union-Find (#843)
  • Loading branch information
SohamTamba authored and sbromberger committed Feb 20, 2018
1 parent 73f0957 commit dc5c443
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/LightGraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ randomwalk, saw, non_backtracking_randomwalk,
# diffusion
diffusion, diffusion_rate,

# coloring
greedy_color,

# connectivity
connected_components, strongly_connected_components, weakly_connected_components,
is_connected, is_strongly_connected, is_weakly_connected, period,
Expand Down Expand Up @@ -185,6 +188,7 @@ include("digraph/cycles/hadwick-james.jl")
include("digraph/cycles/karp.jl")
include("traversals/bfs.jl")
include("traversals/bipartition.jl")
include("traversals/greedy_color.jl")
include("traversals/parallel_bfs.jl")
include("traversals/dfs.jl")
include("traversals/maxadjvisit.jl")
Expand Down
129 changes: 129 additions & 0 deletions src/traversals/greedy_color.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
"""
struct coloring{T}
Store number of colors used and mapping from vertex to color
"""
struct coloring{T<:Integer} <: Any
num_colors::T
colors::Vector{T}
end

best_color(c1::coloring, c2::coloring) = c1.num_colors < c2.num_colors ? c1 : c2

"""
perm_greedy_color(g, seq)
Color graph `g` according to an order specified by `seq` using a greedy heuristic.
seq[i] = v imples that vertex v is the i<sup>th</sup> vertex to be colored.
"""
function perm_greedy_color(
g::AbstractGraph,
seq::Vector{T}
) where T <: Integer

nvg::T = nv(g)
cols = Vector{T}(nvg)
seen = zeros(Bool, nvg + 1)

for v in seq
seen[v] = true
colors_used = zeros(Bool, nvg)

for w in neighbors(g, v)
if seen[w]
colors_used[cols[w]] = true
end
end


for i in one(T):nvg
if colors_used[i] == false
cols[v] = i
break;
end
end
end

return coloring{T}(maximum(cols), cols)
end

"""
degree_greedy_color(g)
Color graph `g` iteratively in the descending order of the degree of the vertices.
"""
function degree_greedy_color(g::AbstractGraph{T}) where T<:Integer
seq = convert(Vector{T}, sortperm(degree(g) , rev=true))
return perm_greedy_color(g, seq)
end

"""
parallel_random_greedy_color(g, reps)
Color graph `g` iteratively in a random order using a greedy heuristic and
choose the best coloring out of `reps` number of colorings computed in parallel.
"""
function parallel_random_greedy_color(
g::AbstractGraph{T},
reps::Integer
) where T<:Integer

best = @parallel (best_color) for i in 1:reps
seq = shuffle(vertices(g))
perm_greedy_color(g, seq)
end

return convert(coloring{T} ,best)
end

"""
seq_random_greedy_color(g, reps)
Color graph `g` iteratively in a random order using a greedy heuristic
and choose the best coloring out of `reps` such random coloring.
"""
function seq_random_greedy_color(
g::AbstractGraph{T},
reps::Integer
) where T <: Integer

seq = shuffle(vertices(g))
best = perm_greedy_color(g, seq)

for i in 2:reps
shuffle!(seq)
best = best_color(best, perm_greedy_color(g, seq))
end
return best
end

"""
random_greedy_color(g, reps=1, parallel=false)
Color graph `g` iteratively in a random order using a greedy heruistic
and choose the best coloring out of `reps` such random coloring.
If parallel is true then the colorings are executed in parallel.
"""
random_greedy_color{T<:Integer}(g::AbstractGraph{T}, reps::Integer = 1, parallel::Bool = false) =
parallel ? parallel_random_greedy_color(g, reps) : seq_random_greedy_color(g, reps)

@doc_str """
greedy_color(g; sort_degree=false, parallel=false, reps = 1)
Color graph `g` based on [Greedy Coloring Heuristics](https://en.wikipedia.org/wiki/Greedy_coloring)
The heuristics can be described as choosing a permutation of the vertices and assigning the
lowest color index available iteratively in that order.
If `sort_degree` is true then the permutation is chosen in reverse sorted order of the degree of the vertices.
`parallel` and `reps` are irrelevant in this case.
If `sort_degree` is false then `reps` colorings are obtained based on random permutations and the one using least
colors is chosen.
If `parallel` is true then this function executes coloring in parallel.
"""
greedy_color{U <: Integer}(g::AbstractGraph{U}; sort_degree::Bool=false, parallel::Bool =false, reps::Integer=1) =
sort_degree ? degree_greedy_color(g) : random_greedy_color(g, reps, parallel)

1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ tests = [
"traversals/bfs",
"traversals/parallel_bfs",
"traversals/bipartition",
"traversals/greedy_color",
"traversals/dfs",
"traversals/maxadjvisit",
"traversals/randomwalks",
Expand Down
32 changes: 32 additions & 0 deletions test/traversals/greedy_color.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@testset "Greedy Coloring" begin

g3 = StarGraph(10)

for g in testgraphs(g3)
for op_sort in (true, false), op_parallel in (true, false)
C = @inferred(greedy_color(g, reps=5, sort_degree=op_sort, parallel=op_parallel))
@test C.num_colors == 2
end
end

g4 = PathGraph(20)
g5 = CompleteGraph(20)

for graph in [g4, g5]
for g in testgraphs(graph)
for op_sort in (true, false), op_parallel in (true, false)
C = @inferred(greedy_color(g, reps=5, sort_degree=op_sort, parallel=op_parallel))

@test C.num_colors <= maximum(degree(g))+1
correct = true
for e in edges(g)
C.colors[src(e)] == C.colors[dst(e)] && (correct = false)
end

@test correct
end
end
end

end

0 comments on commit dc5c443

Please sign in to comment.