1 { Version 991025 experimental (minor changes 050625).
2 Adaptation for AGraph: Alexey A.Chernobaev }
3
4 unit CTrick;
5 (*
6 * The author of this software is Michael Trick. Copyright (c) 1994 by
7 * Michael Trick.
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose without fee is hereby granted, provided that this entire notice
11 * is included in all copies of any software which is or includes a copy
12 * or modification of this software and in all copies of the supporting
13 * documentation for such software.
14 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
15 * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR DOES NOT MAKE ANY
16 * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
17 * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
18 *)
19 (*
20 COLOR.C: Easy code for graph coloring
21 Author: Michael A. Trick, Carnegie Mellon University, trick+@cmu.edu
22 Last Modified: November 2, 1994
23
24 Code is probably insufficiently debugged, but may be useful to some people.
25
26 For more information on this code, see Anuj Mehrotra and Michael A. Trick,
27 "A column generation approach to graph coloring", GSIA Technical report series.
28 *)
29
30 interface
31
32 {$I VCheck.inc}
33
34 uses
35 ExtType, Aliasv, Int16g, Int16v, Aliasm, Int16m, Boolv, Boolm, Graphs,
36 VectErr, GraphErr;
37
ColorConnectedGraphnull38 function ColorConnectedGraph(G: TGraph; Colors: TGenericIntegerVector): Integer;
39
40 implementation
41
ColorConnectedGraphnull42 function ColorConnectedGraph(G: TGraph; Colors: TGenericIntegerVector): Integer;
43 var
44 BestColoring, NumNode, LowerBound, BestClique: Integer;
45 ColorClass, Order, ColorCount: TIntegerVector;
46 Handled: TBoolVector;
47 Adj: TBoolMatrix;
48 ColorAdj: TIntegerMatrix;
49
Greedy_Cliquenull50 function Greedy_Clique(Valid, Clique: TBoolVector): Integer;
51 var
52 I, J, K, Max, Place: Integer;
53 Done: Bool;
54 Order, Weight: TIntegerVector;
55 begin
56 Order:=TIntegerVector.Create(NumNode + 1, 0);
57 Weight:=nil;
58 try
59 Weight:=TIntegerVector.Create(NumNode, 0);
60 Clique.SetToDefault;
61 Place:=0;
62 for I:=0 to NumNode - 1 do
63 if Valid[I] then begin
64 Order[Place]:=I;
65 Inc(Place);
66 end;
67 for I:=0 to NumNode - 1 do
68 if Valid[I] then
69 for J:=0 to NumNode - 1 do
70 if Valid[J] and Adj[I, J] then
71 Weight.IncItem(I, 1);
72 repeat
73 Done:=True;
74 for I:=0 to Place - 2 do begin
75 J:=Order[I];
76 K:=Order[I + 1];
77 if Weight[J] < Weight[K] then begin
78 Order[I]:=K;
79 Order[I + 1]:=J;
80 Done:=False;
81 end;
82 end;
83 until Done;
84 Clique[Order[0]]:=True;
85 for I:=1 to Place - 1 do begin
86 J:=Order[I];
87 for K:=0 to I - 1 do
88 if Clique[Order[K]] and not Adj[J, Order[K]] then
89 Break;
90 Clique[J]:=K = I;
91 end;
92 Max:=0;
93 for I:=0 to Place - 1 do
94 if Clique[Order[I]] then Inc(Max);
95 finally
96 Order.Free;
97 Weight.Free;
98 end;
99 Result:=Max;
100 end; {Greedy_Clique}
101
Max_W_Cliquenull102 function Max_W_Clique(Valid, Clique: TBoolVector; Lower, Target: Integer): Integer;
103 (*
104 Target is a goal value: once a Clique is found with value Target
105 it is possible to return.
106
107 Lower is a bound representing an already found Clique: once it is
108 determined that no Clique exists with value better than Lower, it
109 is permitted to return with a suboptimal Clique.
110
111 Note, to find a Clique of value 1, it is not permitted to just set
112 the Lower to 1: the recursion will not work. Lower represents a
113 value that is the goal for the recursion.
114 *)
115 var
116 I, J, K, Incumb, NewWeight, Place, Place1, Start, Finish, TotalLeft: Integer;
117 Done: Bool;
118 Order, Value: TIntegerVector;
119 Valid1, Clique1: TBoolVector;
120 begin {Max_W_Clique}
121 { entered with 'Lower', 'Target' }
122 Clique.SetToDefault;
123 TotalLeft:=Valid.NumTrue;
124 if TotalLeft < Lower then begin
125 Result:=0;
126 Exit;
127 end;
128 Order:=TIntegerVector.Create(NumNode + 1, 0);
129 try
130 Value:=TIntegerVector.Create(NumNode, 0);
131 try
132 Incumb:=Greedy_Clique(Valid, Clique);
133 if Incumb >= Target then begin
134 Result:=Incumb;
135 Exit;
136 end;
137 if Incumb > BestClique then { Clique of size 'Incumb' found }
138 BestClique:=Incumb;
139 { greedy gave 'Incumb' }
140 Place:=0;
141 for I:=0 to NumNode - 1 do begin
142 if Clique[I] then begin
143 Order[Place]:=I;
144 Dec(TotalLeft);
145 Inc(Place);
146 end;
147 end;
148 Start:=Place;
149 for I:=0 to NumNode - 1 do begin
150 if not Clique[I] and Valid[I] then begin
151 Order[Place]:=I;
152 Inc(Place);
153 end;
154 end;
155 Finish:=Place;
156 for Place:=Start to Finish - 1 do begin
157 I:=Order[Place];
158 Value[I]:=0;
159 for J:=0 to NumNode - 1 do
160 if Valid[J] and Adj[I, J] then
161 Value.IncItem(I, 1);
162 end;
163 repeat
164 Done:=True;
165 for Place:=Start to Finish - 2 do begin
166 I:=Order[Place];
167 J:=Order[Place + 1];
168 if Value[I] < Value[J] then begin
169 Order[Place]:=J;
170 Order[Place + 1]:=I;
171 Done:=False;
172 end;
173 end;
174 until Done;
175 finally
176 Value.Free;
177 end;
178 Valid1:=TBoolVector.Create(NumNode, False);
179 Clique1:=nil;
180 try
181 Clique1:=TBoolVector.Create(NumNode, False);
182 for Place:=Start to Finish - 1 do begin
183 if Incumb + TotalLeft < Lower then begin
184 Result:=0;
185 Exit;
186 end;
187 J:=Order[Place];
188 Dec(TotalLeft);
189 if not Clique[J] then begin
190 Valid1.SetToDefault;
191 Place1:=0;
192 while Place1 < Place do begin
193 K:=Order[Place1];
194 Valid1[K]:=Valid[K] and Adj[J, K];
195 Inc(Place1);
196 end;
197 NewWeight:=Max_W_Clique(Valid1, Clique1, Incumb - 1, Target - 1);
198 if NewWeight + 1 > Incumb then begin { taking new }
199 Incumb:=NewWeight + 1;
200 Clique.Assign(Clique1);
201 Clique[J]:=True;
202 if Incumb > BestClique then { Clique of size 'Incumb' found }
203 BestClique:=Incumb;
204 end;
205 { taking 'Incumb' }
206 if Incumb >=Target then
207 Break;
208 end;
209 end; {for}
210 finally
211 Valid1.Free;
212 Clique1.Free;
213 end;
214 finally
215 Order.Free;
216 end;
217 Result:=Incumb;
218 end; {Max_W_Clique}
219
220 procedure AssignColor(Node, Color: Integer);
221 { 'Node' Color + 'Color' }
222 var
223 Node1: Integer;
224 begin
225 ColorClass[Node]:=Color;
226 for Node1:=0 to NumNode - 1 do
227 if (Node <> Node1) and Adj[Node, Node1] then begin
228 if ColorAdj[Node1, Color] = 0 then ColorCount.IncItem(Node1, 1);
229 ColorAdj.IncItem(Node1, Color, 1);
230 ColorAdj.DecItem(Node1, 0, 1);
231 {$IFDEF CHECK_GRAPHS}
232 if ColorAdj[Node1, 0] < 0 then
233 TGraph.Error(SAlgorithmFailure)
234 {$ENDIF};
235 end;
236 end; {AssignColor}
237
238 procedure RemoveColor(Node, Color: Integer);
239 { 'Node' Color - 'Color' }
240 var
241 Node1: Integer;
242 begin
243 ColorClass[Node]:=0;
244 for Node1:=0 to NumNode - 1 do
245 if (Node <> Node1) and Adj[Node, Node1] then begin
246 if ColorAdj.DecItem(Node1, Color, 1) = 0 then
247 ColorCount.DecItem(Node1, 1);
248 {$IFDEF CHECK_GRAPHS}
249 if ColorAdj[Node1, Color] < 0 then
250 TGraph.Error(SAlgorithmFailure)
251 {$ENDIF};
252 ColorAdj.IncItem(Node1, 0, 1);
253 end;
254 end; {RemoveColor}
255
Colornull256 function Color(I, CurrentColor: Integer): Integer;
257 var
258 J, Max, Place, NewVal: Integer;
259 begin
260 if CurrentColor >= BestColoring then begin
261 Result:=CurrentColor;
262 Exit;
263 end;
264 if BestColoring <= LowerBound then begin
265 Result:=BestColoring;
266 Exit;
267 end;
268 if I >= NumNode then begin
269 Result:=CurrentColor;
270 Exit;
271 end;
272 { Node 'I' color 'CurrentColor' }
273 { find Node with maximum ColorAdj }
274 Max:=-1;
275 Place:=-1;
276 for J:=0 to NumNode - 1 do
277 if not Handled[J] then begin
278 if (ColorCount[J] > Max) or
279 (ColorCount[J] = Max) and (ColorAdj[J, 0] > ColorAdj[Place, 0]) then
280 begin { best now at 'J' }
281 Max:=ColorCount[J];
282 Place:=J;
283 end;
284 end;
285 Order[I]:=Place;
286 Handled[Place]:=True;
287 { using Node 'Place' at level 'I' }
288 for J:=1 to CurrentColor do begin
289 if ColorAdj[Place, J] = 0 then begin
290 ColorClass[Place]:=J;
291 AssignColor(Place, J);
292 NewVal:=Color(I + 1, CurrentColor);
293 if NewVal < BestColoring then begin
294 BestColoring:=NewVal;
295 if Colors <> nil then Colors.Assign(ColorClass);
296 end;
297 RemoveColor(Place, J);
298 if BestColoring <= CurrentColor then begin
299 Handled[Place]:=False;
300 Result:=BestColoring;
301 Exit;
302 end;
303 end;
304 end;
305 if CurrentColor + 1 < BestColoring then begin
306 ColorClass[Place]:=CurrentColor + 1;
307 AssignColor(Place, CurrentColor + 1);
308 NewVal:=Color(I + 1, CurrentColor + 1);
309 if NewVal < BestColoring then begin
310 BestColoring:=NewVal;
311 if Colors <> nil then Colors.Assign(ColorClass);
312 end;
313 RemoveColor(Place, CurrentColor + 1);
314 end;
315 Handled[Place]:=False;
316 Result:=BestColoring;
317 end; {Color}
318
319 var
320 I, J, Place: Integer;
321 Valid, Clique: TBoolVector;
322 begin { ColorConnectedGraph }
323 {$IFDEF CHECK_GRAPHS}
324 if (Directed in G.Features) or not G.Connected then
325 TGraph.Error(SErrorInParameters);
326 {$ENDIF}
327 BestColoring:=0;
328 NumNode:=G.VertexCount;
329 LowerBound:=0;
330 BestClique:=0;
331 Adj:=G.CreateConnectionMatrix;
332 ColorAdj:=nil;
333 ColorClass:=nil;
334 Order:=nil;
335 ColorCount:=nil;
336 Handled:=nil;
337 try
338 ColorAdj:=TIntegerMatrix.Create(NumNode, NumNode + 1, 0);
339 ColorClass:=TIntegerVector.Create(NumNode, 0);
340 Order:=TIntegerVector.Create(NumNode, 0);
341 ColorCount:=TIntegerVector.Create(NumNode, 0);
342 Handled:=TBoolVector.Create(NumNode, False);
343 for I:=0 to NumNode - 1 do
344 for J:=0 to NumNode - 1 do
345 if Adj[I, J] then ColorAdj.IncItem(I, 0, 1);
346 BestColoring:=NumNode + 1;
347 Valid:=TBoolVector.Create(NumNode, True);
348 Clique:=nil;
349 try
350 Clique:=TBoolVector.Create(NumNode, False);
351 BestClique:=0;
352 LowerBound:=Max_W_Clique(Valid, Clique, 0, NumNode);
353 Place:=0;
354 for I:=0 to NumNode - 1 do
355 if Clique[I] then begin
356 Order[Place]:=I;
357 Handled[I]:=True;
358 Inc(Place);
359 AssignColor(I, Place);
360 end;
361 finally
362 Valid.Free;
363 Clique.Free;
364 end;
365 if Colors <> nil then Colors.Assign(ColorClass); { for trivial graph }
366 Result:=Color(Place, Place);
367 if Colors <> nil then Colors.SubScalar(1);
368 finally
369 Adj.Free;
370 ColorAdj.Free;
371 ColorClass.Free;
372 Order.Free;
373 ColorCount.Free;
374 Handled.Free;
375 end;
376 end; { ColorConnectedGraph }
377
378 end.
379