6 #ifndef SparseMatrix_hpp
7 #define SparseMatrix_hpp
15 #include <unordered_map>
19 std::unordered_map<int, T> _matrix = {};
20 int _rows = 0, _cols = 0;
21 static constexpr T _defaultReturn = 0;
22 bool _setSeed =
false;
24 uint _randomGeneratedNumbers;
34 ?
throw std::invalid_argument(
"SparseMatrix: rows and cols must be > 0")
42 index < 0 ?
throw std::invalid_argument(
"SparseMatrix: index must be > 0")
49 static void encode(std::string
const &filename) {
52 std::unordered_map<int, T> matrix = {};
53 file.open(filename, std::ios::in);
57 while (file >> value) {
59 matrix.emplace(std::make_pair(i, value));
64 file.open(filename, std::ios::out);
65 file << rows <<
'\t' << cols <<
'\n';
66 for (
auto const &[key, value] : matrix) {
67 file << key <<
'\t' << value <<
'\n';
74 static void decode(std::string
const &filename) {
75 std::fstream file(filename);
76 int rows, cols, index;
77 std::unordered_map<int, T> matrix = {};
80 while (file >> index >> value) {
81 matrix.emplace(std::make_pair(index, value));
84 file.open(filename, std::ios::out);
85 file << rows <<
'\t' << cols <<
'\n';
86 for (
int i = 0; i < rows * cols; ++i) {
87 if (matrix.find(i) != matrix.end()) {
88 file << matrix[i] <<
'\t';
92 if ((i + 1) % cols == 0) {
101 _randomGeneratedNumbers = 0;
110 if (i >= _rows || j >= _cols || i < 0 || j < 0) {
111 throw std::out_of_range(
"Index out of range");
113 _matrix.emplace(std::make_pair(i * _cols + j, value));
120 if (i >= _rows * _cols || i < 0) {
121 throw std::out_of_range(
"Index out of range");
123 _matrix.emplace(std::make_pair(i, value));
132 if (i >= _rows || j >= _cols || i < 0 || j < 0) {
133 throw std::out_of_range(
"Index out of range");
135 _matrix.insert_or_assign(i * _cols + j, value);
143 if (index < 0 || index > _rows * _cols - 1) {
144 throw std::out_of_range(
"Index out of range");
146 _matrix.insert_or_assign(index, value);
154 if (i >= _rows || j >= _cols || i < 0 || j < 0) {
155 throw std::out_of_range(
"Index out of range");
157 _matrix.find(i * _cols + j) != _matrix.end()
158 ? _matrix.erase(i * _cols + j)
159 :
throw std::runtime_error(
"SparseMatrix: element not found");
165 if (index < 0 || index > _rows - 1) {
166 throw std::out_of_range(
"Index out of range");
168 for (
int i = 0; i < _cols; ++i) {
169 _matrix.erase(index * _cols + i);
171 std::unordered_map<int, T> new_matrix = {};
172 for (
auto const &[key, value] : _matrix) {
173 if (key / _cols < index) {
174 new_matrix.emplace(std::make_pair(key, value));
176 new_matrix.emplace(std::make_pair(key - _cols, value));
180 _matrix = new_matrix;
186 if (index < 0 || index > _cols - 1) {
187 throw std::out_of_range(
"Index out of range");
189 for (
int i = 0; i < _rows; ++i) {
190 _matrix.erase(i * _cols + index);
192 std::unordered_map<int, T> new_matrix = {};
193 for (
auto const &[key, value] : _matrix) {
194 if (key % _cols < index) {
195 new_matrix.emplace(std::make_pair(key - key / _cols, value));
198 std::make_pair(key / _cols * (_cols - 1) + key % _cols - 1, value));
202 _matrix = new_matrix;
204 void clear() noexcept {
215 if (i >= _rows || j >= _cols || i < 0 || j < 0) {
216 throw std::out_of_range(
"Index out of range");
218 return _matrix.contains(i * _cols + j);
225 if (index < 0 || index > _rows * _cols - 1) {
226 throw std::out_of_range(
"Index out of range");
228 return _matrix.contains(index);
234 if (_rows != _cols) {
235 throw std::runtime_error(
236 "SparseMatrix: getDegreeVector only works on square matrices");
239 for (
auto &i : _matrix) {
240 degreeVector.insert_or_assign(i.first / _cols, 0,
241 degreeVector.at(i.first / _cols, 0) + 1);
249 if (_rows != _cols) {
250 throw std::runtime_error(
251 "SparseMatrix: getStrengthVector only works on square matrices");
254 for (
auto &i : _matrix) {
255 strengthVector.insert_or_assign(
256 i.first / _cols, 0, strengthVector.at(i.first / _cols, 0) + i.second);
258 return strengthVector;
264 if (_rows != _cols) {
265 throw std::runtime_error(
266 "SparseMatrix: getLaplacian only works on square matrices");
269 for (
auto &i : _matrix) {
270 laplacian.insert_or_assign(i.first / _cols, i.first % _cols, -1);
273 for (
int i = 0; i < _rows; i++) {
274 laplacian.insert_or_assign(i, i, degreeVector.at(i, 0));
284 if (index >= _rows || index < 0) {
285 throw std::out_of_range(
"Index out of range");
288 for (
auto &it : _matrix) {
289 if (it.first / _cols == index) {
290 row.
insert(it.first % _cols, it.second);
300 if (index >= _cols || index < 0) {
301 throw std::out_of_range(
"Index out of range");
304 for (
auto &it : _matrix) {
305 if (it.first % _cols == index) {
306 col.
insert(it.first / _cols, it.second);
316 if (index >= _rows || index < 0)
317 throw std::out_of_range(
"Index out of range");
318 auto row = this->
getRow(index);
320 throw std::runtime_error(
"SparseMatrix: row is empty");
321 std::pair<int, T> res = row.getRndElement();
322 res.first += index * _cols;
330 if (index >= _cols || index < 0)
331 throw std::out_of_range(
"Index out of range");
332 auto col = this->
getCol(index);
334 throw std::runtime_error(
"SparseMatrix: col is empty");
335 std::pair<int, T> res = col.getRndElement();
344 if (this->
size() == 0)
345 throw std::runtime_error(
"SparseMatrix: matrix is empty");
346 auto it = _matrix.begin();
347 std::mt19937 rng(std::random_device{}());
351 _randomGeneratedNumbers);
353 auto dist = std::uniform_int_distribution<int>(0, this->
size() - 1);
354 std::advance(it, dist(rng));
355 std::pair<int, T> res = *it;
356 ++_randomGeneratedNumbers;
363 for (
int index = 0; index < _rows; index++) {
364 auto row = this->
getRow(index);
366 for (
auto &it : row) {
367 sum += std::abs(it.second);
369 sum < std::numeric_limits<double>::epsilon() ? sum = 1. : sum = sum;
370 for (
auto &it : row) {
371 normRows.
insert(it.first + index * _cols, it.second / sum);
380 for (
int index = 0; index < _cols; index++) {
381 auto col = this->
getCol(index);
383 for (
auto &it : col) {
384 sum += std::abs(it.second);
386 sum < std::numeric_limits<double>::epsilon() ? sum = 1. : sum = sum;
387 for (
auto &it : col) {
388 normCols.
insert(it.first * _cols + index, it.second / sum);
401 int size() const noexcept {
return _matrix.size(); };
404 int max_size() const noexcept {
return this->_rows * this->_cols; }
410 T
at(
int i,
int j)
const {
411 if (i >= _rows || j >= _cols || i < 0 || j < 0) {
412 throw std::out_of_range(
"Index out of range");
414 auto const &it = _matrix.find(i * _cols + j);
415 return it != _matrix.end() ? it->second : _defaultReturn;
421 T
at(
int index)
const {
422 if (index >= _rows * _cols || index < 0) {
423 throw std::out_of_range(
"Index out of range");
425 auto const &it = _matrix.find(index);
426 return it != _matrix.end() ? it->second : _defaultReturn;
433 for (
int i = 0; i < _rows; ++i) {
434 for (
int j = 0; j < _cols; ++j) {
435 auto const &it = _matrix.find(i * _cols + j);
436 it != _matrix.end() ? std::cout << it->second : std::cout << 0;
444 void fprint(std::string
const &filename)
const noexcept {
445 std::ofstream file(filename);
446 file << _rows <<
'\t' << _cols <<
'\n';
448 auto const rdbufBackup = std::cout.rdbuf();
449 std::cout.rdbuf(file.rdbuf());
451 std::cout.rdbuf(rdbufBackup);
456 typename std::unordered_map<int, T>::const_iterator
begin() const noexcept {
457 return _matrix.begin();
461 typename std::unordered_map<int, T>::const_iterator
end() const noexcept {
462 return _matrix.end();
470 if (i >= _rows || j >= _cols || i < 0 || j < 0) {
471 throw std::out_of_range(
"Index out of range");
473 auto const &it = _matrix.find(i * _cols + j);
474 return it != _matrix.end() ? it->second : _defaultReturn;
481 if (index >= _rows * _cols || index < 0) {
482 throw std::out_of_range(
"Index out of range");
484 auto const &it = _matrix.find(index);
485 return it != _matrix.end() ? it->second : _defaultReturn;
489 os << m._rows <<
'\t' << m._cols <<
'\n';
490 for (
auto &it : m._matrix) {
491 os << it.first <<
'\t' << it.second <<
'\n';
497 is >> m._rows >> m._cols;
500 while (is >> index >> value) {
501 m._matrix.emplace(std::make_pair(index, value));
509 template <
typename U>
511 if (this->_rows != other._rows || this->_cols != other._cols) {
512 throw std::runtime_error(
"SparseMatrix: dimensions do not match");
515 std::unordered_map<int, bool> unique;
516 for (
auto &it : this->_matrix) {
517 unique.insert_or_assign(it.first,
true);
519 for (
auto &it : other._matrix) {
520 unique.insert_or_assign(it.first,
true);
522 for (
auto &it : unique) {
523 result.insert(it.first / this->_cols, it.first % this->_cols,
524 this->at(it.first) + other.
at(it.first));
532 template <
typename U>
534 if (this->_rows != other._rows || this->_cols != other._cols) {
535 throw std::runtime_error(
"SparseMatrix: dimensions do not match");
538 std::unordered_map<int, bool> unique;
539 for (
auto &it : this->_matrix) {
540 unique.insert_or_assign(it.first,
true);
542 for (
auto &it : other._matrix) {
543 unique.insert_or_assign(it.first,
true);
545 for (
auto &it : unique) {
546 result.insert(it.first / this->_cols, it.first % this->_cols,
547 this->at(it.first) - other.
at(it.first));
573 auto transpost =
SparseMatrix(this->_cols, this->_rows);
574 for (
auto &it : _matrix) {
575 transpost.insert(it.first % _cols, it.first / _cols, it.second);
584 if (this->_rows != other._rows || this->_cols != other._cols) {
585 throw std::runtime_error(
"SparseMatrix: dimensions do not match");
587 for (
auto &it : other._matrix) {
590 this->operator()(it.first) + it.second)
591 : this->
insert(it.first, it.second);
600 if (this->_rows != other._rows || this->_cols != other._cols) {
601 throw std::runtime_error(
"SparseMatrix: dimensions do not match");
603 for (
auto &it : other._matrix) {
606 this->operator()(it.first) - it.second)
607 : this->
insert(it.first, -it.second);
SparseMatrix class v1.7.0 by Grufoony.
Definition: SparseMatrix.hpp:18
SparseMatrix< double > getNormRows() const
get a matrix of double with every row normalized to 1
Definition: SparseMatrix.hpp:361
int getRowDim() const noexcept
get the number of rows
Definition: SparseMatrix.hpp:395
T at(int i, int j) const
access an element of the matrix
Definition: SparseMatrix.hpp:410
std::unordered_map< int, T >::const_iterator begin() const noexcept
return the begin iterator of the matrix
Definition: SparseMatrix.hpp:456
SparseMatrix< int > getLaplacian()
get the laplacian matrix
Definition: SparseMatrix.hpp:263
void insert_or_assign(int i, int j, T value)
insert a value in the matrix. If the element already exist, it overwrites it
Definition: SparseMatrix.hpp:131
SparseMatrix getCol(int index) const
get a column as a column vector
Definition: SparseMatrix.hpp:299
void insert(int i, int j, T value)
insert a value in the matrix
Definition: SparseMatrix.hpp:109
void setSeed(int seed) noexcept
Set random seed.
Definition: SparseMatrix.hpp:99
bool contains(int i, int j) const
check if the element is non zero
Definition: SparseMatrix.hpp:214
std::pair< int, T > getRndRowElement(int index)
get a random non-zero element from a row
Definition: SparseMatrix.hpp:315
static void encode(std::string const &filename)
Function to read a matrix from a file and rewrite it in a listed way.
Definition: SparseMatrix.hpp:49
SparseMatrix & operator+=(const SparseMatrix< U > &other)
sum of two matrices
Definition: SparseMatrix.hpp:583
SparseMatrix(int rows, int cols)
SparseMatrix constructor.
Definition: SparseMatrix.hpp:32
friend std::istream & operator>>(std::istream &is, SparseMatrix &m)
read the matrix from a stream
Definition: SparseMatrix.hpp:496
void symmetrize()
symmetrize the matrix
Definition: SparseMatrix.hpp:429
SparseMatrix & operator-=(const SparseMatrix< U > &other)
difference of two matrices
Definition: SparseMatrix.hpp:599
SparseMatrix< double > getStrengthVector()
get the strength of all nodes
Definition: SparseMatrix.hpp:248
std::unordered_map< int, T >::const_iterator end() const noexcept
return the end iterator of the matrix
Definition: SparseMatrix.hpp:461
SparseMatrix operator++()
transpose the matrix
Definition: SparseMatrix.hpp:572
std::pair< int, T > getRndElement()
get a random non-zero element from the matrix
Definition: SparseMatrix.hpp:343
SparseMatrix(int index)
SparseMatrix constructor - colum.
Definition: SparseMatrix.hpp:41
void print() const noexcept
print the matrix in standard output
Definition: SparseMatrix.hpp:432
std::pair< int, T > getRndColElement(int index)
get a random non-zero element from a column
Definition: SparseMatrix.hpp:329
friend std::ostream & operator<<(std::ostream &os, const SparseMatrix &m)
print the matrix on a stream
Definition: SparseMatrix.hpp:488
void insert(int i, T value)
insert a value in the matrix
Definition: SparseMatrix.hpp:119
T const & operator()(int index)
access an element of the matrix
Definition: SparseMatrix.hpp:480
int max_size() const noexcept
get the maximum number of elements in the matrix
Definition: SparseMatrix.hpp:404
SparseMatrix getRow(int index) const
get a row as a row vector
Definition: SparseMatrix.hpp:283
T const & operator()(int i, int j)
access an element of the matrix
Definition: SparseMatrix.hpp:469
SparseMatrix operator-(const SparseMatrix< U > &other) const
difference of two matrices
Definition: SparseMatrix.hpp:533
void eraseRow(int index)
remove a row from the matrix
Definition: SparseMatrix.hpp:164
static void decode(std::string const &filename)
Function to read a matrix from a file and rewrite it as a full matrix.
Definition: SparseMatrix.hpp:74
void erase(int i, int j)
remove a value from the matrix
Definition: SparseMatrix.hpp:153
int getColDim() const noexcept
get the number of columns
Definition: SparseMatrix.hpp:398
void insert_or_assign(int index, T value)
insert a value in the matrix. If the element already exist, it overwrites it
Definition: SparseMatrix.hpp:142
T at(int index) const
access an element of the matrix
Definition: SparseMatrix.hpp:421
int size() const noexcept
get the number of non zero elements in the matrix
Definition: SparseMatrix.hpp:401
SparseMatrix operator+(const SparseMatrix< U > &other) const
sum of two matrices
Definition: SparseMatrix.hpp:510
bool contains(int const index) const
check if the element is non zero
Definition: SparseMatrix.hpp:224
SparseMatrix< double > getNormCols() const
get a matrix of double with every column normalized to 1
Definition: SparseMatrix.hpp:378
SparseMatrix< int > getDegreeVector()
get the input degree of all nodes
Definition: SparseMatrix.hpp:233
void eraseColumn(int index)
remove a column from the matrix
Definition: SparseMatrix.hpp:185
void fprint(std::string const &filename) const noexcept
print the matrix on a file
Definition: SparseMatrix.hpp:444