prolog子句定义的最大超出值
我知道如何在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):
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^
的情况下工作。