mushroompot

mushroompot

全栈,全干,全菜。 be a fullstack man, just for fun!
twitter

《邏輯編程入門》快速閱讀筆記

邏輯編程#

新年花了一天多點的時間閱讀了一下《邏輯編程入門》這本書(後稱該書)。個人很早以前就閱讀過邏輯式編程的書籍,但當時主要針對 prolog 語言進行學習。

邏輯編程可以做數據庫嗎?#

與以往閱讀的 prolog 書籍不同,該書最開始就是以一種類似數據庫的視角來推進邏輯式編程的講解。一般的 prolog 書籍會從經典的家族關係作為切入點來講解邏輯式編程的魅力,但該書從 datasets 開始講起。
該書明確的指出了邏輯式編程的形式,即:
facts + rules + query
從邏輯式編程的形式我們便可以看出其與數據庫千絲萬縷的聯繫我們可以回想一下關係型數據庫的形式,以 mysql 為例:

假設我們有一個數據庫
--------------------------
-- 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

% 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 和年齡。我們可以按照下面的方式構建。

% 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(邏輯式編程)的某些特性。

家族關係的經典例子#

我們可以想象一個大家族的族譜,不妨設計一個族譜關係

% 族譜關係的一些事實
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 這個關係時,我們只要寫下這個規則。

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

% 這條規則(rules)說明了grandparent的邏輯關係,
% 即grandparent其實就是父母的父母

從這裡我們能感受到邏輯式編程的一些好處,在我們編寫程序時,其實我們就是在編寫一個邏輯約束的規則,而邏輯式編程語言(例如 prolog)的引擎可以根據這個規則來尋找對應的解(其實本質上是搜索)。

updates#

該書在講解了 facts 和 querys 之後便開始講解 updates,所以該書確實是以一種數據庫的視角來介紹 logic programming 的。
書中舉了一個 update syntax 的例子

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 相關書籍也是個不錯的選擇。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。