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