COGS201 学习笔记 week 2
查询
1 | ?- parent(anakin,Who). |
一个查询可能有多个正确答案
返回false表示没有找到
Conditional Sentences 条件语句
组成:
Consequent 结论
Implication 蕴含关系
Antecedent 前提

1 | mother(X,Y) :- parent(X,Y), female(X). |
若X是Y的父母且X为女性,则X是Y的母亲。
逗号表示‘’和’
1 | father(X,Y) :- parent(X,Y), male(X). |
“若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 | ?- parent(_,anakin). |
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 | ?- mother(X,anakin); mother(X,ben). |
X 是anakin或ben的母亲
Write predicate输出谓词
Prolog不擅长I/O操作——但确实提供“write”谓词
主要用于调试
1 | ?- father(anakin,X), write('No, '), write(X), |
练习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 | parent(padme,leia). |
以及以下查询:
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)统一?若能统一,需为哪些变量赋值?若不能统一,原因是什么?
- brother(luke).
- brother(Y,Z).
- brother(Y,leia).
- brother(luke,threepio).
- sister(leia,luke).