【问题标题】:Existence Exception in Prolog ProgramProlog 程序中存在异常
【发布时间】:2012-04-20 03:03:07
【问题描述】:

我正在尝试在我的 prolog 程序中编写一个规则来确定某人是否是其他人的兄弟。

例如,如果我输入brother_of(chris, X) 它将返回christy,因为chris 是christy 的兄弟。但是,当我输入这个时,我得到一个存在异常。我已经包含了涵盖所有内容的事实,但也许这是我的规则定义中的问题?代码如下。

/* Facts */
female(ella).
female(jodi). 
female(sonya).
female(jane). 
female(christy). 
female(mary).
male(arnold).
male(chris).
male(louis).
male(mark).  
father(arnold).
father(louis).
father(mark).
mother(ella).
mother(jodi).
mother(jane).
mother(mary).
father_of(arnold, chris). /* arnold is the father of chris */
father_of(arnold, christy).
father_of(louis, mark).
father_of(mark, arnold). 
mother_of(mary, chris).
mother_of(mary, christy).          
mother_of(jane, arnold).    
mother_of(ella, sonya).
mother_of(jodi, ella).
mother_of(jodi, mark).

/* Rules */

brother_of(X, Y) :-
    male(X),
    ((father_of(Z, X), father_of(Z, Y));
    (mother_of(W, X), mother_of(W, Y))),
    X =\= Y.

【问题讨论】:

    标签: prolog


    【解决方案1】:

    运算符 =\= 仅用于算术运算 (AFAIK),要查看两个术语是否不同(不可统一),请使用运算符 \=:

    X \= Y.
    

    更新:对cut (!) 目标的简要介绍:当在谓词中使用cut 时,意味着除了已经找到的答案(即您正在搜索树中“切割剩余的分支”)。示例:

    first_child(X,Y) :-
        father_of(X,Y), !.
    
    ?- first_child(arnold,Y).
    
    Y = chris ;
    
    no
    

    到达剪切后,所有在剪切之前的选择点都将被丢弃(但可以在剪切之后创建新的选择点)。在您的示例中,您知道如果 X 和 Y 有同一个父亲,那么他们是否也有同一个母亲是无关紧要的。因此,您可以在“共同父亲”部分成功后立即进行剪辑:

    brother_of(X, Y) :-
        male(X),
        ((father_of(Z, X), father_of(Z, Y), X \= Y, !); # If cut is reached, will not run the next line
        (mother_of(W, X), mother_of(W, Y), X \= Y)).
    

    但是请注意,使用 cut 有很多陷阱(请参阅链接的 Wikipedia 文章中的“green cut”与“red cut”),但这里描述的太多了。 (注意我是如何重复X \= Y - 如果我不这样做,程序有时会失败)

    最后,我还想指出,在编写 Prolog 代码时通常不鼓励使用 ;(不过,您可以在需要时使用)。相反,将其写在两个子句中:

    brother_of(X, Y) :-
        male(X),
        father_of(Z, X),
        father_of(Z, Y), 
        X \= Y,
        !.
    brother_of(X, Y) :-
        male(X),
        mother_of(W, X),
        mother_of(W, Y), 
        X \= Y.
    

    (不过,; vs 两个子句有点主观,所以我不会对此进行过多争论......只要知道两种方式都是可能的,并且会产生相同的结果)

    【讨论】:

    • 成功了,谢谢!但是现在当我问 Brother_of(chris, X) 时,它会返回 christy 两次。在第一次返回 christy 后,我输入“;”确保不再有,不应该有,所以它应该返回“no”,但它再次返回 christy。关于为什么的任何想法?
    • 您需要cut 目标:!。询问我是否需要有关如何使用它的帮助(不知道您是否已经在学习中看到它)
    • 其实我没见过。我该如何使用它?
    • @aclark 没有看到您的评论,正在写回复... :) 无论如何,我希望它有所帮助!
    • 在这里使用 !/0 是不幸的,因为它消除了有效的解决方案,例如在查询 ?-brother_of(X, Y) 中。您可以使用 dif/2 代替 (\=)/2,当它的一个或两个参数都是变量时也可以使用,因此更容易理解和使用。
    猜你喜欢
    • 2023-03-06
    • 2022-07-20
    • 2011-12-12
    • 2011-08-08
    • 1970-01-01
    • 2010-12-24
    • 1970-01-01
    • 2016-11-03
    • 2011-09-20
    相关资源
    最近更新 更多