【发布时间】:2023-05-24 15:12:01
【问题描述】:
我需要计算树之间的编辑距离。 This 论文描述了一种算法,但我无法从中得出正面或反面。你能用更平易近人的方式描述一个适用的算法吗?伪代码或代码都会有所帮助。
【问题讨论】:
我需要计算树之间的编辑距离。 This 论文描述了一种算法,但我无法从中得出正面或反面。你能用更平易近人的方式描述一个适用的算法吗?伪代码或代码都会有所帮助。
【问题讨论】:
这个 Python 库正确地实现了张莎莎算法:Zhang-Shasha: Tree edit distance in Python
它最初是当前接受的答案(带有 tarball 链接的那个)中列出的 Java 源代码的直接端口,但该实现不正确并且几乎不可能运行。
【讨论】:
这里有一些 Java source code(底部的 gzip 压缩包)用于 树编辑距离 算法,可能对您有用。
该页面包含参考资料和一些幻灯片,逐步完成“张和莎莎”算法以及其他有用的链接,以帮助您快速了解。
链接中的代码有错误。 Steve Johnson 和 tim.tadh 提供了working Python code。详情请见Steve Johnson's comment。
【讨论】:
我基于现有 PyGram Python 代码 (https://github.com/Sycondaman/PyGram) 为希望在浏览器和/或 Node.js 中使用 PQ-Gram 算法使用树编辑距离近似的人编写了一个实现 (https://github.com/hoonto/jqgram.git)。 js.
jqgram树编辑距离近似模块实现了服务器端和浏览器端应用的PQ-Gram算法; O(n log n) 时间和 O(n) 空间性能,其中 n 是节点数。算法出处见学术论文:http://www.vldb2005.org/program/paper/wed/p301-augsten.pdf
PQ-Gram 近似比通过 Zhang & Shasha、Klein 或 Guha 等获得真实编辑距离要快得多。 al,他们提供了真正的编辑距离算法,这些算法都执行最小 O(n^2) 时间,因此通常不适合。
通常在实际应用中,如果可以获得多个树与已知标准的相对近似值,则无需知道真实的编辑距离。随着 Node.js 的出现,浏览器和服务器上的 JavaScript 经常处理树结构,最终用户性能通常在算法实现和设计中至关重要;因此 jqgram。
例子:
var jq = require("jqgram").jqgram;
var root1 = {
"thelabel": "a",
"thekids": [
{ "thelabel": "b",
"thekids": [
{ "thelabel": "c" },
{ "thelabel": "d" }
]},
{ "thelabel": "e" },
{ "thelabel": "f" }
]
}
var root2 = {
"name": "a",
"kiddos": [
{ "name": "b",
"kiddos": [
{ "name": "c" },
{ "name": "d" },
{ "name": "y" }
]},
{ "name": "e" },
{ "name": "x" }
]
}
jq.distance({
root: root1,
lfn: function(node){ return node.thelabel; },
cfn: function(node){ return node.thekids; }
},{
root: root2,
lfn: function(node){ return node.name; },
cfn: function(node){ return node.kiddos; }
},{ p:2, q:3, depth:10 },
function(result) {
console.log(result.distance);
});
请注意,lfn 和 cfn 参数指定每棵树应如何独立确定每个树根的节点标签名称和子数组,以便您可以做一些时髦的事情,例如将对象与浏览器 DOM 进行比较。您需要做的就是提供这些函数以及每个根,而 jqgram 将完成其余的工作,调用您提供的 lfn 和 cfn 函数来构建树。所以从这个意义上说,它(无论如何在我看来)比 PyGram 更容易使用。另外,它是 JavaScript,所以在客户端或服务器端使用它!
现在您可以使用的一种方法是使用 jqgram 或 PyGram 来获取一些靠近的树,然后继续使用真正的编辑距离算法来处理较小的树集。为什么要把所有的计算都花在你已经很容易确定距离很远的树上,反之亦然?所以你也可以使用 jqgram 来缩小选择范围。
【讨论】:
在这里您可以找到树编辑距离算法的 Java 实现:
除了 Zhang&Shasha 1989 的算法之外,还有更新的算法的树编辑距离实现,包括 Klein 1998、Demaine 等。 2009 年,以及 Pawlik&Augsten 的稳健树编辑距离 (RTED) 算法,2011 年。
【讨论】:
我使用 jpype 为 APTED 算法制作了一个简单的 Python 包装器 (apted.py):
# To use, create a folder named lib next to apted.py, then put APTED.jar into it
import os, os.path, jpype
global distancePackage
distancePackage = None
global utilPackage
utilPackage = None
def StartJVM():
# from http://www.gossamer-threads.com/lists/python/python/379020
root = os.path.abspath(os.path.dirname(__file__))
jpype.startJVM(jpype.getDefaultJVMPath(),
"-Djava.ext.dirs=%s%slib" % (root, os.sep))
global distancePackage
distancePackage = jpype.JPackage("distance")
global utilPackage
utilPackage = jpype.JPackage("util")
def StopJVM():
jpype.shutdownJVM()
class APTED:
def __init__(self, delCost, insCost, matchCost):
global distancePackage
if distancePackage is None:
raise Exception("Need to call apted.StartJVM() first")
self.myApted = distancePackage.APTED(float(delCost), float(insCost), float(matchCost))
def nonNormalizedTreeDist(self, lblTreeA, lblTreeB):
return self.myApted.nonNormalizedTreeDist(lblTreeA.myLblTree, lblTreeB.myLblTree)
class LblTree:
def __init__(self, treeString):
global utilPackage
if utilPackage is None:
raise Exception("Need to call apted.StartJVM() first")
self.myLblTree = utilPackage.LblTree.fromString(treeString)
'''
# Example usage:
import apted
apted.StartJVM()
aptedDist = apted.APTED(delCost=1, insCost=1, matchCost=1)
treeA = apted.LblTree('{a}')
treeB = apted.LblTree('{b{c}}')
dist = aptedDist.nonNormalizedTreeDist(treeA, treeB)
print dist
# When you are done using apted
apted.StopJVM()
# For some reason it doesn't usually let me start it again
# and crashes the Python interpreter upon exit when I do
# this, so call only as needed.
'''
【讨论】:
树编辑距离有很多变化。如果您可以使用自上而下的树编辑距离,这限制了对叶子的插入和删除,我建议您尝试以下论文:Comparing Hierarchical Data in External Memory。
实现是一个简单的动态规划矩阵,成本为 O(n2)。
【讨论】:
您参考了 ICALP2007 论文的期刊版本,An Optimal Decomposition Algorithm for Tree Edit Distance。
这个版本也有伪代码。
【讨论】: