Prolog从馆藏中获得最大收益

时间:2020-04-09 00:48:19

标签: prolog

这是一个简单的问题。

has(steve, 5).
has(mark, 6).
has(craig, 4).

在Prolog中,您如何从中获得最大收益?

我尝试了has(Who, Max),但这没有帮助。这里有可以使用的运算符吗?

谢谢。

3 个答案:

答案 0 :(得分:5)

?- has(U,S),\+((has(V,T),T>S)).
U = mark,
S = 6 ;
false.

前缀运算符\+读为。由于我们必须反驳的是由中缀运算符,表示的连词,因此必须使用双括号。

使用它时,您应该意识到它是一种限制否定形式,即所谓的negation as failure,它是由Prolog中隐含的closed world assumption使得语义。

或者,做的完全一样

max(U,S) :- has(U,S),notanybetterthan(S).

notanybetterthan(S) :- has(_,T),T>S,!,fail.
notanybetterthan(_).

max(U,S) :- has(U,S),\+anybetterthan(S).

anybetterthan(S) :- has(_,T),T>S.

编辑

正如@WillNess指出的那样,我使用的语法不精确。实际上,双括号是\+的后代,被视为 functor ,而不是 operator 。我们可以在符号后面添加空格

?- has(U,S),\+ (has(V,T),T>S).

答案 1 :(得分:3)

您可以使用标准谓词findall/3keysort/2

| ?- findall(Value-Name, has(Name, Value), Pairs),
     keysort(Pairs, SortedPairs).

Pairs = [5-steve, 6-mark, 4-craig],
SortedPairs = [4-craig, 5-steve, 6-mark]
yes

您想要SortedPairs列表中的最后一对。只需遍历列表,直到到达其最后一个元素。我会留给您写一个last(List, Last)谓词。

更新

Carlo的解决方案很惯用(+1)。但这也是O(n ^ 2)。我的解决方案(包括缺少的last/2谓词)是O(2 * n + n * log(n))。另一方面,由于创建了临时列表,它对垃圾回收器的影响要稍微多一些。如果我们在OP中仅包含树事实,则Carlo的解决方案快约3倍。大约有100个事实,两种解决方案花费的时间大致相同(请注意,确切数字取决于所使用的Prolog系统)。对于许多事实,复杂性的差异变得越来越明显。

答案 2 :(得分:3)

尝试一下:

has(steve, 5).
has(mark, 6).
has(craig, 4).

?- findall(has(X, Y), has(X, Y), Z), maxhas(Z, has(Who, Max)), write([Who, Max]).

maxhas([has(X, Y)], has(X, Y)).
maxhas([has(_, Y)|Hs], has(A, B)) :- maxhas(Hs, has(A, B)), B >= Y.
maxhas([has(X, Y)|Hs], has(X, Y)) :- maxhas(Hs, has(_, B)), B < Y.

我得到:

[mark, 6]Yes.
相关问题