nitc :: POSetGroupColorer :: defaultinit
# Colorize elements `E` introduced by holders `H` in a `POSet`.
#
# Two elements cannot have the same color if they are introduced or inherited by a same holder.
class POSetGroupColorer[H: Object, E: Object]
# The associated conflict graph containing the poset.
#
# The conflict graph is used instead of the original poset so that the conflict graph can be reused
# in different coloration based on the same poset.
var graph: POSetConflictGraph[H]
# The elements to color.
#
# For each holder, the collection of introduced elements is given.
#
# A single element must not be introduced in more than one holder.
var buckets: Map[H, Collection[E]]
# The associated poset.
#
# alias for `graph.poset`
fun poset: POSet[H] do return graph.poset
# The resulting coloring
#
# Each element from buckets is associated to its own color
var colors: Map[E, Int] is lazy do
for h in graph.poset do
used_colors[h] = new HashSet[Int]
end
compute_colors
return colors_cache
end
# Resulting colors
private var colors_cache = new HashMap[E, Int]
# Set of known used colors
private var used_colors = new HashMap[H, HashSet[Int]]
# Build table layout of elements `E` for the holder `h`.
#
# `null` is used to fill places without elements (holes).
fun build_layout(h: H): Array[nullable E]
do
var table = new Array[nullable E]
for s in poset[h].greaters do
var bucket = buckets.get_or_null(s)
if bucket == null then continue
for e in bucket do
var color = colors[e]
if table.length <= color then
for i in [table.length .. color[ do
table[i] = null
end
else
assert table[color] == null else print "in {h}, for {color}: {table[color] or else ""} vs {e}"
end
table[color] = e
end
end
return table
end
# Colorize core, border and crown in that order
private fun compute_colors do
colors_cache.clear
colorize_core
colorize_set(graph.border)
colorize_set(graph.crown)
end
# Core elements cannot have the same color than:
# * one of their parents
# * one of their conflicting elements
private fun colorize_core do
for h in graph.order do
if not graph.core.has(h) then continue
var color = inherit_color(h)
var mincolor = color
var bucket = buckets.get_or_null(h)
if bucket == null then continue
var conflicts = graph.conflicts[h]
var parents = poset[h].greaters
for e in bucket do
color = next_free_color(color, parents)
color = next_free_color(color, conflicts)
colors_cache[e] = color
used_colors[h].add color
#print "{h}: color[{color}] <- {e}"
if mincolor == color then mincolor += 1
color += 1
end
min_colors[h] = mincolor
end
end
# Other elements inherit color from their direct parents
private fun colorize_set(set: Set[H]) do
for h in graph.order do
if not set.has(h) then continue
var color = inherit_color(h)
var mincolor = color
var bucket = buckets.get_or_null(h)
if bucket == null then continue
var parents = poset[h].greaters
for e in bucket do
color = next_free_color(color, parents)
colors_cache[e] = color
used_colors[h].add color
#print "{h}: color[{color}] <- {e} (set)"
if mincolor == color then mincolor += 1
color += 1
end
min_colors[h] = mincolor
end
end
# Get the first available free color.
private fun inherit_color(h: H): Int
do
var res = 0
for p in poset[h].direct_greaters do
var m = min_colors[p]
if m > res then res = m
end
min_colors[h] = res
return res
end
# The first available color for each holder.
#
# Is used by children to start their coloring.
#
# Is updated at the end of a coloring step.
private var min_colors = new HashMap[H, Int]
private fun next_free_color(color: Int, set: Collection[H]): Int do
loop
for h in set do
if used_colors[h].has(color) then
#print "\tin {h}, {color} is used"
color += 1
continue label
end
end
break
end label
return color
end
# Used for debugging only
fun pretty_print do
print "colors:"
for e, c in colors do print " {e}: {c}"
end
end
src/compiler/coloring.nit:287,1--445,3