2014-04-16 198 views
0

我完全和Prolog混淆。我有兩個簡單的謂詞,我試圖找出,但似乎無法讓他們正確。首先,我試圖找出刪除謂詞的變體,我需要從List1中刪除給定元素的所有出現,並查看它是否等於List2。Prolog謂詞不起作用

這就是我試過的。

del(S,[P],[P]). 
del(S,[S],[]). 
del(S,[H1,H2|T],L2) :- H1 = S, del([H2|T],L2). 
del(S,[H1,H2|T],[H1,T2]) :- H1 \= S, del([H2|T],T2). 

其他謂詞需要兩個列表,並採取元件2的所有出現List1中並用4替換它,並認爲如果List1中是一樣的列表2。爲了簡化,沒有子列表。

這些都是我試過的。

change([],[]). 
change([H1,H2|T],L) :- H1 = 2, append([2],L), change([H2|T],L). 
change([H1,H2|T],L) :- H1 \= 2, append(H1,L), change([H2|T],L). 

我想知道我做了什麼錯誤,也許是解釋這些術語是如何工作的。謝謝。

考試

回答

3

del/3

(1) del(S,[P],[P]). 
(2) del(S,[S],[]). 
(3) del(S,[H1,H2|T],L2) :- H1 = S, del([H2|T],L2). 
(4) del(S,[H1,H2|T],[H1,T2]) :- H1 \= S, del([H2|T],T2). 

(1)該規則表示,列表[P]是列表[P]與元件S除去。此規則的問題是SP可能是相同的值,因此該規則並非總是如此。如果你想這是真的所有的時間(是一個有效的規則),你需要規定SP不能被實例化,以相同的值:

del(S, [P], [P]) :- S \= P. 

這是假設,我們甚至需要這個規則,但我們暫時將它留在這裏,因爲在這個新的狀態下,這是正確的。

(2)這條規則說[]是列表[S]與元素S去除。那是真實的。

(3)這條規則說L2是,如果H1S是統一的,L2[H2|T]S刪除刪除列表[H1,H2|T]S但是,缺少一個參數。您有del([H2|T], L2),但del/3被定義爲需要3個參數。我們假設你的意思是S是第一個參數(S仍然是什麼被刪除),所以del(S, [H2|T], L2)。新修理的規則似乎是合乎邏輯的。

(4)這條規則說,* [H1,T2]是列表[H1,H2|T]與如果H1刪除的元素S不unifiable與ST2是列表[H2|T]與中移除的元素S。這與#3有同樣的問題,del/3缺失的參數,我們將再次假設爲S,使其成爲del(S, [H2|T], T2)。另一個問題是,您有[H1,T2]這是一個只有兩個元素的列表:H1T2。另一個錯字。這應該是[H1|T2]。所以修好的規則現在似乎有意義。

只是修復這些粗心的錯誤導致你的謂詞幾乎可以工作!當第一個參數被實例化時,它會產生正確的結果:

| ?- del(a, [a,b,c,a,d,a], L). 

L = [b,c,d] ? a 

no 

此外,它可以清理一下。 H2沒有真正用於第3和第4章。在第3個子句中,可以在謂詞的頭部實例化SH1。因此,這兩個變爲:

(3) del(S, [S|T], L2) :- del(S, T, L2). 
(4) del(S, [H|T], [H|T2]) :- H \= S, del(S, T, T2). 

謂詞在列表中失敗爲空。我不確定這是否是故意的,但是您可能會認爲del(X, [], [])應該爲真(當您從空列表中刪除某個元素時,會生成一個空列表)。如果我們有這樣的規則:

(1a) del(_, [], []). 

我們現在可以擺脫規則(1)和(2),因爲(3)和(4)將照顧他們和遞歸下降到規則(1A)。

此外,該規則還未能在這種情況下:

| ?- del(X, [a,b,c], [a,c]). 

no 

這將是很好,如果這打嗝了,X = b。問題是在條款(4)中,我們檢查H \= S這意味着HS不可統一。如果S是一個變量,則此表達式對我們有效,因爲H \= S將始終失敗(因爲S確實可以統一爲H)。所以我們用dif(H,S)替換它來檢查這些條款是否相同。 某些序言不提供dif/2,在這種情況下,您可以用\==替代此解決方案(H \== S)。我們得到的規則集:

(1) del(_, [], []). 
(2) del(S, [S|T], L2) :- del(S, T, L2). 
(3) del(S, [H|T], [H|T2]) :- dif(H, S), del(S, T, T2). 

讓我們「重讀」的規則:

  1. 從空的列表中移除所有元素是空列表。
  2. 列表[S|T]除去了元件S是列表L2如果L2是列表T移除了元件S
  3. 列表[H|T2]是列表[H|T]移除了元件S如果S不同於HT2是列表T移除了元件S

這看起來簡單得多,雖然只是一些簡單的回頭離開原來的。現在會產生這樣的結果,這是很好的:

| ?- del1(X, [a,b,c,b,d], [a,c,d]). 

X = b ? ; 

(1 ms) no 

考試change/2

(1) change([],[]). 
(2) change([H1,H2|T],L) :- H1 = 2, append([2],L), change([H2|T],L). 
(3) change([H1,H2|T],L) :- H1 \= 2, append(H1,L), change([H2|T],L). 

(1)這條規則是說,如果我們改變所有的2公司在空列表,我們得到的空的清單。聽起來不錯。

(2)這條規則說,如果我把名單[H1,H2|T],我改變了2對4的,我得到L如果H1是2和我追加L[2](這是自[2]總是會失敗不變量 - 見爲append/2append/3在線文檔!append/2是追加列表的列表,例如)和L[H2|T] 2的改變爲4的。這已經沒有任何邏輯意義了。如果我將2更改爲4,我爲什麼要追加[2]?我們要失去append和簡單統一L[4|T2]其中T2[H2|T]其2的改變爲4的。或換句話說:

(2) change([H1,H2|T], L) :- H1 = 2, L = [4|T2], change([H2|T], T2). 

這可以進一步簡化使用在上面的子句的頭部合併統一的方法。另外請注意,我們沒有真正用於在此處顯示H2。所以[H2|T]可以只是一個T

(2) change([2|T], [4|T2]) :- change(T, T2). 

所以我們使用的4而不是2,如果有一個2,然後處理尾巴。

(3)此規則與append/2查詢具有相同的問題(2)。我們可以按照我們與規則(2)做了同樣的模式,並解決非等檢查:

(3) change([H|T], [H|T2]) :- H \== 2, change(T, T2). 

所以我們只是結轉的元素H如果它不是一個2,然後處理尾巴。完整的change謂詞的樣子:

(1) change([], []). 
(2) change([2|T], [4|T2]) :- change(T, T2). 
(3) change([H|T], [H|T2]) :- H \== 2, change(T, T2). 

李自成的規則,看到他們作出合乎邏輯的意義:

  1. 變更2對4層的在空列表是空列表。
  2. 變更2對4名在列表中[2|T]是列表[4|T2]如果T2是列表T與2的改變爲4的。
  3. 變更2對4名在列表中[H|T]是列表[H|T2]如果H2T2是列表T與2的改變爲4的。
+0

太謝謝你了。這非常有幫助。我很欣賞一步一步以及如何閱讀條款。現在對我來說更有意義。 – user3342236

+0

@ user3342236我很高興你發現它有幫助。 :) – lurker

1

讓我們從最簡單的兩個開始:change/2。兩個列表長度相同,並且它們基本相同 - 對於應該由4替換的2的發生是安全的。所以讓我們首先定義爲這樣一對關係:

exch(2, 4). 
exch(X, X) :- 
    dif(X, 2). 

你可能優化這一出於性能考慮到

exch(A, B) :- 
    ( A == 2 -> B = 4 
    ; A \= 2 -> A = B 
    ; A = 2, B = 4 
    ; A = B, dif(A,2) 
    ). 

現在,您的實際定義是

change(Xs, Ys) :- 
    maplist(exch, Xs, Ys). 

以上冗長:

change([], []). 
change([A|As], [B|Bs]) :- 
    exch(A, B), 
    change(As, Bs). 

比較這一定義與建議等的定義,請考慮以下查詢:

?- change([X],[Y]). 
X = 2, 
Y = 4 ; 
X = Y, 
dif(Y, 2). 

del(E, Xs, Ys) :- 
    tfilter(dif_truth, Xs, Ys). 

dif_truth(X, Y, true) :- 
    dif(X, Y). 
dif_truth(X, X, false). 

tfilter( _, [], []). 
tfilter(CT, [E|Es], Fs0) :- 
    call(CT,E,Truth), 
    ( Truth = false, 
     Fs0 = Fs 
    ; Truth = true, 
     Fs0 = [E|Fs] 
    ), 
    tfilter(CT, Es, Fs). 

Further uses

+0

謝謝你解決我的問題的另一種方法。 – user3342236