距離

2016-09-20 167 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].