第2章:誰(shuí)是誰(shuí)的爸爸

2018-02-24 16:03 更新

家譜

假設(shè)我們有這樣一個(gè)家譜圖:

我們現(xiàn)在的任務(wù)是將這個(gè)家譜圖寫(xiě)成程序代碼的形式。請(qǐng)打開(kāi)你最喜歡的文本編輯器,輸入以下代碼。

male(di).
male(jianbo).
female(xin).
female(yuan).
female(yuqing).
father(jianbo,di).
father(di,yuqing).
mother(xin,di).
mother(yuan,yuqing).
grandfather(X,Y):-father(X,Z),father(Z,Y).
grandmother(X,Y):-mother(X,Z),father(Z,Y).
daughter(X,Y):-father(X,Y),female(Y).

這段代碼里面的每一行都代表一個(gè)子句(clause)。其中帶有“:-”的子句叫做規(guī)則(rule),不帶有”:-“的子句叫做事實(shí)(fact)。另外,在Prolog里面諸如”di”和”jianbo”這類以小寫(xiě)英文字母開(kāi)頭的名稱我們稱它們?yōu)樵?atom),以大寫(xiě)英文字母為開(kāi)頭的名稱我們稱它們?yōu)樽兞浚缟厦娉绦蚶锩娴摹盭”和”Y”。顧名思義,原子是常量,即它的值是不可變的,而變量的值可以改變。最后需要講的是,在Prolog里面”,”代表邏輯關(guān)系中的”且”,我們回在后面的章節(jié)里面看到,”;”代表邏輯關(guān)系里面的”或”。

已經(jīng)被這些名稱搞得頭暈了?沒(méi)關(guān)系,我會(huì)在之后的教程里面詳細(xì)的介紹Prolog的數(shù)據(jù)類型和術(shù)語(yǔ),在這里,你只需有初步的了解即可。

保存上述代碼到你的磁盤(pán)的某個(gè)地方,例如在Mac系統(tǒng)里,我把它存到“~/prolog/chapter2.pl”,然后依照第一章里面講的那樣,進(jìn)入SWI-Prolog。在SWI-Prolog里面輸入如下查詢:

?- consult('path/to/your/chapter2.pl').

在我的電腦里,我應(yīng)該這么輸入:

?- consult('~/prolog/chapter2.pl').

這里”consult”的意思是讓SWI-Prolog加載你編寫(xiě)的程序,然后編譯它。輸入完這句查詢以后,敲擊回車鍵,你應(yīng)該得到如下輸出:

% /Users/fengdi/prolog/chapter2.pl compiled 0.00 sec, 3,816 bytes
true.

如果你得到了上述的輸出,那么恭喜你,你的第一個(gè)程序完成了。如果你得到的是其他的錯(cuò)誤的輸出,請(qǐng)重新檢查你的程序代碼是否輸入正確(不過(guò)要記得,千萬(wàn)不要因?yàn)橄胍WC代碼輸入的不出錯(cuò)而直接復(fù)制粘貼代碼,那樣的話你學(xué)不到真正的東西)。下面,讓我們考驗(yàn)一下我們的SWI-Prolog現(xiàn)在都知道些什么。在SWI-Prolog里面輸入下面一個(gè)查詢:

grandfather(X,yuqing).

令人驚訝的事情發(fā)生了!你得到了下列輸出:

X = jianbo.

你的電腦告訴你,”yuqing”的祖父是”jianbo”?,F(xiàn)在請(qǐng)看之前我們編寫(xiě)的”chapter2.pl”程序代碼,我們?cè)诔绦蚶锔緵](méi)有明確的說(shuō)明誰(shuí)是誰(shuí)的祖父,我們只是給了一個(gè)規(guī)則:

grandfather(X,Y):-father(X,Z),father(Z,Y).

我們說(shuō),當(dāng)X是Z的父親并且Z是Y的父親的時(shí)候,X是Y的祖父。然后我們問(wèn),yuqing的祖父是誰(shuí),Prolog就能自動(dòng)幫我們找到答案!

下面再看一個(gè)例子:

parent(keyuan,jianbo).
parent(jianbo,di).
parent(di,yuqing).

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

在這個(gè)例子里面,我們定義了一個(gè)回溯的規(guī)則”ancestor”,規(guī)則可以這樣解讀:我們可以說(shuō)X是Y的祖先基于兩個(gè)條件:X是Y的parent,或者存在一個(gè)Z,使得X是Z的parent并且Z是Y的祖先。請(qǐng)讀者仔細(xì)的想一下,是不是這個(gè)道理呢?為了證明我們的程序的正確性,我們輸入一下查詢:

?- ancestor(keyuan,yuqing).

Prolog會(huì)返回:

true.

這證明了我們的程序是正確的,因?yàn)楦鶕?jù)常識(shí),keyuan是yuqing的曾祖父,所以keyuan是yuqing的祖先。

好了,今天的新內(nèi)容就講到這里,下面是一個(gè)習(xí)題,你可以自己試驗(yàn)一下。

加分習(xí)題

  1. 試著用Prolog描述一下你的家譜,并且做一些簡(jiǎn)單的查詢。(小提示:在編寫(xiě)你的家譜的時(shí)候,你可以試著用一些新的事實(shí),比如:”sister(your_sister,you)”“brother(your_brother,you)”等等)
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)