3

我很难在 Prolog 中思考。这个说法有什么不正确的:

numberList([], 0).
numberList([H|T], Limit) :-
    H is Limit,
    numberList(T, Limit - 1).

我想

?- numberList(X,Limit).

确定[Limit, Limit-1 ... 1]为 Limit 的给定值的唯一解决方案,即

?- numberList(X, 100).

会产生X = [100, 99, 98, ..., 1].

我的猜测是,我在这里的理解有很大问题,因为这不起作用。我不一定要求解决我正在尝试做的事情,我只是想了解为什么我的第一次尝试是错误的。

4

2 回答 2

3

这里潜伏着两个主要问题:

1- 你很难在正确的地方进行统一和算术运算

2-你没有足够检查你的输入

备注 1- (is)/2用于执行算术运算,例如,减去1。可以但不应该用于将变量统一为已经计算过的算术表达式。应该是首选(统一)。Limit(is)/2(=)/2

关于 2 的备注 - 即使您的运算符正确,您的程序也会循环。稍后再谈。

仅通过自己切换运算符不会获得太多收益,因此这是正确的方法:

numberList([], 0).
numberList([Limit|T], Limit) :-
    NewLimit is Limit - 1,
    numberList(T, NewLimit).

在这里你可以看到我在第二个子句的头部隐含地使用了统一,另一种说法如下:

numberList([], 0).
numberList([H|T], Limit) :-
    H = Limit,
    NewLimit is Limit - 1,
    numberList(T, NewLimit).

但是现在,正如您通过尝试这个程序所看到的那样,它找到了一个正确的解决方案,但如果您要求另一个带有;.

原因对于初学者来说可能更难发现:当 Prolog 成功并返回一个解决方案时,它只能通过探索执行过程中留下的选择点来找到新的解决方案。在这里,剩下的唯一选择点是 when Limitis 0。所以它在这种情况下尝试第二个子句而不是第一个子句并循环直到它到达NegativeInfinity. 可悲的是,由于到达那里的行程很长,所以它之前溢出了。这个问题的解决方案是在第二个子句中添加一个保护,指定Limit应该大于0或在第一个子句中添加一个cut,甚至更好:两者都做。问问你自己这样做有没有困难!

于 2012-05-10T18:03:07.107 回答
0

“Limit - 1”被认为是一个函数调用,在 C 语言中它会起作用。它正在询问/命令 Prolog“找到一个减法函数,用 Limit-variable 和 1 调用它”。它要求 Prolog 将“Limit - 1”理解为函数调用结果,但 Prolog 将“Limit - 1”理解为复合术语减法(Limit,1),它是一阶逻辑的谓词

“H is Limit”这也被认为是一个函数调用

Prolog没有功能(???),我认为这种说法对C-人来说是一个很大的障碍。Prolog 没有函数(如 C 等,如数学),而是有谓词(如谓词逻辑、一阶等)

函数是命令微处理器的命令。而是谓词将数据呈现给微处理器以“用微处理器的眼睛看”,将数据呈现给微处理器以感知。

谓词描述一个世界,描述该世界中对象之间的一些关系,微处理器试图验证这些关系。微处理器试图证明这些关系确实存在于它的知识中。这些关系可以在它的知识中多次存在,因此微处理器可以返回多个结果(又名非确定性)

Prolog是一门神奇的编程语言,也许我应该写神奇的描述语言,神奇的模式识别语言,神奇的推理/演绎语言(简单的推理/演绎,它不是一种“人工智能”,推理/演绎就像数字电子逻辑门)。我以前是一个热心的 Visual Studio 程序员,但我已经学习 Prolog 几年了。

C 语言等用于命令,Prolog 语言等用于描述。

于 2015-01-26T17:27:39.047 回答