我正在使用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
安德烈
答案 0 :(得分:1)
你对这三条规则的解释对我来说似乎是合理的。为了比较,我将它们改写为:
delta(T1, T2, 1)
成立。delta(T1, T2, N)
成立。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)然后将差异相加来计算差异。
希望这是在正确的轨道并帮助!