List Prolog谓词不工作
我完全搞不懂序言。我有两个简单的谓词,我正试图弄明白,但似乎不能得到正确的。首先,我试图找出delete谓词的一个变体,在这个变体中,我需要从List1中删除给定元素的所有引用,并查看它是否等于List2 这就是我试过的List Prolog谓词不工作,list,prolog,List,Prolog,我完全搞不懂序言。我有两个简单的谓词,我正试图弄明白,但似乎不能得到正确的。首先,我试图找出delete谓词的一个变体,在这个变体中,我需要从List1中删除给定元素的所有引用,并查看它是否等于List2 这就是我试过的 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). 另一个谓词获取
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).
另一个谓词获取两个列表,获取List1中元素2的所有引用,并将其替换为4,然后查看List1是否与List2相同。要使其更简单,没有子列表
这些就是我尝试过的
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).
我想知道我犯了哪些错误,也许还想解释一下这些术语的工作原理。多谢各位 检查
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) 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) 此规则表示列表[p]
是删除元素S
的列表[p]
。该规则的问题在于S
和P
可能是相同的值,因此该规则并不总是正确的。如果您希望一直都是这样(这是一条有效的规则),则需要规定S
和P
不能实例化为相同的值:
del(S, [P], [P]) :- S \= P.
这是假设我们甚至需要这个规则,但我们暂时把它留在这里,因为在这个新的状态下,它是正确的
(2) 此规则表示[]
是删除元素S
的列表[S]
。这是真的
(3) 这条规则说,如果H1
和S
是统一的,并且L2
是[H2 | T]
删除了S
的,那么L2
就是删除了S
的[H2 | T]
列表。但是,缺少一个论点。您有del([H2 | T],L2)
,但是del/3
被定义为包含3个参数。我们假设您的意思是S
是第一个参数(S
仍然是要删除的参数),因此del(S,[H2 | T],L2)
。新修复的规则似乎符合逻辑
(4) 这条规则说,*[H1,T2]
是列表[H1,H2 | T]
,如果H1
与S
不一致,那么T2
是列表[H2 | T]
,元素S
被删除。这与#3的问题相同,缺少del/3
的参数,我们再次假设它是S
,使其成为del(S,[H2 | T],T2)
。另一个问题是您有[H1,T2]
,这是一个只有两个元素的列表:H1
和T2
。又一个打字错误。这应该是[H1 | T2]
。因此,修复后的规则现在似乎有意义了
仅仅修复这两个粗心的错误就可以使谓词几乎正常工作!实例化第一个参数时,它将生成正确的结果:
| ?- del(a, [a,b,c,a,d,a], L).
L = [b,c,d] ? a
no
此外,它可以被清理一点。H2
在第3和第4条中没有真正使用。在第三个子句中,您可以在谓词的开头实例化S
和H1
。因此,这两个人成为:
(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
,这意味着H
和S
是不可统一的。如果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).
让我们“重读”这些规则:
S
的列表[S|T]
是列表L2
,如果L2
是移除元素S
的列表T
S
不同于H
,T2
是移除元素S
的列表T
,并且T2
是移除元素S
的列表T
| ?- del1(X, [a,b,c,b,d], [a,c,d]).
X = b ? ;
(1 ms) no
检查
变更/2
(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) 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,如果H1
为2,我将得到L
,并且我将L
附加到[2]
(这将在[2]之后一直失败)
不是可变的-参见在线文档了解append/2
和append/3
!append/2
用于附加列表,例如)和L
是[H2 | T]
,其中2改为4。这已经没有任何逻辑意义了。如果我要将2改为4,为什么要在[2]
中添加内容?我们需要丢失追加
,只需将L
与[4 | T2]
统一,其中T2
是[H2 | T]
,其2改为4。换句话说:
(2) change([H1,H2|T], L) :- H1 = 2, L = [4|T2], change([H2|T], T2).
这可以通过在上述条款的开头加入统一的方法进一步简化。同样要注意的是,在这里显示H2
并没有实际用途。所以[
(1) change([], []).
(2) change([2|T], [4|T2]) :- change(T, T2).
(3) change([H|T], [H|T2]) :- H \== 2, change(T, T2).
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).