【发布时间】:2019-12-04 22:46:49
【问题描述】:
我(Prolog 绝对初学者)尝试从 prolog 中理解。这是swi-prolog 中的圣诞老人示例:
gives(santa,leonard,book).
gives(santa,adrian,game).
gives(santa,adrian,smartmax).
likes(leonard,lego).
likes(adrian,lego).
likes(adrian,book).
age(leonard,6).
age(adrian,4).
jealous(C1,C2) :- aggregate_all(count, gives(santa,C1,X), N1),
aggregate_all(count, gives(santa,C2,X), N2),
N1 < N2,
true.
jealous(C1,C2) :- findall(G,
(owns(C2,G),
likes(C1,G),
not(owns(C1,G))
),
Gifts),
length(Gifts,NGifts),
NGifts > 0,
true.
这按预期工作:
?- jealous(adrian,leonard).
true.
但是,当我颠倒代码中两个jealous-predicates 的顺序时:
?- jealous(adrian,leonard).
true ;
false.
这很奇怪:我认为jealous-clauses 会表现为“或”:只要其中一个结果为真,就不应该进行任何进一步的处理。
所以我想知道:如何制作它以使其真正表现为“或”:如果jealous-规则中的任何一个为真,它应该返回true,在所有其他情况下,它是false .我不想要“下一个结果”。我只需要 1 个结果:true 或 false。
我做错了什么? (可能有几件事,所以请赐教:))。
谢谢。
【问题讨论】:
-
您的实施中有一个选择点。这意味着 Prolog 在第一次成功后还有其他选择可以探索(真)。您的
;条目告诉 Prolog 返回选择点并检查更多解决方案。它再也找不到了,因此它以 false 响应。这是正常的 Prolog 行为。 -
嗯,那个选择点取决于我定义的子句的顺序......我不明白为什么 Prolog 在某些情况下会返回,而在其他情况下不会。但是,似乎我找到了解决方案:stackoverflow.com/questions/25346189/prolog-disjunction.
-
是的,没错...我了解
;,但我不明白为什么Prolog 在找到true时要继续。但显然,这是正常行为:p。 -
在 Prolog 中编写“确定性”谓词这样的事情不会留下选择点。在不失一般性的情况下这样做可能非常具有挑战性(例如,如果您使用剪辑)。