Prolog/將它們放在一起
本節旨在結合前幾章的知識並對其進行回顧。Prolog 首先被更詳細地解釋,忠於其基本結構,然後展示一個小型程式,該程式結合了前幾章的知識。
Prolog 程式由規則資料庫組成。這些規則被載入到編譯器中。然後使用者可以在資料庫上執行查詢。編譯器將嘗試證明查詢是正確的。
Prolog 中的一切都用邏輯來描述(Prolog 邏輯是經典謂詞邏輯或一階邏輯的變體)。從原子(最小的位)開始,這些是構成 Prolog 程式或查詢的最重要的邏輯符號。
這些由一個或多個小寫字母組成,以字母開頭。常量不是由其他 Prolog 符號組成(它是一個原子),它在 Prolog 世界中除了它本身之外不代表任何東西。將原子視為 Prolog 世界中的物件是一個好方法。它們沒有附加的含義。有效常量的示例
foo cd_p0345 a dirk
變數是容器。它們可以表示幾乎任何 Prolog 結構,從常量到謂詞。變數由一個或多個小寫或大寫字母組成,以大寫字母開頭。重要的是要注意,Prolog 中的變數與大多數程式語言中的變數功能不同。您不會為它們分配一個值然後使用它們,當您執行一個查詢以嘗試使查詢為真時,Prolog 會為它們分配各種值。有效變數的示例
B Parent Result
謂詞由一個函符(一個或多個小寫字母,以字母開頭)組成,後面可能跟著方括號之間的一些項,用逗號隔開。謂詞根據其項為真或假。有效謂詞的示例
childof(Child, Father) predicate(dog(x), cat(Y)) architect(a_vandelay) termless_predicate
函式的構建方式與謂詞相同,但它不是假或真,它可以代表變數可以代表的任何東西。例如,函式 sqrt(A) 將返回 A 代表的任何數字的平方根。
原子句子是 Prolog 程式中最小的部分,可以取真或假。所有謂詞都是原子句子。一些其他 Prolog 語句,例如統一 (=) 也是原子句子。原子句子的示例
childof(george_w_b, george_b) A = tan(B, C) + D
句子是 Prolog 結構,可以取真或假。原子句子當然就是句子。其他句子(即非原子句子)由透過連線詞連線在一起的原子句子組成。Prolog 中最重要的連線詞是,(“和”連線詞)。如果一個句子用逗號將兩個原子句子連線起來,那麼如果(且僅當)這兩個原子句子都為真,則該句子為真。Prolog 中的大多數句子只是一些謂詞,它們之間用逗號隔開,表示所有原子句子都必須為真,才能使該句子為真。注意:其他連線詞雖然很重要,但將在後面介紹。 句子的示例。
childof(a, b), male(a), female(b) A = B * 3, even(A) dog(poochie), cat(scratchy), mouse(itchy)
規則是一種特殊的句子型別。它在左邊有一個謂詞,在右邊有一個句子,用:-分隔。它以句號結束。句子是 Prolog 程式中的行。規則指出,如果句子為真,則謂詞為真。如果規則中存在變數,則對於任何使句子為真的變數例項化,謂詞都為真。沒有句子在謂詞之後(因此沒有:-)的規則稱為事實,並且被認為是真實的。Prolog 程式中的每個句子都是一個規則。
規則示例。
mother(A) :- has_child(A), female(A). car(porsche). equal(X, X).
項是任何代表物件的 Prolog 結構。常量和函式始終是項,變數可以代表項。
其他 Prolog 概念在詞彙表中解釋。
Prolog 編譯器允許使用者在規則資料庫(Prolog 程式)上執行查詢。查詢是特殊的規則型別,在:-之前沒有謂詞。一旦輸入查詢,Prolog 將在給定資料庫中的規則為真的情況下檢查它是否為真。如果查詢包含變數,Prolog 將嘗試找到一個變數例項化,使查詢為真。
這種變數例項化是基於統一過程。如果 Prolog 正在嘗試驗證查詢:- a(X).並在資料庫中遇到規則a(a).,它將把變數 X 與常量 a 統一起來。換句話說,它將把變數 X 例項化為值 a。由於 a(a) 為真,因此 Prolog 將返回 X = a 作為解決方案。統一採用兩個謂詞,並檢視是否可以使用一個來例項化另一個的變數。以下兩個謂詞統一
p(A, y) p(z, B) unification: A = z, B = y
這些也是如此
q(A, [y,z,C]) q(x, B) unification: A = x, B = [y,z,C]
但是,這些不會統一
q(A, A) q(x, y)
這是因為 A 可以是 x 或 y,但不能同時是兩者。另一方面,這些
q(A, B) q(x, x)
將統一,因為兩個不同的變數可以繫結到同一個常量。
如果 Prolog 正在嘗試驗證查詢:- b(X).並在資料庫中遇到規則b(A) :- c(A).它將把變數 X 統一到變數 A。這兩個變數都沒有被例項化(即,沒有分配給它們值),但它們相互繫結,它們只能被例項化為相同的值。現在,Prolog 將c(A)新增到其查詢列表中以進行驗證。如果它在資料庫中遇到規則c(c) :- d.,它將(臨時)用 c 例項化 A,並嘗試驗證 d。如果 d 成功,Prolog 將返回X = c 作為原始查詢的解決方案,如果 Prolog 無法在資料庫中找到任何使 d 為真的內容,Prolog 將忘記這條規則,並嘗試以其他方式使c(A) 為真。這就是所謂的回溯。
以下程式檢查一列數字的總和是否等於零
sum_is_zero(List) :- sum(List, Sum), % Sum is the sum of the List Sum = 0. % Sum needs to be 0 sum([], 0). % the sum of an empty list is always 0 (stop predicate) sum([FirstNumber|Tail], Sum) :- % The list is split into its first number and its tail sum(Tail, TailSum), % TailSum is the sum of the tail Sum is FirstNumber + TailSum. % Add the first number to that to get the Sum of the list.
程式中的第一個規則非常簡單。它使用 sum 謂詞對列表進行求和,並檢查它是否等於零。後兩個規則構成了 sum 謂詞。第一個規則是停止謂詞。它簡單地說明空列表的和為 0。第二個規則首先將列表拆分為 FirstNumber(列表中的第一個數字,即“頭部”)和 Tail(列表的其餘部分)。它遞迴地計算尾部的和,並將第一個數字新增到尾部的和中。
一些查詢
?- sum_is_zero([1, -1]). Yes ?- sum_is_zero([1, 1, -2]). Yes ?- sum([-1.5, 2.7849, 3.383724], A). A = 4.66862 ; No ?- sum([-1.5, 2.7849, 3.383724], 42). No
(1)以下哪些謂詞對可以統一?如果可以,請給出變數的例項化,如果不可以,請解釋原因。
1 child_of(M, P) child_of(martha, doug) 2 dog(A) dog(B) 3 f(X, Y, e, Z) f(a, b, d, c) 4 r(D, F) r(p, c(martha, D))