Использование Tensor и TensorSymmetry в Eigen3 для вычисления всех пар разностных векторов - PullRequest
0 голосов
/ 15 апреля 2020

У меня есть тензор Nx3 C. N не известно во время компиляции (N 3-координаты считываются из предоставленного пользователем файла данных). Я хотел бы создать тензор NxNx3 (назовите его D) со всеми векторными различиями координат. Таким образом, элемент D будет выглядеть как D(i, j) = C(i) - C(j). В то время как эти различия подписаны, мне нужно, чтобы они шли только в одном направлении (не важно, какое именно, только чтобы оно было последовательным). Я ищу способ оценивать только уникальные элементы без написания двойного числа для -l oop. Документация, которую я нашел для модуля 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, чтобы избежать некоторых избыточных вычитаний.

Буду признателен за любой совет .

1 Ответ

0 голосов
/ 23 апреля 2020

Мое несколько неудовлетворительное решение моей собственной проблемы - написать for-l oop. Это не использует какие-либо симметрии и не допускает ленивых вычислений, но, похоже, дает ожидаемые результаты.

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);
}

Обратите внимание, что если бы кто-то смог обеспечить более плавную / лучшую реализацию этого который использовал преимущества Eigen Tensor, я бы принял их ответ.

...