I need to find all simple non overlapping cycles on undirected graph. To find all existing cycles I made an Objective-C version of the algorithm that I found here:
Finding all cycles in undirected graphs
@interface HSValue : NSObject
@property (nonatomic, assign) CGPoint point;
@end
@implementation HSValue
@end
@interface CyclesFinder ()
@property (nonatomic, strong) NSMutableArray <NSArray<HSValue *>*> *cycles;
@property (nonatomic, strong) NSArray <NSArray<HSValue*>*> *edges;
@end
@implementation CyclesFinder
-(void)findCyclesInGraph:(NSArray <NSArray<HSValue*>*> *)edges {
self.edges = edges;
for (NSInteger i=0; i < self.edges.count; i++) {
for (NSInteger j=0; j < self.edges[i].count; j++) {
[self findNewCycles:@[self.edges[i][j]]];
}
}
}
-(void)findNewCycles:(NSArray <HSValue *> *)path {
HSValue *startNode = path[0];
HSValue *nextNode;
NSArray <HSValue *> *sub;
for (NSInteger i=0; i < self.edges.count; i++) {
NSArray <HSValue *> *edge = self.edges[i];
if ([edge containsObject:startNode]) {
if ([edge[0] isEqual:startNode]) {
nextNode = edge[1];
}
else {
nextNode = edge[0];
}
}
else {
nextNode = nil;
}
if (![path containsObject:nextNode] && nextNode) {
sub = @[nextNode];
sub = [sub arrayByAddingObjectsFromArray:path];
[self findNewCycles:sub];
}
else if (path.count > 2 && [nextNode isEqual:path.lastObject]) {
if (![self cycleExist:path]) {
[self.cycles addObject:path];
break;
}
}
}
}
-(BOOL)cycleExist:(NSArray <HSValue*> *)path {
path = [path sortedArrayUsingSelector:@selector(compare:)];
for (NSInteger i=0; i < self.cycles.count; i++) {
NSArray <HSValue *> *cycle = [self.cycles[i] sortedArrayUsingSelector:@selector(compare:)];
if ([cycle isEqualToArray:path]) {
return TRUE;
}
}
return FALSE;
}
Above algorithm works fine (even if it is not very efficient) and it finds all the possible cycles from the graph on the attached picture (please see picture below):
A-B-H-G-F-D-E-A (valid)
B-C-I-H-B (valid)
G-H-I-L-K-G (valid)
F-G-K-J-F (valid)
F-G-H-I-L-K-J-F (invalid)
A-B-C-I-H-G-F-D-E-A (invalid)
A-B-C-I-L-K-J-F-D-E-A (invalid)
A-B-C-I-H-G--K-J-F-D-E-A (invalid)
A-B-H-I-L-K-G-F-D-E-A (invalid)
A-B-H-G-K-J-F-D-E-A (invalid)
A-B-C-I-L-K-G-F-D-E-A (invalid)
B-C-I-L-K-G-H-B (invalid)
B-C-I-L-K-J-F-G-H-B (invalid)
However when I run the above algorithm I want to end up with only those cycles that I highlighted with coloured polygons on the left hand side example. What I don't want are the cycles like the one on the right hand side example.
My first thought was that overlapping cycle will be a cycle that includes all the points from any other cycles, but this is not always true. Can someone point me into the right direction? Is it possible to modify the above algorithm so it finds only non-overlapping cycles or if not what should I do after finding all cycles to filter them?