- 序言教程
- 序言 - 主页
- Prolog - 简介
- Prolog - 环境设置
- Prolog - 你好世界
- Prolog - 基础知识
- Prolog - 关系
- Prolog - 数据对象
- Prolog - 运算符
- 循环与决策
- 连接词和析取词
- Prolog - 列表
- 递归和结构
- Prolog - 回溯
- Prolog - 不同与不同
- Prolog - 输入和输出
- Prolog - 内置谓词
- 树数据结构(案例研究)
- Prolog - 示例
- Prolog - 基本程序
- Prolog - 剪切示例
- 河内塔问题
- Prolog - 链接列表
- 猴子和香蕉问题
- Prolog 有用资源
- Prolog - 快速指南
- Prolog - 有用的资源
- Prolog - 讨论
Prolog - 关系
关系是我们在 Prolog 中必须适当提及的主要特征之一。这些关系可以表达为事实和规则。之后我们将了解家庭关系,如何在 Prolog 中表达基于家庭的关系,以及家庭的递归关系。
我们将通过创建事实和规则来创建知识库,并对它们进行查询。
Prolog 中的关系
在Prolog程序中,它指定了对象和对象的属性之间的关系。
假设有一条语句“Amit 有一辆自行车”,那么我们实际上是在声明两个对象之间的所有权关系——一个是 Amit,另一个是自行车。
如果我们问一个问题,“阿米特有自行车吗?”,我们实际上是在试图找出一种关系。
关系有很多种,其中有些也可以是规则。即使关系没有明确定义为事实,规则也可以找出关系。
我们可以定义兄弟关系如下 -
两个人是兄弟,如果,
他们都是男性。
他们有同一个父母。
现在考虑我们有以下短语 -
父母(sudip,piyus)。
父母(sudip,raj)。
男(piyus)。
男(拉吉)。
兄弟(X,Y):-父母(Z,X),父母(Z,Y),男性(X),男性(Y)
这些子句可以给我们答案:piyus 和 raj 是兄弟,但这里我们将得到三对输出。它们是:(piyus,piyus),(piyus,raj),(raj,raj)。对于这些对,给定的条件是正确的,但是对于(piyus,piyus),(raj,raj)这对,他们实际上不是兄弟,他们是同一个人。因此,我们必须正确地创建子句才能形成关系。
修改后的关系如下 -
A 和 B 是兄弟,如果 -
A和B均为男性
他们有同一个父亲
他们有同一个母亲
A和B不一样
Prolog 中的家庭关系
在这里我们将看到家庭关系。这是可以使用 Prolog 形成复杂关系的示例。我们想要制作一个家谱,并将其映射为事实和规则,然后我们可以对它们运行一些查询。
假设家谱如下 -
从这棵树上,我们可以了解到,关系很少。这里鲍勃是帕姆和汤姆的孩子,鲍勃还有两个孩子——安和帕特。鲍勃有一个兄弟莉兹,他的父母也是汤姆。所以我们想要做出如下谓词 -
谓词
父母(帕姆,鲍勃)。
父母(汤姆,鲍勃)。
父母(汤姆,莉兹)。
父母(鲍勃,安)。
父母(鲍勃,帕特)。
父母(帕特,吉姆)。
父母(鲍勃,彼得)。
父母(彼得,吉姆)。
从我们的例子中,它有助于说明一些重要的观点 -
我们根据家谱中给定的信息声明对象的 n 元组来定义父关系。
用户可以轻松地向Prolog系统查询程序中定义的关系。
Prolog 程序由以句号终止的子句组成。
关系的参数可以(除其他外)是:具体对象,或常量(例如 pat 和 jim),或一般对象,例如 X 和 Y。我们程序中的第一类对象称为Atomics。第二类对象称为变量。
对系统的问题包含一个或多个目标。
有些事实可以用两种不同的方式来写,例如家庭成员的性别可以用任何一种形式来写 -
女性(帕姆)。
男(汤姆)。
男(鲍勃)。
女(莉兹)。
女(拍拍)。
女(安)。
男(吉姆)。
或者采用下面的形式 -
性别(pam,女性)。
性别(汤姆,男性)。
性别(鲍勃,男性)。
… 等等。
现在,如果我们想建立母亲和姐妹的关系,那么我们可以写如下 -
在 Prolog 语法中,我们可以写 -
母亲(X,Y):-父母(X,Y),女性(X)。
姐妹(X,Y):- 父母(Z,X),父母(Z,Y),女性(X),X \== Y。
现在让我们看看实际演示 -
知识库 (family.pl)
female(pam). female(liz). female(pat). female(ann). male(jim). male(bob). male(tom). male(peter). parent(pam,bob). parent(tom,bob). parent(tom,liz). parent(bob,ann). parent(bob,pat). parent(pat,jim). parent(bob,peter). parent(peter,jim). mother(X,Y):- parent(X,Y),female(X). father(X,Y):- parent(X,Y),male(X). haschild(X):- parent(X,_). sister(X,Y):- parent(Z,X),parent(Z,Y),female(X),X\==Y. brother(X,Y):-parent(Z,X),parent(Z,Y),male(X),X\==Y.
输出
| ?- [family]. compiling D:/TP Prolog/Sample_Codes/family.pl for byte code... D:/TP Prolog/Sample_Codes/family.pl compiled, 23 lines read - 3088 bytes written, 9 ms yes | ?- parent(X,jim). X = pat ? ; X = peter yes | ?- mother(X,Y). X = pam Y = bob ? ; X = pat Y = jim ? ; no | ?- haschild(X). X = pam ? ; X = tom ? ; X = tom ? ; X = bob ? ; X = bob ? ; X = pat ? ; X = bob ? ; X = peter yes | ?- sister(X,Y). X = liz Y = bob ? ; X = ann Y = pat ? ; X = ann Y = peter ? ; X = pat Y = ann ? ; X = pat Y = peter ? ; (16 ms) no | ?-
现在让我们看看我们可以从以前的家庭关系中建立更多的关系。因此,如果我们想建立祖父母关系,可以如下形成 -
我们还可以创建一些其他关系,如妻子、叔叔等。我们可以将这些关系写成如下 -
祖父母(X,Y):- 父母(X,Z),父母(Z,Y)。
祖母(X,Z):-母亲(X,Y),父母(Y,Z)。
祖父(X,Z):-父亲(X,Y),父母(Y,Z)。
妻子(X,Y):-父母(X,Z),父母(Y,Z),女性(X),男性(Y)。
叔叔(X,Z):-兄弟(X,Y),父母(Y,Z)。
那么让我们编写一个 prolog 程序来看看它的实际效果。在这里我们还将看到跟踪执行情况的跟踪。
知识库 (family_ext.pl)
female(pam). female(liz). female(pat). female(ann). male(jim). male(bob). male(tom). male(peter). parent(pam,bob). parent(tom,bob). parent(tom,liz). parent(bob,ann). parent(bob,pat). parent(pat,jim). parent(bob,peter). parent(peter,jim). mother(X,Y):- parent(X,Y),female(X). father(X,Y):-parent(X,Y),male(X). sister(X,Y):-parent(Z,X),parent(Z,Y),female(X),X\==Y. brother(X,Y):-parent(Z,X),parent(Z,Y),male(X),X\==Y. grandparent(X,Y):-parent(X,Z),parent(Z,Y). grandmother(X,Z):-mother(X,Y),parent(Y,Z). grandfather(X,Z):-father(X,Y),parent(Y,Z). wife(X,Y):-parent(X,Z),parent(Y,Z),female(X),male(Y). uncle(X,Z):-brother(X,Y),parent(Y,Z).
输出
| ?- [family_ext]. compiling D:/TP Prolog/Sample_Codes/family_ext.pl for byte code... D:/TP Prolog/Sample_Codes/family_ext.pl compiled, 27 lines read - 4646 bytes written, 10 ms | ?- uncle(X,Y). X = peter Y = jim ? ; no | ?- grandparent(X,Y). X = pam Y = ann ? ; X = pam Y = pat ? ; X = pam Y = peter ? ; X = tom Y = ann ? ; X = tom Y = pat ? ; X = tom Y = peter ? ; X = bob Y = jim ? ; X = bob Y = jim ? ; no | ?- wife(X,Y). X = pam Y = tom ? ; X = pat Y = peter ? ; (15 ms) no | ?-
跟踪输出
在 Prolog 中我们可以跟踪执行情况。要跟踪输出,您必须输入“trace.”进入跟踪模式。然后从输出中我们可以看到我们只是在追踪“pam is mother of who?”。通过将 X = pam 和 Y 作为变量来查看跟踪输出,其中 Y 将是 bob 作为答案。要退出跟踪模式,请按“notrace”。
程序
| ?- [family_ext]. compiling D:/TP Prolog/Sample_Codes/family_ext.pl for byte code... D:/TP Prolog/Sample_Codes/family_ext.pl compiled, 27 lines read - 4646 bytes written, 10 ms (16 ms) yes | ?- mother(X,Y). X = pam Y = bob ? ; X = pat Y = jim ? ; no | ?- trace. The debugger will first creep -- showing everything (trace) yes {trace} | ?- mother(pam,Y). 1 1 Call: mother(pam,_23) ? 2 2 Call: parent(pam,_23) ? 2 2 Exit: parent(pam,bob) ? 3 2 Call: female(pam) ? 3 2 Exit: female(pam) ? 1 1 Exit: mother(pam,bob) ? Y = bob (16 ms) yes {trace} | ?- notrace. The debugger is switched off yes | ?-
家庭关系中的递归
在上一节中,我们已经看到我们可以定义一些家庭关系。这些关系本质上是静态的。我们还可以创建一些递归关系,可以用下图来表达 -
所以我们可以理解,前驱关系是递归的。我们可以使用以下语法来表达这种关系 -
predecessor(X, Z) :- parent(X, Z). predecessor(X, Z) :- parent(X, Y),predecessor(Y, Z).
现在让我们看看实际演示。
知识库 (family_rec.pl)
female(pam). female(liz). female(pat). female(ann). male(jim). male(bob). male(tom). male(peter). parent(pam,bob). parent(tom,bob). parent(tom,liz). parent(bob,ann). parent(bob,pat). parent(pat,jim). parent(bob,peter). parent(peter,jim). predecessor(X, Z) :- parent(X, Z). predecessor(X, Z) :- parent(X, Y),predecessor(Y, Z).
输出
| ?- [family_rec]. compiling D:/TP Prolog/Sample_Codes/family_rec.pl for byte code... D:/TP Prolog/Sample_Codes/family_rec.pl compiled, 21 lines read - 1851 bytes written, 14 ms yes | ?- predecessor(peter,X). X = jim ? ; no | ?- trace. The debugger will first creep -- showing everything (trace) yes {trace} | ?- predecessor(bob,X). 1 1 Call: predecessor(bob,_23) ? 2 2 Call: parent(bob,_23) ? 2 2 Exit: parent(bob,ann) ? 1 1 Exit: predecessor(bob,ann) ? X = ann ? ; 1 1 Redo: predecessor(bob,ann) ? 2 2 Redo: parent(bob,ann) ? 2 2 Exit: parent(bob,pat) ? 1 1 Exit: predecessor(bob,pat) ? X = pat ? ; 1 1 Redo: predecessor(bob,pat) ? 2 2 Redo: parent(bob,pat) ? 2 2 Exit: parent(bob,peter) ? 1 1 Exit: predecessor(bob,peter) ? X = peter ? ; 1 1 Redo: predecessor(bob,peter) ? 2 2 Call: parent(bob,_92) ? 2 2 Exit: parent(bob,ann) ? 3 2 Call: predecessor(ann,_23) ? 4 3 Call: parent(ann,_23) ? 4 3 Fail: parent(ann,_23) ? 4 3 Call: parent(ann,_141) ? 4 3 Fail: parent(ann,_129) ? 3 2 Fail: predecessor(ann,_23) ? 2 2 Redo: parent(bob,ann) ? 2 2 Exit: parent(bob,pat) ? 3 2 Call: predecessor(pat,_23) ? 4 3 Call: parent(pat,_23) ? 4 3 Exit: parent(pat,jim) ? 3 2 Exit: predecessor(pat,jim) ? 1 1 Exit: predecessor(bob,jim) ? X = jim ? ; 1 1 Redo: predecessor(bob,jim) ? 3 2 Redo: predecessor(pat,jim) ? 4 3 Call: parent(pat,_141) ? 4 3 Exit: parent(pat,jim) ? 5 3 Call: predecessor(jim,_23) ? 6 4 Call: parent(jim,_23) ? 6 4 Fail: parent(jim,_23) ? 6 4 Call: parent(jim,_190) ? 6 4 Fail: parent(jim,_178) ? 5 3 Fail: predecessor(jim,_23) ? 3 2 Fail: predecessor(pat,_23) ? 2 2 Redo: parent(bob,pat) ? 2 2 Exit: parent(bob,peter) ? 3 2 Call: predecessor(peter,_23) ? 4 3 Call: parent(peter,_23) ? 4 3 Exit: parent(peter,jim) ? 3 2 Exit: predecessor(peter,jim) ? 1 1 Exit: predecessor(bob,jim) ? X = jim ? (78 ms) yes {trace} | ?-