2015-08-31 41 views
3

我正在學習我的大學的Prolog,並且我被一個問題困住了。 請注意,我是Prolog的新手,我甚至不知道Prolog元素的正確拼寫。我需要「基礎步驟」在Prolog上進行遞歸嗎?

我需要在我的.pl文件中定義一個遞歸規則,我不知道我的規則是否需要「基礎步驟」。檢查我的規則:

recur_disciplinas(X, Y) :- requisito(X, Y). 
recur_disciplinas(X, Y) :- requisito(X, Z), recur_disciplinas(Z, Y). 

這是行得通的,但我不能做類似以下的事情嗎?

recur_disciplinas(X, Y) :- requisito(X, Z), recur_disciplinas(Z, Y). 

當我聲明兩次相同的「規則名稱」(recur_disciplinas(X,Y) :-)時會發生什麼?發生有點像覆蓋?

我目前使用的是swi-prolog。十分感謝大家!

回答

4

如何理解Prolog規則的最好方法是查看:-運算符,該運算符是1970年代渲染的箭頭(是的,Pascal中的賦值運算符:=也是指箭頭)。所以你看看右邊有什麼,並說:如果情況確實如此,我可以得出左側的結論。所以,你正在閱讀從右到左用您的規則:

recur_disciplinas(X, Y) :- requisito(X, Z), recur_disciplinas(Z, Y). 
%       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ read 

你說:只要有一些XYZ使得右手是真的,我們可以得出結論:recur_disciplians(X, Y)成立。現在,讓我們通過刪除requisito(X, Z)來概括這一點。現在所剩下的是:

recur_disciplinas(X, Y) :- /******/ recur_disciplinas(Z, Y). 

這樣你就可以斷定,這recur_disciplinas(Z, Y)持有recur_disciplinas(X, Y)。但是你沒有什麼可以從這個結論開始的!如此有效地這意味着根本就沒有解決這個關係的問題。

它就像在說,只要我能飛,我就會像鳥一樣飛翔。

也許這是真的,但只要你不飛,這一切都是徒勞的。

請參閱this answer如何允許更緊湊地表達您的關係。目標closure(requisito, X, Y)就夠了!它甚至會處理潛在的循環。


作爲一個方面的說法,我懷疑recur是一些動詞,甚至是一個命令。對?儘量避免關係的必要性。迫切需要改變事物。就像「打開燈」一樣,它將世界從燈光切換到打開的世界改變世界。要求告誡無意識的實體做什麼是必要的。如果你想要推理一些事情,那麼命令行爲只是不幸的。把重點放在應該是什麼情況,什麼不是。

1

如果您的規則名稱不止一次,它會在您的控制流中創建或分支。 Prolog將嘗試統一第一個條款。如果它會失敗,它會嘗試第二個子句,第三個等。

在上面的代碼中,recur_disciplinas規則將首先嚐試找到匹配的requisito。如果它失敗了,它會試圖找到一個必要的,傳遞的,遞歸的。

如果您沒有放置基本子句,Prolog將總是嘗試遞歸子句,因此它可能會進入無限循環。

寫作基礎條件並非Prolog獨有的。每種允許遞歸的語言都是一樣的。如果沒有停止條件,您的功能將進入無限循環。

考慮這個過程相當於僞代碼:

def find_disciplinas(X, Y): 
    if find_requisito(X,Y): # halting condition 
    return (X, Y) 
    else: # recursive call 
    for all Z such that find_requisito(X, Z): 
     return find_disciplinas(X, Z) 

,如果你的「requisito」記錄包括一個週期,並且要刪除該停止條件,上述過程將無限循環。

1

這裏我們說recur_disciplinas/2謂詞有兩個參數,你問約兩條款(規則)謂詞是否是必要的。

正如其他答案所說,在遞歸中需要一個「基本情況」,以便遞歸終止,這通常是可取的!最常見的安排就像你的第一個例子:第一個規則是終止條件(基本情況),第二個規則是遞歸步驟(歸納情況)。有人閱讀你的代碼可能會發現這種安排很熟悉,也很容易理解。

但是,基本情況和遞歸步驟可以合併爲一條規則,這有時很有用。例如,我們可以使用OR語法:

recur_disciplinas(X, Y) :- 
    requisito(X, Y) ; (requisito(X, Z), recur_disciplinas(Z, Y)). 

這裏;意味着OR,而這個單一的規則基本上是用於生產的解決方案相同的搜索爲原來的兩個規則的版本。

也可能有多個基本情況,每個情況都有自己的規則或寫入更復雜的「組合」規則。與任何編程規範一樣,清晰和正確應該僅僅通過代碼中的簡潔來珍視。

在一些不常見的情況下,將遞歸步驟定位爲第一條規則並將基本案例移至以下規則可能會比較有利。這需要特別小心,以確保始終達到終止條件,因爲您不希望代碼可能無休止地循環。當一個謂詞被調用時,Prolog引擎總是以第一條規則開始;只有在第一條規則失敗後纔會嘗試以下規則。