树中给定深度的 Prolog 节点数

用户47679

我是 Prolog 的新手。我正在尝试编写一个谓词,它返回中给定深度二叉树的节点数例如,下面的树

在此处输入图片说明

有 1 个深度为 0 的节点(根节点)、2 个深度为 1 的节点、3 个深度为 2 的节点和 3 个深度为 3 的节点。

在我的程序中,二叉树表示为 形式的列表[value, left-child, right-child],其中左右孩子本身可以用相同的方式表示。例如,这里是上述树的表示:

[8, [3, [1, [], []], 
        [6, [4, [], []], 
            [7, [], []]]], 
    [10, [], 
         [14, 
            [13, [], []], 
            []]]]

这是我到目前为止想出的:

nbNodes([_,_,_],1,0).
nbNodes([_,LC,RC],N2,D2) :- 
    nbNodes(LC,NL,D), nbNodes(RC,NR,D), N2 is NL+NR, D2 is D+1.

基于我对 Prolog 的有限理解,这意味着:

  1. 每棵树只有一个深度为 0 的节点。
  2. The number of nodes of depth D2 in a tree is the sum of the number of nodes of depth D2-1 in the left and right child of the three.

    Both assumptions seem correct.

However, when I test my code, the numbers returned (if any) are wrong. For example, the following code outputs "false" instead of "3":

nbNodes([8, [3, [1, [], []], [6, [4, [], []], [7, [], []]]], [10, [], [14, [13, [], []], []]]], N, 2).

What am I doing wrong ? Many thanks in advance.

tiffi

How about

nbNodes( [],0,_).
nbNodes( [_,_,_],1,0).
nbNodes( [_,LC,RC],N2,D2):-
    D2 > 0,
    D is D2-1,
    nbNodes( LC,NL,D), 
    nbNodes( RC,NR,D), 
    N2 is NL+NR.

That is the result:

?- T = [8,[3,[1,[],[]],[6,[4,[],[]],[7,[],[]]]],[10,[],[14,[13,[],[]],[]]]],
   nbNodes(T,N,0).
T = [8, [3, [1, [], []], [6, [4, []|...], [7|...]]], [10, [], [14, [13|...], []]]],
N = 1 ;
false.
    
?- T = [8,[3,[1,[],[]],[6,[4,[],[]],[7,[],[]]]],[10,[],[14,[13,[],[]],[]]]],
   nbNodes(T,N,1).
T = [8, [3, [1, [], []], [6, [4, []|...], [7|...]]], [10, [], [14, [13|...], []]]],
N = 2 ;
false.
    
?- T = [8,[3,[1,[],[]],[6,[4,[],[]],[7,[],[]]]],[10,[],[14,[13,[],[]],[]]]],
   nbNodes(T,N,2).
T = [8, [3, [1, [], []], [6, [4, []|...], [7|...]]], [10, [], [14, [13|...], []]]],
N = 3 ;
false.
    
?- T = [8,[3,[1,[],[]],[6,[4,[],[]],[7,[],[]]]],[10,[],[14,[13,[],[]],[]]]],
   nbNodes(T,N,3).
T = [8, [3, [1, [], []], [6, [4, []|...], [7|...]]], [10, [], [14, [13|...], []]]],
N = 3 ;
false.

?- T = [8,[3,[1,[],[]],[6,[4,[],[]],[7,[],[]]]],[10,[],[14,[13,[],[]],[]]]], 
   nbNodes(T,N,4).
T = [8, [3, [1, [], []], [6, [4, []|...], [7|...]]], [10, [], [14, [13|...], []]]],
N = 0.

The two major changes are that

  1. I added a clause for empty binary trees.
  2. I calculated D from D2, before I call the predicate again and do not calculate D2 from D after the recursive calls.

I guess you are asking what the difference is, because you have been told that Prolog is declarative and thus we need to only specify what is the case (our knowledge base) and not how something can be inferred from our knowledge.

Well, you have been lied at. Prolog is not purely declarative, since there is an order, in which it searches for an answer.

If you want to prove a goal G by the use of a clause

G :- L1,L2,L3.

Prolog tries to prove L1, then L2, then L3 - although from a logical view, this clause says nothing but

IF L1 and L2 and L3 THEN G,

which is logically equivalent to

IF L3 and L1 and L2 THEN G

There might be a proof, if Prolog checked all possible orders, yet it doesn't.

In addition, for many predicates, certain arguments need to be instantiated in order for the predicates to work. One of such predicates is is/2. Its right hand side needs to be fully instantiated for is/2 to work.

Your predicate needs its third argument to be instantiated. When you call nbNodes(LC,NL,D) and nbNodes(RC,NR,D), D is not instantiated. Even if you changed the order of your clauses and put D2 is D+1 before those clauses, this doesn't work, since is/2 needs its right hand side to be fully instantiated, and D is not yet instantiated at that point.

Try asking ?- X is 2. and ?- 2 is X. to see the difference.

要获得更完整的图片,您需要深入研究 Prolog 对分辨率原理的(部分)实现如果您想拥有一种更具声明性的 Prolog,请查看约束逻辑编程。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章