定义谓词序言

Define the predicate Prolog

我正在为即将到来的考试复习一些练习,但在这方面遇到了困难。

Given a list of integers L, define the predicate: add(L,S) which returns a list of integers S in which each element is the sum of all the elements in L up to the same position.

Example:

?- add([1,2,3,4,5],S).

S = [1,3,6,10,15].

所以我的问题是定义谓词是什么意思?看起来很一般。我读过一些线程,但它们提供的内容不多。谢谢!

定义谓词只是指编写一个谓词来完成问题的要求。 在您的问题中,您必须编写 add/2 谓词的定义(“/2”表示它有两个参数)。你可以写下定义:

add(L,S):- add1(L,0,S).

add1([],_,[]).
add1([H|T],Sum,[H1|T1]):- H1 is Sum+H,NSum is Sum+H,add1(T,NSum,T1).

以上谓词为您提供了所需的输出。一个简单的例子:

?- add([1,2,3,4,5],S).
S = [1, 3, 6, 10, 15].

我认为以上或类似的谓词是有人在测试中等待看到的。

一些额外的信息问题

上面谓词的问题是,如果你查询例如:

?- add(S,L).
S = L, L = [] ;
ERROR: is/2: Arguments are not sufficiently instantiated

正如您看到的,当您尝试询问谓词何时成功时,它会给出一个明显的解决方案,而对于进一步的解决方案,它会抛出一个错误。这不是一个很好的愿望 属性。您可以通过使用模块 CLPFD:

来改进它
:- use_module(library(clpfd)).


add(L,S):- add1(L,0,S).

add1([],_,[]).
add1([H|T],Sum,[H1|T1]):- H1 #= Sum+H,NSum #= Sum+H,add1(T,NSum,T1).

现在一些查询:

?- add([1,2,3,4,5],S).
S = [1, 3, 6, 10, 15].

?- add(S,[1,3,6]).
S = [1, 2, 3].

?- add(S,L).
S = L, L = [] ;
S = L, L = [_G1007],
_G1007 in inf..sup ;
S = [_G1282, _G1285],
L = [_G1282, _G1297],
_G1282+_G1285#=_G1307,
_G1282+_G1285#=_G1297 ;

...and goes on..

如您所见,谓词现在可以提供您询问的任何信息!那是因为现在它具有更多的关系行为,而不是之前由于 is/2 谓词而具有的功能行为。 (这些是改进谓词行为的更多信息。对于测试,您可能不允许使用库等...因此您可以只编写一个至少可以回答问题的简单解决方案)。

这是一个很好的练习,可以让您熟悉两个重要的 Prolog 概念:

  • 声明性整数算法 对所有方向的整数进行推理
  • 元谓词 以缩短您的代码。

我们从一个非常简单的关系开始,将整数 I 和整数 S0sum 与新的总和 S 相关联:

sum_(I, S0, S) :- S #= S0 + I.

根据您的 Prolog 系统,您可能需要如下指令:

:- use_module(library(clpfd)).

使用声明性整数算法。

其次,有一个强大的元谓词家族(参见) called scanl/N, which are described in Richard O'Keefe's Prolog library proposal,并且已经在一些系统中实现。在我们的例子中,我们只需要scanl/4.

示例查询:

?- scanl(sum_, [1,2,3,4,5], 0, Sums).
Sums = [0, 1, 3, 6, 10, 15].

完成!

其实,比做的多,因为我们可以全方位使用这个,例如:

?- scanl(sum_, Is, 0, Sums).
Is = [],
Sums = [0] ;
Is = [_2540],
Sums = [0, _2540],
_2540 in inf..sup ;
Is = [_3008, _3014],
Sums = [0, _3008, _3044],
_3008+_3014#=_3044 ;
etc.

这就是我们对真正关系型解决方案的期望!

另请注意 0 作为部分和列表中第一个元素的出现。它满足您对任务的文字描述,但不满足您发布的示例。我将对齐这些作为练习。