Prolog - 对称谓词

时间:2009-04-26 23:28:06

标签: prolog predicate symmetric

我必须在prolog中模拟家谱。 我有对称谓词的问题。 的事实:

parent(x,y).
male(x).
female(y).
age(x, number).

规则:

blood_relation让我很头疼。这就是我所做的:

blood_relation(X,Y):-ancestor(X,Y).
blood_relation(X,Y):-uncle(X,Y);brother(X,Y);sister(X,Y);(mother(Z,Y),sister(X,Z));(father(Z,Y),sister(X,Z));(father(Z,Y),brother(X,Z)).
blood_relation(X,Y):-uncle(X,Z),blood_relation(Z,Y).

我得到了令人满意的结果(我有双版画 - 我可以解决这个问题),问题是我希望这种关系是对称的。现在不是。

blood_relation(johns_father, joh):yes 
blood_relation(john,johns_father): no

所以......有办法解决这个问题。 我需要查询:所有不在血液中的对..

更新

  

第一句话应该满足哪种关系?   blood_relation(X,Y): - blood_relation(X,Y)

抱歉..这是一个糟糕的副本/粘贴..

blood_relation(X,Y):-ancestor(X,Y).

现在修正了。

这是其他规则:

father(X,Y):-parent(X,Y),male(X).  
mother(X,Y):-parent(X,Y),female(X).  
brother(X,Y):-parent(Z,X),parent(Z,Y),male(X).  
sister(X,Y):-parent(Z,X),parent(Z,Y),female(X).  
grandFather(X,Y):-parent(Z,Y),parent(X,Z),male(X).  
grandMother(X,Y):-parent(Z,Y),parent(X,Z),female(X).  
uncle(X,Y):-mother(Z,Y),brother(X,Z).  
ancestor(X,Y):-ancestor(X,Y).  
ancestor(X,Y):-parent(X,Z),ancestor(Z,Y).

母亲的兄弟在叔叔的定义中。这有点奇怪。我已经制定了需要实施的规则,除此之外我不知道如何实施规则。我只是困惑。

知道如何让blood_relation对称吗? not_blood_relation是一个新规则。我需要查询。这个真的让我很头疼。也许是因为关系被写成废话。

没有更多的事实。就这样。所有规则和所有事实。

查询.. not(blood_relation(X,Y))不起作用,我真的不知道为什么。 例如查询:

age(X,Y), Y>18,  
not(parent(X,Z)),write(X),nl,fail.

工作得很好

3 个答案:

答案 0 :(得分:8)

使特定谓词对称的天真解决方案并不是一个体面的解决方案。为了一般性,让我们看一下友情关系,这样人们就不会被舅舅等绊倒。

以下是一些详细描述友谊关系的事实(例如,数字是用户ID,参数的特定顺序来自谁发起了友谊)。

friends(1,2).
friends(5,2).
friends(7,4).

你最初认为像“friends(A,B) :- friends(B,A).”这样的规则可以解决问题,但这会引导你进行无限递归,因为它告诉prolog如果它只是再次交换参数它可能会起作用。有一个名为“@</2”的谓词告诉您一个术语(甚至是一个变量)是否在“标准术语顺序”之前出现在另一个术语之前。技术含义在这里并不是那么重要,但我们关心的是,对于两个不同的术语,它们只适用于它们的一个顺序。我们可以用它来打破无限递归!

此单一规则将使“friend/2”对称。

friends(A,B) :- A @< B, friends(B,A).

尽管如此,但应该采用大型项目​​的方法。回想一下,在我的事实列表中args的排序有一些实际意义(谁发起了友谊)。添加最终规则会破坏对此信息的未来访问,并且对于读取代码的其他人来说,将对称属性隐藏在单行代码中,这在面对一堆硬编码数据时很容易被忽略。

考虑工业强度解决方案:

friended(1,2).
friended(5,2).
friended(7,4).

friends(A,B) :- friended(A,B).
friends(A,B) :- friended(B,A).

它比较庞大,但它可以在不使用模糊谓词的情况下干净利落地读取并保留原始信息(有时您可能希望在实际应用程序中再次使用)。

-

至于找到具有特定属性的对,请确保在使用否定查找实际个体时,始终包含一些谓词以在规则中提供上下文。

potential_enemies(A,B) :- user(A), user(B), \+ friends(A,B).

答案 1 :(得分:1)

有点像家庭作业,不是吗......

大多数prolog初学者没有想到的一个技巧是列表模式匹配。想象[a1,[[a2],[b2,[[e3],[f3]]],[c2]]这样的树,如<tree&gt; = [root,[{{1} }&GT;,<tree1&GT;,...]]:

<tree2

我认为你可以改进这一点,使用对作为根,添加性别,给树的成员的特定关系命名......

答案 2 :(得分:0)

第一个声明应该满足哪种关系?

blood_relation(X,Y):-blood_relation(X,Y).

这并没有告诉你任何你还没有“知道”的东西,并且会导致你的递归头痛。至于“不”的答案,看起来你已经从查询中得到了所有答案,并且解释器只是告诉你已经没有了。

你真的应该发布更多的事实,以及叔叔/ 2的定义,并且有没有理由说你不能匹配母亲的兄弟,只有她的妹妹?您还有很多其他问题需要解决: - )。

对于一切不是血缘关系的人,试试这个:

not_blood_relation(X, Y) :- blood_relation(X, Y), !, fail.
not_blood_relation(X, Y).

问问自己为什么会这样做!