枚举Prolog中的二叉树

时间:2015-03-26 07:20:13

标签: prolog logic-programming catalan instantiation-error

我正在尝试创建Prolog规则,以便在Prolog中以列表形式枚举“二叉树”。我是Prolog的新手。

具有0个节点的树是一个空列表:

[]

具有1个节点的树是:

[[],[]]

具有2个节点的树有两种可能性:

[[],[[],[]]]

[[[],[]],[]]

等等。

以下是我的规则:

bintree(0,[]).
bintree(1,[[],[]]).
bintree(N,[Lc,Rc]) :-
  N > 1,
  bintree(N1,Lc),
  bintree(N2,Rc),
  N1 >= 0,
  N2 >= 0,
  N3 is N1+N2+1,
  N==N3.

0和1的查询显然有效。对于N = 2,它打印一种可能性,但在输入分号后得到另一种可能性时出错。 N> 2的查询直接给出错误。错误总是一样的:

ERROR: >/2: Arguments are not sufficiently instantiated

我在某些网站上看到了这个错误,但我无法弄清楚导致此错误的原因。

提前感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

使用CLPFD库将有助于为生成大小提供一个干净的解决方案。然后你不需要一个不稳定的(;))integer/1谓词,这可能有问题:

:- use_module(library(clpfd)).

bintree(0,[]).
bintree(1,[[],[]]).
bintree(N, [L, R]) :-
    N #> 1,
    N #= N1 + N2 + 1,
    N1 #>= 0, N2 #>= 0,
    bintree(N1, L), bintree(N2, R).

或更简单(感谢@ repeat'的建议):

bintree(0,[]).
bintree(N, [L, R]) :-
    N #> 0,
    N #= N1 + N2 + 1,
    N1 #>= 0, N2 #>= 0,
    bintree(N1, L), bintree(N2, R).

?- bintree(4, L).
L = [[], [[], [[], [[], []]]]] ;
L = [[], [[], [[[], []], []]]] ;
L = [[], [[[], []], [[], []]]] ;
L = [[], [[[], [[], []]], []]] ;
L = [[], [[[[], []], []], []]] ;
L = [[[], []], [[], [[], []]]] ;
L = [[[], []], [[[], []], []]] ;
L = [[[], [[], []]], [[], []]] ;
L = [[[], [[], [[], []]]], []] ;
L = [[[], [[[], []], []]], []] ;
L = [[[[], []], []], [[], []]] ;
L = [[[[], []], [[], []]], []] ;
L = [[[[], [[], []]], []], []] ;
L = [[[[[], []], []], []], []] ;
false.

?-

CLPFD是表达数字约束的一种很好的声明方式。

答案 1 :(得分:0)

我知道我在一年前发布了这个问题,但我设法在不使用任何库的情况下解决了这个问题。这是我的解决方案:

%binary tree generator
bintree(0,[]). %0 nodes - empty list
bintree(1,[[],[]]). %1 node - list containing 2 empty lists
bintree(N,[Cl,Cr]) :-
    N>=2, %check only if at least 2 nodes
    between(0,N,Nl), %let Nl be in [0,N]
    between(0,N,Nr), %similarly for Nr
    Ns is Nl+Nr+1, %total no. of nodes should add up correctly
    N==Ns, %so check for that
    bintree(Nl,Cl), %children should also be valid binary trees
    bintree(Nr,Cr).