使用 Eigen3 的 Tensor 和 TensorSymmetry 计算所有差分向量对
Using Eigen3's Tensor and TensorSymmetry to compute all pairs of difference vectors
我有一个 Nx3 张量 C
。 N 在编译时未知(从用户提供的数据文件中读取 N 3 坐标)。我想创建一个 NxNx3 张量(称之为 D
),其中包含坐标的所有矢量差。因此,D
的元素看起来像 D(i, j) = C(i) - C(j)
。虽然这些差异已签署,但我只需要它们朝一个方向发展(哪个方向并不重要,只要保持一致即可)。我正在寻找一种方法来只评估唯一元素,而不仅仅是编写双 for 循环。我为 Eigen TensorSymmetry 模块找到的文档并没有完全说明如何做到这一点,或者它是否可能。值得一提的是,我能够使用以下方法为一个维度编写一个 numpy 式的差异差异:
Eigen::array<int, 2> flip({1,0});
Eigen::array<int, 2> bc({1,N});
d = c.broadcast(bc) - c.broadcast(bc).shuffle(flip);
这里c是一个长度为N的1阶张量,d是一个NxN大小的2阶张量。
我尝试了 NxNx3 张量的各种排列,排列或扩展 Nx3 输入数据,但似乎找不到任何看起来正确的东西。我现在正在使用的是这样的表达式:
Eigen::array<int, 3> expand({N, N, 3});
Eigen::array<int, 3> trans({1,0,2});
Tensor<double, 2> C(N, 3);
Tensor<double, 3> D(N, N, 3);
// fill up C from file-object like thing foo not relevant to this problem
for (auto i = 0; i < N; i++)
for (auto j = 0; j < 3; j++)
C(i, j) = foo.getCoords()[j];
D = C.broadcast(expand) - C.broadcast(expand).shuffle(trans);
上面的代码可以编译,但会产生明显错误的结果(甚至没有预期的维度,这很奇怪...)。我已经尝试了各种扩展选项的排列,例如 expand({N,3,1})
和 expand({1,N,3})
,还有 trans
,但显然我在这里缺少一些东西;还没有任何效果。
正如我上面提到的,我也不知道如何或是否可以利用 D
的反对称性来避免一些多余的减法。
如有任何建议,我们将不胜感激。
我对自己的问题不太满意的解决方案是编写一个 for 循环。这没有利用任何对称性,也没有允许惰性求值,但它确实给出了预期的结果。
Eigen::array<int, 2> bcChip({N, 3});
for (auto i = 0; i < N; i++){
D.chip(i, 0) = C - C.chip(i, 0).eval().broadcast(bcChip);
}
请注意,如果有人能够提供 slicker/better 实现并利用 Eigen Tensor 的功能,我会接受他们的回答。
我有一个 Nx3 张量 C
。 N 在编译时未知(从用户提供的数据文件中读取 N 3 坐标)。我想创建一个 NxNx3 张量(称之为 D
),其中包含坐标的所有矢量差。因此,D
的元素看起来像 D(i, j) = C(i) - C(j)
。虽然这些差异已签署,但我只需要它们朝一个方向发展(哪个方向并不重要,只要保持一致即可)。我正在寻找一种方法来只评估唯一元素,而不仅仅是编写双 for 循环。我为 Eigen TensorSymmetry 模块找到的文档并没有完全说明如何做到这一点,或者它是否可能。值得一提的是,我能够使用以下方法为一个维度编写一个 numpy 式的差异差异:
Eigen::array<int, 2> flip({1,0});
Eigen::array<int, 2> bc({1,N});
d = c.broadcast(bc) - c.broadcast(bc).shuffle(flip);
这里c是一个长度为N的1阶张量,d是一个NxN大小的2阶张量。
我尝试了 NxNx3 张量的各种排列,排列或扩展 Nx3 输入数据,但似乎找不到任何看起来正确的东西。我现在正在使用的是这样的表达式:
Eigen::array<int, 3> expand({N, N, 3});
Eigen::array<int, 3> trans({1,0,2});
Tensor<double, 2> C(N, 3);
Tensor<double, 3> D(N, N, 3);
// fill up C from file-object like thing foo not relevant to this problem
for (auto i = 0; i < N; i++)
for (auto j = 0; j < 3; j++)
C(i, j) = foo.getCoords()[j];
D = C.broadcast(expand) - C.broadcast(expand).shuffle(trans);
上面的代码可以编译,但会产生明显错误的结果(甚至没有预期的维度,这很奇怪...)。我已经尝试了各种扩展选项的排列,例如 expand({N,3,1})
和 expand({1,N,3})
,还有 trans
,但显然我在这里缺少一些东西;还没有任何效果。
正如我上面提到的,我也不知道如何或是否可以利用 D
的反对称性来避免一些多余的减法。
如有任何建议,我们将不胜感激。
我对自己的问题不太满意的解决方案是编写一个 for 循环。这没有利用任何对称性,也没有允许惰性求值,但它确实给出了预期的结果。
Eigen::array<int, 2> bcChip({N, 3});
for (auto i = 0; i < N; i++){
D.chip(i, 0) = C - C.chip(i, 0).eval().broadcast(bcChip);
}
请注意,如果有人能够提供 slicker/better 实现并利用 Eigen Tensor 的功能,我会接受他们的回答。