Я использую тензорный аспект библиотеки Eigen в C ++ и хотел бы вычислить поэлементное произведение одного собственного Tensor, умноженное на скалярную сумму элементов во втором Eigen Tensor.Что-то вроде:
#include <Eigen/Dense>
Eigen::Tensor<float,2>u(5,5);
Eigen::Tensor<float,2>v(5,5);
u.setConstant(1.f);
v.setConstant(2.f);
Eigen::Tensor<float,2>ans(5,5);
ans = u*v.sum();
Однако оператор * таким образом не поддерживается.
README предлагает использовать метод .constant()
, связанный с объектами Tensor.И хотя
ans = u*u.constant(5.);
auto ans2 = u.sum();
компилируется и функционирует должным образом
ans = u*u.constant(v.sum());
нет.
error: no matching function for call to ‘Eigen::Tensor<float, 2>::constant(const Eigen::TensorReductionOp<Eigen::internal::SumReducer<float>, const Eigen::DimensionList<long int, 2ul>, const Eigen::Tensor<float, 2>, Eigen::MakePointer>)’
ans = u*u.constant(v.sum());
^
Из дальнейшего прочтения видно, что это потому, что u.constant()
ожидает, что ему будет передано скалярное значение, тогда как v.sum()
возвращает «не оцененное выражение» (см. Тензорные операциии C ++ "auto" in README ).Существует также предположение, что оценка v.sum()
может быть принудительно вызвана с помощью .eval()
, хотя это, похоже, возвращает другой тип «не оцененного выражения», хотя и с ForcedEvalOp
, помеченным в конце.
error: no matching function for call to ‘Eigen::Tensor<float, 2>::constant(const Eigen::TensorForcedEvalOp<const Eigen::TensorReductionOp<Eigen::internal::SumReducer<float>, const Eigen::DimensionList<long int, 2ul>, const Eigen::Tensor<float, 2>, Eigen::MakePointer> >)’
ans = u*u.constant(v.sum().eval());
^
Раздел TODO README упоминает:
" Представление скалярных значений: Скалярные значения часто представлены тензорами размера 1 и ранга 1. Это будетболее логично и удобно использовать вместо этого тензоры ранга 0. Например, Tensor :: maximum () в настоящее время возвращает Tensor. Аналогично, внутреннее произведение 2 1d-тензоров (через сокращения) возвращает 1d-тензор. В будущем эти операции могутобновиться, чтобы вместо этого возвращались 0d-тензоры. "
Это означает, что v.sum()
должен возвращать тензор ранга 1 длины 1. Но оператор ()
, обычно используемый для индексации, кажется, не может получить доступ к своему значению вИспользуемая форма для u.constant()
и:
ans = u*u.constant(v.sum()(0))
также не компилируется.
error: no match for call to ‘(const Eigen::TensorReductionOp<Eigen::internal::SumReducer<float>, const Eigen::DimensionList<long int, 2ul>, const Eigen::Tensor<float, 2>, Eigen::MakePointer>) (int)’
ans = u*u.constant(v.sum()(0));
^
, как и
ans = u*u.constant(v.sum().eval()(0))
.
error: no match for call to ‘(const Eigen::TensorForcedEvalOp<const Eigen::TensorReductionOp<Eigen::internal::SumReducer<float>, const Eigen::DimensionList<long int, 2ul>, const Eigen::Tensor<float, 2>, Eigen::MakePointer> >) (int)’
ans = u*u.constant(v.sum().eval()(0));