这就是我所拥有的。
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).
答案 0 :(得分:2)
简而言之,Prolog不是一种功能语言。因此,在distance/3
谓词的第一个版本中,术语sqrt((V1-V2)^2 + D2)
永远不会被计算为算术表达式。在第二个版本中,您不能将标准内置谓词is/2
与distance([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
表示到目前为止累积的值。