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
Browse files Browse the repository at this point in the history
  • Loading branch information
SohamTamba committed Feb 17, 2018
1 parent b1debf0 commit 342fc12
Show file tree
Hide file tree
Showing 4 changed files with 192 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
155 changes: 155 additions & 0 deletions src/traversals/greedy_color.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
"""
struct coloring{T}
Store number of colors used and mapping from vertex to color
"""
struct coloring{T<:Integer}
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[Int(cols[w])] = true
end
end


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

result = coloring{T}(maximum(cols), cols)
return result
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{U}) where U<:Integer
seq::Vector{U} = sortperm(degree(g, vertices(g)) , rev=true)
result = perm_greedy_color(g, seq)
return result
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,
reps::Integer
)

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

return 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,
reps::Integer
)

seq = shuffle(vertices(g))
best::coloring = 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.
"""
function random_greedy_color(
g::AbstractGraph,
reps::Integer = 1,
parallel::Bool = false
)

if !parallel
return seq_random_greedy_color(g, reps)
else
return parallel_random_greedy_color(g, reps)
end

end

"""
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.
"""
function greedy_color(
g::AbstractGraph{U};
sort_degree::Bool=false,
parallel::Bool = false,
reps::Integer=1,
)::coloring{U} where U <: Integer

result = coloring(zero(U), zeros(U, nv(g)))
if sort_degree
result = degree_greedy_color(g)
else
result = random_greedy_color(g, reps, parallel)
end
return result
end

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 op1 in (true, false), op2 in (true, false)
C = @inferred(greedy_color(g, reps=50, sort_degree=op1, parallel=op2))
@test C.num_colors == 2
end
end

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

for graph in [g4, g5]
for g in testgraphs(graph)
for op1 in (true, false), op2 in (true, false)
C = @inferred(greedy_color(g, reps=50, sort_degree=op1, parallel=op2))

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

@test correct
end
end
end

end

0 comments on commit 342fc12

Please sign in to comment.