2011-03-02 71 views
1

在這個任務中,我有一個Prolog數據庫,裏面充滿了例如邊緣(2,0) 邊緣(1,3)prolog需要建議嗎?

邊緣表示兩點連接。

我被要求寫一個叫做reach(i,j,k)的函數,其中i是起點,j是終點,k是你可以使用的步數。需要K來停止遞歸循環,例如,

假設我得到的唯一邊緣是從1到3,並且我試圖達到6.然後我無法一次從1to6得到。所以我會尋找我可以去的地方,看看我能不能從那裏到達6.我一次可以到達的第一個地方是3,所以我會嘗試從那裏到達6。

我這樣做像這樣:

%% Can you get there in one step (need two rules because all links are 
%% from smaller to greater, but we may need to get from greater to smaller. 

reach1(I, J,_K) :- 
    edge(I, J). 
reach1(I, J,_K) :- 
    edge(J, I). 
%% Chhose somewhere you can get to in one step: can you get from there 
%% to your target? 
reach1(I,J,K) :- 
    K>1, 
    edge(I, B), 
    K1 is K-1, 
    reach1(B,J,K1). 

reach1(I,J,K) :- 
    K>1, 
    edge(B, I), 
    K1 is K-1, 
    reach1(B,J,K1). 

這個工作,但是我堅持的第二部分中,我們被要求不要使用k,但使用「切」來做到這一點。

有沒有人知道如何做到這一點或可以給我一些指針?

+2

你可能想看看http://stackoverflow.com/questions/3970977/traverse-undirected-graph-in-prolog/3971936#3971936討論圖的遍歷。那裏的解決方案並不使用剪裁,但我相信它更加優雅。當然,您可以重新編寫該解決方案,以便在到達已訪問的節點後使用剪切修剪回溯樹。 – gusbro 2011-03-02 13:32:33

+0

我不遵循「這樣做」的意思,但不使用K,因爲它構成** reach1/3 **規範的一部分。此外,前兩條規則,即「單步」情況下,大概不會有'_K',而是'1'作爲** reach1 **的第三個參數。發現路徑的一個普遍問題是如何避免無限遞歸,例如從1到2,回到1,回到2,等等,沒有朝着真正的目標前進。也許最初的練習旨在探索防止這種循環的各種方法。目前的要求很難說清楚。 – hardmath 2011-03-02 14:09:15

回答

0

切割確保一旦目標以某種方式得到解決,它就不會尋找其他方式。

例如:

reach(I, J,_K) :- 
    edge(I, J). 

沒有切 - 如果由於某種原因Prolog的回溯,它會嘗試從我到達至J另一種方式。 你可能會覺得有沒有點到達該點的另一個方式,如果簡單的邊緣工作,而在這種情況下,你可以這樣做:

reach(I, J,_K) :- 
    edge(I, J), 
    !. 

其中「切割」的任何替代這個目標,但一個Prolog的發現。