根据Prolog中常见子树的数量,树之间的递归相似性

时间:2013-05-05 16:29:36

标签: prolog

我正在使用SWI Prolog来学习Prolog,我发现这个代码片段很难找到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.

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

他以这种方式对树进行了抨击:

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个子树是真的:?!?!

3)否则,如果普遍的delta \ 2谓词都失败了,无论T1和T2如何,它们都有0个共同的树

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

什么是给你的?这是什么逻辑?

TNX

安德烈

1 个答案:

答案 0 :(得分:1)

你对这三条规则的解释对我来说似乎是合理的。为了比较,我将它们改写为:

    如果T1和T2具有相同的值并且为空(叶节点),则
  1. delta(T1, T2, 1)成立。
  2. 如果T1和T2有N个公共子树,则
  3. delta(T1, T2, N)成立。
  4. 如果T1和T2有0个公共子树,则
  5. delta(T1, T2, 0)成立。
  6. 我不清楚为什么这些削减是必要的。我认为它们是绿色削减,因为一对树不能同时拥有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)然后将差异相加来计算差异。

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