поэлементные операции с матрицей boost c++ ublas и векторными типами

StackOverflow https://stackoverflow.com/questions/773667

Вопрос

я хотел бы выполнять поэлементные функции для типов матрицы и вектора, например.логарифмировать каждый элемент, возводить в степень каждый элемент, применять специальные функции, такие как гамма и дигамма и т. д.(аналогично обработке этих функций в Matlab применительно к матрицам и векторам.)

Я предполагаю, что написать вспомогательную функцию, которая бы грубо применяла ее для каждой желаемой функции, было бы достаточно, но это кажется расточительным.

аналогично, вики-сайт Boost предлагает некоторый код для векторизовать стандартные функции, но это кажется довольно сложным.

Был предложен valarray, но я бы хотел избежать преобразования между типами данных, так как мне нужны типы данных ublas для других операций (матричные продукты, разреженные матрицы и т. д.).

любая помощь очень ценится.

Это было полезно?

Решение

ПРЕДУПРЕЖДЕНИЕ

Следующий ответ неверен.См. «Редактировать» внизу.Я оставил первоначальный ответ как есть, чтобы дать контекст и отдать должное тем, кто указал на ошибку.


Я не особо знаком с библиотеками повышения, поэтому может быть более стандартный способ сделать это, но я думаю, что вы можете делать все, что хотите, с итераторами и STL. трансформировать шаблон функции.А введение в документацию библиотеки uBLAS говорит, что его классы разработаны так, чтобы быть совместимыми с тем же поведением итератора, которое используется в STL.Матрица повышения и векторные шаблоны — все есть итераторы который можно использовать для доступа к отдельным элементам.Вектор имеет begin() и end(), и матрица имеет begin1(), end1(), begin2(), и end2()1 разновидности представляют собой итераторы по столбцам, а 2 разновидности являются построчными итераторами.См. документацию по повышению на векторное выражение и МатричноеВыражение для получения дополнительной информации.

Использование STL transform алгоритме вы можете применить функцию к каждому элементу итерируемой последовательности и присвоить результат другой итерируемой последовательности той же длины или той же последовательности.Итак, чтобы использовать это для вектора повышения uBLAS, вы можете сделать это:

using namespace boost::numeric::ublas;

// Create a 30 element vector of doubles
vector<double> vec(30);

// Assign 8.0 to each element.
std::fill(vec.begin(), vec.end(), 8.0);

// Perform the "Gamma" function on each element and assign the result back
// to the original element in the vector.
std::transform(vec.begin(), vec.end(), vec.begin(), boost::math::tgamma);

Для матрицы это будет в основном то же самое: вы должны использовать либо 1 или 2 семейство итераторов.Какой из них вы выберете, зависит от того, является ли расположение памяти вашей матрицы основным по строкам или по основным столбцам.Беглый просмотр документации uBLAS наводит меня на мысль, что это может быть любой из них, поэтому вам нужно будет изучить код и определить, какой из них используется, чтобы выбрать наиболее эффективный порядок итерации.

matrix<double> mat(30, 30);
.
.
.

std::transform(mat.begin1(), mat.end1(), mat.begin1(), boost::math::tgamma);

Функция, которую вы передаете в качестве последнего аргумента, может быть функцией, принимающей одинарный аргумент типа double и возвращающей значение типа double.Это также может быть функтор.

Это не совсем то же самое, что приведенный вами пример векторизации, но похоже, что он должен быть довольно близок к тому, что вы хотите.


РЕДАКТИРОВАТЬ

Похоже, мне следовало проверить свою рекомендацию, прежде чем ее давать.Как отмечалось другими, итераторы «1» и «2» выполняют итерацию только по одной строке/столбцу матрицы.Обзорная документация Boost вводит в заблуждение по этому поводу.Он утверждает, что begin1() «Возвращает итератор1, указывающий на начало матрицы» и что end1() «Возвращает итератор1, указывающий на конец матрицы».Убило бы их слово «столбец матрицы» вместо «матрица»?Я предположил, что iterator1 был итератор по столбцам, который выполнял итерацию по всей матрице.Чтобы узнать, как это сделать правильно, см. Ответ Лантерн Руж.

Другие советы

Использование begin1() / end1() не будет работать, поскольку он обеспечивает доступ к элементу в позиции столбца по умолчанию (0):следовательно, вы просто получаете доступ ко всем элементам в первом столбце.Лучше (в том смысле, что вы получаете ожидаемое поведение) получить последовательный доступ через:

std::transform(mat.data().begin(), mat.data().end(),
               mat.data().begin(), boost::math::tgamma) ;

Я подозреваю, что это может быть случай, когда реализация не совсем завершена.

Наслаждаться!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top