3 -- This is a generic graph coloring library, abstracted over the type of
4 -- the node keys, nodes and colors.
6 {-# OPTIONS -fno-warn-missing-signatures #-}
30 -- | Try to color a graph with this set of colors.
31 -- Uses Chaitin's algorithm to color the graph.
32 -- The graph is scanned for nodes which are deamed 'trivially colorable'. These nodes
33 -- are pushed onto a stack and removed from the graph.
34 -- Once this process is complete the graph can be colored by removing nodes from
35 -- the stack (ie in reverse order) and assigning them colors different to their neighbors.
38 :: ( Uniquable k, Uniquable cls, Uniquable color
39 , Eq color, Eq cls, Ord k
40 , Outputable k, Outputable cls, Outputable color)
41 => UniqFM (UniqSet color) -- ^ map of (node class -> set of colors available for this class).
42 -> Triv k cls color -- ^ fn to decide whether a node is trivially colorable.
43 -> (Graph k cls color -> k) -- ^ fn to choose a node to potentially leave uncolored if nothing is trivially colorable.
44 -> Graph k cls color -- ^ the graph to color.
46 -> ( Graph k cls color -- the colored graph.
47 , UniqSet k -- the set of nodes that we couldn't find a color for.
48 , UniqFM k ) -- map of regs (r1 -> r2) that were coaleced
49 -- r1 should be replaced by r2 in the source
51 colorGraph colors triv spill graph0
53 -- do aggressive coalesing on the graph
54 (graph_coalesced, rsCoalesce)
55 = coalesceGraph triv graph0
57 -- run the scanner to slurp out all the trivially colorable nodes
59 = colorScan colors triv spill [] emptyUniqSet graph_coalesced
61 -- color the trivially colorable nodes
62 (graph_triv, ksNoTriv)
63 = assignColors colors graph_coalesced ksTriv
65 -- try and color the problem nodes
66 (graph_prob, ksNoColor) = assignColors colors graph_triv (uniqSetToList ksProblems)
68 -- if the trivially colorable nodes didn't color then something is wrong
69 -- with the provided triv function.
70 in if not $ null ksNoTriv
71 then pprPanic "colorGraph: trivially colorable nodes didn't color!" empty
73 $$ text "ksTriv = " <> ppr ksTriv
74 $$ text "ksNoTriv = " <> ppr ksNoTriv
76 $$ dotGraph (\x -> text "white") triv graph1) -}
80 , listToUFM rsCoalesce)
82 colorScan colors triv spill safe prob graph
84 -- empty graphs are easy to color.
85 | isNullUFM $ graphMap graph
88 -- Try and find a trivially colorable node.
89 | Just node <- find (\node -> triv (nodeClass node)
91 (nodeExclusions node))
92 $ eltsUFM $ graphMap graph
94 = colorScan colors triv spill
95 (k : safe) prob (delNode k graph)
97 -- There was no trivially colorable node,
98 -- Choose one to potentially leave uncolored. We /might/ be able to find
99 -- a color for this later on, but no guarantees.
101 = colorScan colors triv spill
102 safe (addOneToUniqSet prob k) (delNode k graph)
105 -- | Try to assign a color to all these nodes.
108 :: ( Uniquable k, Uniquable cls, Uniquable color, Eq color )
109 => UniqFM (UniqSet color) -- ^ map of (node class -> set of colors available for this class).
110 -> Graph k cls color -- ^ the graph
111 -> [k] -- ^ nodes to assign a color to.
112 -> ( Graph k cls color -- the colored graph
113 , [k]) -- the nodes that didn't color.
115 assignColors colors graph ks
116 = assignColors' colors graph [] ks
118 where assignColors' _ graph prob []
121 assignColors' colors graph prob (k:ks)
122 = case assignColor colors k graph of
124 -- couldn't color this node
125 Nothing -> assignColors' colors graph (k : prob) ks
127 -- this node colored ok, so do the rest
128 Just graph' -> assignColors' colors graph' prob ks
131 assignColor colors u graph
132 | Just c <- selectColor colors graph u
133 = Just (setColor u c graph)
140 -- | Select a color for a certain node
141 -- taking into account preferences, neighbors and exclusions.
142 -- returns Nothing if no color can be assigned to this node.
144 -- TODO: avoid using the prefs of the neighbors, if at all possible.
147 :: ( Uniquable k, Uniquable cls, Uniquable color, Eq color)
148 => UniqFM (UniqSet color) -- ^ map of (node class -> set of colors available for this class).
149 -> Graph k cls color -- ^ the graph
150 -> k -- ^ key of the node to select a color for.
153 selectColor colors graph u
154 = let -- lookup the node
155 Just node = lookupNode graph u
157 -- lookup the available colors for the class of this node.
159 = lookupUFM colors (nodeClass node)
161 -- find colors we can't use because they're already being used
162 -- by a node that conflicts with this one.
165 $ map (lookupNode graph)
169 colors_conflict = mkUniqSet
171 $ map nodeColor nsConflicts
173 -- colors that are still ok
174 colors_ok_ex = minusUniqSet colors_avail (nodeExclusions node)
175 colors_ok = minusUniqSet colors_ok_ex colors_conflict
177 -- the colors that we prefer, and are still ok
178 colors_ok_pref = intersectUniqSets
179 (mkUniqSet $ nodePreference node) colors_ok
184 -- we got one of our preferences, score!
185 | not $ isEmptyUniqSet colors_ok_pref
186 , c : _ <- uniqSetToList colors_ok_pref
189 -- it wasn't a preference, but it was still ok
190 | not $ isEmptyUniqSet colors_ok
191 , c : _ <- uniqSetToList colors_ok
194 -- leave this node uncolored