Проблема с подразделом Armadillo

#armadillo

#armadillo

Вопрос:

Следующий фрагмент выдает ошибку компиляции:

 arma::Mat<double> a(10,10,arma::fill::zeros);
arma::ucolvec w = whatever1;
whatever2 = a.rows(w).each_col()   another-col-vector;
 

Ошибка заключается в том, что в arma::subview_elem2 нет элемента с именем each_col .

В ряде случаев в Armadillo стандартные функции массива не всегда доступны в выражениях или результатах других вызовов функций. Очевидно, что функция rows() возвращает не объект Mat, а объект subview_elem2, предположительно для оптимизации. Другим способом сделать это было бы объявить все функции массива в интерфейсах / чистых абстрактных классах, которые реализуют Mat и другие внутренние классы, такие как подвиды. Кажется, должно быть возможно сделать все выражения массива Armadillo взаимозаменяемыми с объектами массива, кроме операций записи для выражений, которые генерируют только r-значения.

Итак… Я мог бы пожелать следующего

a) Объяснение того, какие методы недоступны для каких результатов. б) Желательно включить все комбинации методов массива, которые имеют смысл.

При отсутствии вышеизложенного, как можно достичь желаемого результата, который заключается в оценке выражения:

a.rows(w).each_col()

??

Ответ №1:

Некоторая предварительная информация о armadillo

Библиотека armadillo интенсивно использует шаблоны, и большинство операций возвращают шаблоны выражений. Фактическое вычисление выполняется только тогда, когда вы присваиваете результат переменной. Вот почему вы не должны сохранять результат некоторых вычислений с использованием armadillo auto .

Например, учитывая некоторые матрицы A B и C , что-то вроде

 auto D = A * B   C;
 

не будет выполнять вычисления, и в нем хранится только шаблон выражения D . С другой стороны, используя

 arma::mat D = A * B   C;
 

принудительно выполнит вычисление, и результат будет сохранен D .

Решение вашей проблемы

В частности, на ваш вопрос, что-то вроде a.rows(w) возвращает шаблон выражения типа subview_elem2 (этот файл определен в исходном коде armadillo_bits/subview_elem2_bones.hpp ). У этого «временного типа» нет .each_col метода, что приводит к получению ошибки. Один из способов — сохранить результат a.rows(w) в переменной, но поскольку переменная вас не интересует, вы можете использовать этот .eval() метод. .eval() Метод заставляет шаблон выражения выполнять фактические вычисления до этого момента, и, таким образом, последующий вызов .each_col будет работать. То есть заменить

 a.rows(w).each_col()   another-col-vector;
 

с

 a.rows(w).eval().each_col()   another-col-vector;
 

Комментарии:

1. Функция .eval() отлично работает в этом контексте, хотя в целом мы должны быть осторожны с ее использованием. В документации говорится: «Эта функция должна использоваться экономно и только в тех случаях, когда это абсолютно необходимо; беспорядочное использование может снизить производительность»

2. Да, я согласен. Выражения шаблонов используются не просто так. Они могут оптимизировать операции, когда значение действительно необходимо (когда вы присваиваете переменной). Когда вы используете eval, вы удаляете эту возможность, но в данном случае это кажется необходимым. Armadillo — очень зрелая библиотека, и я бы предположил, что отсутствие each_col метода в subview_elem2 , вероятно, связано с тем, что это было бы либо невозможно, либо это было бы так же эффективно, как наличие eval там.