为什么我的Prolog距离功能不起作用?

时间:2014-04-16 20:58:14

标签: prolog

这就是我所拥有的。

distance([],[],0).
distance([V1|T1],[V2|T2], sqrt((V1-V2)^2 + D2)):-
   distance([T1],[T2],D2).

它消除了全局堆栈错误。 我也尝试过:

distance([V],[V],0).
distance([V1|T1],[V2|T2], D):-
   D2 is distance([T1],[T2],D2),
   D is sqrt((V1-V2)^2 + D2).

它说参数没有充分实例化。

我正在尝试计算sqrt((x1-y1)^ 2 + ... +(xn-yn)^ 2)。

编辑:

这就是我现在所拥有的,它现在就挂了。

distance([],[],0).
distance([X1|X2],[Y1|Y2],D):-
   distance([X2],[Y2],D2),
   D is sqrt((X1-Y1)^2 + D2).

编辑:

我现在上班了,谢谢。这是我的解决方案。

sumd([],[],0).
sumd([X|X2],[Y|Y2],D):- sumd(X2,Y2,D2), D is (X - Y)^2 + D2.

distance([X|X2],[Y|Y2],D):- sumd([X|X2],[Y|Y2],S), D is sqrt(S).

2 个答案:

答案 0 :(得分:2)

简而言之,Prolog不是一种功能语言。因此,在distance/3谓词的第一个版本中,术语sqrt((V1-V2)^2 + D2)永远不会被计算为算术表达式。在第二个版本中,您不能将标准内置谓词is/2distance([T1],[T2],D2)一起使用,这不会被识别为算术表达式(在标准Prolog中,您无法定义自己的算术函数)。您现在可以根据此信息修复问题并回复distance/3谓词的新定义吗?

答案 1 :(得分:1)

既然你有一个可行的解决方案(这始终是第一步),你可以考虑改进它。您有一个使用递归使用两个子句定义的谓词sumd/3:一个基本子句,当输入列表为空或者使用general,recursive,子句完成遍历输入列表时使用。但是有一个问题:递归调用sumd(X2,Y2,D2)不是子句体中的最后一个调用。实际结果是,sumd/3谓词需要与输入列表的长度成比例的空间,因为每次进行递归调用时,需要保存以下目标D is (X - Y)^2 + D2,因为它只会证明了递归调用后证明了这一点。在内部,D is (X - Y)^2 + D2目标保存在堆栈中。解决方案是使用尾递归定义,即递归调用是子句体中最后一个的定义。这可以通过使用将扮演累加器角色的附加参数轻松完成。我们的想法是在遍历输入列表时使用此参数累积部分结果。当您到达基本案例时,即当您完成遍历输入列表时,累计值将是最终值。第一个子句很简单,用于初始化累加器。鉴于我们将累积一个总和,初始值将为零:

distance(List1, List2, Distance) :-
    distance(List1, List2, 0, Distance).

现在我们的distance/4辅助谓词的基本情况,考虑到上面的解释:

distance([], [], Distance, Distance).

你现在可以自己写一个递归的案例吗?

distance([X| Xs], [Y| Ys], Distance0, Distance) :-
    ...

注意Distance0表示到目前为止累积的值。