1

我正在尝试在 prolog 中做一个小项目,用户可以输入一个列表,然后计算列表中的平均值、最大值等。

到目前为止一切顺利,但我在编写 max 函数时遇到了问题(在列表中找到最大数)。代码是:

maxN([X],X):-!.
maxN([X|L],X) :- maxN(L,M), X > M.
maxN([X|L],M) :- maxN(L,M), M >= X.

该函数本身单独工作,但我收到此错误消息:

声明为“procedure”的谓词“forma::maxN/2 (i,o)”实际上是“nondeterm”forma.pro

这是我在 *.cl 定义中的谓词:

maxN: (integer* Z, integer U) 过程 (i,o)。

我不能将其声明为不确定,因为它会导致我的整个表格出现问题。你能帮我/给一个提示如何使它成为一个程序吗?我在想我必须在某个地方进行削减,但到目前为止我的尝试都失败了。

PS我正在使用Visual Prolog 7.4。

编辑:在尝试了将两条规则合二为一或使用累加器的替代方案之后,我现在知道谓词是“确定”而不是过程。根据我的 Prolog 指南,这意味着谓词现在没有多个解决方案,而是有可能失败。基本上我到目前为止所做的所有代码变体都让我有了一个“决心”。

4

2 回答 2

1

问题是 Prolog 在您的第二条和第三条规则之间看到了一个选择点。换句话说,你,人类,知道两者都是真实的X > MM >= X但不能都是真实的,但 Prolog 无法推断出这一点。

IMO 最好的办法是用一条规则重新表述这两条规则:

maxN([X], X) :- !.
maxN([X|L], Max) :- 
   maxN(L, M), 
   X > M -> Max = X
          ; Max = M.

这样一来,就没有需要修剪的额外选择点了。

遵循@CapelliC 的建议,您还可以使用累加器对其进行重新表述:

maxN([X|Xs], Max) :- maxN_loop(Xs, X, Max).

maxN_loop([], Max, Max).
maxN_loop([X|Xs], Y, Max) :- 
   X > Y -> maxN_loop(Xs, X, Max)
          ; maxN_loop(Xs, Y, Max).
于 2013-06-20T14:47:25.617 回答
1

抱歉,我不知道您使用的 Prolog 方言,我的建议是尝试在第二个子句之后添加一个剪切:

maxN([X|L],X) :- maxN(L,M), X > M, !.

一般来说,我认为可以将递归过程确定性地转换为尾递归。不幸的是,这需要添加一个累加器:

maxN([],A,A).
maxN([X|L],A,M) :- X > A, !, maxN(L,X,M).
maxN([X|L],A,M) :- maxN(L,A,M).

当然,顶级调用应该成为

maxN([F|L],M) :- maxN(L,F,M).
于 2013-06-20T14:43:43.033 回答