Prolog谓词不起作用

时间:2014-04-16 00:12:16

标签: list prolog

我与Prolog完全混淆。我有两个简单的谓词,我试图弄清楚,但似乎无法使它们正确。首先,我试图找出一个删除谓词的变体,我需要从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).

另一个谓词采用两个列表,并在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).

我想知道我所犯的错误,也许是对这些术语如何起作用的解释。谢谢。

2 个答案:

答案 0 :(得分: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无法实例化为相同的值:< / p>

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

假设我们甚至需要这条规则,但我们暂时将它留在这里,因为在这个新状态下,它是正确的。

(2)此规则表明 []是已删除元素[S]的列表S 。那是真的。

(3)此规则表明,如果L2[H1,H2|T]统一且{S H1就会移除S列表L2 1}} [H2|T]移除S但是,缺少参数。您有del([H2|T], L2)del/3被定义为接受3个参数。我们假设您的意思是S是第一个参数(S仍然被删除了),所以del(S, [H2|T], L2)。新修复的规则似乎是合乎逻辑的。

(4)此规则表明* [H1,T2][H1,H2|T]列表,如果SH1无法统一,则S已移除T2 {1}}列表[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)以检查这些术语是否相同。 有些Prolog不提供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).

让我们重读&#34;这些规则:

  1. 从空列表中删除的任何元素都是空列表。
  2. 删除了元素[S|T]的列表S是列表L2 ,如果 L2是列表T,则元素S已删除。
  3. 如果 [H|T2][H|T]不同,S列表S已移除的元素H,{ {1}}列表T2已删除元素T
  4. 这看起来简单得多,虽然只是简单的几次改造远离原版。它现在将产生这个结果,这很好:

    S

    考试| ?- del1(X, [a,b,c,b,d], [a,c,d]). X = b ? ; (1 ms) no

    change/2

    (1)这条规则说如果我们改变空列表中的所有2,我们得到空列表。听起来不错。

    (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). 和2更改为4,如果[H1,H2|T]为2,我会L我将H1追加到L(由于[2]不变,因此会始终失败 - 请参阅[2]append/2的在线文档!{{1}例如,}用于附加列表列表,而append/3append/2,其中2更改为4&s。这根本没有任何逻辑意义。如果我将2改为4,为什么我要向L添加内容?我们需要丢失[H2|T],只需将[2]append统一L [4|T2],其中{2}已更改为4&s 。换句话说:

    T2

    这可以使用如上所述在条款的头部中结合统一的方法进一步简化。另请注意,我们并没有真正使用[H2|T]在这里可见。因此(2) change([H1,H2|T], L) :- H1 = 2, L = [4|T2], change([H2|T], T2). 只能是H2

    [H2|T]

    所以我们使用4而不是2,如果有2,则处理尾部。

    (3)此规则与T查询具有相同的问题(2)。我们可以遵循与规则(2)相同的模式,并修复不相等的检查:

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

    所以我们只是继承元素append/2,如果它不是2,那么处理尾巴。完整的(3) change([H|T], [H|T2]) :- H \== 2, change(T, T2). 谓词如下所示:

    H

    重新阅读规则,看到它们具有逻辑意义:

    1. 在空列表中将2&2 39改为4&是空列表。
    2. 如果 change是列表{{1>,则列表(1) change([], []). (2) change([2|T], [4|T2]) :- change(T, T2). (3) change([H|T], [H|T2]) :- H \== 2, change(T, T2). 中的2到2更改为列表[2|T] 将2&2更改为4&#39; s。
    3. 如果 [4|T2]不是T2,则列表T中的2到2更改为列表[H|T] }和[H|T2]是列表H,其中2更改为4。

答案 1 :(得分:1)

让我们从最简单的两个开始:change/2。两个列表都具有相同的长度,它们基本相同 - 对于2的出现是安全的,应该用4代替。所以让我们首先定义这样一对的关系:

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