我认为适当的解决方案是将这个功能抽象为一个函数。该功能很可能是模板化的;它很可能会使用循环——毕竟循环会很短。许多矩阵运算是使用循环实现的——这不是问题。
例如,给定您的示例...
MatrixXd p0(2, 4);
p0 <<
1, 23, 6, 9,
3, 11, 7, 2;
MatrixXd p1(2, 2);
p1 <<
2, 20,
3, 10;
那么我们可以构造一个矩阵D使得D (i,j) = | p 0 (i) - p 1 (j)| 2
MatrixXd D(p0.cols(), p0.rows());
for (int i = 0; i < p1.cols(); i++)
D.col(i) = (p0.colwise() - p1.col(i)).colwise().squaredNorm().transpose();
我认为这很好 - 我们可以使用一些广播来避免 2 级嵌套:我们迭代p 1的点,但不超过p 0的点,也不超过它们的维度。
但是,如果您观察到,您可以制作一个单行线| p 0 (i) - p 1 (j)| 2 = | p 0 (i)| 2 + | p 1 (j)| 2 - 2 p 0 (i) T p 1 (j)。特别是,最后一个组件只是矩阵乘法,所以D = -2 p 0 T p 1 + ...
剩下要填的空白是由一个只依赖于行的组件组成的;以及仅依赖于列的组件:这些可以使用逐行和逐列操作来表示。
最后的“oneliner”是:
D = ( (p0.transpose() * p1 * -2
).colwise() + p0.colwise().squaredNorm().transpose()
).rowwise() + p1.colwise().squaredNorm();
您还可以将 rowwise/colwise 技巧替换为具有1向量的(外部)产品。
两种方法都会产生以下(平方)距离:
1 410
505 10
32 205
50 185
您必须对最快的基准进行基准测试,但是看到循环获胜我不会感到惊讶,而且我希望这也更具可读性。