规则
规则由几个互相依赖的简单句(谓词)组成。用来描述事实之间的依赖关系,如:因果关系,蕴含关系,对应关系
规则的实质就是存储起来得查询
其语法结构如下:
head:-body
head 为谓词的定义部分,和事实一样,也包括谓词名和参数说明
:- 连接符 表示 蕴含
body 一个或多个目标,用“,”连接,表示 且
如上一章中的混合查询按规则保存下来即为:
where_food(X,Y):-location(X,Y),edible(X).
房间Y中,有可食事物的条件是:X位于Y 中,且X具有 edible属性
继续用上一章举例子,在文件的最后追加一个规则
where_food(X,Y):-location(X,Y),edible(X).
文件内容如下:
room(kitchen). room(office). room(hall). room('dining room'). room(cellar). location(nani,'washing mechine'). location(desk,office). location(apple,kitchen). location(broccoli,kitchen). location(crackers,kitchen). location(flashlight,desk). location('washing mechine',cellar). location(computer,office). door(office,hall). door(kitchen,office). door(hall,'dining room'). door(kitchen,cellar). door('dining room',kitchen). edible(apple). edible(crackers). tastes_yucky(broccoli). turned_off(flashlight). here(kitchen). where_food(X,Y):-location(X,Y),edible(X).
我们可以做如下动作:
1、查找所有有可食食品的房间,和可食食品。
?- where_food(X,Y). X = apple, Y = kitchen ; X = crackers, Y = kitchen ; false.
2、验证某个房间中是否存在某食物
?- where_food(apple,kitchen). true .
3、查找某个房间中所有的可食用食物
?- where_food(X,kitchen). X = apple ; X = crackers.
4、查找可食用食物的所在的房间
?- where_food(apple,R).
R = kitchen.
综上所述,其实就是根据已经输入的事实,求解该规则的一个或两个变量的值。
规则的工作原理
首先prolog把目标和规则的子句的头部进行匹配,如果成功,那么prolog就把该规则的body部分作为新的目标进行匹配。
所以上面的 wherer_food 的debug信息如下:
?- where_food(X,kitchen). T Call: (7) where_food(_G2943, kitchen) T Call: (8) location(_G2943, kitchen) T Exit: (8) location(apple, kitchen) T Call: (8) edible(apple) T Exit: (8) edible(apple) T Exit: (7) where_food(apple, kitchen) X = apple ; T Redo: (8) location(_G2943, kitchen) T Exit: (8) location(broccoli, kitchen) T Call: (8) edible(broccoli) T Fail: (8) edible(broccoli) T Redo: (8) location(_G2943, kitchen) T Exit: (8) location(crackers, kitchen) T Call: (8) edible(crackers) T Exit: (8) edible(crackers) T Exit: (7) where_food(crackers, kitchen) X = crackers.
对于 寻找Nani这个游戏,我们可以增添如下的规则:
/*定义两个房间相连*/ connect(X,Y):-door(X,Y). connect(X,Y):-door(Y,X). /*列出该房间的所有物品*/ list_things(Place):-location(X,Place),tab(3),write(X),nl,fail. /*列出所有和该房间相邻的房间*/ list_connect(Place):-connect(Place,X),tab(3),write(X),nl,fail.
做一个测试:
?- list_things(kitchen). apple broccoli crackers false. ?- list_connect(kitchen). office cellar dining room false.
如图所示,list_things展示了该房间内的所有东西,list_connect显示了所有的和该房间相邻的所有房间。
但是这两个规则都有一个问题,都是 fail 结尾,如果我们把他们联用的时候,会由于fail,导致回溯。从而出现问题。
?- list_things(kitchen),list_connect(kitchen). apple broccoli crackers false.
list_connect(kitchen) 没有运行
所以我们要解决这个问题。
故我们在应该在添加两条事实,从而实现list_things和list_connect 都返回true。
list_things(_).
list_connect(_).
"_" 为空变量,表示我们不关心或者是暂时无法求值的变量。 这里取 我们不关心的意思。
?- list_things(kitchen),list_connect(kitchen). apple broccoli crackers office cellar dining room true.
现在我们可以编写一条规则,查看小女孩所在的房间,并列出房间内所有的物品以及和该房间相邻的房间。
look:-here(Place),write('You are in the '),write(Place),nl,write('You can see '),list_things(Place),write('You can go to '),nl,list_connect(Place).
所以到目前位置,整个 test.pl 文件如下
room(kitchen). room(office). room(hall). room('dining room'). room(cellar). location(nani,'washing mechine'). location(desk,office). location(apple,kitchen). location(broccoli,kitchen). location(crackers,kitchen). location(flashlight,desk). location('washing mechine',cellar). location(computer,office). door(office,hall). door(kitchen,office). door(hall,'dining room'). door(kitchen,cellar). door('dining room',kitchen). edible(apple). edible(crackers). tastes_yucky(broccoli). turned_off(flashlight). here(kitchen). where_food(X,Y):-location(X,Y),edible(X). connect(X,Y):-door(X,Y). connect(X,Y):-door(Y,X). list_things(Place):-location(X,Place),tab(3),write(X),nl,fail. list_things(_). list_connect(Place):-connect(Place,X),tab(3),write(X),nl,fail. list_connect(_). look:-here(Place),write('You are in the '),write(Place),nl,write('You can see '),list_things(Place),write('You can go to '),nl,list_connect(Place).
运行如下
?- look. You are in the kitchen You can see apple broccoli crackers You can go to office cellar dining room true.