boost :: ublas как получить определитель матрицы int?

Я нашел функцию, которая вычисляет определитель матрицы boost :: ublas:

template<typename ValType>
ValType det_fast(const ublas::matrix<ValType>& matrix)
{
// create a working copy of the input
ublas::matrix<ValType> mLu(matrix);
ublas::permutation_matrix<std::size_t> pivots(matrix.size1());

auto isSingular = ublas::lu_factorize(mLu, pivots);
if (isSingular)
return static_cast<ValType>(0);

ValType det = static_cast<ValType>(1);
for (std::size_t i = 0; i < pivots.size(); ++i)
{
if (pivots(i) != i)
det *= static_cast<ValType>(-1);

det *= mLu(i, i);
}

return det;
}

Эта функция работает нормально, но только с нецелыми типами (она отлично работает с float и double). Когда я пытаюсь передать так же матрица, но с типом int, я получил ошибку компиляции:

Ошибка проверки в файле c: \ boost \ boost_1_58_0 \ boost \ numeric \ ublas \ lu.hpp в строке 167:
единственное число! = 0 || detail :: expression_type_check (prod (triangular_adaptor (m), triangular_adaptor (m)), см)
неизвестное местоположение (0): фатальная ошибка в «BaseTest»: std :: logic_error: внутренняя логика

Это ошибка Boost или моя функция не так?
Какие изменения я могу сделать, чтобы избежать этой ошибки?

4

Решение

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

Вы можете отключить проверку типов, используя

#define BOOST_UBLAS_TYPE_CHECK 0

прежде чем включает. Но подумай дважды! Посмотрите на пример

#include <iostream>
#define BOOST_UBLAS_TYPE_CHECK 0
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/lu.hpp>
namespace ublas = boost::numeric::ublas;

template<typename ValType>
ValType det_fast(const ublas::matrix<ValType>& matrix)
{
// create a working copy of the input
ublas::matrix<ValType> mLu(matrix);
ublas::permutation_matrix<std::size_t> pivots(matrix.size1());

auto isSingular = ublas::lu_factorize(mLu, pivots);
if (isSingular)
return static_cast<ValType>(0);

ValType det = static_cast<ValType>(1);
for (std::size_t i = 0; i < pivots.size(); ++i)
{
if (pivots(i) != i)
det *= static_cast<ValType>(-1);

det *= mLu(i, i);
}

return det;
}

int main()
{
ublas::matrix<int> m (3, 3);
for (unsigned i = 0; i < m.size1 (); ++ i)
for (unsigned j = 0; j < m.size2 (); ++ j)
m (i, j) = 3 * i + j;
std::cout << det_fast(m) << std::endl;
}

Очевидно, что матрица m единственное число, и если вы измените тип с int в double функции возвращают ноль. Но с int это возвращается -48,

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

Также вы можете создать ublas::matrix<int> без каких-либо ошибок и назначить его ublas::matrix<float>, Таким образом, один из способов правильно рассчитать определитель является перегрузка det_fast и удалить define заявление.

int det_fast(const ublas::matrix<int>& matrix)
{
return (int)det_fast(ublas::matrix<float>(matrix));
}

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

Посмотрите на стол, где average time время полного определения определителя (для int с операцией копирования) из 5 запусков программы.

size |  average time, ms
------------------------
|    int      float
------------------------
100  |    9.0        9.0
200  |   46.6       46.8
300  |  156.4      159.4
400  |  337.4      331.4
500  |  590.8      609.2
600  |  928.2     1009.4
700  | 1493.8     1525.2
800  | 2162.8     2231.0
900  | 3184.2     3025.2

Вы можете подумать, что для int это быстрее, но это не так. В среднем для большего количества пробежек я уверен, что вы получите небольшое ускорение с float (Я думаю, около 0-15 мс, что является ошибкой измерения времени). Также, если мы измерим время копирования, мы увидим, что для размера матрицы меньше 3000 x 3000 оно близко к нулю (это также около 0-15 мс, что является ошибкой измерения времени). Для больших матриц время копирования увеличивается (например, для матрицы 5000 x 5000 это 125 мс). Но есть одно важное замечание! Время копирования меньше 1,0% всех определителей для расчета int Тип матрицы и она значительно уменьшается с ростом размера!

Все эти меры были сделаны для программы, скомпилированной с Visual Studio 2013 в конфигурации выпуска с улучшенной версией 1.58. Время измерялось с clock функция. Процессор Intel Xeon E5645 2,4 ГГц.

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

2

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector