【问题标题】:How to generate all pairs of natural numbers in Prolog?如何在 Prolog 中生成所有自然数对?
【发布时间】:2018-01-01 21:47:11
【问题描述】:

问题陈述:

我正在尝试在 Prolog (SWI-Prolog) 中生成所有自然数对,

即正式有一个函数f(X,Y),这样:

在使用未绑定变量XY 调用f(X,Y) 后,对于每对自然数 (m, n),存在一个 n0,这样在按分号 n0 次后,Prolog 将返回 (X,Y)=(m,n)

尝试失败:

我希望使用Cantor's pairing function 编写函数。简而言之,它按如下方式枚举对:(0,0), (1,0), (0,1), (2,0), (1,1), (0,2), (3,0 ), (2,1), (1,2), (0,3), (4,0)...

我是这样表达的:

gen(0,0).                                          % 'root'
gen(M,0) :- gen(0, X), M is X+1.                   % 'jump to the previous diagonal'
gen(M,N) :- gen(X, Y), M is X-1, N is Y+1, N > 0.  % 'a step inside a diagonal'

但是,由于 Prolog 搜索的实际工作方式,这最终导致第二条规则反复调用自身,ad 无穷大,最终由于堆栈空间不足而崩溃(它在此之前返回的唯一结果是 (0,0) 和(1,0),然后它就卡住了,反复失败关于 '0 是 0+1' 的第二条规则)。


您对如何使这种或任何其他优雅的方法发挥作用有任何想法吗?

谢谢。


编辑 - 我的解决方案。

根据接受的答案(谢谢!),我编写了以下代码,按预期工作:

range(Min, _, Min).
range(Min, Max, Val) :- NewMin is Min+1, Max >= NewMin, range(NewMin, Max, Val).

natnum(0).
natnum(N) :-
    natnum(N0),
    N is N0 + 1.

gen(A,B) :-
    natnum(N),
    range(0, N, B),
    A is N - B.

使用时:

?- gen(X,Y).
X = 0,
Y = 0 ;

X = 1,
Y = 0 ;

X = 0,
Y = 1 ;

X = 2,
Y = 0 ;

X = 1,
Y = 1 ;

X = 0,
Y = 2 ;

X = 3,
Y = 0

and so on...

【问题讨论】:

  • 作为一个术语,Prolog 没有函数,而是谓词。它们不是一回事。

标签: prolog


【解决方案1】:

我给你一个开始:

让我们从一个谓词开始,它在回溯时创建所有自然数,每个解产生一个单个这样的数字:

纳特姆(0)。 natnum(N) :- N #= N0 + 1, 纳特数(N0)。

示例查询:

?- natnum(N). N = 0 ; N = 1 ; N = 2; N = 3 ; 等等

然后,我们观察到我们可以通过限制每对的 sum 来生成这样的对而不会陷入无限循环。例如:

对(A-B):- 纳特姆(N), N #>= A + B, #>= 0, B #>= 0, 标签([A,B])。

示例查询:

?- 对(P)。 P = 0-0 ; P = 0-0 ; P = 0-1 ; P = 1-0 ; P = 0-0 ; P = 0-1 ; P = 0-2 ; P = 1-0 ; P = 1-1; P = 2-0 ; P = 0-0 ; P = 0-1 ; P = 0-2 ; P = 0-3; P = 1-0 ; P = 1-1。

这显然不是完美的:例如,一些对被报告冗余。但是,总体思路应该很清楚:使用良好的构建块来控制对的生成。

【讨论】:

  • 谢谢!我根据您的回答编写了我想要的代码,并将其编辑到问题正文中。
  • 对于natnum的例子,为什么我只得到N=0作为查询结果?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-10
  • 1970-01-01
  • 1970-01-01
  • 2019-09-05
  • 1970-01-01
  • 2017-11-14
相关资源
最近更新 更多