PROLOG[手工计算]

PROLOG[手工计算],prolog,Prolog,我正在用prolog练习手工计算,你能给我解释一下并演示一下这个问题的手工计算吗?这样我就可以获得更多的理解 在一个涉及文本处理的Prolog项目中(这里不再讨论),已经实现了谓词duplicate/2来复制列表的每个条目。 下面是duplicate/2的作用示例: ?- duplicate([w,o,r,d], D). D = [w,w,o,o,r,r,d,d] . ?- duplicate([], D). D = []. 下面显示了duplicate/2的定义。记下重复的手工计算/2

我正在用prolog练习手工计算,你能给我解释一下并演示一下这个问题的手工计算吗?这样我就可以获得更多的理解

在一个涉及文本处理的Prolog项目中(这里不再讨论),已经实现了谓词duplicate/2来复制列表的每个条目。 下面是duplicate/2的作用示例:

?- duplicate([w,o,r,d], D).

D = [w,w,o,o,r,r,d,d] .

?- duplicate([], D).

D = [].
下面显示了duplicate/2的定义。记下重复的手工计算/2

duplicate(L, D) :- duplicate(L,[], D). % clause 0

duplicate([], Acc, D) :- reverse(Acc, D). % clause 1

duplicate([H|T], Acc, D) :- duplicate(T, [H, H|Acc], D). % clause 2
(涉及辅助谓语duplicate/3)三个谓语中的每一个
子句(编号为0、1、2)是在手工计算中执行的。

好吧,让我们来看看示例查询的简化版本
duplicate([w],D])。
。只有一个规则头,它有两个参数:第0条中的一个,L=[w]和D1=D。(1)正文告诉我们,我们应该派生
重复([w],],D)
。第1条的标题不匹配,因为[]和[w]无法统一。这使得第2条:[w]=[H | T]与H=w和T=[](2)、Acc=[]和D2=D保持一致。现在我们的新目标是重复([],[w,w],D),它只与第1(3)条相匹配。我们的目标是
反向([w,w],D)
,这是内置谓词。如果D与[w,w]的相反列表相统一,则为真,因此D=[w,w]。现在我们没有任何目标来推导,并且已经找到了一个完整的推导。因为我们总是重命名规则的变量,所以D仍然是原始查询中的变量,这意味着D=[w,w]是查询的正确答案替换

我承认我有点懒,只有一个重复的字母,对Acc的反转似乎有点毫无意义。要了解为什么有必要这样做,您可以尝试对重复([x,y],D)进行相同的推导,其中累加器应该是[y,y,x,x],因为元素总是在前面

另一个有趣的练习是
duplicate(X[w,w])
并检查
duplicate(X[w])
失败的原因(提示:查看统一问题[w]=[H,H | Acc])。到目前为止还没有包含的是回溯:在查询
duplicate(X,Y)
的情况下,您的目标匹配多个头部,您得到多个解决方案(实际上是无限多个)

玩得开心

(1) 规则的正确性与它的变量的命名方式无关。当我们有两个来自不同规则的同名变量D时,我们需要将其中一个规则中的D重命名为其他变量,比如D1

(2) 您可以在提示下通过输入统一作为查询来检查这一点:

1 ?- [w] = [H|T].
H = w,
T = [].
(3) 原因是列表[H | T]至少有一个元素,而[]没有。您可以在提示符下再次检查此项:

2 ?- [] = [H|T].
false.

好了,让我们来看一下示例查询的简化版本
duplicate([w],D)。
。只有一个规则头,它有两个参数:第0条中的一个,L=[w]和D1=D。(1)正文告诉我们,我们应该派生
重复([w],],D)
。第1条的标题不匹配,因为[]和[w]无法统一。这使得第2条:[w]=[H | T]与H=w和T=[](2)、Acc=[]和D2=D保持一致。现在我们的新目标是重复([],[w,w],D),它只与第1(3)条相匹配。我们的目标是
反向([w,w],D)
,这是内置谓词。如果D与[w,w]的相反列表相统一,则为真,因此D=[w,w]。现在我们没有任何目标来推导,并且已经找到了一个完整的推导。因为我们总是重命名规则的变量,所以D仍然是原始查询中的变量,这意味着D=[w,w]是查询的正确答案替换

我承认我有点懒,只有一个重复的字母,对Acc的反转似乎有点毫无意义。要了解为什么有必要这样做,您可以尝试对重复([x,y],D)进行相同的推导,其中累加器应该是[y,y,x,x],因为元素总是在前面

另一个有趣的练习是
duplicate(X[w,w])
并检查
duplicate(X[w])
失败的原因(提示:查看统一问题[w]=[H,H | Acc])。到目前为止还没有包含的是回溯:在查询
duplicate(X,Y)
的情况下,您的目标匹配多个头部,您得到多个解决方案(实际上是无限多个)

玩得开心

(1) 规则的正确性与它的变量的命名方式无关。当我们有两个来自不同规则的同名变量D时,我们需要将其中一个规则中的D重命名为其他变量,比如D1

(2) 您可以在提示下通过输入统一作为查询来检查这一点:

1 ?- [w] = [H|T].
H = w,
T = [].
(3) 原因是列表[H | T]至少有一个元素,而[]没有。您可以在提示符下再次检查此项:

2 ?- [] = [H|T].
false.
duplicate(L,D):-duplicate(L,[],D)。%第0条

重复([],Acc,D):-反向(Acc,D)。%第1条

duplicate([H | T],Acc,D):-duplicate(T[H,H | Acc],D)。%第2条

下面的快速手工计算为了我的理解,如果我错了,请纠正我,并告诉我是否正确,因为我是prolog新手。

duplicate[w,o,r,d],d)子句0-->duplicate([w,o,r,d],].d)。
第2条-->重复[w,o,r,d],Acc,d)-->第2条重复([o,r,d],[w,w],],d),

我可以继续阅读第2条,继续复制列表的标题,我可以这样做,直到列表为空[]。然后我可以动议第1条

我可以把我的列表放到累加器中,然后把它倒过来产生[d,d,r,r,o,o,w,w]

以下是第1条的手工计算。

第1条副本[w,w,o,o,r,r,d,d]——第1条的背面([w,w,o,o,r,r,d,d])。

D=[D,D,r,r,o,o,w,w]

重复(L,D):-重复(L,[],D)。%第0条

重复([]
solve(true) --> [].
solve((A,B)) --> !, solve(A), solve(B).
solve(A) --> {rule(A,B)}, [(A :- B)], solve(B).
rule(duplicate([], []), true).
rule(duplicate([X|Y], [X,X|Z]), duplicate(Y,Z)).

?- solve(duplicate([w,o],X),L,[]).
X = [w,w,o,o],
L = [(duplicate([w,o],[w,w,o,o]) :- duplicate([o],[o,o])),
     (duplicate([o],[o,o]) :- duplicate([],[])),
     (duplicate([],[]) :- true)]