定义谓词maxlist(List,Max),以便Max是数字列表List中的最大数字

时间:2019-03-06 23:37:54

标签: list prolog

  

练习3.17“人工智能的Prolog编程”,作者:   伊万·布特拉科(Ivan Btrako)

我了解max谓词,但是在跟踪maxList时遇到了麻烦。我正在尝试用伪代码编写逻辑来帮助我

  1. 获取第一和第二个元素并进行比较,得出 最高
  2. 取最大值并将其与第三个元素进行比较 列表,如果更大,则覆盖最大值,然后再次重复直到 列表为空。

但是,我不了解给出的解决方案,因此尝试跟踪它并失败了。我在将MaxRest映射到Max和基本情况时遇到了麻烦。另外,我不理解为什么在将[X,Y | Rest]与[Y | T]统一时prolog不会给出错误。示例[1,3,[7,2]]与[3 | [7,2]]。

max(X,Y,X):-
   X>=Y.
max(X,Y,Y):-
  X<Y.

maxlist( [X], X). %what does this line do?
maxlist( [X,Y|Rest], Max):- 
  maxlist( [Y|Rest], MaxRest),
  max(X, MaxRest,Max).

任何帮助跟踪将不胜感激。

2 个答案:

答案 0 :(得分:2)

由于您了解max/3,因此无法解释。

maxlist( [X], X). %what does this line do?
maxlist( [X,Y|Rest], Max):- 
  maxlist( [Y|Rest], MaxRest),
  max(X, MaxRest,Max).

这是经典的递归列表模式,该模式在处理项目之前进行递归。带有尾部调用的普通递归列表模式为

process_list([H|T],R) :-
  process_item(H,R),
  process_list(T,R).
process_list([],R).

但是这里是

process_list([H|T],R) :-
  process_list(T,R),
  process_item(H,R).
process_list([],R).

在遍历列表后处理项目的地方。

这也一次处理两个项目,即

 [H1,H2|T]

因为比较需要两项。

maxlist( [X,Y|Rest], Max):- 
  maxlist( [Y|Rest], MaxRest),

只是将值从列表中删除,然后将它们推入堆栈,以便在回溯时将具有一个用于比较的值,即MaxRest是{中所有值的最大值{1}}和当前值Rest。您可能会认为应该是X,但是当列表中只有一项时,列表实际上是Y,实际上是[Y|[]],并且与该子句{{ 1}}。

那么[Y]的作用是什么?列表的常见基本情况只是返回列表的maxlist( [X], X).,但是在这种情况下,仅需要最后一个值作为值返回,因此这将maxlist( [X], X).从第一个列表中移出参数,并将其作为第二个参数中的值返回,以便当列表中只有一项时,它变为predicate([],R).,这是最大值。当执行X时,它具有MaxRest返回值的值,并且在解构列表时在堆栈上具有max(X, MaxRest,Max)的值。结果是MaxRest,它作为X中的第三个参数返回,在再次回溯时成为Max的值。

问问这是否没有道理。


  

我不明白为什么Prolog在统一时不给出错误   [X,Y | Rest]与[Y | Rest]。

     

示例[1,3,[7,2]]与[3 | [7,2]]

实际上

maxlist( [X,Y|Rest], Max)

因此,尽管您的示例确实给出了错误,但这并不是要做什么

MaxRest

从列表?- [1,3,[7,2]] = [3|[7,2]]. false. 开始,并与[X,Y|Rest] and [Y|Rest] 统一

[1,2,3,4]

请注意,[X,Y|Rest]将是?- [1,2,3,4] = [X,Y|Rest]. X = 1, Y = 2, Rest = [3, 4].

[Y|Rest]

请勿尝试将[2|[3,4]]?- [1,2,3,4] = [X,Y|Rest],A = [Y|Rest]. X = 1, Y = 2, Rest = [3, 4], A = [2, 3, 4]. 统一,而应将[X,Y|Rest][Y|Rest]Rest,{{1 }}存储在堆栈中,但没有传递到stackframe的下一级。

如果您真的想了解列表,请使用此列表查看它们

Rest

如果您拥有本书的第4版,请参阅第61页的图3.1。

答案 1 :(得分:2)

Prolog谓词根据逻辑来定义关系,该逻辑说如果(:-)主体为true,则子句的头部为true。这可以帮助您正确读取谓词:

max(X,Y,X):-
   X>=Y.

这说:

  

XXY的最大值。如果 X >= Y为真。

您可以类似地阅读max(X,Y,Y)的条款。

现在看看:

maxlist( [X], X).

在这里,我们将maxlist定义为列表的最大值。该特殊条款说:

  

X是列表[X]的最大值。

在这种情况下,没有 if 条件(:-),因为无需其他条件即可建立此规则。

然后有一个递归子句:

maxlist( [X,Y|Rest], Max):- 
  maxlist( [Y|Rest], MaxRest),
  max(X, MaxRest,Max).

这说:

  

Max是列表[X,Y|Rest]的最大值如果 MaxRest是列表[Y|Rest]的最大值而Max是列表的最大值XMaxRest的最大值。

此递归子句和先前的基本案例子句完全定义maxlist。如果您仔细阅读该书,它应该看起来完全合乎逻辑。


  

我不明白为什么将[X,Y|Rest][Y|T]统一时prolog不会给出错误

我不明白此评论。 Prolog在代码中没有尝试统一这两个术语。您的示例示例[1,3,[7,2]][3|[7,2]]不会统一,因为第一个是三个元素的列表:1、3和[7,2],而另一个是三个元素的列表:3 ,7和2。要使两个列表不可统一,不仅长度必须相同,而且列表中的每个对应术语也必须不可统一。

然后,什么会使[X,Y|Rest][Y|T]无法确定?您可以将[X,Y|Rest]编写为[X|[Y|Rest]],如果满足以下条件,则很容易看到它们是无法确定的:

X = Y,
[Y|Rest] = T

换句话说,列表必须具有(a)至少两个元素,并且(b)前两个元素相同。