第5章 Prolog基礎(chǔ).ppt_第1頁
第5章 Prolog基礎(chǔ).ppt_第2頁
第5章 Prolog基礎(chǔ).ppt_第3頁
第5章 Prolog基礎(chǔ).ppt_第4頁
第5章 Prolog基礎(chǔ).ppt_第5頁
免費(fèi)預(yù)覽已結(jié)束,剩余59頁可下載查看

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、第5章 Prolog基礎(chǔ),本章介紹學(xué)習(xí)關(guān)于Prolog編程最基本的內(nèi)容,包括Horn子句、Prolog推理機(jī)、程序控制、Prolog算符等。 Visual Prolog是面向?qū)ο蟮?、?yán)格類型化的和模式檢驗(yàn)的。在編寫Visual Prolog程序時(shí),必須掌握這些內(nèi)容。但在這里,我們將集中于編寫代碼這個(gè)核心問題,也就是說,編寫這些代碼時(shí)暫時(shí)不考慮類、類型和模式。 我們將使用包含在Visual Prolog 6中的PIE例子。PIE是一個(gè)經(jīng)典的Prolog解釋器,通過使用它,可以學(xué)會(huì)和試驗(yàn)Prolog程序,而不必關(guān)心類、類型等方面的知識(shí)。 內(nèi)容是基于使用Build 6004或以后的Visual Pr

2、olog 6版本,否則,PIE應(yīng)用程序?qū)⒉粫?huì)像我們描述的這樣工作。這個(gè)編譯號(hào)可以在VDE的About對(duì)話框中找到。,第5章 Prolog基礎(chǔ),5.1 Horn子句邏輯 5.2 Prolog推理機(jī) 5.3 擴(kuò)展家庭定理 5.4 Prolog是一種編程語言 5.5 程序控制 5.6 Prolog算符 本章小結(jié)與習(xí)題,5.1 Horn子句邏輯,Visual Prolog和其他用語都是基于Horn子句邏輯的。Horn子句邏輯是對(duì)事物及其相互關(guān)系進(jìn)行推理的形式系統(tǒng)。 在自然語言中,我們可以這樣表達(dá)一個(gè)陳述句: John是Bill 的父親. 這里我們涉及兩個(gè)實(shí)體,John和Bill,以及他們之間的關(guān)系,即

3、一個(gè)是另一個(gè)的父親。在Horn子句邏輯中,可以這樣形式化地表述上面的陳述句: father(“Bill”, “John”). 上面的father是帶有兩個(gè)參量的一個(gè)謂詞或關(guān)系,它表示第二個(gè)人是第一個(gè)人的父親。,5.1 Horn子句邏輯,像“John是Bill 的父親”這樣的陳述稱為事實(shí),而“X是Z的祖父,如果X是Y的父親且Y是Z的父親”稱為規(guī)則。 我們可以用事實(shí)和規(guī)則來形成定理,一個(gè)定理是事實(shí)和規(guī)則的集合,讓我們陳述一個(gè)小定理: father(Bill, John). father(Pam, Bill). grandFather(Person, GrandFather) :- father(P

4、erson, Father), father(Father, GrandFather).,5.1 Horn子句邏輯,這個(gè)定理的作用是回答這樣一些問題: John是Sue的父親嗎? 誰是Pam的父親? John是Pam的祖父嗎? . 這些問題稱為目標(biāo)(goal)。它們可以這樣形式化表述: ?- father(Sue, John). ?- father(Pam, X). ?- grandFather(Pam, John).,5.1 Horn子句邏輯,這些問題被稱為目標(biāo)子句(goal clause)或簡稱為目標(biāo)(goal)。事實(shí)(facts)、規(guī)則(rules)及目標(biāo)(goals)合起來稱為Horn

5、子句,因此得名Horn子句邏輯。 一個(gè)Prolog程序是一個(gè)定理和目標(biāo)的集合。當(dāng)程序開始時(shí),它試圖使用定理,為目標(biāo)找到一個(gè)解。,5.2 Prolog推理機(jī),PIE (Prolog Inference Engine),即Prolog推理機(jī),隨Visual Prolog 6一起提供。 在開始之前,必須先安裝和建立PIE 1) 在Windows開始菜單中選擇“安裝例子”,(Start - Visual Prolog 6 - Install Examples)。 2) 用VDE打開PIE項(xiàng)目,且運(yùn)行該程序。,5.2 Prolog推理機(jī),當(dāng)程序啟動(dòng)后,其情形如下圖5.1所示。,圖5.1 Prolog推理

6、機(jī),5.2 Prolog推理機(jī),選擇菜單File - New,鍵入前面的父親子句和祖父子句,如圖5.2所示。,圖5.2 子句代碼,5.2 Prolog推理機(jī),當(dāng)編輯器窗口激活時(shí),選擇Engine - Reconsult,將會(huì)把文件裝入到推理機(jī)。在對(duì)話框中,還將得到這樣一個(gè)消息: Reconsulted from: .pieExeFILE4.PRO 無論用編輯器如何裝入,其內(nèi)容都不會(huì)保存到文件之中。如果想要保存內(nèi)容,必須使用菜單命令File - Save。 菜單File - Consult不管文件是否因編輯而打開,都會(huì)裝載磁盤文件中的內(nèi)容。 一旦查閱過定理,就可以回答各種目標(biāo)。,5.2 Prol

7、og推理機(jī),在對(duì)話框窗口的空白行上,鍵入一個(gè)目標(biāo),不帶前綴“?-”。例如,鍵入如圖5.3所示的查詢代碼。,圖5.3 鍵入目標(biāo),5.2 Prolog推理機(jī),當(dāng)插字符號(hào)位于行尾時(shí),按下鍵盤上的輸入鍵。PIE現(xiàn)在將把從該行的開頭到插字符號(hào)之間的文本當(dāng)作目標(biāo)來執(zhí)行。于是,就可以看到如圖5.4所示的結(jié)果。,圖5.4 查詢目標(biāo)對(duì)話框,5.3 擴(kuò)展家庭定理,使用諸如mother和grandMother這樣的謂詞,可以直接擴(kuò)展家庭定理。讀者應(yīng)該試著親自去做,也可以試著添加上更多的人。我們建議讀者使用自己家庭中的人,因?yàn)檫@樣易于驗(yàn)證,且可以不考慮添加的這個(gè)人是否真正是自己的祖母。 給出謂詞mother和fath

8、er,我們還可以定義雙親(parent)這個(gè)謂詞。一位母親是雙親,一位父親也是雙親,因此我們可以使用兩個(gè)子句來定義雙親: parent(Person, Parent) :- mother(Person, Parent). parent(Person, Parent) :- father(Person, Parent). 第一個(gè)規(guī)則可以解讀為:如果Parent是Person的mother,則Parent是Person的雙親(parent)。 還可以用分號(hào)“;”來定義雙親(parent)關(guān)系,分號(hào)代表“或(or)”。,5.3 擴(kuò)展家庭定理,parent(Person, Parent) :- mot

9、her(Person, Parent); father(Person, Parent). 這條規(guī)則可以解讀為:如果Parent是Person的mother或(or)Parent是Person的father,則Parent是Person的雙親(parent)。 我們強(qiáng)烈建議讀者盡可能少用或根本不用這個(gè)分號(hào)“;”。之所以這樣建議,是基于以下理由: 1) 逗號(hào)“,”和分號(hào)“;”之間在印刷上的差別非常小,但語義上的差別卻很大。分號(hào)“;”常常是引起混淆的一個(gè)根源,因?yàn)樗菀妆徽`解為逗號(hào)“,”,特別是當(dāng)它處于一個(gè)長行的末尾時(shí)。 2) Visual Prolog只允許在最外一層使用分號(hào)(PIE允許任意層次的

10、嵌套)。,5.4 Prolog是一種編程語言,Prolog可以作為專家系統(tǒng)來使用,但它本身卻是作為一種程序語言而設(shè)計(jì)出來的。 我們遺漏了把Horn子句邏輯變?yōu)橐环N程序設(shè)計(jì)語言的兩個(gè)重要因素: 1)嚴(yán)格的搜索順序或程序控制 2)副效應(yīng),5.5 程序控制,當(dāng)試圖為如下目標(biāo)尋找一個(gè)解時(shí): ?- father(X, Y). 可以有許多實(shí)現(xiàn)方式。例如,如果只考慮定理中的第二個(gè)事實(shí),那么,就可得到一個(gè)解。 但是Prolog不使用隨機(jī)搜索策略,而總是使用同一種策略。系統(tǒng)保持一個(gè)當(dāng)前目標(biāo),始終從左到右進(jìn)行求解。 例如,如果當(dāng)前目標(biāo)是: ?- grandFather(X, Y), mother(Y, Z) 那么

11、,系統(tǒng)就會(huì)嘗試在求解子目標(biāo)mother(Y, Z)之前,首先求解子目標(biāo)grandFather(X, Y )。如果第一個(gè)(即最左面的)子目標(biāo)不能被求解,則全部問題就沒有解,第二個(gè)子目標(biāo)根本就不用再嘗試求解。,5.5 程序控制,當(dāng)求解一個(gè)特定子目標(biāo)時(shí),事實(shí)和規(guī)則將被自上而下進(jìn)行嘗試。 當(dāng)使用規(guī)則求解了一個(gè)子目標(biāo)時(shí),當(dāng)前目標(biāo)中待求解的那個(gè)子目標(biāo)將被其規(guī)則右邊的那些子目標(biāo)所代替。 例如,如果當(dāng)前目標(biāo)是: ?- grandFather(X, Y), mother(Y, Z). 而我們使用規(guī)則 grandFather(Person, GrandFather) :- father(Person, Fathe

12、r), father(Father, GrandFather). 去求解第一個(gè)子目標(biāo),則作為結(jié)果的當(dāng)前目標(biāo)是 ?- father(X, Father), father(Father, Y), mother(Y, Z).,5.5 程序控制,注意,規(guī)則中的某些變量已經(jīng)被子目標(biāo)中的變量替換,我們將在后面詳細(xì)解釋這一點(diǎn)。 給定這種評(píng)價(jià)策略,就可以更多地從程序上解釋子句的控制過程。 考慮這個(gè)規(guī)則: grandFather(Person, GrandFather) :- father(Person, Father), father(Father, GrandFather). 給定嚴(yán)格的評(píng)價(jià)策略,我們可以這

13、樣解讀這個(gè)規(guī)則:為了求解grandFather(Person, GrandFather),首先要求解father(Person, Father),然后再求解father(Father, GrandFather)。或者這樣理解:當(dāng)調(diào)用grandFather(Person, GrandFather) 時(shí),首先要調(diào)用father(Person, Father),然后再調(diào)用father(Father, GrandFather)。 有了這種程序上的解讀,我們就可以理解,所謂的謂詞實(shí)際上就相當(dāng)于其他編程語言中的過程或子例程。它們之間主要的區(qū)別在于一個(gè)Prolog謂詞對(duì)于一個(gè)單個(gè)提問可以返回多個(gè)結(jié)果或沒有結(jié)

14、果(即失?。_@一點(diǎn)將在下一節(jié)詳細(xì)進(jìn)行討論。,5.5.1 失敗,在定理中,一個(gè)謂詞提問可能沒有任何一個(gè)解。例如調(diào)用parent(Hans, X),因?yàn)椴淮嬖谶m用于Hans的雙親關(guān)系的事實(shí)或規(guī)則,所以沒有一個(gè)解。我們就說這個(gè)謂詞調(diào)用失?。╢ail)。如果目標(biāo)失敗了,則說明定理中完全不存在針對(duì)該目標(biāo)的解。下一節(jié)將解釋在通常情況下,即當(dāng)它不是一個(gè)失敗的目標(biāo)時(shí),如何處理失敗。,5.5.2 回溯,在Prolog程序的過程性解釋中,“或(or)”以相當(dāng)特殊的方式進(jìn)行處理??紤]下面的子句: parent(Person, Parent) :- mother(Person, Parent); father(Pe

15、rson, Parent). 從邏輯上解讀,我們這樣解釋這個(gè)子句:如果Parent是Person的母親,或(or)Parent是Person的父親,則Parent是Person的雙親。,5.5.2 回溯,對(duì)于Parent謂詞的提問,“或(or)”引出了兩個(gè)可能的解。Prolog處理這種多項(xiàng)選擇時(shí),往往首先嘗試第一個(gè)選擇,隨后根據(jù)需要,再回溯到下一個(gè)備份的選擇,等等。 在程序執(zhí)行期間,來自早期謂詞調(diào)用的許多備份的選擇(稱為回溯點(diǎn))可能繼續(xù)存在。如果有的謂詞調(diào)用失敗了,那我們將回到上一個(gè)回溯點(diǎn)嘗試另一個(gè)選擇性的解。如果沒有回溯點(diǎn)存在了,則整個(gè)目標(biāo)就失敗了,也意味著沒有一個(gè)解存在。 這樣,我們就可以

16、這樣解釋上面的子句:當(dāng)parent(Person, Parent)被調(diào)用時(shí),首先給第二個(gè)選擇性的解(即對(duì)于調(diào)用father(Person, Parent))記錄一個(gè)回溯點(diǎn),接著再調(diào)用mother(Person, Parent)。,5.5.2 回溯,例 為闡明程序如何執(zhí)行,我們來詳細(xì)考察一個(gè)例子。考慮下面這些子句: mother(Bill, Lisa). father(Bill, John). father(Pam, Bill). father(Jack, Bill). parent(Person, Parent) :- mother(Person, Parent); father(Person

17、, Parent). 然后考慮目標(biāo): ?- father(AA, BB), parent(BB, CC).,5.5.3 改進(jìn)家庭定理,如果繼續(xù)處理上述家庭關(guān)系,就可能會(huì)發(fā)現(xiàn)難于處理諸如兄弟、姐妹這樣的關(guān)系,這是因?yàn)橐_定一個(gè)人的性別是相當(dāng)困難的,除非這個(gè)人是一位父親或母親。 問題是我們選擇了一個(gè)不好的方式來形式化這個(gè)定理。原因在于,我們從考慮實(shí)體間的關(guān)系開始。如果我們首先考慮實(shí)體本身,那結(jié)果就會(huì)不同。 我們的主要實(shí)體是人,人都有名字(在這個(gè)簡單的例子中,我們?nèi)匀挥妹謥順?biāo)識(shí)人。而在一個(gè)真正有規(guī)模的程序中,這一點(diǎn)未必成立。)。人有性別。人還有許多其他的特性,但與我們的興趣無關(guān),所以沒有出現(xiàn)在我們

18、的上下文中。,5.5.3 改進(jìn)家庭定理,由此我們這樣定義一個(gè)person謂詞: person(Bill, male). person(John, male). person(Pam, female). person謂詞的第一個(gè)參數(shù)是名字,第二個(gè)參數(shù)是性別。 我們不是使用mother和father作為事實(shí),而是選擇parent作為事實(shí),將mother和father作為規(guī)則: parent(Bill, John). parent(Pam, Bill). father(Person, Father) :- parent(Person, Father), person(Father, male). 注

19、意,當(dāng)father是一個(gè)“導(dǎo)出”關(guān)系時(shí),不可能有女性的父親。所以這個(gè)定理在內(nèi)部要保持一致,在這一點(diǎn)上不能有其他的形式。,5.5.4 遞歸,利用上面給出的原則,大多數(shù)家庭關(guān)系是容易建立的。但當(dāng)它涉及到像祖先這樣的“無窮”關(guān)系時(shí),我們將需要更多的規(guī)則。如果我們遵循上述原則,就應(yīng)該這樣定義祖先: ancestor(Person, Ancestor) :- parent(Person, Ancestor). ancestor(Person, Ancestor) :- parent(Person, P1), parent(P1, Ancestor). ancestor(Person, Ancestor)

20、 :- parent(Person, P1), parent(P1, P2), parent(P2, Ancestor). . 主要問題是子句的排列永遠(yuǎn)不會(huì)完結(jié)??朔@一問題的方法是使用一個(gè)遞歸定義,即像下面這樣,根據(jù)它自身進(jìn)行的定義:,5.5.4 遞歸,ancestor(Person, Ancestor) :- parent(Person, Ancestor). ancestor(Person, Ancestor) :- parent(Person, P1), ancestor(P1, Ancestor). 這一聲明是說,雙親是一個(gè)祖先,雙親的祖先還是祖先。 如果還沒有熟悉這種遞歸的概念,就

21、可能會(huì)覺得遞歸很難處理。遞歸是Prolog 程序的基礎(chǔ),需要反復(fù)加以使用,然后才會(huì)習(xí)慣。 讓我們?cè)囍鴪?zhí)行一個(gè)祖先ancestor目標(biāo): ?- ancestor(Pam, AA). 我們?yōu)榈诙€(gè)ancestor子句設(shè)置一個(gè)回溯點(diǎn),然后執(zhí)行第一個(gè)子句。這時(shí),新的目標(biāo)為: ?- parent(Pam, AA).,5.5.4 遞歸,這樣很快找到一個(gè)解: AA=Bill. 然后,我們?cè)噲D通過使用第二個(gè)ancestor子句的回溯點(diǎn)來找尋另一個(gè)解。這時(shí),新的目標(biāo)為: ?- parent(Pam, P1), ancestor(P1, AA). 由于Bill是Pam的雙親,所以我們找到P1= Bill。接著,目

22、標(biāo)為: ?- ancestor(Bill, AA). 為了求解這個(gè)目標(biāo),我們首先為第二個(gè)ancestor子句設(shè)置一個(gè)回溯點(diǎn),然后執(zhí)行第一個(gè)子句。這時(shí)給出下列目標(biāo): ?- parent(Bill, AA). 這個(gè)目標(biāo)又給出一個(gè)解: AA = John. 所以我們找到Pam的兩個(gè)祖先:Bill和John。,5.5.4 遞歸,如果我們使用第二個(gè)ancestor子句的回溯點(diǎn),將得到下列目標(biāo): ?- parent(Bill, P1), ancestor(P1, AA). 在這里,我們將再一次發(fā)現(xiàn)John是Bill的雙親,因此P1為John。這又給出了目標(biāo): ?- ancestor(John, AA).

23、如果我們繼續(xù)求解這個(gè)目標(biāo),將發(fā)現(xiàn)這個(gè)目標(biāo)沒有任何一個(gè)解存在。所以,歸根到底我們只可能找到Pam的兩個(gè)祖先。,5.5.4 遞歸,遞歸是一種非常強(qiáng)大的功能,但它也有一點(diǎn)難于控制。使用遞歸時(shí),切記以下兩個(gè)要點(diǎn): 遞歸必須能夠前進(jìn); 遞歸必須能夠終止。 在上面的代碼中,第一個(gè)子句確保該遞歸能夠終止,這是因?yàn)檫@個(gè)子句不是遞歸的,即它沒有對(duì)該謂詞本身進(jìn)行調(diào)用。第二個(gè)子句是遞歸的。在第二個(gè)子句中,我們保證在進(jìn)行遞歸調(diào)用之前,更深一層地回退一個(gè)祖先步。也就是說,我們確保在問題求解過程中將不斷取得一些進(jìn)展。,5.5.5 副效應(yīng),除了嚴(yán)謹(jǐn)?shù)挠?jì)算順序以外,Prolog也有一些副效應(yīng)。例如,Prolog有一些用于讀、

24、寫操作的預(yù)定義謂詞。 下面的目標(biāo)將輸出找到的Pam的祖先: ?- ancestor(Pam, AA), write(Ancestor of Pam : , AA), nl(). ancestor調(diào)用將找到Pam的一個(gè)祖先,并放在AA中。 write調(diào)用將輸出字符串Ancestor of Pam : ,然后輸出AA的值。 nl調(diào)用將會(huì)使輸出轉(zhuǎn)入到一個(gè)新行。 當(dāng)在PIE中運(yùn)行程序時(shí),PIE自己會(huì)給出結(jié)果。所以會(huì)造成你的結(jié)果和PIE的結(jié)果混在一起,所得出的結(jié)果可能并不是想要的。,5.5.5 副效應(yīng),避免PIE本身輸出結(jié)果的一個(gè)非常簡單的方法就是確保該目標(biāo)沒有解??紤]下面的目標(biāo): ?- ancesto

25、r(Pam, AA), write(Ancestor of Pam : , AA), nl(), fail. fail是一個(gè)預(yù)先定義的謂詞,它總是失敗,即不會(huì)有解。 前三個(gè)謂詞調(diào)用和上面的效果完全相同:若一個(gè)祖先被找到(如果存在的話),則把它寫出來。接著調(diào)用fail,程序失敗。因此如果可能,我們應(yīng)追尋一個(gè)回溯點(diǎn)。 在追尋該回溯點(diǎn)時(shí),找到另一個(gè)祖先(如果存在的話),把它寫出來,然后再失敗,如此反復(fù)。 于是,我們將找到并且輸出所有的祖先,直到最后不再有回溯點(diǎn),目標(biāo)執(zhí)行失敗。,5.5.5 副效應(yīng),這里有以下要點(diǎn)需要加以注意: 1)目標(biāo)本身不存在一個(gè)單一的解,從而使我們所想要的全部解都作為副效應(yīng)形式給

26、出; 2)副效應(yīng)在失敗計(jì)算中也存在。 這些情形是一個(gè)事物的兩個(gè)方面,但他們代表了不同階層的觀點(diǎn)。第一個(gè)階層樂觀地表明可以利用的一些可能性,而第二個(gè)階層比較悲觀,提醒要注意利用副效應(yīng),因?yàn)榧词巩?dāng)前目標(biāo)不產(chǎn)生任何解,它們照樣也會(huì)完成。 任何人學(xué)習(xí)Prolog時(shí),遲早都會(huì)經(jīng)歷來自部分失敗程序的意外輸出的情況。也許下面這個(gè)建議可以對(duì)此有所幫助:將計(jì)算性代碼與執(zhí)行輸入輸出的代碼分開來。 在我們上面的例子中,所有的謂詞都是計(jì)算謂詞。它們會(huì)計(jì)算出一些家庭關(guān)系。如果需要把解(例如“雙親”)寫出來的話,就構(gòu)造另外一個(gè)謂詞來寫出雙親,而讓這個(gè)謂詞調(diào)用計(jì)算雙親的謂詞。,5.5.6 小結(jié),在這一節(jié)中,我們學(xué)習(xí)了Pro

27、log的一些基本特性,我們學(xué)習(xí)了事實(shí)、規(guī)則和目標(biāo),學(xué)習(xí)了Prolog的執(zhí)行策略,包括失敗和回溯,同樣發(fā)現(xiàn)回溯可以給出多個(gè)結(jié)果,最后學(xué)習(xí)了副效應(yīng)。,5.6 Prolog算符,本節(jié)繼續(xù)介紹Prolog編程的基本思想。在本節(jié),我們主要關(guān)心Prolog中的數(shù)據(jù)在被操作之前,是怎樣被模型化的。因此,并沒有太多關(guān)于代碼執(zhí)行的例子。我們假定讀者已經(jīng)熟悉了執(zhí)行策略(execution strategy)對(duì)結(jié)果的影響和副效應(yīng)(side effects)是怎樣把一個(gè)Prolog程序的邏輯轉(zhuǎn)化為所需結(jié)果的。 與上一節(jié)一樣,我們將繼續(xù)使用PIE環(huán)境來學(xué)習(xí)Prolog,只有在本書的后部分內(nèi)容才有必要進(jìn)入Visual P

28、rolog 6可視化開發(fā)環(huán)境VDE。 本節(jié)主要內(nèi)容包括:,5.6 Prolog算符,算符 深入理解算符 算符與謂詞 算符作為參數(shù) 算符遞歸 算符使用策略 小結(jié),5.6.1 算符,在上一節(jié),所有的人都用名字Bill、John和Pam等表示。現(xiàn)在,Bill、John和Pam惟一代表各個(gè)人的名字。這些名字的值是簡單數(shù)據(jù)類型或簡單論域(simple domains)。作為人名時(shí),這種簡單論域的類型是字符串,其它的簡單論域可以是數(shù)(如:123或3.14)、符號(hào)(如:xyz或chi1_10)和字符(如:5或c)。 然而,人是由包含名字在內(nèi)的更多特性所表示的,當(dāng)我們需要表達(dá)所有特性而不僅僅是名字時(shí)怎么辦?也

29、就是說,我們需要某些機(jī)制來表示復(fù)合論域(compound domains),它是更為簡單論域的一個(gè)集合。 在上一節(jié),我們?cè)囍ㄟ^向PIE系統(tǒng)加入集中于實(shí)體(entities)而不是關(guān)系的事實(shí)把個(gè)人的多種特征放在一塊兒,比如名字name和性別gender,從而給出了如下事實(shí): person(Bill, male). person(John, male). person(Pam, female).,5.6.1 算符,然而,有一個(gè)更優(yōu)雅的方法可以讓我們把注意力集中在被表示的實(shí)體上。 我們可以將姓名和性別用被稱為復(fù)合論域的形式封裝在一個(gè)包中,然后整個(gè)封裝可以用一個(gè)Prolog子句中的一個(gè)邏輯變量來表

30、示,像其它任意變量一樣。例如,上述事實(shí)可以被一般地表示為: person(Name,Gender) 注意,上面的句子既不是一個(gè)事實(shí)也不是一個(gè)謂詞。邏輯上,它表示程序中的名為person的復(fù)合論域,每個(gè)person有兩個(gè)特征,由邏輯變?cè)狽ame和Gender表示。單詞person就是所謂的算符,變?cè)狽ame和Gender就是它的參數(shù)。以后應(yīng)用這些算符來封裝我們的事實(shí)。 由于復(fù)合論域總有算符,從此我們將用算符來代表各種復(fù)合論域。,5.6.1 算符,現(xiàn)在,讓我們用新定義的算符person改變上節(jié)的第一個(gè)例子,參見圖5.5。 注意,在我們使用的PIE(Prolog推理機(jī))中,我們可以直接使用復(fù)合論域而

31、不必事先聲明(比如說,我們不必為了讓代碼運(yùn)行而定義一個(gè)名為person的謂詞或事實(shí))。,圖5.5 person算符,5.6.1 算符,觀察表示father關(guān)系的兩個(gè)事實(shí),可以發(fā)現(xiàn)人的定義比以前更豐富了(原來的代碼已經(jīng)被注釋掉了在/*和*/之間)。這時(shí),每一個(gè)人使用person算符描述他們的名字和性別,而在上一節(jié),我們只使用了人的名字。 更改代碼后,使用Engine - Reset,確保PIE已經(jīng)復(fù)位。然后,用Engine - Reconsult重新求解。 以前,在對(duì)話窗口中的空白行上輸入一個(gè)目標(biāo)(前面不帶“?”號(hào))。如圖5.6所示的那樣。,5.6.1 算符,圖5.6 目標(biāo)代碼,5.6.1 算符

32、,在行尾輸入完句號(hào)后,按鍵盤上的回車鍵,PIE將把行首到句號(hào)的文本當(dāng)作目標(biāo)來執(zhí)行,然后就可以看到如圖5.7所示的結(jié)果。,圖5.7 目標(biāo)代碼結(jié)果,5.6.2 深入理解算符,看一下謂詞grandfather,就會(huì)發(fā)現(xiàn)一個(gè)微妙的問題,一個(gè)人應(yīng)該有兩個(gè)祖父:一個(gè)來自爸爸那邊,一個(gè)來自媽媽那邊,但按前面定義的謂詞grandfather,只能得到從爸爸那邊來的祖父。 因此,謂詞grandfather應(yīng)該重寫為: grandFather(Person,TheGrandFather):- parent(Person,ParentOfPerson), father(ParentOfPerson,TheGrand

33、Father). 這個(gè)謂詞邏輯考慮到了任一雙親的父親都是祖父的常識(shí)。 為了讓它工作,需要再定義一個(gè)用到算符person的謂詞father。這個(gè)謂詞將遍歷系統(tǒng)中定義的parents事實(shí)數(shù)據(jù)庫。對(duì)于找到父親們來講,這是一個(gè)比把他們作為事實(shí)列出來(如前所示)更為明智的做法。因?yàn)橥ㄟ^后者可以用類似的形式來擴(kuò)展概念,找出母親。,5.6.2 深入理解算符,可以寫成下面兩種形式中的任意一種: /*1st version */ father(P, F) :- parent(P, F), F = person(_, male). %Line 2 或者 /* 2nd version */ father(P, pe

34、rson(Name, male) :- parent(P, person(Name, male).,5.6.2 深入理解算符,以上兩個(gè)版本的邏輯是相同的,但交給Prolog推理機(jī)的方法不同。第一個(gè)版本中,Prolog依次檢查代碼中的parent事實(shí),并看其是否與從謂詞頭傳遞來的第一個(gè)邏輯變量(p) 匹配。如果該變量確實(shí)匹配,則檢查第二個(gè)參數(shù)是不是person算符,且person算符的第二個(gè)參數(shù)是不是字符串male。 這個(gè)例子體現(xiàn)了算符的一個(gè)重要特性:一個(gè)算符的多個(gè)參數(shù)可以通過常見的Prolog變量和綁定值被分離和檢查(就像本例中的字符串精確匹配)。在第二行(第一個(gè)版本中用“%Line 2”注釋

35、的地方),我們會(huì)發(fā)現(xiàn)仍用了一個(gè)匿名變量(下劃線)作為person算符的第一個(gè)參數(shù),因?yàn)槲覀儾魂P(guān)心father具體叫什么名字。,5.6.2 深入理解算符,第二個(gè)版本與第一個(gè)版本功能相同。但在這里,檢查雙親事實(shí)集合的同時(shí),找到正確的P值,就停下來并返回正確的算符給謂詞頭,倘若該謂詞的第二個(gè)參數(shù)是字符串“male”,則該算符不再綁定到任何Prolog中間變量,但在第一個(gè)版本不是這樣。 第二個(gè)版本比第一個(gè)要簡潔,但有時(shí)這種寫法對(duì)初學(xué)者來說可能更難讀一些。 現(xiàn)在,讓我們?cè)谝粋€(gè)具有person事實(shí)的完整例子中使用這些代碼,如圖5.8所示。,5.6.2 深入理解算符,圖5.8 目標(biāo)代碼結(jié)果,5.6.2 深入

36、理解算符,把上面的代碼輸入PIE中,并給出如下目標(biāo): grandFather(person(Pam,female),W) 結(jié)果如圖5.9所示。,圖5.9 目標(biāo)代碼結(jié)果,5.6.3 算符與謂詞,從技術(shù)角度講,一個(gè)算符代表一個(gè)將多個(gè)論域綁定到一塊兒的邏輯功能。簡言之,算符是一種使Prolog推理機(jī)把數(shù)據(jù)的各個(gè)部分放在一起的一種機(jī)制,它有效地把數(shù)據(jù)的各部分放在一個(gè)通用的盒子中。在需要時(shí),像前面的例子,也可以獲得其成分。它看起來也許像一個(gè)Prolog事實(shí)或一個(gè)謂詞調(diào)用,但它不是,它只是一份數(shù)據(jù),一個(gè)在很大程度上可以像一個(gè)字符串或數(shù)一樣操作的數(shù)據(jù)。 請(qǐng)注意,算符與其它編程語言中的函數(shù)毫無關(guān)系。它不能夠進(jìn)

37、行運(yùn)算。它只不過簡單地代表復(fù)合論域并把自身的參數(shù)集成在一起。,5.6.3 算符與謂詞,從通過研究上面的例子,你會(huì)發(fā)現(xiàn)用邏輯變量代表由算符表示的數(shù)據(jù)時(shí)無需做特別的操作。表示這些數(shù)據(jù)的變量可以像其它任何變量一樣書寫:以大寫字母開頭。因此,看一下本節(jié)例子中的grandFather謂詞,你就會(huì)發(fā)現(xiàn)它與前面一節(jié)中定義的同一謂詞完全一樣,畢竟該謂詞的邏輯沒有改變。所以,該謂詞中所用的變量也就沒有任何變化。 使用算符的最大好處在于,修改代碼時(shí),可以自由地改變算符的內(nèi)部參數(shù)而對(duì)使用該算符的謂詞無需做大的改動(dòng)。 也就是說,如果想讓person(在后續(xù)版本中)有更多的參數(shù),我們?nèi)匀粺o需對(duì)謂詞grandFather

38、做任何改動(dòng)。,5.6.4 算符作為參數(shù),上一節(jié)中,算符person有兩個(gè)參數(shù):Name和Gender。兩者正好都是像常量“Bill”和“Male”這樣的簡單論域。然而,我們也可以把一個(gè)算符作為另一個(gè)算符的參數(shù)。 假定我們想對(duì)一對(duì)夫婦(丈夫和妻子)定義一個(gè)算符,就可以使用這樣一個(gè)算符。 myPredicate(ACouple):- ACouple=couple(person(Husband,male), person(Wife,female) ), . 本例中,你會(huì)發(fā)現(xiàn)這個(gè)算符用另外兩個(gè)算符來定義,每一個(gè)算符都是變量和常量的混合體。這正好反映了數(shù)據(jù)被描述的邏輯。這里所用的邏輯是丈夫總是Male而

39、妻子總是Female,一對(duì)夫婦由一個(gè)丈夫和一個(gè)妻子組成。所有這些都與通常的夫婦概念相一致。,5.6.4 算符作為參數(shù),盡管在PIE中,我們無法預(yù)定義算符的實(shí)際語法類型,但在Visual Prolog中可以這樣定義。這樣定義一個(gè)算符的好處在于,當(dāng)我們用實(shí)際數(shù)據(jù)將算符實(shí)例化時(shí),Prolog推理機(jī)將總是檢查其類型的一致性。 這引出了算符的另一重要特性:算符couple由兩個(gè)參數(shù)定義且參數(shù)的位置反映了他們的邏輯結(jié)合關(guān)系。第一部分中已經(jīng)解釋過了,謂詞參數(shù)的位置由設(shè)計(jì)代碼的程序員給出。一經(jīng)給出,就必須總是采用這樣的位置形式。 該法則同樣適用于算符的構(gòu)造:例如算符couple,我們恰好把husband作為第

40、一個(gè)參數(shù),wife作為第二個(gè)參數(shù)。一旦這樣做,以后無論何時(shí)用到此算符,就必須保證husband總在前面,而wife總在后面。,5.6.4 算符作為參數(shù),現(xiàn)在回頭看一下算符couple,有人會(huì)說,如果不能保證第一個(gè)參數(shù)總是一個(gè)丈夫(總是男性),且第二個(gè)總是一個(gè)妻子(女性),那應(yīng)該怎樣定義它的參數(shù)?這時(shí),可定義一個(gè)更簡化的couple算符如下: myPredicate(ACouple):- ACouple=couple(Husband,Wife), . 因此,讓我們把husband和wife顛倒過來用,但這一次我們是在不知道哪個(gè)是husband的位置,哪個(gè)是wife的位置的情況下使用的。,5.6.

41、4 算符作為參數(shù),myPredicate(Couple):- Couple=couple(person(PersonsName,PersonsGender), person(SpouseName,SpouseGender) ),. 上面的算符中,下面的兩個(gè)例子都具有邏輯意義: myPredicate(C1):- C1=couple(person(Bill, male),person(Pam, female),. /* or */ myPredicate(C2):- C2=couple(person(Pam, female),person(Bill, male),.,5.6.4 算符作為參數(shù),需

42、要指出的是,在PIE(和其它許多Prolog推理機(jī))中,通過算符的定義,無法看出該算符是接受簡單論域還是復(fù)合論域。這是由于在PIE中,復(fù)合論域可以不經(jīng)聲明而直接使用,這與程序員的想法不同。 例如,我們想用下面的復(fù)合論域: person(Name,Gender) 那么PIE將很容易接受像下面這樣的邏輯變量: regardingAPerson(Somebody):- Somebody=person(Pam, person(Pam, person(Pam, person(Pam,female) ) ) ), . 實(shí)際上,這在當(dāng)前上下文中沒有任何邏輯意義。幸運(yùn)的是,Visual Prolog在區(qū)分簡單

43、論域和復(fù)合論域方面作了許多很好的工作,所以,看了后面的教程,讀者就不會(huì)有這些問題了。,5.6.5 算符遞歸,使用算符描述數(shù)據(jù)時(shí),可以像其它任何數(shù)據(jù)一樣操作。例如,讓我們簡短地回顧前面用到的謂詞ancestor。 為了確定某人是否是另一個(gè)人的先輩,我們使用遞歸定義了該謂詞,也就是說,引用了自身的定義。就像這樣: ancestor(Person, Ancestor) :- parent(Person, Ancestor). ancestor(Person, Ancestor) :- parent(Person, P1), ancestor(P1, Ancestor). 這個(gè)定義表示,父母是先輩,并

44、且父母的先輩也是先輩。我們會(huì)發(fā)現(xiàn),上面的變量可以很好地代表簡單論域或復(fù)合論域。,5.6.5 算符遞歸,因而我們這樣定義數(shù)據(jù): parent(person(Bill,male),person(John,male). parent(person(pam,female),person(Bill,male). 如果現(xiàn)在讓PIE求解如下目標(biāo): P=person(pam,female),ancestor(P,Who) 將得到如圖5.10所示的結(jié)果。,5.6.5 算符遞歸,PIE推理機(jī)循環(huán)檢查parent事實(shí)來找到可能的答案。順便說一下,在上面的求解中,你會(huì)發(fā)現(xiàn)我們?cè)诮oPIE指定目標(biāo)時(shí)將復(fù)合論域person綁定到變量P。其目的是用來讓代碼更易讀,但同時(shí)也演示了我們可以將一份數(shù)據(jù)指定為復(fù)合論域賦給任何Prolog變量。,圖5.10 目標(biāo)代碼結(jié)果,5.6.6 算符使用策略,有了模型化的數(shù)據(jù),軟件才會(huì)盡可能的好。建模的意思,就是建立外部真實(shí)世界和軟件內(nèi)部數(shù)據(jù)結(jié)構(gòu)的關(guān)系。如果數(shù)據(jù)模型很差,軟件一般來說也很差;或者最多也是沒有效率。這對(duì)于任何的編程語言和任何軟件都是成立的。這也正是在前面的內(nèi)容中,我們努力把注意力集中在實(shí)體上并盡量不使用更多事實(shí)的原因。類似地,在本節(jié),我們介紹了算符的概念,以使被模型化的實(shí)體的數(shù)據(jù)更清晰。 Prolog的好處在于,它可以用一種內(nèi)部代碼能夠高效使用的形式

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論