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

Add greedy_color for Graph Coloring #844

Merged
merged 3 commits into from
Feb 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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