序言— 对称谓词
我必须在序言中模拟家谱。 我有对称谓词的问题。 事实:
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, john):yes
blood_relation(john,johns_father): no
那么..有没有办法解决这个问题。 我需要查询:所有不在 Blood_relation 中的对..
更新:
第一个语句应该满足什么类型的关系? 血液关系(X,Y):-血液关系(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
是一条新规则。 我需要查询。 这个实在是让我很头疼。 也许是因为关系写得像垃圾。
没有更多的事实了。 就这样。 所有规则,所有事实。
query.. not(blood_relation(X,Y))
不起作用,我真的不知道为什么。
例如查询:
age(X,Y), Y>18,
not(parent(X,Z)),write(X),nl,fail.
工作得很好
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使特定谓词对称的简单解决方案与一个不错的解决方案相差不远。 为了一般性起见,让我们看一下友谊关系,这样人们就不会被叔叔之类的事情绊倒。
以下是一些详细说明友谊关系的事实(例如,数字是用户 ID,参数的特定顺序来自发起友谊的人)。
您最初会认为像“
friends(A,B) :-friends(B,A).
”这样的规则可以解决问题,但这会导致无限递归,因为它告诉序言:如果它只是再交换一次参数,它可能会起作用。 有一个名为“@”的谓词,它告诉您一个术语(甚至是一个变量)是否按照“术语的标准顺序”出现在另一个术语之前。 技术含义在这里并不那么重要,但我们关心的是,对于两个不同的术语,它仅适用于它们的一种排序。 我们可以用它来打破无限递归!
这条规则将负责使“
friend/2
”对称。尽管这很简洁,但对于大型项目,您应该采取一种方法。 回想一下,我的事实列表中参数的顺序具有一些实际意义(谁发起了友谊)。 添加最终规则破坏了将来对该信息的访问,并且对于阅读代码的其他人来说,将对称属性隐藏在一行代码中,这在面对硬编码数据块时很容易被忽略。
考虑工业强度的解决方案:
它体积更大,但它可以清晰地读取而不使用晦涩的谓词,并保留原始信息(有一天您可能会在实际应用程序中再次需要这些信息)。
--
至于查找不具有特定属性的对,请确保当您使用否定来查找实际个体时,始终在规则中包含一些谓词以提供上下文。
The naive solution to making a particular predicate symmetric isn't that far from a decent one. For the sake of generality, let's look at a friendship relation so people don't get tripped up on uncles and the like.
Here are some facts detailing a friendship relation (where, say, the numbers are user ids and the particular ordering of the arguments came from who initiated the friendship).
You'd initially think a rule like "
friends(A,B) :- friends(B,A).
" would fix things right up, but this leads you to infinite recursion because it tells prolog that if it just swaps the argument one more time it might just work. There is a predicate called "@</2
" that tells you whether one term (even a variable) comes before another in the "standard order of terms". The technical meaning isn't all that important here, but what we care about is that for two different terms it is only true for one ordering of them. We can use this to break the infinite recursion!This single rule will take care of making "
friend/2
" symmetric.As neat as this is, there is an approach way you should take for large projects. Recall that the ordering of the args in my list of facts had some actual meaning (who initiated the friendship). Adding the final rule destroyed future access to this information and, for other people reading the code, hides the symmetric property in a single line of code which is easy to ignore in the face of a block of hard-coded data.
Condsider the industrial-strength solution:
It is bulkier, but it reads cleanly without using obscure predicates and retains the original information (which you might want again someday in a real application).
--
As for finding pairs that don't have a specific property, make sure you always include some predicate to provide context in your rule when you use negation to look for actual individuals.
有点像家庭作业,不是吗……
大多数 prolog 初学者都没有想到的一个技巧是列表模式匹配。 想象一棵像 [a1,[[a2],[b2,[[e3],[f3]]],[c2]]] 的树,如>=[root, [>,>,...]]:
我认为你可以对此进行改进,例如使用对作为根,添加性别,为树中成员的特定关系命名...
A bit looks like a homework, isn't it...
One trick which most of beginners of prolog don't think of is list pattern matching. Think of a tree like [a1,[[a2],[b2,[[e3],[f3]]],[c2]]] as in
<tree
>=[root,[<tree1
>,<tree2
>,...]]:I think you can improve upon this like, using pairs as roots, adding genders, giving names to specific relations of members of the tree...
第一个语句应该满足什么类型的关系?
这并没有告诉你任何你不“知道”的事情,并且会导致你的递归头痛。 至于“否”答案,看起来您已经从查询中获得了将要获得的所有答案,而解释器只是告诉您没有更多答案。
您确实应该发布更多事实以及叔叔/2 的定义,并且您是否有理由不匹配母亲的兄弟,而只匹配她的妹妹? 您还有很多其他问题需要解决:-)。
对于所有非血缘关系的事情,试试这个:
问问自己为什么它有效!
What kinds of relationships is the first statement supposed to satisfy?
That isn't telling you anything that you don't already "know" and is going to cause you recursion headaches. As for the 'no' answer, is looks like you've already gotten all of the answers from the query that you are going to get, and the interpreter is just telling you that there aren't any more.
You really should post more facts, and the definition of uncle/2, and is there a reason why you're not matching a mother's brother, just her sister? You have lots of other issues to work on :-).
For everything that is not a blood relation, try this:
And ask yourself why it works!