1

我正在尝试在我的序言程序中编写一条规则,以确定某人是否是其他人的兄弟。

例如,如果我输入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.
4

1 回答 1

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 代码时通常不鼓励使用 using(不过,您可以在需要时使用)。相反,将其写在两个子句中:

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.

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

于 2012-04-20T03:07:22.837 回答