ИЗМЕНИТЬ Исходный код, который я написал, не работает должным образом, поэтому я удалил его. Но следуя той же идее, объясненной ниже, если вы потратите некоторое время на размышления, правило Крамера не понадобится, и код можно немного упростить следующим образом:
def distance(v1, v2, u) :
u = np.array(u, ndmin=2)
v = np.vstack((v1, v2))
vv = np.dot(v, v.T) # shape (2, 2)
uv = np.dot(u, v.T) # shape (n ,2)
ab = np.dot(np.linalg.inv(vv), uv.T) # shape(2, n)
w = u - np.dot(ab.T, v)
return np.sqrt(np.sum(w**2, axis=1)) # shape (n,)
Чтобы убедиться, что он работает правильно, я упаковал код Дэйва в функцию как distance_3d
и попробовал следующее:
>>> d, n = 3, 1000
>>> v1, v2, u = np.random.rand(d), np.random.rand(d), np.random.rand(n, d)
>>> np.testing.assert_almost_equal(distance_3d(v1, v2, u), distance(v1, v2, u))
Но, конечно, теперь это работает для любого d
:
>>> d, n = 1000, 3
>>> v1, v2, u = np.random.rand(d), np.random.rand(d), np.random.rand(n, d)
>>> distance(v1, v2, u)
array([ 10.57891286, 10.89765779, 10.75935644])
Вы должны разложить свой вектор, назовем его u
, в сумме двух векторов, u = v + w
, v
находятся в плоскости, поэтому их можно разложить как v = a * v1 + b * v2
, а w
перпендикулярно плоскости, и, таким образом, np.dot(w, v1) = np.dot(w, v2) = 0
.
Если вы напишите u = a * v1 + b * v2 + w
и возьмете скалярное произведение этого выражения с v1
и v2
, вы получите два уравнения с двумя неизвестными:
np.dot(u, v1) = a * np.dot(v1, v1) + b * np.dot(v2, v1)
np.dot(u, v2) = a * np.dot(v1, v2) + b * np.dot(v2, v2)
Поскольку это всего лишь система 2x2, мы можем решить ее, используя правило Крамера:
uv1 = np.dot(u, v1)
uv2 = np.dot(u, v2)
v11 = np.dot(v1, v2)
v22 = np.dot(v2, v2)
v12 = np.dot(v1, v2)
v21 = np.dot(v2, v1)
det = v11 * v22 - v21 * v12
a = (uv1 * v22 - v21 * uv2) / det
b = (v11 * uv2 - uv1 * v12) / det
Отсюда вы можете получить:
w = u - v = u - a * v1 - b * v2
а расстояние до плоскости является модулем w
.
person
Jaime
schedule
01.02.2013
np.vectorize
никогда не бывает очень быстрым, как указывает его строка документации. - person Fred Foo   schedule 01.02.2013