我有一大组(> 1000)有向无环图,每组有一个大(> 1000)顶点。顶点被标记,标签的基数较小(<30)
我想识别(挖掘)在整个图集中经常出现的子结构。
我们正在寻找的输出是给定图中的子结构及其(数量)外观的列表。
我试图研究问题,并且(似乎总是伴随我发生)这个问题是NP完全的。据我所知,gSpan是解决此问题的最常用算法。但是,如上所述,我不是在图中寻找任何常见的子结构,而只是在遵循某些规则的结构中寻找。为了减少搜索空间,应该可以使用它。
对如何解决此问题有任何见解?
更新:我可能应该补充一点,上述规则可以在一定程度上递归。例如“标记为A的顶点,其中至少有两个子代为B,每个子代至少有一个子代为A”。最大递归深度在1到10之间。
更新II:指出我们不是在搜索已知或首选的子结构,而是对其进行挖掘。没有汤匙针。
最佳答案
我在回答中假设您正在尝试最小化运行时间,并且不想花费过多的时间编写代码来做到这一点。起初,我在学习编写高效算法时遇到的一件事是有时多次通过可能会更有效。在这种情况下,我要说的是,从根本上讲,您希望获得两遍:
首先,创建一个过滤器,使您可以忽略大多数(如果不是全部)非重复模式。为了做到这一点:
在第二遍时,您将需要执行“更重”的过程以实际确认匹配。为了做到这一点:
该算法将在大型数据集上非常快速地运行,因为它将大大减少适当缓存级别上的压力。您还可以进行一些增强,以使其在不同的情况下表现更好。
关于上述内容的一些注意事项:
无论如何,总结一下运行时复杂性,我会说这确实取决于。许多人忽略了以下事实:增加数据的工作集将导致内存访问的成本不均等。从根本上讲,上述算法虽然性能良好,但如果对其进行了适当的调整,将可以在较小的数据集上非常快速地运行,但是对于更大的数据集,它确实非常有用,因为它允许以高效的方式将工作数据集保持在任何缓存级别合适的方法(L1,L2,L3,RAM,本地磁盘,本地网络等)。算法的复杂性取决于数据,但是我不认为可以创建更快的算法。我确实省略了如何表示子图,并且在那里要做一些工作来实现最佳算法,但是在不了解更多信息的情况下,我无法确定存储该信息的最佳方法。
一种算法的运行速度不能比我所介绍的算法快得多的原因是,第一遍将比第二遍运行所需的工作少得多,因为它不需要分支,并且进行按位运算的工作也较少。因此,我们可以说,它对我们正在进行的总体工作没有多大作用。第二阶段也要尽可能地高效。您必须(用有限的位集合来完美地描述每种可能性的方法,我将在后面解释),然后实际比较每个图形特征并将信息写入某处。唯一的变量是检查您是否需要执行此操作的工作量。尽可能多地检查一下您可以将错误率缩放到0%的程度。
对于较小的数据集,两次通过对您有利的原因是,您可以在更少量的内存中拥有大量的布隆基数。但是,对于非常小的数据集,您最好只使用第二步,而忽略第一步。但是,至少,您需要为每个哈希目标存储一个指针。这意味着对于相同级别的过滤,您将需要写入32或64倍的数据。对于足够小的数据集,这无关紧要,因为读取是读取,写入是写入,但是对于较大的数据集,这可以允许您完成相同级别的过滤,同时保留给定的缓存级别。在必须跨多台计算机或多线程工作的情况下,此算法提供的机制将更加高效,因为可以更快地合并数据,并且可以交换有关潜在匹配的更多信息。
现在,最后,正如我提到的,如果进一步减少每次迭代中要检查的功能数量,则可能会稍微好一些。例如,如果您仅检查32个可能的标签以及每次通过中具有特定标签的子代的数量(且该标签的上限为1024),则可以用15位完美地表示。如果将计数限制为255,则可以使用32K完美存储此信息。为了实现这一点,您需要使用我上面提到的迭代,递归和分片策略,然后还需要跟踪源图和其他一些信息。老实说,我怀疑除非在非常有限的情况下,否则这种方法是否会奏效,但出于完整性考虑,我将其包括在内。
无论如何,这是我对Stack Overflow的第一个答案,所以不要对我太在意。我希望这可以帮到你!
关于algorithm - 大量图集中指导常见子结构的挖掘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41170348/