1. 问题背景
- 关系图(Relationship)

- 核心代码
parent(pam, bob).
parent(tom, bob).
parent(tom, liz).
parent(bob, ann).
parent(bob, pat).
parent(pat, jim).
- 问题:需要查询jim的grandparent
- 关系图(Relatinoship)

- 我的代码
parent(_ jim), parent(P, _).
- 查询结果
- 发现与真实的结果相差甚远,

- 于trace后发现原因,是因为在执行完第一个
parent(_, jim)
之后,在parent(P, _)
没有传值,所以其实第一个parent查出了jim的父母,pat
但是因为第二个parent(P, _)
的影响, P
的值可以是随意的,第一个parent
的限制并没有传到第二个parent这里。

- 但是这个地方也没有redo回
parent(_, jim)
,很奇怪
2. 效率问题
- 以下两个查询语句都可以查询jim的祖父母,
parent(X,Y), parent(Y, jim).
和 parent(Y,jim), parent(X, Y)
, 但是后者效率更快,因为更精确,直接得到Y的值然后查询;然而第一个是随即乱查,查完之后再拿随机的值来对比。 - Simpelst first, 明确的值first。原因:明确的值可以减少我们的搜索流程。
- Trace:
parent(X,Y), parent(Y, jim).

- Trace:
parent(Y,jim), parent(X, Y)

3. Unary clause 和 Binary clause
- Unary clause - 通常用于表示object的属性(properties)
female(pam).
male(tom).
male(bob).
female(liz).
female(pat).
female(ann).
male(jim).
- Binary clause - 通常用于表示object与object之间的联系(relationship)
sex(pam, feminine).
sex(tom, masculine).
sex(bob, masculine).
4. Some baisc terms
- facts: simple facts
parent(pam, bob).
parent(tom, bob).
parent(tom, liz).
- questions: query that wants to be satisfied
-? parent(X, bob).
- rules: some rules
offspring(Y, X) :- parent(X, Y).
- Difference between facts and rules
- Facts: something that is always.
- Rules: something that is conditional, including a condition part and a conclusion part.
- head: conclusion part, body: condition part.
- For all X, Y: Y is an offspring of X if X is the parent of Y.

- More exmpales,
- Definition of
mother
, which can be written as mother(X,Y) :- female(X), parent(X,Y).
- For all X, Y: X is the mother of Y if X is female and X is the parent of Y.
5. 书写格式
- For clearity of codes, we will often choose to write the head of a clause and each goal of the body on a seperate line.
- We will also indent goals in order to make the difference between the head and the goals more visible.
6. 无记忆问题(重复自己)
- Prolog在查询的时候,并不会代入之前我们查询的条件,我们之前也验证了,当我们输入goals
parent(_ jim), parent(P, _).
的时候,没有办法查询到jim的祖父母,而是把所有的 parent
的relationship给查出来了,原因就是prolog的无记忆性,它在过了parent(_, jim)
之后,由于这个_
是匿名变量,并不会传参给下一个,所以下一个查询语句就变成了 parnet(P, _)
就相当于第一个条件不存在一样,自然把所有的parent
的 relationship都给查出来了。 - 同样我们也遇到了sister查询的问题
sister(X,Y) :- female(X), parent(Z, X), parent(Z, Y).
- 这样的rules查出来的
sister
会带有自己,是因为前方一路传参虽然没有错,(但是由于无记忆性),它的参数边传递会边掉。所以最后查出来的 Z
虽然是我们想要的,这个相当于就是一个新的clause, parent(Z, _)
自然就会把 Z
的所有子女给打印出来了。 - 所以对于这类无记忆性问题的解决办法之一,可以最后加一个判断,给把相同的排除掉
sister(X,Y) :- female(X), parent(Z, X), parent(Z, Y), different(X, Y).
- 解决!
- 注意 这个地方
different(X, Y)
是个伪代码,我们假设Prolog有这个代码,如果你直接这样复制是不会生效,有用的!
7. Summary
- Prolog clauses are of three types: facts, rules and questions.
- Facts declare things that are always, unconditionally true.
- Rules declare things that are true depending on a given condition.
- Questions are that the user can ask the program what things are true.
- Prolog clauses consist of the head and the body.
- The body is a list of goals separated by commas. Commas are understood as conjunctions.
- Facts are clauses that have the empty body (only conclusion).
- Questions only have the body (only condition).
- Rules have the head and the (non-empty) body (both conclusion and condition).
- Reading & Understanding
- Rules语句:
hasachild(X) :- parent(X,Y).
- For all X and Y, if X is a parent of Y then X has a child.
- For all X, X has a child if there is some Y such that X is a parent of Y.