跳轉到內容

Prolog/數學、函式和等式

來自華夏公益教科書

本節介紹如何在 prolog 中使用數學,使用函式和等式。

Prolog 中的數字

[編輯 | 編輯原始碼]

Prolog,像任何其他程式語言一樣,對數字有表示。數字像常量一樣使用,並像計算機上的任何地方一樣表示,以下是謂詞中處理數字的有效方式

a(12, 345).
a(A) :- b(A, 234.3).
a(345.3409857) :- b(23476.923804).

要對數字執行數學運算,我們需要函式。要將數學運算的結果儲存在變數中,我們需要更仔細地檢視等式。

到目前為止,謂詞始終代表簡單的真或假。謂詞 a(A, B) 是真還是假,取決於 A 和 B 的值。函式是表示值的謂詞。例如,sin() 謂詞是一個函式。sin(0) 代表值 0,sin(1) 代表值 0.841471。函式可以在任何可以使用數字或常量的地方使用,在查詢、謂詞和規則中。例如,如果事實 p(0). 位於您的程式中,則查詢 ?- p(sin(0)). 將與其統一。

以下常見的數學函式內置於大多數 Prolog 實現中

函式 示例 結果
+ 2 + 3 5
- 36 - 5 31
* 4 * 3 12
/ 36/5 7.2
^ 4 ^ 2 16
sin sin(3) 0.14112

(待補充表格)

請注意,函式本身無法計算。查詢 ?- sin(3). 將失敗,因為 sin() 被實現為函式而不是謂詞。

函式和謂詞之間的區別之一是,謂詞的含義(或定義)通常由您自己定義,在您的程式中。當您使用 sin() 之類的函式時,它們已經在您的 prolog 實現中定義了。換句話說,prolog 不會在您的程式中找到定義,而是在其 內建 謂詞庫中找到。您可以建立自己的函式,但您通常不需要這樣做。

有幾種等式,含義略有不同。這裡我們只看 = 運算子和 is 運算子。首先,看一下

?- A is 36/5.

此查詢將數學運算 36/5 的結果分配給變數 A。因此 Prolog 將回答

A = 7.2

這個想法可能來自其他程式語言。然而,= 運算子非常不同。它不求解右側,而是將其保留為公式。所以你會得到這個

?- A = 36/5.
A = 36/5

Prolog 不會將運算的結果分配給變數 A,而是將運算分配給 A,而不進行求解。

您可以在查詢中看到相同的情況。如果您詢問

?- (31 is (36-5)).

您將得到“是”,因為 (36-5) 已被求解。但是,如果您詢問

?- (31 = (36-5)).

您將得到“否”,因為 Prolog 會將數字 (31) 與公式 (36-5) 進行比較,而不是與求解公式的結果進行比較。

is 運算子專門用於數學函式。左運算元必須是變數,右運算元必須是所有變數都已例項化的數學函式。= 運算子用於變數的統一,並且可以用於任何兩個運算元(儘管如果兩個運算元不同,並且無法透過以特定方式例項化變數來使其相同,則它將失敗)。

Prolog 知道許多其他比較兩個項或例項化變數的方法,但就目前而言,這兩個就足夠了。在處理函式時,我們幾乎總是使用 is 運算子。

現在我們已經瞭解了函式和等式,我們可以開始用數學進行程式設計。

plus(A, B, C) :- C is A + B.

此謂詞將兩個數字(A 和 B)相加,並將結果與 C 統一。以下程式稍微複雜一些。

fac(0,1).
fac(A,B) :- 
      A > 0, 
      Ax is A - 1,
      fac(Ax,Bx), 
      B is A * Bx.

此程式計算 A 的階乘(數學表示法中的 A!)。

它遞迴地工作。第一條規則指出 0 的階乘是 1。第二條規則指出,大於 0 的數字 A 的階乘是 A-1 的階乘乘以 A。

(1) Prolog 對以下查詢(在空資料庫上)將給出什麼答案?嘗試自己思考答案,然後使用 Prolog 編譯器驗證它。

  • ?- X = 1 + 2 + 3.
  • ?- X is 100/10.
  • ?- X is (14 + 16)/3, X + 3 = Y.
  • ?- X = 1000/100 + 5, Y is X.

(2) 編寫一個名為 sigma 的謂詞,使得當 N=A+(A+1)+(A+2)+...+(B-2)+(B-1)+B 時,sigma(A,B,N) 為真。換句話說,. 您可以假設 A 和 B 是整數,且 B>A。使用以下查詢測試您的謂詞

?- sigma(4,9,X).
X = 39 ;
fail.

?- sigma(-7,-2,X).
X = -27 ;
fail. 

?- sigma(-5,5,X).
X = 0 ;
fail.

(3) 本章末尾顯示的階乘程式違反了使用遞迴規則的指南之一。在第二條規則中

fac(A,B) :- 
      A > 0, 
      Ax is A - 1,
      fac(Ax,Bx), 
      B is A * Bx.

遞迴部分不是規則中的最後一個謂詞。

  • 展示 Prolog 如何評估查詢 ?- fac(3, X). 並解釋為什麼程式如此設定。
  • 解釋為什麼行 A > 0 是必要的。如果缺少該行,Prolog 在找到答案後會做什麼?

練習答案

[編輯 | 編輯原始碼]

(1)  ?- X = 1 + 2 + 3.

     X = 1 + 2 + 3.
    
    ?- X is 100/10.
     X = 10.
    ?- X is (14 + 16)/3, X + 3 = Y.
     X = 10.
     Y = 10 + 3.
    ?- X = 1000/100 + 5, Y is X.
     X = Y, Y = 15.

(2) 像往常一樣,解決這個問題的方法不止一種。以下是一種與階乘謂詞類似地使用遞迴的方法。

sigma(A,A,A).
sigma(A,B,N) :-
	B>A, %What do you think would happen if you removed this line? Try it. Why does this happen?
	A1 is A+1,
	sigma(A1,B,N1),
	N is A+N1.


尾遞迴方式:sigma(A,B,N):- add_1(A,B, A, N).

add_1(B,B,N,N).

add_1(A,B,Count,N):-

   B > A,
   A1 is A + 1,
   Count1 is Count + A1,
   add_1(A1, B, Count1, N).

上一個:列表 下一個:組合

華夏公益教科書