查询

1
2
3
?- parent(anakin,Who).
Who = luke
Who = leia

一个查询可能有多个正确答案

返回false表示没有找到

Conditional Sentences 条件语句

组成:

Consequent 结论

Implication 蕴含关系

Antecedent 前提

image-20260113195140657

1
mother(X,Y) :- parent(X,Y), female(X).

若X是Y的父母且X为女性,则X是Y的母亲。

逗号表示‘’和’

1
2
father(X,Y) :- parent(X,Y), male(X).
grandparent(X,Y) :- parent(X,Z), parent(Z,Y)

“若X是某个Z的父母,且Z是Y的父母,则X是Y的祖父母。”

Negation 否定

Prolog 中的“非”符号是 \+

例:

1
?- parent(X,luke), \+ female(X).

找到luke的父母中不是女性的那位

Equality 相等

Prolog 支持等式: X=Y,但通常不需要单独写 X=Y 而是直接用同一个变量名

写法 A(用等式把两个变量连起来)

1
parent(X,Y), parent(Z,A), Y = Z

写法 B(直接用同一个变量):

1
parent(X,Y), parent(Y,A).

Negated equalit 否定相等

否定相等非常有用

1
sibling(X,Y) :- parent(Z,X), parent(Z,Y), \+ X = Y

解释:

parent(Z,X), parent(Z,Y):X 和 Y 有同一个父母 Z

\+ X = Y:并且 X 不能和 Y 统一(直观上就是 X 和 Y 不是同一个人

练习1

1.写 “sister” 和 “brother” 的定义(提示:利用我们已经定义的“sibling”概念)

答案 brother(X, Y) :- sibling(X, Y), male(X).
sister(X,Y) :- sibling(X,Y),female(X).

2.查询:luke的妹妹(sister)是谁?

答案 ?- sister(X, luke).

3.为“great-grandparent”写一个定义。(提示:利用“grandparent”的概念…)

答案 great_grandparent(GGP, X) :- grandparent(GGP, P), parent(P, X).

4.查询:知识库中是否存在某人的曾祖父母与他人存在亲属关系?

(答案代补充)

Anonymous variable 匿名变量

Prolog 使用 _ 符号作为匿名变量,当需要验证某事物存在但不关心其具体内容时使用

1
2
?- parent(_,anakin).
true

Anakin 是否有父亲?

切勿将匿名变量用于需重复使用的值

如:

1
grandparent(X,Y) :- parent(X,Z), parent(Z,Y)

Z的值至关重要

1
grandparent(X,Y) :- parent(X,_), parent(_,Y) 

将导致错误结果

Disjunction 析取

Prolog 支持 AND、IF/THEN、NOT 以及 OR 运算符

OR 运算符用分号 ; 表示

1
2
3
?- mother(X,anakin); mother(X,ben).
X = shmi
X = lei

X 是anakin或ben的母亲

Write predicate输出谓词

Prolog不擅长I/O操作——但确实提供“write”谓词
主要用于调试

1
2
3
4
?- father(anakin,X), write('No, '), write(X),
write(', I am your father.’).
No, luke, I am your father.
No, leia, I am your fath

练习2

1.找出某个角色的子女 ,但该角色本身并非父母

答案 ?- (father(X,Y) ; mother(X,Y)),
      \+ (father(Y,_) ; mother(Y,_)).

2.找出所有既是兄弟(brother)又是曾祖父母(great-grandparent)的角色, 但我们不关心他们是某人的兄弟还是某人的曾祖父母

答案 ?- brother(X,_);great-grandparent(X,_).

Terms 项

Prolog包含多种项:

常量(constant)

变量(variable)

数字(number)

constant 常量

Prolog常量必须以小写字母开头

后可跟任意数量的字母、下划线或数字, 常量也可为带引号的字符串

因此以下均为合法常量:
• sue
• opp_sex
• mamboNumber
• ‘Who are you?’

variable 变量

Prolog 变量必须以大写字母开头
后可跟任意数量的字母下划线数字

因此以下均为合法变量:
• X
• P1
• MyDog
• The_biggest_number
• Variable_27b

Atomic sentences 原子句(或称”atoms原子”)

具有如下形式:

1
predicate(term1, …, termk).

• predicate: 谓词名(必须是一个常量/atom,一般小写开头
term1 … termk:参数项,每个项要么是 常量,要么是 变量

注意标点符号:
• 括号
• 每个词条之间的逗号
• 句末的句号

谓词的项数(term)k称为谓词的元数(arity)
• 若k=0,则括号可省略。

例如:

  • likes(john, mary).likes/2(2 个参数)
  • human(socrates).human/1

Conditional sentences 条件句

Conditional sentences have the form:

1
head :- body_1, ..., body_n.

若n=0,则应省略:-符号,此时该结构即成为原子(atom)

Clauses 子句

Prolog程序是由一串 clauses(子句)的序列组成

也就是:你写的一行一行东西,本质上都是“子句”。

1
Clause=原子句 或 条件句

Unification 统一

也就是 Prolog 在回答查询时,如何把“你问的问题”和“知识库里的事实/规则”对上号,并自动求出变量该取什么值

假设知识库中有:

1
2
parent(padme,leia).
child(X,Y) :-parent(Y,X).

以及以下查询:

1
?- child(leia,padme).

那么prolog如何进行查询呢?

1.逐行看程序

​ Prolog 在尝试证明一个目标时,会按照知识库里规则/事实出现的顺序去尝试。

2.找一行能和 parent(padme, leia) 统一

​ 假设当前我们需要证明(或已经推导出)这个子目标

parent(padme, leia).

​ Prolog 就会在 KB 里找一条能与它 统一 的事实或规则头。

​ 如果有“完全匹配”的行,会最简单

​ 如果我们有一个 exact match,它就会统一

​ 如child(leia, padme).

• 在Prolog中,统一(Unification)两个子句(clauses)意味着使它们相同。
• 我们不能改变常量、谓词名称(predicate names)或谓词(predicate)的参数数量。
• 但遇到变量时,可为其赋予任意所需值。

• 因此统一(Unification)两个子句(clauses),即为子句(clauses)中的变量寻找值,使子句最终变得相同。

[!NOTE]

如果统一(Unification)一直做不出来(或者做出来但证明不了),Prolog 会怎么办?

答案是:Prolog会一直试、回溯、一直试到知识库末尾;都不行才返回 false。

在更复杂的程序中
可能存在:
• 不止一个正确答案
• 同一个答案可能有不止一种推导方式
• 多步推理(递归)

练习3

以下哪个表达式能与brother(luke,X)统一?若能统一,需为哪些变量赋值?若不能统一,原因是什么?

  1. brother(luke).
  2. brother(Y,Z).
  3. brother(Y,leia).
  4. brother(luke,threepio).
  5. sister(leia,luke).