4

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

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

[]

一棵有 1 个节点的树是:

[[],[]]

具有 2 个节点的树有 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

我在一些网站上读到了这个错误,但我不知道是什么导致了这个错误。

提前感谢您的帮助。

4

2 回答 2

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 是一种很好的、​​声明式的表达数字约束的方式。

于 2015-03-26T12:51:51.467 回答
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).
于 2017-02-16T14:01:56.357 回答