#include "src/storage/FlexibleSparseMatrix.h" #include "src/storage/SparseMatrix.h" #include "src/storage/BitVector.h" #include "src/adapters/CarlAdapter.h" #include "src/utility/constants.h" namespace storm { namespace storage { template FlexibleSparseMatrix::FlexibleSparseMatrix(index_type rows) : data(rows), columnCount(0), nonzeroEntryCount(0) { // Intentionally left empty. } template FlexibleSparseMatrix::FlexibleSparseMatrix(storm::storage::SparseMatrix const& matrix, bool setAllValuesToOne) : data(matrix.getRowCount()), columnCount(matrix.getColumnCount()), nonzeroEntryCount(matrix.getNonzeroEntryCount()), nontrivialRowGrouping(matrix.hasNontrivialRowGrouping()) { if (nontrivialRowGrouping) { rowGroupIndices = matrix.getRowGroupIndices(); } for (index_type rowIndex = 0; rowIndex < matrix.getRowCount(); ++rowIndex) { typename storm::storage::SparseMatrix::const_rows row = matrix.getRow(rowIndex); reserveInRow(rowIndex, row.getNumberOfEntries()); for (auto const& element : row) { // If the probability is zero, we skip this entry. if (storm::utility::isZero(element.getValue())) { continue; } if (setAllValuesToOne) { getRow(rowIndex).emplace_back(element.getColumn(), storm::utility::one()); } else { getRow(rowIndex).emplace_back(element); } } } } template void FlexibleSparseMatrix::reserveInRow(index_type row, index_type numberOfElements) { this->data[row].reserve(numberOfElements); } template typename FlexibleSparseMatrix::row_type& FlexibleSparseMatrix::getRow(index_type index) { return this->data[index]; } template typename FlexibleSparseMatrix::row_type const& FlexibleSparseMatrix::getRow(index_type index) const { return this->data[index]; } template typename FlexibleSparseMatrix::row_type& FlexibleSparseMatrix::getRow(index_type rowGroup, index_type offset) { assert(rowGroup < this->getRowGroupCount()); assert(offset < this->getRowGroupSize(rowGroup)); return getRow(rowGroupIndices[rowGroup] + offset); } template typename FlexibleSparseMatrix::row_type const& FlexibleSparseMatrix::getRow(index_type rowGroup, index_type offset) const { assert(rowGroup < this->getRowGroupCount()); assert(offset < this->getRowGroupSize(rowGroup)); return getRow(rowGroupIndices[rowGroup] + offset); } template std::vector::index_type> const& FlexibleSparseMatrix::getRowGroupIndices() const { return rowGroupIndices; } template typename FlexibleSparseMatrix::index_type FlexibleSparseMatrix::getRowCount() const { return this->data.size(); } template typename FlexibleSparseMatrix::index_type FlexibleSparseMatrix::getColumnCount() const { return columnCount; } template typename FlexibleSparseMatrix::index_type FlexibleSparseMatrix::getNonzeroEntryCount() const { return nonzeroEntryCount; } template typename FlexibleSparseMatrix::index_type FlexibleSparseMatrix::getRowGroupCount() const { return rowGroupIndices.size(); } template typename FlexibleSparseMatrix::index_type FlexibleSparseMatrix::getRowGroupSize(index_type group) const { if (group == getRowGroupCount() - 1) { return getRowCount() - rowGroupIndices[group]; } else { return rowGroupIndices[group + 1] - rowGroupIndices[group]; } } template ValueType FlexibleSparseMatrix::getRowSum(index_type row) const { ValueType sum = storm::utility::zero(); for (auto const& element : getRow(row)) { sum += element.getValue(); } return sum; } template void FlexibleSparseMatrix::updateDimensions() { this->nonzeroEntryCount = 0; this->columnCount = 0; for (auto const& row : this->data) { for (auto const& element : row) { assert(!storm::utility::isZero(element.getValue())); ++this->nonzeroEntryCount; this->columnCount = std::max(element.getColumn() + 1, this->columnCount); } } } template bool FlexibleSparseMatrix::empty() const { for (auto const& row : this->data) { if (!row.empty()) { return false; } } return true; } template bool FlexibleSparseMatrix::hasNontrivialRowGrouping() const { return nontrivialRowGrouping; } template void FlexibleSparseMatrix::createSubmatrix(storm::storage::BitVector const& rowConstraint, storm::storage::BitVector const& columnConstraint) { for (uint_fast64_t rowIndex = 0; rowIndex < this->data.size(); ++rowIndex) { auto& row = this->data[rowIndex]; if (!rowConstraint.get(rowIndex)) { row.clear(); row.shrink_to_fit(); continue; } row_type newRow; for (auto const& element : row) { if (columnConstraint.get(element.getColumn())) { newRow.push_back(element); } } row = std::move(newRow); } } template storm::storage::SparseMatrix FlexibleSparseMatrix::createSparseMatrix() { storm::storage::SparseMatrixBuilder matrixBuilder(getRowCount(), getColumnCount()); for (uint_fast64_t rowIndex = 0; rowIndex < getRowCount(); ++rowIndex) { auto& row = this->data[rowIndex]; for (auto const& entry : row) { matrixBuilder.addNextValue(rowIndex, entry.getColumn(), entry.getValue()); } } return matrixBuilder.build(); } template bool FlexibleSparseMatrix::rowHasDiagonalElement(storm::storage::sparse::state_type state) { for (auto const& entry : this->getRow(state)) { if (entry.getColumn() < state) { continue; } else if (entry.getColumn() > state) { return false; } else if (entry.getColumn() == state) { return true; } } return false; } template std::ostream& FlexibleSparseMatrix::printRow(std::ostream& out, index_type const& rowIndex) const { index_type columnIndex = 0; row_type row = this->getRow(rowIndex); for (index_type column = 0; column < this->getColumnCount(); ++column) { if (columnIndex < row.size() && row[columnIndex].getColumn() == column) { // Insert entry out << row[columnIndex].getValue() << "\t"; ++columnIndex; } else { // Insert zero out << "0\t"; } } return out; } template std::ostream& operator<<(std::ostream& out, FlexibleSparseMatrix const& matrix) { typedef typename FlexibleSparseMatrix::index_type FlexibleIndex; // Print column numbers in header. out << "\t\t"; for (FlexibleIndex i = 0; i < matrix.getColumnCount(); ++i) { out << i << "\t"; } out << std::endl; if (matrix.hasNontrivialRowGrouping()) { // Iterate over all row groups FlexibleIndex rowGroupCount = matrix.getRowGroupCount(); for (FlexibleIndex rowGroup = 0; rowGroup < rowGroupCount; ++rowGroup) { out << "\t---- group " << rowGroup << "/" << (rowGroupCount - 1) << " ---- " << std::endl; FlexibleIndex endRow = rowGroup+1 < rowGroupCount ? matrix.rowGroupIndices[rowGroup + 1] : matrix.getRowCount(); // Iterate over all rows. for (FlexibleIndex row = matrix.rowGroupIndices[rowGroup]; row < endRow; ++row) { // Print the actual row. out << rowGroup << "\t(\t"; matrix.printRow(out, row); out << "\t)\t" << rowGroup << std::endl; } } } else { // Iterate over all rows for (FlexibleIndex row = 0; row < matrix.getRowCount(); ++row) { // Print the actual row. out << row << "\t(\t"; matrix.printRow(out, row); out << "\t)\t" << row << std::endl; } } // Print column numbers in footer. out << "\t\t"; for (FlexibleIndex i = 0; i < matrix.getColumnCount(); ++i) { out << i << "\t"; } out << std::endl; return out; } // Explicitly instantiate the matrix. template class FlexibleSparseMatrix; template std::ostream& operator<<(std::ostream& out, FlexibleSparseMatrix const& matrix); #ifdef STORM_HAVE_CARL template class FlexibleSparseMatrix; template std::ostream& operator<<(std::ostream& out, FlexibleSparseMatrix const& matrix); #endif } // namespace storage } // namespace storm