遞歸是Prolog中最本家兒要而又最難于把握的概念之一,Prolog是一門聲明式編程說話,當你處置事物調集時,如列表或樹,你會經常利用遞歸而不是迭代。
1的算術運算
1的調試
讓我們先從這一個簡單的例子來領會遞歸的性質吧。
在ancestor子句中的一個子句會利用ancestor子句。在這個例子中,ancestor(Z, Y)是一個遞歸的子方針。father 是實現遞歸子方針的焦點事實。法則ancestor/2有兩個子句。
若是一個法則由多個子句構成,那么此中一個子句為真,則這個法則為真。可以把子句間的逗號算作是前提“與”的關系,把子句之間的句號算作是前提“或”的關系。
我們可以測試一下這個法則:
我們起首扣問命題ancestor(john_boy_sr, john_boy_jr).和ancestor(zeb, john_boy_jr).是否為真,接著給出變量Who,別離尋找zeb的兒女和john_boy_jr的祖先。
我們已經可以在常識庫中利用這個法則實現兩個目標:尋找祖先和兒女。
一個整數的階乘界說為,該數與小于它的全數正整數的積,一個整型數的階乘用該數及后面的感慨號暗示(!)。好比:5! = 5 × 4 ×3 × 2 × 1。一般形式為:
n! = n × (n - 1) × (n - 2) ×……× 3 × 2 × 1
然而,一個整型數的階乘還可能暗示為這個整型數與公比其小1 的阿誰整型數的階乘的乘積,例如:5!=5×4!。這種階乘的界說體例就表現了遞歸,因為它操縱階乘自界說階乘。是以,任一正整數的階乘可用下面遞歸界說給出:
n! = n × (n-1)!
在數學的界說上,0的階乘等于1。是以,階乘的完整界說如下:
0! = 1(遏制前提)
n! = n x (n - 1)!(遞歸界說)
轉換當作Prolog法式如下圖所示:
在扣問后,獲得成果后按回車。運行成果如圖所示。值得注重的是,在常識庫中遏制前提應該放在遞歸法則前面,這一點是至關主要的。因為若是不是如許,遏制前提將永遠不會知足。假如把法則放在遏制前提前面,那么Prolog反復進入常識庫時將起首碰到它,并與其進行匹配,即使是應知足遏制前提時,也毫不會與遏制前提匹配,從而引起無限遞歸。
數學的斐波那契數列是一個正整數數列,它與黃金比例有著緊密親密的聯系。該數列的下一個數是由其前面兩個數相加獲得的,頭兩個數均為1。該數列如下:
1,1,2,3,5,8,13,21,34,55,……
通式為:
f(1) = 1 (兩個遏制前提)
f(2) = 1
f(n) = f(n-1) + f(n-2) (遞歸法則)
這里用Num1、Num2這兩個變量別離來暗示序數Num項的前面兩項;變量Term1和Term2別離暗示前兩項斐波那契數的成果。來轉換當作Prolog法式如下圖所示:
運行后的成果如下圖所示。從截圖可以看出,這些遞歸的法式還存在一些問題,好比在已經得出成果后,若是按“;”鍵試圖查找另一個解時,會呈現錯誤的謎底,甚至起頭報錯。因為若是查找另一個成果,會從頭進入遞歸前提,會再次減去數字,因而會報錯。我將會鄙人次介紹Prolog的另一個機制——截斷。
以上幾個實例用于申明遞歸的Prolog法式。年夜大都較年夜的Prolog法式都可能包含遞歸,遞歸是年夜大都Prolog法式中的本家兒要節制手段。
在編寫遞歸途序時,應服膺下述幾點:
?所有遞歸法則都必需有遏制前提,若是沒有遏制前提,遞歸法則將無盡頭地遞歸下去。
?一般環境下,遏制前提應該放在常識庫中遞歸法則的上方。因為若是總找不到遏制前提,也將導致無限遞歸。
?凡是,在編寫Prolog法式時應盡量采用遞歸,這要求自問如下問題:
?是否可以把問題用其自身表達出來?
?遏制前提是什么?
總的來說,遞歸法則具有下列一般形式:
遞歸法則的遏制前提.
遞歸謂詞 :-
某些初始計較,
遞歸謂詞,
某些最終運算.
0 篇文章
如果覺得我的文章對您有用,請隨意打賞。你的支持將鼓勵我繼續創作!