在学习了前三章内容后,我们应该对Prolog编程有了直观和理性的认识。由于合一、变量初始化、证明搜索和递归都是Prolog的核心概念,所以有如下更多的一些实践和练习。
这里我会先录入题目,后期再给出我自己的程序代码和一些思考。
实践1
试想有如下的描述迷宫的知识库。其中的事实描述了点和点之间的联通关系,即connected/2谓词逻辑给出了这样的事实:迷宫中能从参数1的点,直接到达参数2的点。而且,
联通关系是有方向的、单向不能往返的:
connected(1,2). connected(3,4). connected(5,6). connected(7,8). connected(9,10). connected(12,13). connected(13,14). connected(15,16). connected(17,18). connected(19,20). connected(4,1). connected(6,3). connected(4,7). connected(6,11). connected(14,9). connected(11,15). connected(16,12). connected(14,17). connected(16,19).
请写出一个谓词逻辑path/2,给出迷宫中哪些点是能够联通(直接或者间接)的。比如,点5是否能够达到点10?当起点是1时,能够到达哪些点?
实践2
有如下的交通信息知识库:
byCar(auckland, hamilton).
byCar(hamilton, raglan).
byCar(valmont, saarbruecken).
byCar(valmont, metz).
byTrain(metz, frankfurt).
byTrain(saarbruecken, frankfurt).
byTrain(metz, paris).
byTrain(saarbruecken, paris).
byPlane(frankfurt, bangkok).
byPlane(frankfurt, singapore).
byPlane(paris, losAngeles).
byPlane(bangkok, auckland).
byPlane(singapore, auckland).
byPlane(losAngeles, auckland).
请写出一个谓词逻辑travel/2,可以描述从一个地点到达另外一个地点(间接或者直接),可以通过car、train和plane进行换乘。比如,如果查询:
?- travel(valmont, raglan).
Prolog会回答true。
实践3
所以,通过实践2中的谓词逻辑travel/2,可以知道Valmont可以达到Raglan。这很有用,但是当你计划一段旅行的时候,你希望更确切的一些信息,比如其中详细的路途是
怎么样的。请写一个谓词逻辑travel/3,可以告诉具体的路径,比如,如果查询:
?- travel(valmont, losAngeles, X).
X = go(valmont, metz, go(metz, paris, go(paris, losAngeles)))
实践4
扩展实践3中的谓词逻辑travel/3,使其不仅能够给出从一个地方到另一个地方的路由,并且能够给出如何到达的方式。即,新的程序可以让我们知道,在旅行的每一段,是
使用的car,train还是plane作为交通工作的。
实践5
写出一个3元谓词combine1/3,将头两个参数的列表,合并为第三个参数的列表,例如:
?- combine1([a, b, c], [1, 2, 3], X).
X = [a, 1, b, 2, c, 3]
?- combine2([f, b, yip, yup], [glu, gla, gli, glo], Result).
X = [f, glu, b, gla, yip, gli, yup, glo]
写出一个3元谓词combine2/3,将头两个参数的列表,合并为第三个参数的列表,例如:
?- combine2([a, b, c], [1, 2, 3], X).
X = [[a, 1], [b, 2], [c, 3]]
?- combine2([f, b, yip, yup], [glu, gla, gli, glo], Result).
X = [[f, glu], [b, gla], [yip, gli], [yup, glo]]
写一个3元谓词combine3/3,将头两个参数的列表,合并为第三个参数的列表,例如:
?- combine3([a, b, c], [1, 2, 3], X).
X = [j(a,1), j(b,2), j(c,3)]
?- combine3([f, b, yip, yup], [glu, gla, gli, glo]).
X = [j(f, glu), j(b, gla), j(yip, gli), j(yup, glo)]
今后的学习中,我会找更多的一些实践题目,包括著名的数独问题,四色地图问题,八皇后问题,汉诺塔问题等等,一一分析。关于这章实践的答案,会陆续附上。
我的答案和解释:
实践1的path/2定义如下:
path(X, Y) :- connected(X, Y).
path(X, Y) :- connected(X, Z), path(Z, Y).
思路:首先考虑直接连通的情况,作为基础子句;然后考虑递归:设置一个中间变量Z,X和Z直接连通,然后Z和Y递归调用Path。