我正在尝试解决一个问题,即我有一个坐标列表,并希望得到最接近一个点。
实施例: 我得到了坐标[[1,2],[3,4],[10,3]],并希望得到距离原点[0,0]最近的点。 [1,2]在这个例子中。
我写了这个:
list_min([H|T], Min):-
list_min(T, H, Min).
list_min([], H, H).
list_min([L|Ls], Min0, Min) :-
point(P),
distance(Min0,P,D0),
distance(L,P,D1),
Lower is min(D0, D1),
assert(candidate(Min0)),
assert(candidate(L)),
forall(candidate(X),distance(X,P,Lower)),
retractall(candidate(_)),
list_min(Ls, X, Min).
distance(A,B,D):-
A = [A1,A2],
B = [B1,B2],
Y is B2 - A2,
X is B1 - A1,
D is sqrt(X*X + Y*Y).
然而,看起来它总是在forall线上失败。我做错了什么?有没有更好的方法来做到这一点?
答案 0 :(得分:2)
您可以使用库(aggregate):
distance_min(L, MinXY) :-
distance_min(L, 0, 0, MinXY).
distance_min(L, X0, Y0, MinXY) :-
aggregate(min(D, [X,Y]),
(member([X,Y], L), D is sqrt((X-X0)^2+(Y-Y0)^2)),
MinXY).
试验:
?- distance_min([[1,2],[3,4],[10,3]], R).
R = min(2.23606797749979, [1, 2]).
修改强>
....
assert(candidate(Min0)),
assert(candidate(L)),
forall(candidate(X),distance(X,P,Lower)),
retractall(candidate(_)),
...
我没有评论你的代码,但现在这里有一个暗示:这些线条真的很糟糕,而且真的没用。承认forall / 2成功,您期望得到什么结果?
无论如何,forall / 2失败是因为Lower
它已经从上面的语句(Lower is min(D0, D1)
)实例化了,因此距离/ 3将在D
不匹配的地方失败。
答案 1 :(得分:2)
使用SWI-Prolog,您还可以使用功能样式:
:- use_module(library(lambda)).
point([0,0]). % The reference point
% Entry point predicate
% First parameter : a list of points
% Second parameter (result) : the point closest to the reference point
list_min([H|Tail], Min) :-
point(Reference),
distance(H, Reference, D),
foldl(\X^Y^Z^(distance(X, Reference, DX),
Y = [Cur_D, _Cur_P],
( DX < Cur_D
-> Z = [DX, X]
; Z = Y)),
Tail, [D, H], Min).
distance(A,B,D):- % copy-pasted from your version
A = [A1,A2],
B = [B1,B2],
Y is B2 - A2,
X is B1 - A1,
D is sqrt(X*X + Y*Y).
答案 2 :(得分:1)
我提出了一个没有建议的库或四叉树的解决方案,我保留在基本的序言中(我在SWI中写道)。
如果我正确理解您的问题,实际上不需要assert
/ retract
/ forall
。我假设point(P)
说P是我们计算距离的唯一定义的参考点,但它有点奇怪(我会将它用作参数,以确保它是唯一的)。
point([0,0]). % The reference point
% Entry point predicate
% First parameter : a list of points
% Second parameter (result) : the point closest to the reference point
list_min([H|Tail], Min) :-
point(Reference),
distance(H, Reference, D),
list_min(Tail, H, D, Min).
% First parameter : the list remaining to consider
% Second parameter : the closest point, at this point of the computation
% Third parameter : the corresponding (minimum) distance, at this point of the computation
% Fourth parameter : the result (one point, to be bound at the end of computation)
list_min([], CurrentMin, _, CurrentMin). % Stop condition : list processed
list_min([Candidate|Tail], CurrentMin, CurrentDist, Min) :-
point(Reference),
distance(Candidate, Reference, CandidateDist),
(
% if the new candidate is not better, keep the current candidate
CurrentDist < CandidateDist ->
list_min(Tail, CurrentMin, CurrentDist, Min)
;
% if the new candidate is better, take it as the current candidate
list_min(Tail, Candidate, CandidateDist, Min)
).
distance(A,B,D):- % copy-pasted from your version
A = [A1,A2],
B = [B1,B2],
Y is B2 - A2,
X is B1 - A1,
D is sqrt(X*X + Y*Y).
答案 3 :(得分:0)
使用四叉树进行2D http://en.wikipedia.org/wiki/Quadtree