?數(shù)據(jù)與表達(dá)式
1、領(lǐng)域
(1)標(biāo)準(zhǔn)領(lǐng)域.
Turbo prolog中不定義變量的類型,只說明謂詞中各個(gè)項(xiàng)的取值域.由上面我們知道, Turbo prolog 有整數(shù)、實(shí)數(shù)、字符、串 和 符號(hào)這5種標(biāo)準(zhǔn)域.另外,它還有結(jié)構(gòu)、表和文件這3種復(fù)合域.
(2)結(jié)構(gòu).
結(jié)構(gòu)也稱復(fù)合對(duì)象,它是 Turbo prolog 謂詞中的一種特殊的參量項(xiàng)(類似于謂詞邏輯中的函數(shù)).結(jié)構(gòu)的一般形式為:
《函子》(《參量表》)1
其中函子及參量的標(biāo)識(shí)符與謂詞相同.注意,這意味著結(jié)構(gòu)中還可包含結(jié)構(gòu).所以,復(fù)合對(duì)象可表達(dá)樹形數(shù)據(jù)結(jié)構(gòu).例如下面的謂詞:
likes(“Tom”, sports(football, basketball, table_tennis)).1
中的
sports(football, basketball, table_tennis)1
就是一個(gè)結(jié)構(gòu),即復(fù)合對(duì)象.又如:
person(“張華”, student(“清華大學(xué)”), address(“中國”, “北京”)).
reading(“王宏”, book(“人工智能技術(shù)導(dǎo)論”, “西安電子科技大學(xué)出版社”)).
friend(father(“Li”), father(“Zhao”)).123
這幾個(gè)謂詞中都有復(fù)合對(duì)象.
復(fù)合對(duì)象在程序中的說明,需分層進(jìn)行.例如,對(duì)于上面的謂詞:
likes(“Tom”, sports(football, basketball, table_tennis)).1
在程序中可說明如下:
domains
name = symbol
sy = symbol
sp = sports(sy, sy, sy)
predicates
likes(name, sp)123456
(3)表.
表的一般形式是:
[x1, x2, ..., xn]1
其中xi(i=1,2,...,n)為 Prolog 的項(xiàng),一般要求同一個(gè)表的元素必須屬于同一領(lǐng)域.不含任何元素的表稱為空表,記為[].例如下面就是一些合法的表.
[1,2,3]
[ apple, orange, banana, grape, cane]
[“Prolog”, “MAENS”, “PROGRAMMING”, “in logic”]
[[a, b], [c, d], [e]]
[]12345
表的最大特點(diǎn)是其元素個(gè)數(shù)可在程序運(yùn)行期間動(dòng)態(tài)變化.表的元素也可以是結(jié)構(gòu)或表,且這時(shí)其元素可以屬于不同領(lǐng)域.例如:
[name(“LiMing”), age(20), sex(male), address(xian)]
[[1, 2], [3, 4, 5], [6, 7]]12
都是合法的表.后一個(gè)例子說明,表也可以嵌套.
實(shí)際上,表是一種特殊的結(jié)構(gòu),它是遞歸結(jié)構(gòu)的另一種表達(dá)形式.這個(gè)結(jié)構(gòu)的函數(shù)名取決于具體的 Prolog 版本,這里我們就用一個(gè)圓點(diǎn)來表示.下面就是一些這樣的結(jié)構(gòu)及它們的表的表示形式:
結(jié)構(gòu)形式表形式
·(a, [])[a]
·(a, ·(b, []))[a, b]
·(a, ·(b, ·(c, [])))[a, b, c]
表的說明方法是在其組成元素的說明符后加一個(gè)星號(hào)*.如:
domains
lists = string*
predicates
pl(lists)1234
就說明謂詞 pl 中的項(xiàng) lists 是一個(gè)由串 string 組成的表.
對(duì)于由結(jié)構(gòu)組成的表,至少分3步說明.例如對(duì)于下面謂 p 中的表
對(duì)于由結(jié)構(gòu)組成的表,至少分3步說明.例如對(duì)于下面謂 p 中的表
p([name(“Liming”), age(20)])1
則需這樣說明:
domains
rec=seg*
seg=name(string); age(integer)
predicates
p(rec)12345
2、常量與變量
由上面的領(lǐng)域可知, Turbo Prolog的常量有整數(shù)、實(shí)數(shù)、字符、串、符號(hào)、結(jié)構(gòu)、表 和 文件 這8種數(shù)據(jù)類型.同理, Turbo Prolog 的變量也就有這8種取值.另外,變量名要求必須是以大寫字母或下劃線開頭的字母、數(shù)字和下劃線 序列,或者只有一個(gè)下劃線(這種變量稱為無名變量).
3、算術(shù)表達(dá)式
Turbo Prolog 提供了 5 種最基本的算術(shù)運(yùn)算:加、減、乘、除 和 取模,相應(yīng)運(yùn)算符號(hào)為“+”、“-”、“*”、“/”、“mod”.這 5 種運(yùn)算的順序?yàn)椋骸?”、“/”、“mod”優(yōu)先于“+”、“-”.同級(jí)從左到右按順序運(yùn)算,括號(hào)優(yōu)先.
算術(shù)表達(dá)式的形式與數(shù)學(xué)中的形式基本一樣.例如:
數(shù)學(xué)中的算術(shù)表達(dá)式Turbo Prolog 中的算術(shù)表達(dá)式
x + yzX + Y * Z
ab - c / dA * B - C / D
u mod vU mod V(表示求U除以V所得的余數(shù))
即, Turbo Prolog 中算術(shù)表達(dá)式采用通常數(shù)學(xué)中使用的中綴形式.這種算術(shù)表達(dá)式為 Prolog 的一種異體結(jié)構(gòu),若以 Prolog 的結(jié)構(gòu)形式來表示,則它們應(yīng)為:
+(X, *(Y, Z))
-(*(A, B), /(C, D))
mod(U, V)123
所以,運(yùn)算符“+”、“-”、“*”、“/”和“mod”實(shí)際也就是 Prolog 內(nèi)部定義好了的函數(shù)符.
在 Turbo Prolog 程序中,如果一個(gè)算術(shù)表達(dá)式中的變?cè)勘粚?shí)例化(即被約束),則這個(gè)算術(shù)表達(dá)式的值就會(huì)被求出.求出的值可用來實(shí)例化某變量,也可用來同其他數(shù)量進(jìn)行比較,用一個(gè)算術(shù)表達(dá)式的值實(shí)例化一個(gè)變量的方法是用謂詞“is”或“=”來實(shí)現(xiàn)的.例如:
Y is X + 5或Y = X + 5 (*)123
就使變量 Y 實(shí)例化為 X+5 的值(當(dāng)然 X 也必須經(jīng)已被某值實(shí)例化),可以看出,這里對(duì)變量 Y 的實(shí)例化方法類似于其他高級(jí)程序語言中的“賦值”,但又不同于賦值.例如,在 Prolog 中下面的式子是錯(cuò)誤的:
X = X + 11
需要說明的是,雖然 Prolog 是一種邏輯程序設(shè)計(jì)語言,但在目前的硬件條件下卻非突破邏輯框架不可.這是因?yàn)橛行?shí)用操作是無法用邏輯描述的(如輸入與輸出),有些算術(shù)運(yùn)算在原則上可用邏輯描述,但這樣做效率太低.為此, Prolog 提供了若干內(nèi)部謂詞(亦稱 預(yù)定義謂詞),來實(shí)現(xiàn)算術(shù)運(yùn)算、輸入與輸出等操作.所謂內(nèi)部謂詞,就是 Prolog 的解釋程序中,預(yù)先用實(shí)現(xiàn)語言定義好的用戶可直接作為子目標(biāo)調(diào)用的謂詞.一般的 Prolog 實(shí)用系統(tǒng)都配有 100 個(gè)以上的內(nèi)部謂詞,這些內(nèi)部謂詞涉及輸入輸出、算術(shù)運(yùn)算、搜索控制、文件操作和圖形聲音等方面,它們是實(shí)用 Prolog 程序設(shè)計(jì)所必不可少的.這樣,上面的(*)式以及下面的關(guān)系表達(dá)式稱為異體謂詞.
4、關(guān)系表達(dá)式
Turbo Prolog 提供了 6 種常用的關(guān)系運(yùn)算,即 小于、小于或等于、等于、大于、大于或等于、不等于,其運(yùn)算符依次為:
《, 《=, =,》,》=, 《》1
Turbo Prolog 的關(guān)系表達(dá)式的形式和數(shù)學(xué)中的也基本一樣,例如:
數(shù)學(xué)中的關(guān)系式Turbo Prolog 中的關(guān)系式
X + 1 ≥ YX + 1》= Y
X ≠ YX 《》 Y
即, Turbo Prolog 中的關(guān)系式也用中綴形式.當(dāng)然,這種關(guān)系式為 Turbo Prolog 中的異體原子.若按 Turbo Prolog 中的原子形式來表示,則上面的兩個(gè)例子為:
》=(X +1, Y) 和 《》(X, Y)1
所以上述 6 種關(guān)系運(yùn)算符,實(shí)際上也就是 Turbo Prolog 內(nèi)部定義好了的 6 個(gè)謂詞.這 6 個(gè)關(guān)系運(yùn)算符可用來比較兩個(gè)算術(shù)表達(dá)式的大小.例如:
brother(Name1, Name2) :- person(Name1, man, Age1),
person(Name2, man, Age2),
mother(Z, Name1), mother(Z, Name2), Age1》 Age2.123
需要說明的是,“=”的用法比較特殊,它既可以表示比較,也可以表示約束值,即使在同一個(gè)規(guī)則中的同一個(gè)“=”也是如此.例如:
p(X, Y, Z) :- Z = X + Y.1
當(dāng)變量 X、Y、Z全部被實(shí)例化時(shí),“=”就是比較符.如對(duì)于問題:
Goal: p(3, 5, 8).1
機(jī)器回答“yes”,而對(duì)于:
Goal: p(3, 5, 7).1
機(jī)器回答“no”.即這時(shí)機(jī)器把 X+Y 的值與Z的值進(jìn)行比較.但當(dāng) X,Y 被實(shí)例化,而 Z 未被實(shí)例化時(shí), “=”號(hào)就是約束符,如:
Goal: P(3, 5, Z).1
機(jī)器回答“Z = 8”.這時(shí),機(jī)器使 Z 實(shí)例化為 X+Y 的結(jié)果.
?輸入與輸出
雖然 Prolog 能自動(dòng)輸出目標(biāo)子句中的變量的值,但這種輸出功能必定有限,往往不能滿足實(shí)際需要;另外,對(duì)通常大多數(shù)的程序來說,運(yùn)行時(shí)從鍵盤上輸人有關(guān)數(shù)據(jù)或信息也是必不可少的.為此每種具體 Prolog 一般都提供專門的輸人和輸出謂詞,供用戶直接調(diào)用.例如,下面就是 Turbo Prolog 的幾種輸入輸出謂詞:
readin(X).這個(gè)謂詞的功能是從鍵盤上讀取一個(gè)字符串,然后約束給變量 X .
readint(X).這個(gè)謂詞的功能是從鍵盤上讀取一個(gè)整數(shù),然后約束給變量 X,如果鍵盤上打入的不是整數(shù),則該謂詞失敗.
readreal(X).這個(gè)謂詞的功能是從鍵盤上讀取一個(gè)實(shí)數(shù),然后約束給變量 X,如果鍵盤上打入的不是實(shí)數(shù),則該謂詞失敗.
readchar(X).這個(gè)謂詞的功能是從鍵盤上讀取一個(gè)字符,然后約束給變量 X,如果鍵盤上打入的不是單個(gè)字符,則該謂詞失敗.
write(X1, X2, …, Xn).這個(gè)謂詞的功能是把項(xiàng) Xi(i=1,2,…,n) 的值顯示在屏幕上或者打印在紙上,當(dāng)有某個(gè) Xi 未實(shí)例化時(shí),該謂詞失敗.其中的 Xi 可以是變量,也可以是字符串或數(shù)字.例如:
write(“computer”, “Prolog”, Y, 1992)
nl(換行謂詞).它使后面的輸出(如果有的話)另起一行.另外,利用 write的輸出項(xiàng)“ ”也同樣可起到換行作用.例如:
write(“name”), nl, write(“age”)
與
write(“name”, “ ”, “age”)
的效果完全一樣.
舉個(gè)例子:
用上面的輸入輸出謂詞編寫一個(gè)簡單的學(xué)生成績數(shù)據(jù)庫查詢程序.
PREDICATES
student(integer, string, real)
grade
GOAL
grade.
CLAUSES
student(1, “張三”, 90.2).
student(2, “李四”, 95.5).
student(3, “王五”, 96.4).
grade :- write(“請(qǐng)輸人姓名:”), readln(Name),
student(_, Name, Score),
nl, write(Name, “的成績是”, Score).
grade :- write(“對(duì)不起,找不到這個(gè)學(xué)生!”).12345678910111213
下面是程序運(yùn)行時(shí)的屏幕顯示
請(qǐng)輸入姓名:王五
王五的成績是96.412
四、分支與循環(huán)
Prolog 本來沒有分支和循環(huán)語句,但可以利用其邏輯機(jī)制實(shí)現(xiàn)分支和循環(huán)效果.
1、分支
對(duì)于通常的 IF-THEN-ELSE 分支結(jié)構(gòu),Prolog可用兩條同頭的(同頭即指結(jié)論相同)并列規(guī)則實(shí)現(xiàn).例如,將:
IF X》0 THEN X:=1
ELSE X:=012
用 Prolog實(shí)現(xiàn)則是:
br :- X》 0, X = 1.
br :- X = 0.12
類似地,對(duì)于多分支,可以用多條規(guī)則實(shí)現(xiàn).例如:
br :- X》 0, X = 1.
br :- X = 0, X = 0.
br :- X 《 0, X = -1.123
2、循環(huán)
Prolog 可以實(shí)現(xiàn)計(jì)循環(huán)次數(shù)的 FOR 循環(huán),也可以實(shí)現(xiàn)不計(jì)循環(huán)次數(shù)的 DO 循環(huán).
舉個(gè)例子:
下面的程序段就實(shí)現(xiàn)了循環(huán),它使得 write 語句重復(fù)執(zhí)行了3次,而打印輸出了3個(gè)學(xué)生的記錄:
student(1, “張三”, 90.2).
student(2, “李四”, 95.5).
student(3, “王五”, 96.4).
print :- student(Number, Name, Score),
write(Number, Name, Score), nl,
Number = 3.123456
可以看出,程序第一次執(zhí)行,student 謂詞與第一個(gè)事實(shí)匹配,write 語句便輸出了張三同學(xué)的記錄.但當(dāng)程序執(zhí)行到最后一句時(shí),由于 Number 不等于 3,則該語句失敗,于是,引起回溯.而 write 語句和 nl 語句均只能執(zhí)行一次,所以繼續(xù)向上回溯到 student 語句.這樣,student 謂詞則因失敗而重新匹配.這一次與第二個(gè)事實(shí)匹配,結(jié)果輸出了李四的記錄.同理,當(dāng)執(zhí)行到最后一句時(shí)又引起了回溯.write 語句第三次執(zhí)行后,由于 Number 已等于3,所以最后一個(gè)語句成功,程序段便運(yùn)行結(jié)束.
這個(gè)例子可以看做是計(jì)數(shù)循環(huán).當(dāng)然,也可以通過設(shè)置計(jì)數(shù)器而實(shí)現(xiàn)真正的計(jì)數(shù)循環(huán).下面的程序段實(shí)現(xiàn)的則是不計(jì)數(shù)的 DO 循環(huán):
student(1, “張三”, 90.2).
student(2, “李四”, 95.5).
student(3, “王五”, 96.4).
print :- student(Number, Name, Score),
write(Number, Name, Score), nl,
fail.
print :-.1234567
這個(gè)程序段中的 fail 是一個(gè)內(nèi)部謂詞,它的語義是恒失敗.這個(gè)程序段與上面的程序段的差別僅在于把原來用計(jì)數(shù)器(或標(biāo)記數(shù))進(jìn)行循環(huán)控制的語句變成了恒失敗謂詞 fail,另外又增加了一個(gè) print 語句,增加這個(gè)語句的目的是為程序設(shè)置一個(gè)出口.因?yàn)?fail 是恒失敗,下面若無出口的話,將引起 print 本身的失敗,進(jìn)而又會(huì)導(dǎo)致程序的連鎖失敗.
還需說明的是,用 Prolog的遞歸機(jī)制也可以實(shí)現(xiàn)循環(huán),不過用遞歸實(shí)現(xiàn)循環(huán)通常需與表相配合.另外,遞歸的缺點(diǎn)是容易引起內(nèi)存溢出,故通常的循環(huán)多是用上述方法實(shí)現(xiàn)的.
?動(dòng)態(tài)數(shù)據(jù)庫
動(dòng)態(tài)數(shù)據(jù)庫就是在內(nèi)存中實(shí)現(xiàn)的動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu).它由事實(shí)組成,程序可以對(duì)它操作,所以在程序運(yùn)行期間它可以動(dòng)態(tài)變化.Turbo Prolog 提供了 3 個(gè)動(dòng)態(tài)數(shù)據(jù)庫操作謂詞,即:
asserta(《 fact》)
assertz(《 fact》)
retract(《 fact》)123
其中 fact 表示事實(shí).這 3 個(gè)謂詞的功能如下:
asserta(《 fact》) 把 fact 插入當(dāng)前動(dòng)態(tài)數(shù)據(jù)庫中的同名謂詞的事實(shí)之前.
assertz(《 fact》) 把 fact 插入當(dāng)前動(dòng)態(tài)數(shù)據(jù)庫中的同名謂詞的事實(shí)之后.
retract(《 fact》) 把 fact 從當(dāng)前動(dòng)態(tài)數(shù)據(jù)庫中刪除.
例如語句:
asserta(student(20, “李明”, 90.5)).1
將在內(nèi)存的謂詞名為 student 的事實(shí)前插入一個(gè)新事實(shí):
student(20, ‘’李明“, 90.5)1
如果內(nèi)存中還沒有這樣的事實(shí),則它就是第一個(gè).又如語句:
retract(student(20, _, _)).1
將從內(nèi)存的動(dòng)態(tài)數(shù)據(jù)庫中的刪除事實(shí):
student(20, _, _)1
它可解釋為學(xué)號(hào)為 20 的一個(gè)學(xué)生的記錄.注意,這里用了無名變量 “_”.
可以看出,Turbo Prolog 提供的動(dòng)態(tài)數(shù)據(jù)庫機(jī)制,可非常方便地實(shí)現(xiàn)堆棧、隊(duì)列等動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu),提供的數(shù)據(jù)庫操作謂詞大大簡化了編程.
另外,Turbo Prolog 還提供了兩個(gè)文件操作謂詞:
save(《 filename》).
consult(《 filename》).12
其中 save 可將當(dāng)前內(nèi)存中的事實(shí)存入文件“filename”中,consult 則將文件“filename”中的事實(shí)調(diào)入內(nèi)存.
評(píng)論
查看更多