根据Prolog中公共子树的数量,树之间的递归相似度

Posted

技术标签:

【中文标题】根据Prolog中公共子树的数量,树之间的递归相似度【英文标题】:Recursive similarity between trees according to the number of common subtrees in Prolog 【发布时间】:2013-05-05 16:29:35 【问题描述】:

我正在使用 SWI Prolog 研究 Prolog,我发现这个代码 sn-p 有很多困难,它发现 2 个二叉树是否有 N 个公共子树(具有相同的根):

/* BASE CASE: T1 and T2 are two tree composed of only the root X so it is
             TRUE that they have exactly one common subtree
*/
delta(tree(X,[]),tree(X,[]),1):- !.

/* RULE: T1 and T2 are DIFFERENT and are structured tree.
         It is TRUE that T1 and T2 have N subtrees if it is TRUE that:
*/
delta(tree(X,RX),tree(X,RX1),N):- sons(RX,SX), 
                                  sons(RX1,SX)
                              subdelta(RX,RX1,N), 
                                  !.
/* Else whatever T1 and T2 it is true that they have 0 common tree
   (here we are in the case that the previous delta\2 predicate are 
   boot failed) 
*/
delta(_,_,0):- !.

subdelta([],[],1).

subdelta([T1|R1],[T2|R2], N):-
    delta(T1,T2,N1),
    subdelta(R1,R2, NR),
    N is (1 + N1)*NR.

我认为如果第一棵树与第二棵树有 N 个公共子树,则 delta/3 谓词是正确的

他这样说树:

tree(F, LIST_OF_SUBTREES).

例如,这是一棵由根 X 和两片叶子 u 和 v 组成的树:

tree(x, [tree(u,[]), tree(v,[])])

我认为 delta/3 谓词它被拒绝为 3 种可能的情况:

1) T1 和 T2 是仅由根 X 组成的两棵树,因此它们只有一个公共子树是正确的

**2) T1 和 T2 是不同的,并且是具有更多级别的结构化树,因此 T1 和 T2 有 N 个子树,如果为 TRUE,则为 TRUE:?!?!

3) 否则,如果前面的 delta\2 谓词都失败了,那么无论 T1 和 T2 有 0 个公共树都是真的

我认为这种解释是正确的(我希望如此......)但我在理解第二条规则时遇到了一些困难:什么可能是 sons/2 谓词(在我看来,这请注意内置谓词的 SWI Prolog,我正在学习的幻灯片上没有它的实现)

什么适合你?它的逻辑是什么?

Tnx

安德烈亚

【问题讨论】:

【参考方案1】:

您对这三个规则的解释在我看来是合理的。为了比较,我将它们改写为:

    如果 T1 和 T2 具有相同的值并且为空(叶节点),delta(T1, T2, 1) 成立。 如果 T1 和 T2 有 N 个公共子树,delta(T1, T2, N) 成立。 如果 T1 和 T2 有 0 个公共子树,delta(T1, T2, 0) 成立。

我不清楚为什么这些削减是必要的。我想它们是绿色切割,因为一对树不能同时有 1、N 和 0 个公共子树。

sons/2 很有趣。我可以想象它以几种不同的方式工作。我们确定的一件事是,如果两棵树有共同的子树,sons/2 应该生成相同的值;它必须以这种方式工作,否则sons(RX, SX), sons(RX1, SX) 将永远无法工作。 (请注意,该行缺少逗号)。

剩下的一个问题是,sons/2 是通过生成所有子树还是只生成最近的一对?在我看来,它可能只生成最近的对,因为subdelta/3 调用delta/3,导致间接递归。如果sons/2 生成所有子树,这将导致无限递归或至少大量不必要的工作。所以我敢打赌sons/2 看起来像这样:

sons(tree(_,Children), X) :- member(X, Children).

这表明至少有一种情况,delta/3 会做一些比人们乍一看更智能的事情:T1 和 T2 是彼此的反射。 T1 和 T2 的sons/2 将左与右统一,然后将右与左统一,因此您将通过共享子树获得最大相似度,但不是精确结构。

对此我最感到惊讶的是delta/3 似乎没有计算差异,它似乎计算了相似之处。这不是人们对名称所期望的,而是从实现中得出的。很难想象如何直接计算差异——上限是多少?例如,对于文件,您可以通过说每行可以相同 (0) 或不同 (1) 来计算差异,然后将差异相加。

希望这是在正确的轨道上并有所帮助!

【讨论】:

我仍然觉得这个话题很难,但现在感谢你的帮助,我认为我有新的基础来推理这个问题!!!这对我来说并不完全清楚,但在接下来的几天里,我会对此进行推理,稍后我会提出任何其他疑问:-) 我认为你在进步,但你需要对自己多一点信心。 我最大的问题是我不能参加这门课程,因为我在工作,这是我最后一次大学考试......所以我很焦虑:-) 这实际上解释了很多。我想知道你怎么会在课堂上需要这么多帮助,但如果你一个人去做,那么你能以如此之快的速度走到这一步,真是令人印象深刻。 :) 还认为我每周在办公室工作 2 晚(从 23 到 7 点),因此每周被扔石头 3 天 ... :-/ 我必须结束大学学习,然后找到一份新工作 呵呵

以上是关于根据Prolog中公共子树的数量,树之间的递归相似度的主要内容,如果未能解决你的问题,请参考以下文章

树递归遍历————二叉搜索树的最近公共祖先

leetcode-235二叉搜索树的最近公共祖先

LeetCode235-二叉搜索树的最近公共祖先

寻找二叉树中的最低公共祖先结点----LCA(Lowest Common Ancestor )问题(递归)

寻找二叉树两个节点的最低公共祖先

(树)根据中序后序构建二叉树