Я пытаюсь создать симметричную матрицу n x n
матрицу и заполните ее, используя n*(n+1)/2
размерный массив с использованием boost
библиотека в c++
,
Пока я могу создать матрицу и заполнить ее случайными значениями, используя следующий код
#include <iostream>
#include <fstream>
#include </usr/include/boost/numeric/ublas/matrix.hpp>
#include </usr/include/boost/numeric/ublas/matrix_sparse.hpp>
#include </usr/include/boost/numeric/ublas/symmetric.hpp>
#include </usr/include/boost/numeric/ublas/io.hpp>
using namespace std;int test_boost () {
using namespace boost::numeric::ublas;
symmetric_matrix<double, upper> m_sym (3, 3);
double filler[6] = {0, 1, 2, 3, 4, 5};
for (unsigned i = 0; i < m_sym.size1 (); ++ i)
for (unsigned j = i; j < m_sym.size2 (); ++ j)
m_sym (i, j) = filler[i+j*m_sym.size1()];
std::cout << m_sym << std::endl;
return 0;
}
Что я пытаюсь сделать, это заполнить верхнюю (или нижнюю) часть симметричной матрицы, используя значения из массива filler
, Таким образом, выходная верхняя симметричная матрица должна быть
| 0 | 1 | 2 |
------------------------------------------------
0 | 0 1 3
1 | 1 2 4
2 | 3 4 5
Есть идеи, как это сделать?
Я бы немного упростил это, просто сохранив итератор, который пересекает заполнитель от начала до конца:
symmetric_matrix<double, upper> m_sym (3, 3);
double filler[6] = {0, 1, 2, 3, 4, 5};
assert(m_sym.size1() == m_sym.size2());
double const* in = std::begin(filler);
for (size_t i = 0; i < m_sym.size1(); ++ i)
for (size_t j = 0; j <= i && in != std::end(filler); ++ j)
m_sym (i, j) = *in++;
Печать: Жить на Колиру
Я бы лично предложил создать вспомогательную функцию, такую как:
#include <iostream>
#include <fstream>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/symmetric.hpp>
#include <boost/numeric/ublas/io.hpp>
namespace bnu = boost::numeric::ublas;
template <typename T = double>
bnu::symmetric_matrix<T, bnu::upper> make_symmetric(std::initializer_list<T> filler) {
size_t n = (sqrt(8*filler.size() + 1) - 1)/2;
assert((n*(n+1))/2 == filler.size());
bnu::symmetric_matrix<T, bnu::upper> result(n, n);
auto in = std::begin(filler);
for (size_t i = 0; i < result.size1(); ++ i)
for (size_t j = 0; j <= i && in != std::end(filler); ++ j)
result (i, j) = *in++;
return result;
}
int main() {
std::cout << make_symmetric({0,1,2}) << "\n";
std::cout << make_symmetric({0,1,2,3,4,5}) << "\n";
std::cout << make_symmetric({0,1,2,3,4,5,6,7,8,9}) << "\n";
}
Печать
[2,2]((0,1),(1,2))
[3,3]((0,1,3),(1,2,4),(3,4,5))
[4,4]((0,1,3,6),(1,2,4,7),(3,4,5,8),(6,7,8,9))
Примечание: проверка размера использует расширение серии для
1 + ... + n
и обратная сторона этого:n = 1/2 (sqrt(8 x + 1) - 1)
Других решений пока нет …