prolog中列表中包含的向量之间的距离

时间:2016-09-20 16:14:12

标签: list vector prolog distance

我对prolog很新,我正在尝试编写一个谓词

distance_all(List, List_of_distances).

其输入是列表组合向量colhordinates的列表:

INPUT = [[1,2,3],[2,3,4],[1,7,3],[1,6,3]]

并输出一个列表,其中包含每个点与另一个点之间的所有距离。

我试着这样做但是(对不起伪代码)。  我真的不知道如何在Prolog中处理它!

  1. 距离(point1,point2)= D_1-2

    距离(point1,point3)= D_1-3

    直到距离(point1,last_point)= D_1-last

    距离(point2,point3)= D_2-3

    距离(point2,point4)= D_2-4

    距离(point2,last_point)= D_2-last 如此...

  2. 所以输出就像

    OUTPUT = [D_1-2,D_1-3,.....,D_1-last,D_2-3,D_2-4,...... D_2-last ...]。

    我已经实现了一个谓词

    距离(Vector1,Vector2,D)。

    其中D是Vector1和Vector2之间的欧几里德距离(2D,3D或其他)

    另一个问题

    如果我想记住产生最小距离的原始矢量怎么办?

    例如

    ? - distance_all([[1,1],[1,2],[6,3],[8,2]],Lo)。 Lo = [1.0,5.385164807134504,7.0710678118654755,5.0990195135927845,7.0,2.23606797749979]

    最小距离是1.0 ......但是在哪个向量之间?比方说A和B

    我需要在A B

    上使用另一个谓词

4 个答案:

答案 0 :(得分:1)

怎么样?
distance_all_h(_, [], [], []).

distance_all_h(_, [], [Hn | Tn], Lo) :-
  distance_all_h(Hn, Tn, Tn, Lo).

distance_all_h(V, [Hi | Ti], Ln, [Ho | Lo]) :-
  distance(V, Hi, Ho),
  distance_all_h(V, Ti, Ln, Lo).

distance_all([], []).

distance_all([Hi | Ti], Lo) :-
  distance_all_h(Hi, Ti, Ti, Lo).

当输入列表为空时,输出列表为空。

否则,想法是创建一个接收

的辅助子句(distance_all_h / 3)

1)输入列表的头部

2)输入列表的尾部(用头部校准距离)

3)再次输入列表的尾部(当第二个参数被消耗时用以下头重启)

4)输出列表

---编辑---

  

如果我想记住原始载体的原因,该怎么办?   最小距离?

返回最小距离的修改解(distance_all中的第三个参数)和与最小距离对应的矢量耦合列表(第四个参数)

考虑到更多的矢量对可以对应相同的最小距离。

% 1000000000 is intended as a number bigger than every distance
distance_all_h(_, [], [], [], 1000000000, []).

distance_all_h(_, [], [Hn | Tn], Lo, Md, ABl) :-
  distance_all_h(Hn, Tn, Tn, Lo, Md, ABl).

distance_all_h(V, [Hi | Ti], Ln, [Ho | Lo], Ho, [[V, Hi]]) :-
  distance(V, Hi, Ho),
  distance_all_h(V, Ti, Ln, Lo, Dd, _),
  Ho < Dd.

distance_all_h(V, [Hi | Ti], Ln, [Ho | Lo], Dd, ABl) :-
  distance(V, Hi, Ho),
  distance_all_h(V, Ti, Ln, Lo, Dd, ABl),
  Ho > Dd.

distance_all_h(V, [Hi | Ti], Ln, [Ho | Lo], Ho, [[V, Hi] | ABt]) :-
  distance(V, Hi, Ho),
  distance_all_h(V, Ti, Ln, Lo, Ho, ABt).

distance_all([], [], 0, []).

distance_all([Hi | Ti], Lo, Md, ABl) :-
  distance_all_h(Hi, Ti, Ti, Lo, Md, ABl).

答案 1 :(得分:1)

如果你的Prolog有图书馆(aggregate),你不介意效率,你可以做

distance_min(List, MinDist,P1,P2) :-
    aggregate(min(D,(X,Y)), R^(select(X,List,R),member(Y,R), distance(X,Y,D)), min(MinDist,(P1,P2))).

distance([X1,X2],[Y1,Y2],D) :-
    D is sqrt((Y1-X1)*(Y1-X1)+(Y2-X2)*(Y2-X2)).
distance([X1,X2,X3],[Y1,Y2,Y3],D) :-
    D is sqrt((Y1-X1)*(Y1-X1)+(Y2-X2)*(Y2-X2)+(Y3-X3)*(Y3-X3)).

?- distance_min([[1,1],[1,2],[6,3],[8,2]],D,X,Y).
D = 1.0,
X = [1, 1],
Y = [1, 2].

答案 2 :(得分:1)

在没有findallaggregate的情况下编写它的中等简短基本方法就是这样的。

首先,一个谓词找到两个坐标列表之间的欧几里德距离:

d([P|Ps], [Q|Qs], D) :-
        sum_diff_sq(Ps, Qs, (P-Q)^2, R),
        D is sqrt(R).

sum_diff_sq([], [], V, V).
sum_diff_sq([P|Ps], [Q|Qs], V0, V+V0) :-
        sum_diff_sq(Ps, Qs, (P-Q)^2, V).

这将计算一对坐标之间的距离,每个坐标都是一个数字列表。

?- d([1], [1], D).
D = 0.0.

?- d([1], [2], D).
D = 1.0.

?- d([1,1], [2,2], D).
D = 1.4142135623730951.

?- d([1,1,1], [2,2,2], D).
D = 1.7320508075688772.

?- d([1,1,1,1], [2,2,2,2], D).
D = 2.0.

然后,计算所有可能的距离:

points_distances([], []).
points_distances([P|Ps], Ds) :-
        rest_distances(Ps, P, Ds, Ds0),
        points_distances(Ps, Ds0).

points_distances/2以递归方式列出头部与列表尾部中每个坐标之间的距离(因此,每对之间的距离将在结果中)。

rest_distances([], _, Back, Back).
rest_distances([P|Ps], X, [D|Ds], Back) :-
        d(P, X, D),
        rest_distances(Ps, X, Ds, Back).

这只是计算坐标列表和坐标之间的距离。结果是差异列表。

要使用它:

?- points_distances([[1,1],[1,2],[6,3],[8,2]], D).
D = [1.0, 5.385164807134504, 7.0710678118654755, 5.0990195135927845, 7.0, 2.23606797749979].

?- points_distances([[1,2,3],[2,3,4],[1,7,3],[1,6,3]], D).
D = [1.7320508075688772, 5.0, 4.0, 4.242640687119285, 3.3166247903554, 1.0].

如果您愿意,可以“保存”哪一对坐标彼此相距一段距离。例如,将rest_distances/4的第二个子句的头部改为:

rest_distances([P|Ps], X, [D|Ds], Back)

为:

rest_distances([P|Ps], X, [D-pq(X,P)|Ds], Back)

现在,在重新加载程序之后,您可以对points_distances/2的结果进行排序并获取其中的第一个元素,就像在另一个答案中一样:

?- points_distances( [[1,2,3],[2,3,4],[1,7,3],[1,6,3]] , D),
   keysort(D, [Min_dist-pq(P,Q)|_]).
D = [1.7320508075688772-pq([1, 2, 3], [2, 3, 4]),
     5.0-pq([1, 2, 3], [1, 7, 3]),
     4.0-pq([1, 2, 3], [1, 6, 3]),
     4.242640687119285-pq([2, 3, 4], [1, 7, 3]),
     3.3166247903554-pq([2, 3|...], [1, 6|...]),
     1.0-pq([1|...], [1|...])],
Min_dist = 1.0,
P = [1, 7, 3],
Q = [1, 6, 3].

答案 3 :(得分:0)

你可以写:

distance_all(Input_list,Output_list):-
         findall(L,combinations(Input_list,L),List),
         find_distances(List,Output_list).

combinations([],[]).
combinations(Lin,[Vector1,Vector2]):-choose(Vector1,Lin,L),choose(Vector2,L,_).

choose(H,[H|T],T).
choose(H1,[_|T],T1):-choose(H1,T,T1).

find_distances([],[]).
find_distances([[Vector1,Vector2]|T],[D|T1]):-
         distance(Vector1,Vector2,D),
         find_distances(T,T1).

更新

对于你可以改变的第二个问题:

find_distances([],[]).
find_distances([[Vector1,Vector2]|T],[D-[Vector1,Vector2]|T1]):-
             distance(Vector1,Vector2,D),
             find_distances(T,T1).

因此,不会返回距离列表,而是对其进行编码,以便每个元素都采用以下形式:D-[Vector-n,Vector-m]

要查找最小距离,请使用keysort / 2:

distance_all(Input_list,Output_list):-
         findall(L,combinations(Input_list,L),List),
         find_distances(List,L1),
         keysort(L1,L2),
         find_distances2(L2,Output_list).

Keysort对列表进行排序,以便第一个元素具有min d,您可以通过添加以上内容来获取它,例如:L1=[Dmin-[Vector1,Vector2]|_]

由于列表L1具有上述形式,为了获得第一个问题的输出列表,您可以通过写入来简单地保留输出列表中的距离:

find_distances([],[]).
find_distances([D-[Vector1,Vector2]|T],[D|T1]):-find_distances(T,T1).
相关问题