【问题标题】:Python implementation of a graph-similarity-grading algorithm图相似度分级算法的 Python 实现
【发布时间】:2012-08-20 18:18:35
【问题描述】:

我正在寻找执行以下任务的算法的 Python 实现:

给定两个可能包含循环及其根的有向图, 为两张图的相似度打分。

(Python的difflib可以对两个序列执行的方式)

希望这样的实现存在。否则,我会尝试自己实现一个算法。在这种情况下,最好的算法是什么(就简单性而言)。

算法的工作方式对我来说并不重要,尽管它的复杂性很重要。 此外,使用不同数据结构的算法也是可以接受的,只要我描述的图可以用这个 DS 表示。

我会强调,实现会更好。

编辑:
似乎同构算法不相关。有人建议图形编辑距离更重要,这将我的搜索范围缩小到执行图形编辑距离将图形减少为树然后执行树编辑距离的解决方案
节点本身由几行汇编代码组成。

【问题讨论】:

  • “相似性”对我来说似乎有点模糊。我不知道的有向图的相似性是否具有普遍意义?
  • 您查看过各种Python graph libraries 是否已经实现了某些功能?
  • @gnibbler 感谢您的回复。通过相似性,我的意思是:如果两个图的节点之间存在双射(同构),则图是相等的。如果它们的编辑距离很短,则图是相似的。如果图都具有最大公共子图,则图有点相似,依此类推。link
  • @YaronK 每两个非空图都有一个最大公共子图,当然除非它们被标记
  • @MartijnPieters 我已经考虑过 NetworkX 和 igraph。它们都允许检查同构,无论是否存在,尽管它们都不允许量化相似性。

标签: python algorithm graph


【解决方案1】:

另一种方法是使用所谓的特征向量相似度。基本上,您计算每个图的邻接矩阵的拉普拉斯特征值。对于每个图,找到最小的 k 个,使得 k 个最大特征值之和构成所有特征值之和的至少 90%。如果两个图之间 k 的值不同,则使用较小的那个。然后,相似性度量是图之间最大 k 个特征值之间的平方差之和。这将在 [0, ∞) 范围内生成相似度度量,其中接近零的值更相似。

例如,如果使用networkx

def select_k(spectrum, minimum_energy = 0.9):
    running_total = 0.0
    total = sum(spectrum)
    if total == 0.0:
        return len(spectrum)
    for i in range(len(spectrum)):
        running_total += spectrum[i]
        if running_total / total >= minimum_energy:
            return i + 1
    return len(spectrum)

laplacian1 = nx.spectrum.laplacian_spectrum(graph1)
laplacian2 = nx.spectrum.laplacian_spectrum(graph2)

k1 = select_k(laplacian1)
k2 = select_k(laplacian2)
k = min(k1, k2)

similarity = sum((laplacian1[:k] - laplacian2[:k])**2)

【讨论】:

  • 这看起来很有趣@ESultanik,你有这个方法的参考论文吗?谢谢!
  • @Rodolphe This is a student report,但它作为一个比较好的介绍/调查。
  • 你能想出一种方法来规范化这种相似性方法,以便它可以检测出近似子图吗?例如,如果 G1 有 100 个节点和 200 条边,而 G2 有 5 个节点和 7 条边,您需要通过节点和边数差异的函数来调整相似度阈值。
  • 另外,使用特征值的绝对值是否有意义?否则,负数将导致总数满足较小的 k。不确定这是否是我们想要的,因为一个大的负特征值意味着拉普拉斯函数的特征多项式的根会有很大的不同。
  • 是的,@ESultanik!!!感谢您提醒我您的实现是用 Python 实现的!你太棒了-谢谢!
【解决方案2】:

我们最终做的是实现一个算法:"Heuristics for Chemical Compound Matching"

我们使用 NetworkX 来表示抓地力和寻找最大集团。

编辑:

基本上,您创建一个新图,每个节点 (v) 代表图 A (a) 中的节点与图 B (b) 中的节点的可能配对

如果在您的应用程序中两个节点 (a,b) 相似或不相似,则从新图中删除对应于不同配对 (a,b) 的节点 (v)。 如果它们不相互矛盾,则将两个节点连接到一条边。 例如,配对 (a,b) 和 (a,c) 相互矛盾(有关正式定义,请参阅文章)。 然后,您会在新图中找到一个具有最大节点数的团。

如果在您的应用程序中两个节点的相似性不是二元的,您可以在一个范围内(例如 (0,1))赋予新节点的权重。 您可以启发式地删除相似度等级低于预定义阈值的新节点。 然后,您会在新图中找到一个具有最大权重(节点分配权重的总和)的集团。

无论哪种方式,您都会生成相似度等级:集团的大小/总权重除以原始图的属性的函数(A 和 B 的大小/权重的最大/最小/平均值) .

一个不错的功能是,您可以从找到的集团中推断出相似性的“来源”——“更强”的配对。

进一步说明: 约束取决于应用程序。我们使用该方法来比较成对的功能控制流图。通常,该方法找到第一个图中的某些节点与第二个图中的某些节点的匹配(子图到子图)。关联图中的每个节点表示来自第一个图中的单个节点与第二个图中的单个节点的可能匹配。由于最终选择了一个团(节点的子集),因此一条边意味着两个匹配项不相互矛盾。要申请不同的应用程序,您应该询问可能配对的标准是什么(或者我要创建哪些节点),以及选择一个配对如何影响另一个配对的选择(或者我如何将节点与边连接)。

【讨论】:

  • 太棒了,我正在寻找这样的算法。你愿意分享吗?
  • 我很难理解为什么 (a,b) 和 (a,c) 相互矛盾。为什么 a 不能与多个节点配对?我试图在 R 中转录上面的算法,但我陷入了矛盾的阶段。任何帮助@YaronK?这是一个粘贴箱:pastebin.com/ua5XrTG0
  • @areyoujokingme 如果 a 'a' 节点与 'b' 节点匹配,并且 'b' 与 'c' 是不同的节点,则 'a' 不能与 ' 匹配C'。一个节点只能与另一个图中的一个节点匹配。
  • 这是您的方法的先决条件,不是吗 - 因为它适用于化学结构?我实际上想将此算法用于蛋白质-蛋白质相互作用图,在这种情况下,当然允许蛋白质 A 与 B 和 C 相互作用,等等。这有意义吗?那么,对于 PPI,这个算法还有用吗?我不确定..
  • @areyoujokingme 我已经编辑了答案并试图参考您的问题。我希望这可以澄清事情。
【解决方案3】:

这是一个老问题,但我想分享我的方法。 我有一个 CVRP(Capacitated Vehicle Routing Problem)任务。我的启发式算法生成了几个不同的图表以找到解决方案。 为了不陷入局部最优,我使用了放松和修复程序。

此时,我必须过滤掉过于相似的解决方案。 由于大多数启发式方法在本地搜索过程中使用系统的邻域变化来提供解决方案,因此Edit 距离 (Levenshtein distance) 对我来说是完美的。 Levenshtein 算法的复杂度为 O(n*m),其中 n 和 m 是两个字符串的长度。因此,通过图形节点和路线的字符串表示,我能够找出相似性。 edit operations 可以被认为是neighborhood operations,因此它可以被认为是搜索空间距离(而不是解决方案空间距离)。

牺牲一些速度的更好/通用方法是Needleman-Wunsch 算法。 Needleman-Wunsch 是一种混合相似性度量,它概括了 Levenshtein 距离并考虑了两个字符串之间的全局对齐。具体来说,它是通过为两个输入字符串之间的每个对齐分配一个分数并选择最佳对齐的分数来计算的,即最大分数。两个字符串之间的对齐是它们字符之间的一组对应关系,允许有间隙。

例如:

import py_stringmatching as sm
nw = sm.NeedlemanWunsch(gap_cost=0.5, sim_func=lambda s1, s2: (0.0 if s1 == s2 else 1.0))
print('\nNeedleman-Wunsch: ', nw.get_raw_score('045601230', '062401530'))

在示例中,您可以使用自定义的 Levenshtein 算法。

Git 中存在 Levenshtein 的快速实现(使用 Cython、Numpy 等)。
py_stringmatching 是一个不错的库,其中包含以下相似性算法列表:

  • 仿射间隙
  • 袋子距离
  • 余弦
  • 骰子
  • Editex
  • 广义杰卡德
  • 汉明距离
  • 杰卡尔
  • 加罗
  • 雅罗·温克勒
  • 列文斯坦
  • 蒙格埃尔坎
  • Needleman Wunsch
  • 重叠系数
  • 部分比率
  • 部分令牌排序
  • 比率
  • 史密斯-沃特曼
  • 软 TF/IDF
  • Soundex
  • TF/IDF
  • 令牌排序
  • 特沃斯基索引

【讨论】:

  • 如果我们使用这种方法,我们首先要把图形变成一个字符串,对吧?像 [node1[node2, node3[node4, node5]]] ?
  • 是的正确,你需要有一个字符串表示
  • 好的,你知道有什么实现/库吗?
  • 发布一个包含详细信息的问题,我会尽力提供帮助
【解决方案4】:

我认为你定义相似度的方式不是很标准,所以可能更容易找到同构检查、图编辑距离和最大公共子图的实现,然后自己组合它们。

但是,人们应该明白,计算这样的相似性度量可能会很昂贵,因此如果有很多图表,您可能需要先进行某种筛选。

igraph 可以检查同构,例如。

编辑:实际上你可能只需要编辑距离,因为 MCS 的存在通常是无关紧要的,正如我在上面指出的那样,如果编辑距离为 0,两个图无论如何都是同构的.

【讨论】:

  • 感谢您的回复。图编辑距离或最大公共子图怎么样 - 你是否熟悉任何试图解决这些问题的 Python 算法实现(最好不昂贵)?
  • @YaronK 任何可用的 exact 图编辑距离算法都将是昂贵的,即非多项式,因为该问题至少与图同构 @ 987654322@。我不知道这种算法的任何实现,但有兴趣看看。
  • @YaronK 似乎文献还描述了许多有效的近似解决方案,它们适用于某些类型的图。你看的那些是从哪里来的?
  • 我所指的图表实际上是用图表表示的函数的控制流。
  • @YaronK 这意味着节点标有语句和/或函数名称,对吧?
猜你喜欢
  • 1970-01-01
  • 2011-09-17
  • 1970-01-01
  • 2018-03-09
  • 2021-06-29
  • 2013-03-18
  • 2011-02-28
  • 2011-08-13
相关资源
最近更新 更多