简体   繁体   English

在无向图中查找所有非重叠环

[英]Finding all non overlapping cycles in an undirected graph

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:为了找到所有现有的循环,我制作了我在这里找到的算法的 Objective-C 版本:

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):上面的算法工作正常(即使它不是很有效)并且它从附图上的图表中找到所有可能的循环(请参见下图):

ABHGFDEA (valid) ABHGFDEA(有效)

BCIHB (valid) BCIHB(有效)

GHILKG (valid) GHILKG(有效)

FGKJF (valid) FGKJF(有效)

FGHILKJF (invalid) FGHILKJF(无效)

ABCIHGFDEA (invalid) ABCIHGFDEA(无效)

ABCILKJFDEA (invalid) ABCILKJFDEA(无效)

ABCIHG--KJFDEA (invalid) ABCIHG--KJFDEA(无效)

ABHILKGFDEA (invalid) ABHILKGFDEA(无效)

ABHGKJFDEA (invalid) ABHGKJFDEA(无效)

ABCILKGFDEA (invalid) ABCILKGFDEA(无效)

BCILKGHB (invalid) BCILKGHB(无效)

BCILKJFGHB (invalid) BCILKJFGHB(无效)

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?是否可以修改上述算法,使其仅找到不重叠的循环,否则在找到所有循环来过滤它们后我应该怎么做?

There isn't enough information just in the undirected graph itself to determine which cycles are which.仅在无向图中没有足够的信息来确定哪些循环是哪些。 For example, consider that the following 2 diagrams yield identical undirected graphs:例如,考虑以下 2 个图产生相同的无向图:

A-----B      E-------------F
|     |       \           /
C-----D        \ A-----B /
|     |         \|     |/
E-----F          C-----D

But for the diagram on the left, you want the cycles ABDCA and CDFEC, while for the diagram on the right, you want the cycles ABDCA and EFDBACE.但是对于左侧的图表,您需要循环 ABDCA 和 CDFEC,而对于右侧的图表,您需要循环 ABDCA 和 EFDBACE。 Thus the undirected graph inferred from the diagram isn't enough -- you need to somehow incorporate spatial information from the original diagram.因此,从图中推断出的无向图是不够的——您需要以某种方式合并来自原始图中的空间信息。

I'm working on this same problem and a lot of your comments were helpful, especially the comment that all edges will have an area on each side.我正在解决同样的问题,您的很多评论都很有帮助,尤其是所有边的每一侧都有一个区域的评论。 Thus you could say that each edge has a "left area" and a "right area".因此,您可以说每条边都有一个“左侧区域”和一个“右侧区域”。

You can add all graph edges to a queue in any order.您可以按任何顺序将所有图形边添加到队列中。 Peek at the first edge, pick its vertex closer to your origin.查看第一条边,选择靠近原点的顶点。 Move to the neighbor that is the most counter-clockwise.移动到最逆时针的邻居。 continue this until you have reached your starting vertex.继续这个直到你到达你的起始顶点。 All of these edges bound your first area.所有这些边都限定了您的第一个区域。 I would give it a unique ID and assign it to a "left area" property of those edges.我会给它一个唯一的 ID 并将它分配给这些边缘的“左区域”属性。

Peek at the first edge in the queue and check if it has a "left area".查看队列中的第一个边缘并检查它是否有“左侧区域”。 If it does check if it has a "right area" if it does not proceed in a clockwise manner and find the right area.如果它确实检查它是否有“正确区域”,如果它没有以顺时针方式进行并找到正确的区域。 If it has both areas assigned dequeue it and grab the next one.如果它分配了两个区域,则将其出列并获取下一个区域。

should be O(e+v) so pretty quick, right?应该是 O(e+v) 这么快,对吧?

This is a little bit stream of consciousness but I wanted to get it written down.这是一点点意识流,但我想把它写下来。 I'll be writing the algorithm for my actual app and I'll make tweaks as I find problems in it.我将为我的实际应用编写算法,并在发现问题时进行调整。

Of course I'm open to feedback and suggestions :)当然,我愿意接受反馈和建议:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM