生成两个正交向量,它们与特定方向正交。

17

在numpy中,生成两个正交向量a和b的最简单和最有效的方法是什么,使得这两个向量的叉积等于另一个已知的单位向量k?

我知道会有无数对满足条件axb=k和a.b=0,只要满足这些条件,对于我来说哪一对都没关系。


ab是形状为(3,)(具有3个元素的一维数组)?你如何“手动”完成这个任务? - hpaulj
是的。a、b和k的形状都是(3,)。我知道如何手动完成它。我有5个方程式,6个未知数,这是否意味着没有简单的方法(只需几行代码)?我必须使用scipy中的数值方法来解决它吗? - Physicist
我在考虑接受答案中的叉积和点积的代数版本。对于小数组,它们的速度同样快。 - hpaulj
3个回答

21
Gram-Schmidt过程将完全做到这一点。例如:
>>> k  # an arbitrary unit vector k is not array. k is must be numpy class. np.array
np.array([ 0.59500984,  0.09655469, -0.79789754])

获取第一个:
>>> x = np.random.randn(3)  # take a random vector
>>> x -= x.dot(k) * k       # make it orthogonal to k
>>> x /= np.linalg.norm(x)  # normalize it

要获得第二个:
>>> y = np.cross(k, x)      # cross product with k

并且进行验证:
>>> np.linalg.norm(x), np.linalg.norm(y)
(1.0, 1.0)
>>> np.cross(x, y)          # same as k
array([ 0.59500984,  0.09655469, -0.79789754])
>>> np.dot(x, y)            # and they are orthogonal
-1.3877787807814457e-17
>>> np.dot(x, k)
-1.1102230246251565e-16
>>> np.dot(y, k)
0.0

3
当k是不同的向量时,这个代码不起作用。>>> k = np.array([ 0.0, 0.0215, -1.334]) >>> x = np.random.randn(3) >>> x -= x.dot(k) * k >>> x /= np.linalg.norm(x) >>> np.dot(x, k) 0.38532052441276377 - Miae Kim
非常好,加上René Wirnata下面的答案,即使第一个输入向量不是单位向量,这也可以工作。 - Charly Empereur-mot

13

很抱歉,由于声望不足,我无法将其作为评论发布。

关于@behzad.nouri的回答,请注意如果k不是单位向量,则该代码将不再给出正交向量!

正确而通用的做法是减去随机向量的纵向部分。此的通用公式在这里

因此,您只需在原始代码中替换此内容:

>>> x -= x.dot(k) * k / np.linalg.norm(k)**2

4
这种方法被称为Gram-Schmidt过程 - Miae Kim
所以这在两种情况下都有效,无论k是单位向量还是不是,对吗? - Charly Empereur-mot
好的,是的,它确实这样。 - Charly Empereur-mot

1
假设支持正交基的向量是u。
b1 = np.cross(u, [1, 0, 0])   # [1, 0, 0] can be replaced by other vectors, just get a vector orthogonal to u
b2 = np.cross(u, b1)
b1, b2 = b1 / np.linalg.norm(b1), b2 / np.linalg.norm(b2)

如果您喜欢,这是一个更短的答案。

获取转换矩阵

B = np.array([b1, b2])
TransB = np.dot(B.T, B)
u2b = TransB.dot(u) # should be like [0, 0, 0]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接