最大值由prolog子句定义的值

时间:2009-11-09 15:20:14

标签: prolog

我知道如何在Prolog中迭代列表以找到最大值,但是如果每个东西都是单独的子句呢?例如,如果我有一堆猫科动物和他们的年龄,我怎么能找到最老的小猫?

cat(sassy, 5).
cat(misty, 3).
cat(princess, 2).

我的第一个想法是“嗯,最老的猫是没有老年人存在的猫”。但我无法将其转化为prolog。

oldest(X) :- cat(X, AgeX), cat(Y, AgeY), X \= Y, \+ AgeX < AgeY, print(Y).

这仍然错误地匹配“有雾”。这样做的正确方法是什么?有没有什么方法可以更直接地迭代年龄来选择最大值?

5 个答案:

答案 0 :(得分:6)

一种方法是

oldest(X) :- cat(X, AgeX), \+ Y^(cat(Y, AgeY), Y \= X, AgeX < AgeY).

您还可以使用setof / 3获取所有猫的列表并从中获得最大值。

答案 1 :(得分:4)

猫是最老的,如果它是一只猫,并且没有比它更老的猫。让我们在Prolog中写一下:

oldest(X):- cat(X, _), not( thereAreOlders(X)), !.
thereAreOlders(X):- cat(X, N), cat(C, M), C\=X, M > N.

如果您咨询:

?- oldest(X).
X = sassy.

答案 2 :(得分:2)

这是一个循环遍历所有解决方案的解决方案,始终记录比以前更好的解决方案。最后,返回最佳解决方案。

录制是使用assert/1完成的,如果你的Prolog提供(SWI-Prolog),你也可以使用不可回溯的全局变量。

这种方法的好处是只考虑每个解决方案一次,即复杂度O(n)。所以,即使它看起来比starblue的解决方案更糟糕,它也应该运行得更好。

% Data
cat(sassy, 5).
cat(misty, 3).
cat(miisu, 10).
cat(princess, 2).

% Interface
oldest_cat(Name) :-
    loop_through_cats,
    fetch_oldest_cat(Name).

loop_through_cats :-
    cat(Name, Age),
    record_cat_age(Name, Age),
    fail ; true.


:- dynamic current_oldest_cat/2.

record_cat_age(Name, Age) :-
    current_oldest_cat(_, CAge),
    !,
    Age > CAge,
    retract(current_oldest_cat(_, _)),
    assert(current_oldest_cat(Name, Age)).

record_cat_age(Name, Age) :-
    assert(current_oldest_cat(Name, Age)).


fetch_oldest_cat(Name) :-
    retract(current_oldest_cat(Name, _Age)).

用法示例:

?- oldest_cat(Name).

Name = miisu

Miisu是典型的爱沙尼亚猫名。 ;)

答案 3 :(得分:0)

在风格上 - 这里有一些不同的方法(一些非常优雅,另一些更“可读”)。如果你是一个初学者 - 选择你自己的,首选的做事方式 - 无论多么低效。

您可以稍后学习提高效率的技巧。享受Prolog-它是一种美丽的语言。

答案 4 :(得分:-2)

我不太记得Prolog,但我知道你不应该像使用命令式编程语言那样考虑解决问题。