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