Prolog否定更多解决方案

tci*_*ler 1 prolog backtracking negation

我有一点问题,不知道在哪里找到解决方案.你可能听说过飞鸟的问题:

bird(eagle).
bird(penguin).
can_fly(penguin):-!,fail.
can_fly(X):-bird(X).
Run Code Online (Sandbox Code Playgroud)

我试图修改并将这些知识用于某些"爱情故事".想象一下

maried(a, b).
maried(c, d).
lovers(a, d).
likes(X, Y):-maried(X, Y).
Run Code Online (Sandbox Code Playgroud)

现在我想说"如果X与Y结婚,但X是Z的情人,那么X不喜欢Y,但喜欢Z".我试过这个:

likes(X, Y) :- lovers(X, Y).
likes(X, Y) :- maried(X, Y), lovers(X, _),!,fail.
likes(X, Y) :- maried(X, Y).
Run Code Online (Sandbox Code Playgroud)

除非我想评估目标,否则它有效

likes(A, B).
Run Code Online (Sandbox Code Playgroud)

如果数据库中有更多的事实并且Prolog找到第一个骗子,它将停止回溯,我找不到任何其他解决方案.也许之后会很明显,但现在我没有任何想法......

提前致谢(也许对不起我的英文:))

小智 5

你的第一个例子已经不太有用了.你可以问:

  • 老鹰是鸟吗?
  • 企鹅是一只鸟吗?
  • 鹰能飞吗?
  • 企鹅可以飞吗?

但你甚至不能问,"哪些鸟可以飞?":

?- can_fly(Bird).
false.
Run Code Online (Sandbox Code Playgroud)

如果你想要能够提出更一般的问题,例如"哪只鸟可以飞?",或"哪只鸟不能飞?",你需要明确列出飞鸟或非飞鸟.由于大多数鸟类可以飞行,让我们明确列出非飞行鸟类:

bird(eagle).
bird(penguin).
bird(ostrich).
bird(dodo).
bird(sparrow).
bird(pigeon).

flightless_bird(penguin).
flightless_bird(ostrich).
flightless_bird(dodo).

bird_of_pray(eagle).

extinct(dodo).
extinct(wooly_mammoth).

can_fly(Bird) :-
    bird(Bird),
    \+ flightless_bird(Bird).

extinct_bird(Bird) :-
    bird(Bird),
    extinct(Bird).
Run Code Online (Sandbox Code Playgroud)

注意使用ISO谓词进行否定\+/1.如果无法证明目标,那就确实如此.它比您正在使用的故障切割组合更清洁.

如何组织你的知识是一个完全不同的问题.我给出的例子不完整,不一定是最好的方法.作为一般规则,您应该尝试将数据保持为规范化形式,事实和事实条款扮演表和表行的角色.

希望这个答案指向正确的方向.