2012-04-16 142 views
1

我對Prolog完全陌生,並且在做家庭作業。我的程序應該採用兩個等長的列表,並執行D = sqrt((X1-Y1)^ 2 +(X2-Y2)^ 2 + ... +(XN-YN)^ 2)。我已經編寫了代碼來獲得正確的答案,但它沒有正確顯示。我認爲這可能是邏輯流程的一個問題,因爲它看起來像是在一個無限循環中結束。它應該是這樣的:Prolog邏輯流程

?- distance([1,2,3], [2,3,4], D). 
D = 1.732051. 

我的代碼是給我正確的結果,但它打印它想:

?- distance([1,2,3],[2,3,4],D). 
1.732051 
true 

只是因爲我有一條線在那裏打印的結果。它也沒有結束(沒有時期),直到我進入,這就是爲什麼我害怕我有一個循環。如何更改我的代碼或重定向我的邏輯,使其正常打印?

distance([],[],D) :- 
    F is sqrt(D), 
    format("~f~n", [F]). 

distance([A|T1], [B|T2], D) :- 
    var(D), 
    S is (A-B)*(A-B), 
    distance(T1, T2, S); 
    C is A-B, 
    E is C*C, 
    F is D+E, 
    distance(T1, T2, F). 
+0

不應該'F'評價爲'd-E',而不是'd + E'?你希望遞歸距離是總距離減去每次第一項的距離。我也對'distance(T1,T2,S)'這一行感到困惑;'你可以評論一下嗎? – ely 2012-04-16 21:49:41

+0

N/M,我明白你現在在做什麼..在最後一個參數中累積距離的總和。我認爲這有點混亂,但是正確。所以唯一的問題是奇怪的印刷。我認爲這與你缺乏真正的基礎案例有關。在你的方法中,距離([],[],0)不會成立。另請注意,代碼在運行時如何掛起,等待額外的'。'。返回true後。 – ely 2012-04-16 22:01:05

回答

2

你的程序沒有進入死循環,否則你很可能會在某個時候出現堆棧溢出錯誤。 發生什麼事是你的代碼留下了一個開放的選擇點,所以最終解釋器試圖重做(失敗)。 您沒有按預期得到結果,因爲調用過程中使用的變量D永遠不會被綁定。

你最好解決這個問題,思考如何遞歸地建模。在這種情況下,你可以例如在輸入列表爲空時和不在時輸入列表分開問題(我在這裏假設用空列表調用你的過程將產生0結果)。

因此,在這種情況下,您將創建兩個子句,一個用於基本情況(空列表),另一個用於遞歸步驟。我還將使用一個在使用累加器組成的prolog中使用的常用方法。

所以我們創建距離/ 3事實只會調用使用該蓄電池另一個過程:

distance(L1,L2,F) :- 
    distance(L1, L2, 0, F). 

我們用蓄電池持有的平方項差之和的部分結果(AB) *(AB)在你的代碼:

現在我們先從基本情況(空列表):

distance([],[],S,F) :- 
    F is sqrt(S). 

這裏我們規定的時候,沒有更多的項目留我是累加器的平方根。

我們現在跟隨遞歸步驟,計算每個列表中第一項的平方項差異並進行遞歸。

distance([A|T1], [B|T2], D, SQRT) :- 
    S is D+(A-B)*(A-B), 
    distance(T1, T2, S, SQRT). 

現在我們正在這樣做:

?- distance([1,2,3],[2,3,4],D). 
D = 1.7320508075688772. 
+0

當然!謝謝你如此清晰簡潔地解釋一切。我使用了你給我的修改,現在它可以工作。謝謝! – AmberWolfe 2012-04-16 22:38:16

0

我不明白,使用format功能,因此,所有我能做的就是提供這個我自己嘗試。我認爲你的嘗試有一個缺點,就是遞歸的基本情況沒有明確說明。

考慮下面我的做法:

distance([],[],0). 
distance([A],[A],0). 
distance([A|T1],[B|T2],D) :- 
    distance(T1,T2,F), 
    D is sqrt((A-B)*(A-B) + F*F). 
+0

請注意,您正在計算另一個功能。例如,在你要做的3個項目列表中,(A1-B1)^ 2 + sqrt((A2-B2)^ 2 + sqrt((A3-B3)^ 2)^ 2)^ 2'。你的第二個基本情況也是沒有必要的。 – gusbro 2012-04-16 22:15:09

+0

第二個基本情況比沒有情況快嗎?也許也更強大的數字(儘管通常這在Prolog中不是問題)。 – ely 2012-04-16 22:15:40

+0

問題是它不太清楚。如果你希望它更快,也更強大,你可能應該使用累加器來允許尾遞歸(否則你可能會遇到棧問題) – gusbro 2012-04-16 22:17:47

0

我認爲你應該使用的蓄電池:

distance(L1, L2, D) :- 
    distance(L1, L2, 0, D). 

distance([], [], TT, D) :- 
    D is sqrt(D). 

distance([X1 | Y1], [X2 | Y2], TT, D) :- 
    TT1 is TT + (X1 - X2) * X1 - X2), 
    distance(Y1, Y2, TT1, D).