《Introduction to Logic Progrmming》快速阅读笔记

logic programming

新年花了一天多点的时间阅读了一下《Introduction to Logic Progrmming》这本书（后称该书）。个人很早以前就阅读过逻辑式编程的书籍，但当时主要针对 prolog 语言进行学习。

logic programming 可以做数据库吗？

与以往阅读的 prolog 书籍不同，该书最开始就是以一种类似数据库的视角来推进逻辑式编程的讲解。一般的 prolog 书籍会从经典的家族关系作为切入点来讲解逻辑式编程的魅力，但该书从 datasets 开始讲起。
该书明确的指出了逻辑式编程的形式，即：
facts + rules + query
从逻辑式编程的形式我们便可以看出其与数据库千丝万缕的联系我们可以回想一下关系型数据库的形式，以 mysql 为例：

Copy
假设我们有一个数据库
--------------------------
-- iD -- name -- age -----
-- 0 -- tim -- 32 -----
-- 1 -- ada -- 23 -----
-- 2 -- tom -- 23 -----
--------------------------
此时我们利用 mysql的查询语句，查询名字为tim的客户的所有信息
select * from person where name = 'tim';
我们可以得到
--------------------------
-- iD -- name -- age -----
-- 0 -- tim -- 32 -----
--------------------------

如果我们用 prolog 表达上述过程，我们可以如此构建 datasets

Copy
% facts

person(0,tim,32).
person(1,ada,23).
person(2,tom,23).

%query

person(X,tim,Y).

% result

X = 0.
Y = 32.

prolog 代码如上所述，我们首先构建了一组事实 (facts)，然后根据这组事实查询想要的变量，最后我们可以得到查询结果。
但以这种方式构建 facts 可能有有些问题，以 person (0,tim,32) 为例，我们并不能得到每个值得含义，例如 0 和 32 我们无法看出其为 id 和年龄。我们可以按照下面的方式构建。

Copy
% facts

person(id(0),name(tim),age(32)).
person(id(1),name(ada),age(23)).
person(id(2),name(tom),age(23)).

%query

person(X,name(tim),Y).

% result

X = id(0).
Y = age(32).

这样我们就可以标注出每个位置值的含义了
当然，仅从这个例子来看，prolog 比起 mysql 没什么好处，反而可能增添一些存储负担。
我们能发现仅仅做这种简单的查询时，prolog 并不能展现其优势。我们还是得拿出经典的家族关系例子来展现 prolog（逻辑式编程）的某些特性。

家族关系的经典例子

我们可以想象一个大家族的族谱，不妨设计一个族谱关系

Copy
% 族谱关系的一些事实
male(charles).
male(william).
male(peter).
male(henry).
male(andrew).
male(edward).
male(viscount).
male(savanna).

female(elizabeth).
female(anne).
female(zara).
female(beatrice).
female(eugenie).
female(louise).
female(isla).

parent(elizabeth,charles).
parent(elizabeth,anne).
parent(elizabeth,andrew).
parent(elizabeth,edward).

parent(anne,peter).
parent(anne,zara).
parent(charles,william).
parent(charles,henry).
parent(andrew,beatrice).
parent(andrew,eugenie).
parent(edward,louise).
parent(edward,viscount).
parent(peter,savanna).
parent(peter,isla).

% 其中 male 表示男性，female 表示女性，parent(X,Y)表示 X 时 Y 的父母（父亲或母亲）

当我们面对一些逻辑问题时，使用逻辑式编程便可大大减少我们的时间，例如我们想查询 grandparent 这个关系时，我们只要写下这个规则。

Copy
grandparent(X,Y) :- parent(X,Z),parent(Z,Y).

% 这条规则（rules）说明了grandparent的逻辑关系，
% 即grandparent其实就是父母的父母

从这里我们能感受到逻辑式编程的一些好处，在我们编写程序时，其实我们就是在编写一个逻辑约束的规则，而逻辑式编程语言（例如 prolog）的引擎可以根据这个规则来寻找对应的解（其实本质上是搜索）。

updates

该书在讲解了 facts 和 querys 之后便开始讲解 updates, 所以该书确实是以一种数据库的视角来介绍 logic programming 的。
书中举了一个 update syntax 的例子

Copy
p(a,b) & ~q(b) ==> ~p(a,b) & p(b,a)
p(X,Y) & ~q(Y) ==> ~p(X,Y) & p(Y,X)

这样我们便更新了数据库中的规则。

data structrue

该书紧接着讲述了 lists sets 和 trees 三种类型的数据结构，这里和其他介绍 prolog 的书籍区别不大。

总结

《introduce to logic programming》 这本书还是值得一读的，通过阅读这本书可以很好的了解 logic programming。先阅读这本书再阅读 prolog 相关书籍也是个不错的选择。