1 //
2 // Graph.m
3 // UltraGraph 10000
4 //
5 // Created by Jamie Griffin on Mon Mar 01 2004.
6 // Copyright (c) 2004 __MyCompanyName__. All rights reserved.
7 //
8 //Version 1.0b6
9
10 #import "Graph.h"
11
12
13 @implementation Graph
14
15
16 #pragma mark *** init / copy methods ***
17
18 //create an empty graph
19 -(id)init
20 {
21 if (self =[super init])
22 {
23 verticies = [[NSMutableArray alloc] init];
24 threeColorings = [[NSMutableArray alloc] init];
25 //NSLog(@"New Graph made, size = %d",[verticies count]);
26 }
27 return self;
28 }
29
30 //makes a new graph from another, either copying or not
31 //skips the threeColorings array
32 -(id)initWithGraphNoColors:(Graph *)graph copyItems:(BOOL)copy;
33 {
34 if (self =[super init]);
35 {
36 NSLog(@"no color init");
37 verticies = [[NSMutableArray alloc]initWithArray:[graph graphAsArray] copyItems:copy];
38 threeColorings = [[NSMutableArray alloc] init];
39 }
40 return self;
41 }
42
43 //makes a new graph from another, either copying or not
44 -(id)initWithGraph:(Graph *)graph copyItems:(BOOL)copy
45 {
46 if (self =[super init]);
47 {
48 verticies = [[NSMutableArray alloc]initWithArray:[graph graphAsArray] copyItems:copy];
49 NSMutableArray *tempColorings = [[NSMutableArray alloc]initWithArray:[graph threeColorings] copyItems:copy];
50 threeColorings = tempColorings;
51 if (copy)
52 {
53 NSLog(@"New Graph with Graph(init call, COPY), size = %d",[verticies count]);
54 if ([threeColorings count]>0)
55 {
56 int i;
57 for (i=0; i<[threeColorings count]; i++)
58 NSLog([[threeColorings objectAtIndex:i] graphAsString]);
59 }
60 }
61 }
62 return self;
63 }
64
65 //class method to copy a graph
66 +(Graph *)graphWithGraph:(Graph *)graph copyItems:(BOOL)copy
67 {
68 Graph *duplicate = [[Graph alloc] initWithGraph:graph copyItems:copy];
69 //NSLog(@"New Graph with Graph(class call), size = %d",[[duplicate graphAsArray]count]);
70 return duplicate;
71 }
72
73 //the init method for loading from file
74 -(id)initWithCoder:(NSCoder *)coder
75 {
76 if (self =[super init])
77 {
78 verticies = [[NSMutableArray alloc] init];
79 verticies = [coder decodeObject];
80 threeColorings = [[NSMutableArray alloc] init];
81 threeColorings = [coder decodeObject];
82 //NSLog(@"New Graph from archiver");
83 }
84 //NSLog([self graphAsString]);
85 return self;
86 }
87
88
89
90 +(Graph *)loadGraphFromTextFile:(NSString *)file
91 {
92 int i;
93 Graph *thisGraph = [[Graph alloc] init];
94
95 NSString *graphAsString = [[NSString alloc] initWithContentsOfFile:file];
96 //NSLog(graphAsString);
97
98 //separate the vertices
99 NSArray *stringVertices = [graphAsString componentsSeparatedByString:@";"];
100 //NSLog(@"There are %d vertices", [stringVertices count]);
101
102 //parse each vertex
103 for (i=0; i<[stringVertices count]; i++)
104 {
105 Vertex *thisVertex = [[Vertex alloc] initWithString:[stringVertices objectAtIndex:i]];
106 [thisGraph addVertex:thisVertex withCopy:FALSE];
107
108 }
109 return thisGraph;
110
111 }
112
113 //for NSCopying
114 //ignoring the zone for now
115 -(id)copyWithZone:(NSZone *)zone
116 {
117 return [Graph graphWithGraph:self copyItems:FALSE];
118 }
119
120 #pragma mark ***accessor methods***
121
122 -(NSMutableArray *)graphAsArray
123 {
124 return verticies;
125 }
126
127 -(unsigned)count
128 {
129 return [verticies count];
130 }
131
132 -(NSMutableArray *)threeColorings
133 {
134 return threeColorings;
135 }
136
137 //gets the vertex with the given number
138 //we cannot simply look at the array order since vertices
139 //are not necessarily in order
140
141 //there is no need to sort the vertices so this O(n) time loop is fine
142
143 //post: returns nil if the number was not found
144 -(id)vertexWithNumber:(int)thisNumber
145 {
146 int i;
147 for (i=0; i<[verticies count]; i++)
148 {
149 if ([[verticies objectAtIndex:i] number]==thisNumber)
150 {
151 return [verticies objectAtIndex:i];
152
153 }
154 }
155
156 return nil;
157 }
158
159 -(Vertex *)vertexWithPosition:(int)thisPosition
160 {
161 return [verticies objectAtIndex:thisPosition];
162 }
163
164 //returns the graph as a string
165 //including the 3-colorings
166 -(NSString *)graphAsString
167 {
168 int i;
169 NSMutableString *stringToBuild = [[NSMutableString alloc] init];
170
171 //first, the graph uncolored
172 for (i=0; i<[verticies count]-1; i++)
173 {
174 [stringToBuild appendString:[[verticies objectAtIndex:i] stringVertex]];
175 [stringToBuild appendString:@";"];
176 }
177 [stringToBuild appendString:[[verticies objectAtIndex:[verticies count]-1] stringVertex]];
178
179 [stringToBuild appendString:@"------"];
180
181 int j;
182
183 //now the 3-colorings
184 for (j=0; j<[threeColorings count]; j++)
185 {
186 NSArray *thisColoringArray = [[threeColorings objectAtIndex:j] graphAsArray];
187 [stringToBuild appendString:@"**"];
188 int k;
189 for (k=0; k<[thisColoringArray count]-1; k++)
190 {
191 [stringToBuild appendString:[[thisColoringArray objectAtIndex:k] stringVertex]];
192 [stringToBuild appendString:@";"];
193 }
194
195 //simply to avoid a trailing ";"
196 if ([thisColoringArray count]>0)
197 {
198 [stringToBuild appendString:[[thisColoringArray objectAtIndex:[thisColoringArray count]-1] stringVertex]];
199 }
200
201 }
202 //NSLog(stringToBuild);
203 return stringToBuild;
204 }
205
206
207 #pragma mark ***mutator methods***
208
209
210 //add a vertex, either copy it or not
211 -(void)addVertex:(Vertex *)thisVertex withCopy:(BOOL)copy
212 {
213 if (copy)
214 {
215 [verticies addObject:[Vertex vertexWithVertex:thisVertex]];
216 }
217 else
218 {
219 [verticies addObject:thisVertex];
220 }
221 }
222
223 //breaks the graph into subgraphs
224
225 /*
226 At this point the breakdown is random (actually not so random, most graphs
227 come in nearly in order so the breakdown is often based on number)
228
229 This is where the Separator Theorem will be used to make the breakdown
230 along the lines of least connectivity for quicker recombination later
231 */
232
233 //all copies, the original is not affected and may be deleted
234 //without adversely affecting the subgraphs
235 -(NSArray *)breakGraphInParts:(int)numParts
236 {
237 int h,i;
238 NSMutableArray *graphs = [[NSMutableArray alloc] init];
239
240 for (h=0; h<numParts; h++)
241 {
242 [graphs addObject:[[Graph alloc]init]];
243 }
244 for (i=0; i<[verticies count];i++)
245 {
246 //integer division is ideal here
247 [[graphs objectAtIndex:i%numParts] addVertex:[verticies objectAtIndex:i] withCopy:FALSE];
248 }
249 return graphs;
250 }
251
252 //combines the current graph with otherGraph and stores the resulting graph
253 //in the current object
254 -(void)combineThisWithGraph:(Graph *)otherGraph
255 {
256 NSArray *theseColorings = [self threeColorings];
257 NSArray *otherColorings = [otherGraph threeColorings];
258 NSMutableArray *tempColorings = [[NSMutableArray alloc] init];
259 int numThese=[theseColorings count];
260 int numOthers=[otherColorings count];
261 int i,j,k,m;
262
263 for (i=0; i<numThese; i++)
264 {
265 Graph *workingGraph = [[Graph alloc] initWithGraph:[theseColorings objectAtIndex:i]copyItems:FALSE];
266 NSLog(@"Working Graph:");
267 NSLog([workingGraph graphAsString]);
268
269 for (j=0; j<numOthers; j++)
270 {
271 //for every vertex in otherGraph
272 Graph *thisOtherGraph = [[Graph alloc] initWithGraph:[otherColorings objectAtIndex:j]copyItems:FALSE];
273 NSLog(@"Other Graph:");
274 NSLog([otherGraph graphAsString]);
275
276 for (k=0; k<[thisOtherGraph count]; k++)
277 {
278 NSLog(@"adding a vertex");
279 [workingGraph addVertex:[thisOtherGraph vertexWithNumber:k]withCopy:TRUE];
280 }
281 if ([workingGraph isThisGraphProperlyThreeColored])
282 {
283 [tempColorings addObject:workingGraph];
284 }
285 }
286 [workingGraph release];
287
288 }
289
290 //fix the current graph to represent changes
291 [threeColorings release];
292 threeColorings=tempColorings;
293 for (m=0; m<[otherGraph count]; m++)
294 {
295 [verticies addObject:[otherGraph vertexWithPosition:m]];
296 }
297
298 }
299
300 //this method looks at this graph and determines if it is properly three colored
301 -(BOOL)isThisGraphProperlyThreeColored
302 {
303 int vertex, i, thisConnection;
304 Vertex *thisVertex;
305 //for every vertex
306 for (vertex=0; vertex<[verticies count]; vertex++)
307 {
308 thisVertex=[self vertexWithNumber:vertex];
309 //NSLog(@"Now looking at: %d,%d %d",[thisVertex number],vertex,[verticies count]);
310 //NSLog([thisVertex stringVertex]);
311
312 //for every connection on that vertex
313 for(i=0;i<[thisVertex numConnections];i++)
314 {
315 thisConnection = [[[thisVertex connections] objectAtIndex:i] intValue];
316 //NSLog(@"%d",thisConnection);
317
318 //see if a connection has the same color as this vertex
319 if ([[self vertexWithNumber:thisConnection] getColor]==[thisVertex getColor])
320 {
321 //NSLog(@"Not a 3-coloring");
322 return FALSE;
323 }
324 }
325 }
326 //we didn't find any problems, so it must work
327 NSLog(@"YES!!!");
328 // [connectionInput setStringValue:[self stringColors:thisGraph]];
329 return TRUE;
330 }
331
332
333 //this method should be used from outside to generate the 3-colorings
334 -(NSMutableArray *)getThreeColorings
335 {
336 NSLog(@"Emtying the threeColorings");
337 [threeColorings removeAllObjects];
338 [self recursiveCheck:self];
339 return threeColorings;
340 }
341
342
343 //this is the recursive function that finds the 3-colorings
344
345 /*
346 This method generates all possible colorings, even stupid ones such as all the
347 same color. This was done by choice since I am looking for a general case solution.
348 We could look for K(4) or K(2,3) configurations but this would save negligible time
349 and does not help to generalize the solution.
350 */
351
352 -(void)recursiveCheck:(Graph *)remainingVerticies
353 {
354 //NSLog(@"Recursive call");
355 //NSLog([self graphAsString]);
356
357 int i,color;
358
359 //termination of this branch
360 if ([[remainingVerticies graphAsArray] count]==1)
361 {
362 for (i=0;i<3;i++)
363 {
364
365 [[[remainingVerticies graphAsArray] objectAtIndex:0] setThisColor:i];
366 if([self isThisGraphProperlyThreeColored])
367 {
368 //we have found a 3-coloring so make a copy and add it to the list
369 NSLog(@"recursive init");
370 [threeColorings addObject:[[Graph alloc] initWithGraphNoColors:self copyItems:TRUE]];
371 }
372 }
373 }
374 else
375 {
376
377 /* this is a bit messy:
378 It changes the color of the actual verticies array then checks each of
379 the end branches for proper 3-coloring. no copys are made during
380 this phase EVER, the whole graph is copied only if it is
381 a 3-coloring
382 */
383 for (color=0;color<3;color++)
384 {
385 //NSLog(@"Mid vertex check");
386
387 [[[remainingVerticies graphAsArray] objectAtIndex:0] setThisColor:color];
388 Graph *tempGraph = [Graph graphWithGraph:remainingVerticies copyItems:FALSE];
389 [[tempGraph graphAsArray] removeObjectAtIndex:0];
390 //the recursive call
391 [self recursiveCheck:tempGraph];
392 }
393 }
394 }
395
396
397
398
399 #pragma mark **encoding method***
400
401 //encoder method for saving
402 -(void)encodeWithCoder:(NSCoder *)coder
403 {
404 [coder encodeObject:verticies];
405 [coder encodeObject:threeColorings];
406 }
407 @end
syntax highlighted by Code2HTML, v. 0.9.1