2016-08-18 6 views
3

Учитывая два набора точек в n-мерном пространстве, как можно сопоставить точки от одного набора к другому, так что каждая точка используется только один раз, а общее эвклидовое расстояние между пары точек минимизированы?Минимизировать общее расстояние между двумя наборами точек в Python

Например,

import matplotlib.pyplot as plt 
import numpy as np 

# create six points in 2d space; the first three belong to set "A" and the 
# second three belong to set "B" 
x = [1, 2, 3, 1.8, 1.9, 3.4] 
y = [2, 3, 1, 2.6, 3.4, 0.4] 

colors = ['red'] * 3 + ['blue'] * 3 

plt.scatter(x, y, c=colors) 
plt.show() 

example of point distance minimization problem

Таким образом, в приведенном выше примере, цель будет отображать каждую красную точку на синюю точку, так что каждая синяя точка используется только один раз, а сумма расстояний между точками минимизируется.

я наткнулся this question, который помогает решить первую часть задачи - вычислить расстояние между всеми парами точек через множеств с помощью функции scipy.spatial.distance.cdist().

Оттуда я мог бы, вероятно, проверить каждую перестановку отдельных элементов из каждой строки и найти минимум.

Приложение, которое я имею в виду, включает в себя довольно небольшое количество точек данных в трехмерном пространстве, поэтому подход грубой силы может быть прекрасным, но я решил проверить, знает ли кто-нибудь более эффективное или изящное решение первый.

+0

Так что этот вопрос, кажется, об алгоритме, который зависит от языка? – moooeeeep

+0

Эти два набора всегда одинакового размера? – moooeeeep

+1

Не является ли эта проблема экземпляром задачи [линейное присвоение суммы] (http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.linear_sum_assignment.html)? – Stelios

ответ

2

Пример присвоения (отображения) элементов одного множества в точках к элементам другого множества точек, таких, что сумма евклидово расстояние минимизируется.

import numpy as np 
import matplotlib.pyplot as plt 
from scipy.spatial.distance import cdist 
from scipy.optimize import linear_sum_assignment 

np.random.seed(100) 

points1 = np.array([(x, y) for x in np.linspace(-1,1,7) for y in np.linspace(-1,1,7)]) 
N = points1.shape[0] 
points2 = 2*np.random.rand(N,2)-1 

C = cdist(points1, points2) 

_, assigment = linear_sum_assignment(C) 

plt.plot(points1[:,0], points1[:,1],'bo', markersize = 10) 
plt.plot(points2[:,0], points2[:,1],'rs', markersize = 7) 
for p in range(N): 
    plt.plot([points1[p,0], points2[assigment[p],0]], [points1[p,1], points2[assigment[p],1]], 'k') 
plt.xlim(-1.1,1.1) 
plt.ylim(-1.1,1.1) 
plt.axes().set_aspect('equal') 

enter image description here

+0

Спасибо! Отмечая это как решение, поскольку Стелиос первым предложил использовать «scipy.optimize.linear_sum_assignment», а для подробного примера кода, демонстрирующего приложение от начала до конца. –

2

Там в известном алгоритме для этого, The Hungarian Method For Assignment, который работает во время O (п).

В SciPy, вы можете найти реализацию в scipy.optimize.linear_sum_assignment

+0

Хорошо выглядеть! Просто чтобы быть ясным - 'linear_sum_assigment()' принимает матрицу _cost_, которая в этом случае будет выводиться из 'scipy.spatial.distance.cdist()', а не сами исходные точки данных, правильно? –

+0

@ KeithHughitt Абсолютно. Вы можете посмотреть на слайды, кстати, они вполне читаемы. –

 Смежные вопросы

  • Нет связанных вопросов^_^