prolog子句定义的最大超出值

prolog子句定义的最大超出值,prolog,Prolog,我知道如何在Prolog中迭代列表以找到最大值,但是如果每件事都是一个单独的子句呢?例如,如果我有一群猫科动物和它们的年龄,我怎么才能找到最老的小猫呢 cat(sassy, 5). cat(misty, 3). cat(princess, 2). 我的第一个想法是“嗯,最老的猫是一只没有老猫的猫”。但是我不能把它翻译成序言 oldest(X) :- cat(X, AgeX), cat(Y, AgeY), X \= Y, \+ AgeX < AgeY, print(Y). 最老的(X):

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

cat(sassy, 5).
cat(misty, 3).
cat(princess, 2).
我的第一个想法是“嗯,最老的猫是一只没有老猫的猫”。但是我不能把它翻译成序言

oldest(X) :- cat(X, AgeX), cat(Y, AgeY), X \= Y, \+ AgeX < AgeY, print(Y).
最老的(X):-cat(X,AgeX),cat(Y,AgeY),X\=Y,\+AgeX
这仍然错误地匹配“misty”。正确的方法是什么?是否有更直接的方法,只需在各个年龄段反复选择max?

一种方法是

oldest(X) :- cat(X, AgeX), \+ Y^(cat(Y, AgeY), Y \= X, AgeX < AgeY).
最老的(X):-cat(X,AgeX),\+Y^(cat(Y,AgeY),Y\=X,AgeX
您还可以使用setof/3获取所有猫的列表,并从中获取最大值。

一种方法是

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

您也可以使用setof/3来获取所有cat的列表,并从中获取最大值。

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

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

如果猫是猫,没有比它大的猫,那么猫是最老的。让我们用序言来写:

oldest(X):- cat(X, _), not( thereAreOlders(X)), !.
thereAreOlders(X):- cat(X, N), cat(C, M), C\=X, M > N.
如果您咨询:

?- oldest(X).
X = sassy.

如果一只猫是最年长的,而且没有比它年长的猫。让我们用序言来写:

oldest(X):- cat(X, _), not( thereAreOlders(X)), !.
thereAreOlders(X):- cat(X, N), cat(C, M), C\=X, M > N.
如果您咨询:

?- oldest(X).
X = sassy.

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

录制是使用
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是典型的爱沙尼亚猫名

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

录制是使用
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是典型的爱沙尼亚猫名

从风格上讲——这里有几种不同的方法(有些非常优雅,有些更“可读”)。如果你是一个初学者——选择自己喜欢的做事方式——不管效率有多低


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

从风格上讲,这里有几种不同的方法(有些非常优雅,有些更“可读”)。如果你是一个初学者——选择自己喜欢的做事方式——不管效率有多低


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

那太难看了,我宁愿使用setof、bagof或findall来获得O(n)的复杂性。(我的一行代码和Juanjo的解决方案是O(n^2)。)嗯,丑陋可以隐藏在接口谓词后面。setof对结果进行排序,这样就不会得到O(n)复杂度。使用findall,您将遍历解决方案两次,一次构建一个列表(如果您有几十亿只猫,它甚至可能无法放入内存),然后遍历列表。实际上,测试所有建议解决方案的速度和内存消耗是很酷的。这太难看了,我宁愿使用setof、bagof或findall来获得O(n)复杂度。(我的一行代码和Juanjo的解决方案是O(n^2)。)嗯,丑陋可以隐藏在接口谓词后面。setof对结果进行排序,这样就不会得到O(n)复杂度。使用findall,您将遍历解决方案两次,一次构建一个列表(如果您有几十亿只猫,它甚至可能无法放入内存),然后遍历列表。实际上,测试所有建议的解决方案的速度和内存消耗是很酷的。应该补充:SWI prolog有一个优秀的分析器,可以帮助您关注昂贵的条款。try it-profile(我的目标)。应该补充一点:SWI prolog有一个优秀的分析器来帮助您关注昂贵的子句。试一试-profile(我的目标)。什么是
^
呢?当我在事实上使用它时,我得到了未定义的过程:^/2只能作为setof/3和bagof/3的第二个参数出现。
^
是一个存在量词。似乎您的Prolog系统(SWI?)将其使用限制在
setof/3
bagof/3
。在这里,你并不真正需要
Y^
,这只是一种惯常的方式来强调
Y
在否定中是存在量化的(“不存在比X早的Y类”)。是的,SWI序言。谢谢你的解释。据我所知,它确实在没有
Y^
的情况下工作。
^
做什么?当我在事实上使用它时,我得到了未定义的过程:^/2只能作为setof/3和bagof/3的第二个参数出现。
^
是一个存在量词。似乎您的Prolog系统(SWI?)将其使用限制在
setof/3
bagof/3
。在这里,你并不真正需要
Y^
,这只是一种惯常的方式来强调
Y
在否定中是存在量化的(“不存在比X早的Y类”)。是的,SWI序言。谢谢你的解释。就我所知,它确实在没有
Y^
的情况下工作。