距离

2016-09-20 107 views
1

我很新的序言和我想写一个谓语距离

distance_all(List, List_of_distances). 

其输入是列表cointaining矢量coohordinates的列表:

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

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

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

  1. 距离(点1,点2)= D_1-2

    距离(点1,POINT3)= D_1-3

    直到距离(点1,last_point)= D_1-最后

    距离(点2,POINT3)= D_2-3

    距离(POINT2,point4)= D_2-4

    d istance(POINT2,last_point)= D_2-最后 ANS等等...

所以输出等

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

我已经执行的谓词

距离(向量1,Vector2,d)。

其中d是向量1和Vector2之间(或任何在2D,3D)的欧氏距离


另一个问题

如果我想记住起源的最小距离原来的载体?

例如

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

的最小距离为1.0 ...但是至极向量之间?可以说是A和B

我需要使用另一个谓词那些A B

回答

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). 

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

否则,这个想法是创建一个帮助子句接收

1(distance_all_h/3))的输入列表

2)输入列表的尾部的头部(给calcolate与距离头)

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). 
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). 

UPDATE

关于第二个问题,你可以改变:

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排序列表,以便使第一元件将具有最小d,你可以把它通过添加上述用于例如:L1=[Dmin-[Vector1,Vector2]|_]

因为列表L1的形式如上所述,为了得到你的第一个问题的输出列表中写,你可以简单的保持在输出列表仅距离:

find_distances([],[]). 
find_distances([D-[Vector1,Vector2]|T],[D|T1]):-find_distances(T,T1). 
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]. 
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].