Browse Source

Further maintenance work on sparse matrix implementation.

Former-commit-id: 56885d90bf
tempestpy_adaptions
dehnert 11 years ago
parent
commit
4376708a46
  1. 434
      src/storage/SparseMatrix.cpp
  2. 77
      src/storage/SparseMatrix.h

434
src/storage/SparseMatrix.cpp

@ -1,11 +1,3 @@
/*
* SparseMatrix.cpp
*
* Created on: Nov 18, 2013
* Author: Manuel Sascha Weiand
*/
#include <iomanip>
#include <boost/functional/hash.hpp>
#include "src/storage/SparseMatrix.h"
@ -18,352 +10,232 @@ extern log4cplus::Logger logger;
namespace storm {
namespace storage {
// Functions of the nested ConstIterator class.
template<typename T>
template<typename ValueType>
SparseMatrix<T>::BaseIterator<ValueType>::BaseIterator(ValueType* valuePtr, uint_fast64_t const* columnPtr) : valuePtr(valuePtr), columnPtr(columnPtr) {
// Intentionally left empty.
}
template<typename T>
SparseMatrix<T>::ConstIterator::ConstIterator(T const* valuePtr, uint_fast64_t const* columnPtr) : valuePtr(valuePtr), columnPtr(columnPtr) {
template<typename ValueType>
SparseMatrix<T>::BaseIterator<ValueType>::BaseIterator(SparseMatrix<T>::BaseIterator<ValueType> const& other) : valuePtr(other.valuePtr), columnPtr(other.columnPtr) {
// Intentionally left empty.
}
template<typename T>
typename SparseMatrix<T>::ConstIterator& SparseMatrix<T>::ConstIterator::operator++() {
template<typename ValueType>
typename SparseMatrix<T>::template BaseIterator<ValueType>& SparseMatrix<T>::BaseIterator<ValueType>::operator=(BaseIterator<ValueType> const& other) {
if (this != &other) {
valuePtr = other.valuePtr,
columnPtr = other.columnPtr;
}
return *this;
}
template<typename T>
template<typename ValueType>
SparseMatrix<T>::BaseIterator<ValueType>& SparseMatrix<T>::BaseIterator<ValueType>::operator++() {
this->valuePtr++;
this->columnPtr++;
return *this;
}
template<typename T>
typename SparseMatrix<T>::ConstIterator& SparseMatrix<T>::ConstIterator::operator*() {
template<typename ValueType>
SparseMatrix<T>::BaseIterator<ValueType>& SparseMatrix<T>::BaseIterator<ValueType>::operator*() {
return *this;
}
template<typename T>
bool SparseMatrix<T>::ConstIterator::operator!=(ConstIterator const& other) const {
template<typename ValueType>
bool SparseMatrix<T>::BaseIterator<ValueType>::operator!=(BaseIterator<ValueType> const& other) const {
return this->valuePtr != other.valuePtr;
}
template<typename T>
typename SparseMatrix<T>::ConstIterator& SparseMatrix<T>::ConstIterator::operator=(ConstIterator const& other) {
this->valuePtr = other.valuePtr;
this->columnPtr = other.columnPtr;
return *this;
template<typename ValueType>
bool SparseMatrix<T>::BaseIterator<ValueType>::operator==(BaseIterator<ValueType> const& other) const {
return this->valuePtr == other.valuePtr;
}
template<typename T>
uint_fast64_t SparseMatrix<T>::ConstIterator::column() const {
template<typename ValueType>
uint_fast64_t SparseMatrix<T>::BaseIterator<ValueType>::column() const {
return *columnPtr;
}
template<typename T>
T const& SparseMatrix<T>::ConstIterator::value() const {
template<typename ValueType>
ValueType& SparseMatrix<T>::BaseIterator<ValueType>::value() const {
return *valuePtr;
}
// Functions of the nested Rows class.
template<typename T>
SparseMatrix<T>::Rows::Rows(T const* valuePtr, uint_fast64_t const* columnPtr, uint_fast64_t entryCount) : valuePtr(valuePtr), columnPtr(columnPtr), entryCount(entryCount) {
SparseMatrix<T>::rows::rows(T* valuePtr, uint_fast64_t const* columnPtr, uint_fast64_t entryCount) : valuePtr(valuePtr), columnPtr(columnPtr), entryCount(entryCount) {
// Intentionally left empty.
}
template<typename T>
typename SparseMatrix<T>::ConstIterator SparseMatrix<T>::Rows::begin() const {
return ConstIterator(valuePtr, columnPtr);
typename SparseMatrix<T>::iterator SparseMatrix<T>::rows::begin() {
return iterator(valuePtr, columnPtr);
}
template<typename T>
typename SparseMatrix<T>::ConstIterator SparseMatrix<T>::Rows::end() const {
return ConstIterator(valuePtr + entryCount, columnPtr + entryCount);
typename SparseMatrix<T>::iterator SparseMatrix<T>::rows::end() {
return iterator(valuePtr + entryCount, columnPtr + entryCount);
}
// Functions of the nested ConstRowsIterator class.
template<typename T>
SparseMatrix<T>::ConstRowIterator::ConstRowIterator(T const* startValuePtr, uint_fast64_t const* startColumnPtr, uint_fast64_t const* rowPtr) : startValuePtr(startValuePtr), startColumnPtr(startColumnPtr), rowPtr(rowPtr) {
SparseMatrix<T>::const_rows::const_rows(T const* valuePtr, uint_fast64_t const* columnPtr, uint_fast64_t entryCount) : valuePtr(valuePtr), columnPtr(columnPtr), entryCount(entryCount) {
// Intentionally left empty.
}
template<typename T>
typename SparseMatrix<T>::ConstRowIterator& SparseMatrix<T>::ConstRowIterator::operator++() {
++rowPtr;
return *this;
}
template<typename T>
bool SparseMatrix<T>::ConstRowIterator::operator!=(ConstRowIterator const& other) const {
return this->rowPtr != other.rowPtr;
typename SparseMatrix<T>::const_iterator SparseMatrix<T>::const_rows::begin() const {
return const_iterator(valuePtr, columnPtr);
}
template<typename T>
typename SparseMatrix<T>::ConstIterator SparseMatrix<T>::ConstRowIterator::begin() const {
return ConstIterator(startValuePtr + *rowPtr, startColumnPtr + *rowPtr);
typename SparseMatrix<T>::const_iterator SparseMatrix<T>::const_rows::end() const {
return const_iterator(valuePtr + entryCount, columnPtr + entryCount);
}
template<typename T>
typename SparseMatrix<T>::ConstIterator SparseMatrix<T>::ConstRowIterator::end() const {
return ConstIterator(startValuePtr + *(rowPtr + 1), startColumnPtr + *(rowPtr + 1));
SparseMatrix<T>::SparseMatrix(uint_fast64_t rows, uint_fast64_t columns, uint_fast64_t entries) : rowCount(rows), columnCount(columns), entryCount(entries), internalStatus(UNINITIALIZED), valueStorage(), columnIndications(), rowIndications(), currentEntryCount(0), lastRow(0), lastColumn(0) {
storagePreallocated = rows != 0 && columns != 0 && entries != 0;
prepareInternalStorage();
}
// Functions of the SparseMatrix class.
template<typename T>
SparseMatrix<T>::SparseMatrix(uint_fast64_t rows, uint_fast64_t cols) : rowCount(rows), colCount(cols),
nonZeroEntryCount(0), internalStatus(MatrixStatus::UnInitialized), currentSize(0), lastRow(0) {
SparseMatrix<T>::SparseMatrix(uint_fast64_t size, uint_fast64_t entries) : SparseMatrix(size, size, entries) {
// Intentionally left empty.
}
template<typename T>
SparseMatrix<T>::SparseMatrix(uint_fast64_t size)
: rowCount(size), colCount(size), nonZeroEntryCount(0),
internalStatus(MatrixStatus::UnInitialized), currentSize(0), lastRow(0) {
SparseMatrix<T>::SparseMatrix(SparseMatrix<T> const& other) : rowCount(other.rowCount), columnCount(other.columnCount), entryCount(other.entryCount), storagePreallocated(other.storagePreallocated), valueStorage(other.valueStorage), columnIndications(other.columnIndications), rowIndications(other.rowIndications), internalStatus(other.internalStatus), currentEntryCount(other.currentEntryCount), lastRow(other.lastRow), lastColumn(other.lastColumn) {
// Intentionally left empty.
}
template<typename T>
SparseMatrix<T>::SparseMatrix(SparseMatrix<T>&& other)
: rowCount(other.rowCount), colCount(other.colCount), nonZeroEntryCount(other.nonZeroEntryCount),
valueStorage(std::move(other.valueStorage)), columnIndications(std::move(other.columnIndications)),
rowIndications(std::move(other.rowIndications)), internalStatus(other.internalStatus),
currentSize(other.currentSize), lastRow(other.lastRow) {
SparseMatrix<T>::SparseMatrix(SparseMatrix<T>&& other) : rowCount(other.rowCount), columnCount(other.columnCount), entryCount(other.entryCount), storagePreallocated(other.storagePreallocated), valueStorage(std::move(other.valueStorage)), columnIndications(std::move(other.columnIndications)), rowIndications(std::move(other.rowIndications)), internalStatus(other.internalStatus), currentEntryCount(other.currentEntryCount), lastRow(other.lastRow), lastColumn(other.lastColumn) {
// Now update the source matrix
other.rowCount = 0;
other.colCount = 0;
other.nonZeroEntryCount = 0;
other.internalStatus = MatrixStatus::Error;
other.currentSize = 0;
other.columnCount = 0;
other.entryCount = 0;
other.storagePreallocated = false;
other.internalStatus = MatrixStatus::UNINITIALIZED;
other.currentEntryCount = 0;
other.lastRow = 0;
other.lastColumn = 0;
}
template<typename T>
SparseMatrix<T>::SparseMatrix(const SparseMatrix<T> & other)
: rowCount(other.rowCount), colCount(other.colCount), nonZeroEntryCount(other.nonZeroEntryCount),
valueStorage(other.valueStorage), columnIndications(other.columnIndications),
rowIndications(other.rowIndications), internalStatus(other.internalStatus),
currentSize(other.currentSize), lastRow(other.lastRow) {
}
template<typename T>
SparseMatrix<T>::SparseMatrix(uint_fast64_t rowCount, uint_fast64_t colCount, uint_fast64_t nonZeroEntryCount,
std::vector<uint_fast64_t>&& rowIndications,
std::vector<uint_fast64_t>&& columnIndications, std::vector<T>&& values)
: rowCount(rowCount), colCount(colCount), nonZeroEntryCount(nonZeroEntryCount),
valueStorage(values), columnIndications(columnIndications),
rowIndications(rowIndications), internalStatus(MatrixStatus::Initialized),
currentSize(0), lastRow(0) {
SparseMatrix<T>::SparseMatrix(uint_fast64_t columnCount, std::vector<uint_fast64_t>&& rowIndications, std::vector<uint_fast64_t>&& columnIndications, std::vector<T>&& values) : rowCount(rowIndications.size() - 1), columnCount(columnCount), entryCount(values.size()), valueStorage(std::move(values)), columnIndications(std::move(columnIndications)), rowIndications(std::move(rowIndications)), internalStatus(INITIALIZED), currentEntryCount(0), lastRow(0), lastColumn(0) {
// Intentionally left empty.
}
template<typename T>
storm::storage::SparseMatrix<T>& SparseMatrix<T>::operator=(SparseMatrix<T> const& other) {
this->rowCount = other.rowCount;
this->colCount = other.colCount;
this->nonZeroEntryCount = other.nonZeroEntryCount;
SparseMatrix<T>& SparseMatrix<T>::operator=(SparseMatrix<T> const& other) {
// Only perform assignment if source and target are not the same.
if (this != &other) {
rowCount = other.rowCount;
columnCount = other.columnCount;
entryCount = other.entryCount;
this->valueStorage = other.valueStorage;
this->columnIndications = other.columnIndications;
this->rowIndications = other.rowIndications;
valueStorage = other.valueStorage;
columnIndications = other.columnIndications;
rowIndications = other.rowIndications;
this->internalStatus = other.internalStatus;
this->currentSize = other.currentSize;
this->lastRow = other.lastRow;
return *this;
internalStatus = other.internalStatus;
currentEntryCount = other.currentEntryCount;
lastRow = other.lastRow;
lastColumn = other.lastColumn;
}
template<typename T>
void SparseMatrix<T>::initialize(uint_fast64_t nonZeroEntries) {
// Check whether initializing the matrix is safe.
if (internalStatus != MatrixStatus::UnInitialized) {
triggerErrorState();
LOG4CPLUS_ERROR(logger, "Trying to initialize matrix that is not uninitialized.");
throw storm::exceptions::InvalidStateException("Trying to initialize matrix that is not uninitialized.");
} else if ((rowCount * colCount) < nonZeroEntries) {
triggerErrorState();
LOG4CPLUS_ERROR(logger, "Trying to initialize a matrix with more non-zero entries than there can be.");
throw storm::exceptions::InvalidArgumentException("Trying to initialize a matrix with more non-zero entries than there can be.");
} else {
// If it is safe, initialize necessary members and prepare the
// internal storage.
nonZeroEntryCount = nonZeroEntries;
lastRow = 0;
if (!prepareInternalStorage()) {
triggerErrorState();
throw std::bad_alloc();
} else {
setState(MatrixStatus::Initialized);
}
}
return *this;
}
template<typename T>
void SparseMatrix<T>::addNextValue(const uint_fast64_t row, const uint_fast64_t col, T const& value) {
// Check whether the given row and column positions are valid and throw
// error otherwise.
if ((row > rowCount) || (col > colCount)) {
triggerErrorState();
LOG4CPLUS_ERROR(logger, "Trying to add a value at illegal position (" << row << ", " << col << ") in matrix of size (" << rowCount << ", " << colCount << ").");
throw storm::exceptions::OutOfRangeException() << "Trying to add a value at illegal position (" << row << ", " << col << ") in matrix of size (" << rowCount << ", " << colCount << ").";
void SparseMatrix<T>::addNextValue(uint_fast64_t row, uint_fast64_t column, T const& value) {
// Depending on whether the internal data storage was preallocated or not, adding the value is done somewhat
// differently.
if (storagePreallocated) {
// Check whether the given row and column positions are valid and throw error otherwise.
if (row > rowCount || column > columnCount) {
throw storm::exceptions::OutOfRangeException() << "Illegal call to SparseMatrix::addNextValue: adding entry at out-of-bounds position (" << row << ", " << column << ") in matrix of size (" << rowCount << ", " << columnCount << ").";
}
// If we switched to another row, we have to adjust the missing
// entries in the row_indications array.
if (row != lastRow) {
for (uint_fast64_t i = lastRow + 1; i <= row; ++i) {
rowIndications[i] = currentSize;
}
lastRow = row;
}
// Finally, set the element and increase the current size.
valueStorage[currentSize] = value;
columnIndications[currentSize] = col;
++currentSize;
// Check that we did not move backwards wrt. the row.
if (row < lastRow) {
throw storm::exceptions::InvalidArgumentException() << "Illegal call to SparseMatrix::addNextValue: adding an element in row " << row << ", but an element in row " << lastRow << " has already been added." << std::endl;
}
template<typename T>
void SparseMatrix<T>::insertNextValue(const uint_fast64_t row, const uint_fast64_t col, T const& value, bool pushRowIndication) {
// Check whether the given row and column positions are valid and throw
// error otherwise.
if (row < lastRow) {
triggerErrorState();
LOG4CPLUS_ERROR(logger, "Trying to insert a value at illegal position (" << row << ", " << col << ").");
throw storm::exceptions::OutOfRangeException() << "Trying to insert a value at illegal position (" << row << ", " << col << ").";
// Check that we did not move backwards wrt. to column.
if (row == lastRow && column < lastColumn) {
throw storm::exceptions::InvalidArgumentException() << "Illegal call to SparseMatrix::addNextValue: adding an element in column " << column << " in row " << row << ", but an element in column " << lastColumn << " has already been added in that row." << std::endl;
}
// If we switched to another row, we have to adjust the missing entries in the rowIndications array.
// If we switched to another row, we have to adjust the missing entries in the row indices vector.
if (row != lastRow) {
if (storagePreallocated) {
// If the storage was preallocated, we can access the elements in the vectors with the subscript
// operator.
for (uint_fast64_t i = lastRow + 1; i <= row; ++i) {
if (pushRowIndication) {
rowIndications.push_back(currentSize);
rowIndications[i] = currentEntryCount;
}
} else {
rowIndications[i] = currentSize;
// Otherwise, we need to push the correct values to the vectors, which might trigger reallocations.
for (uint_fast64_t i = lastRow + 1; i <= row; ++i) {
rowIndications.push_back(currentEntryCount);
}
}
rowCount = row + 1;
lastRow = row;
}
// Finally, set the element and increase the current size.
valueStorage.push_back(value);
columnIndications.push_back(col);
++nonZeroEntryCount;
++currentSize;
// Check that we also have the correct number of columns.
colCount = std::max(colCount, col + 1);
}
lastColumn = column;
template<typename T>
void SparseMatrix<T>::insertEmptyRow(bool pushRowIndication) {
if (pushRowIndication) {
rowIndications.push_back(currentSize);
// Finally, set the element and increase the current size.
if (storagePreallocated) {
valueStorage[currentEntryCount] = value;
columnIndications[currentEntryCount] = column;
++currentEntryCount;
} else {
rowIndications[lastRow + 1] = currentSize;
valueStorage.push_back(value);
columnIndications.push_back(column);
}
++rowCount;
++lastRow;
}
template<typename T>
void SparseMatrix<T>::finalize(bool pushSentinelElement) {
void SparseMatrix<T>::finalize() {
// Check whether it's safe to finalize the matrix and throw error otherwise.
if (!isInitialized()) {
triggerErrorState();
LOG4CPLUS_ERROR(logger, "Trying to finalize an uninitialized matrix.");
throw storm::exceptions::InvalidStateException("Trying to finalize an uninitialized matrix.");
} else if (currentSize != nonZeroEntryCount) {
triggerErrorState();
LOG4CPLUS_ERROR(logger, "Trying to finalize a matrix that was initialized with more non-zero entries than given (expected " << nonZeroEntryCount << " but got " << currentSize << " instead)");
throw storm::exceptions::InvalidStateException() << "Trying to finalize a matrix that was initialized with more non-zero entries than given (expected " << nonZeroEntryCount << " but got " << currentSize << " instead).";
if (internalStatus == INITIALIZED) {
throw storm::exceptions::InvalidStateException() << "Illegal call to SparseMatrix::finalize: finalizing an initialized matrix is forbidden.";
} else if (storagePreallocated && currentEntryCount != entryCount) {
throw storm::exceptions::InvalidStateException() << "Illegal call to SparseMatrix::finalize: expected " << entryCount << " entries, but got " << currentEntryCount << " instead.";
} else {
// Fill in the missing entries in the row_indications array.
// (Can happen because of empty rows at the end.)
// Fill in the missing entries in the row indices array, as there may be empty rows at the end.
if (storagePreallocated) {
for (uint_fast64_t i = lastRow + 1; i < rowCount; ++i) {
rowIndications[i] = currentSize;
rowIndications[i] = currentEntryCount;
}
// Set a sentinel element at the last position of the row_indications array. This eases iteration work, as
// now the indices of row i are always between rowIndications[i] and rowIndications[i + 1], also for the
// first and last row.
if (pushSentinelElement) {
rowIndications.push_back(nonZeroEntryCount);
} else {
rowIndications[rowCount] = nonZeroEntryCount;
}
setState(MatrixStatus::ReadReady);
}
}
template<typename T>
inline bool SparseMatrix<T>::getValue(uint_fast64_t row, uint_fast64_t col, T* const target) const {
// Check for illegal access indices.
if ((row > rowCount) || (col > colCount)) {
LOG4CPLUS_ERROR(logger, "Trying to read a value from illegal position (" << row << ", " << col << ").");
throw storm::exceptions::OutOfRangeException("Trying to read a value from illegal position.");
return false;
}
// In case the element is not on the diagonal, we have to iterate
// over the accessed row to find the element.
uint_fast64_t rowStart = rowIndications[row];
uint_fast64_t rowEnd = rowIndications[row + 1];
while (rowStart < rowEnd) {
// If the lement is found, write the content to the specified
// position and return true.
if (columnIndications[rowStart] == col) {
*target = valueStorage[rowStart];
return true;
}
// If the column of the current element is already larger than the
// requested column, the requested element cannot be contained
// in the matrix and we may therefore stop searching.
if (columnIndications[rowStart] > col) {
break;
}
++rowStart;
}
// Set 0 as the content and return false in case the element was not found.
*target = 0;
return false;
for (uint_fast64_t i = lastRow + 1; i < rowCount; ++i) {
rowIndications.push_back(currentEntryCount);
}
template<typename T>
inline T& SparseMatrix<T>::getValue(uint_fast64_t row, uint_fast64_t col) {
// Check for illegal access indices.
if ((row > rowCount) || (col > colCount)) {
LOG4CPLUS_ERROR(logger, "Trying to read a value from illegal position (" << row << ", " << col << ").");
throw storm::exceptions::OutOfRangeException("Trying to read a value from illegal position.");
}
// we have to iterate
// over the accessed row to find the element.
uint_fast64_t rowStart = rowIndications[row];
uint_fast64_t rowEnd = rowIndications[row + 1];
while (rowStart < rowEnd) {
// If the lement is found, return it.
if (columnIndications[rowStart] == col) {
return valueStorage[rowStart];
// We put a sentinel element at the last position of the row indices array. This eases iteration work,
// as now the indices of row i are always between rowIndications[i] and rowIndications[i + 1], also for
// the first and last row.
if (storagePreallocated) {
rowIndications[rowCount] = entryCount;
} else {
rowIndications.push_back(entryCount);
}
// If the column of the current element is already larger than the
// requested column, the requested element cannot be contained
// in the matrix and we may therefore stop searching.
if (columnIndications[rowStart] > col) {
break;
internalStatus = INITIALIZED;
}
++rowStart;
}
throw storm::exceptions::InvalidArgumentException("Trying to get a reference to a non-existant value.");
}
template<typename T>
@ -373,86 +245,60 @@ namespace storage {
template<typename T>
uint_fast64_t SparseMatrix<T>::getColumnCount() const {
return colCount;
}
template<typename T>
bool SparseMatrix<T>::isReadReady() {
return (internalStatus == MatrixStatus::ReadReady);
return columnCount;
}
template<typename T>
bool SparseMatrix<T>::isInitialized() {
return (internalStatus == MatrixStatus::Initialized || internalStatus == MatrixStatus::ReadReady);
return internalStatus == INITIALIZED;
}
template<typename T>
typename SparseMatrix<T>::MatrixStatus SparseMatrix<T>::getState() {
return internalStatus;
uint_fast64_t SparseMatrix<T>::getEntryCount() const {
return entryCount;
}
template<typename T>
bool SparseMatrix<T>::hasError() const {
return (internalStatus == MatrixStatus::Error);
}
template<typename T>
uint_fast64_t SparseMatrix<T>::getNonZeroEntryCount() const {
return nonZeroEntryCount;
}
template<typename T>
bool SparseMatrix<T>::makeRowsAbsorbing(storm::storage::BitVector const& rows) {
bool result = true;
void SparseMatrix<T>::makeRowsAbsorbing(storm::storage::BitVector const& rows) {
for (auto row : rows) {
result &= makeRowAbsorbing(row, row);
makeRowAbsorbing(row, row);
}
return result;
}
template<typename T>
bool SparseMatrix<T>::makeRowsAbsorbing(storm::storage::BitVector const& rowGroupConstraint, std::vector<uint_fast64_t> const& rowGroupIndices) {
bool result = true;
void SparseMatrix<T>::makeRowsAbsorbing(storm::storage::BitVector const& rowGroupConstraint, std::vector<uint_fast64_t> const& rowGroupIndices) {
for (auto rowGroup : rowGroupConstraint) {
for (uint_fast64_t row = rowGroupIndices[rowGroup]; row < rowGroupIndices[rowGroup + 1]; ++row) {
result &= makeRowAbsorbing(row, rowGroup);
makeRowAbsorbing(row, rowGroup);
}
}
return result;
}
template<typename T>
bool SparseMatrix<T>::makeRowAbsorbing(const uint_fast64_t row, const uint_fast64_t column) {
// Check whether the accessed state exists.
void SparseMatrix<T>::makeRowAbsorbing(const uint_fast64_t row, const uint_fast64_t column) {
if (row > rowCount) {
LOG4CPLUS_ERROR(logger, "Trying to make an illegal row " << row << " absorbing.");
throw storm::exceptions::OutOfRangeException() << "Trying to make an illegal row " << row << " absorbing.";
return false;
throw storm::exceptions::OutOfRangeException() << "Illegal call to SparseMatrix::makeRowAbsorbing: access to row " << row << " is out of bounds.";
}
// Iterate over the elements in the row that are not on the diagonal
// and set them to zero.
uint_fast64_t rowStart = rowIndications[row];
uint_fast64_t rowEnd = rowIndications[row + 1];
// Iterate over the elements in the row that are not on the diagonal and set them to zero.
T* valuePtr = valueStorage.data() + rowIndications[row];
T* valuePtrEnd = valueStorage.data() + rowIndications[row + 1];
uint_fast64_t* columnPtr = columnIndications.data() + rowIndications[row];
// If the row has no elements in it, we cannot make it absorbing, because we would need to
// move all elements in the vector of nonzeros otherwise.
if (rowStart >= rowEnd) {
LOG4CPLUS_ERROR(logger, "Cannot make row " << row << " absorbing, because there is no entry in this row.");
throw storm::exceptions::InvalidStateException() << "Cannot make row " << row << " absorbing, because there is no entry in this row.";
// If the row has no elements in it, we cannot make it absorbing, because we would need to move all elements
// in the vector of nonzeros otherwise.
if (valuePtr >= valuePtrEnd) {
throw storm::exceptions::InvalidStateException() << "Illegal call to SparseMatrix::makeRowAbsorbing: cannot make row " << row << " absorbing, but there is no entry in this row.";
}
// If there is at least one nonzero entry in this row, we can just set it to one, modify its
// column indication to the one given by the parameter and set all subsequent elements of this
// row to zero.
valueStorage[rowStart] = storm::utility::constantOne<T>();
columnIndications[rowStart] = column;
for (uint_fast64_t index = rowStart + 1; index < rowEnd; ++index) {
valueStorage[index] = storm::utility::constantZero<T>();
columnIndications[index] = 0;
// If there is at least one entry in this row, we can just set it to one, modify its column value to the
// one given by the parameter and set all subsequent elements of this row to zero.
*valuePtr = storm::utility::constantOne<T>();
*columnPtr = column;
for (; valuePtr != valuePtrEnd; ++valuePtr) {
*valuePtr = storm::utility::constantZero<T>();
*columnPtr = 0;
}
return true;
}
template<typename T>

77
src/storage/SparseMatrix.h

@ -154,8 +154,7 @@ namespace storm {
/*!
* This class represents a number of consecutive rows of the matrix.
*/
template<typename ValueType>
class BaseRows {
class rows {
public:
/*!
* Constructs an object that represents the rows defined by the value of the first entry, the column
@ -165,25 +164,25 @@ namespace storm {
* @param columnPtr A pointer to the column of the first entry of the rows.
* @param entryCount The number of entrys in the rows.
*/
Rows(ValueType* valuePtr, uint_fast64_t const* columnPtr, uint_fast64_t entryCount);
rows(T* valuePtr, uint_fast64_t const* columnPtr, uint_fast64_t entryCount);
/*!
* Retrieves an iterator that points to the beginning of the rows.
*
* @return An iterator that points to the beginning of the rows.
*/
BaseIterator<ValueType> begin();
iterator begin();
/*!
* Retrieves an iterator that points past the last entry of the rows.
*
* @return An iterator that points past the last entry of the rows.
*/
BaseIterator<ValueType> end() const;
iterator end();
private:
// The pointer to the value of the first entry.
ValueType* valuePtr;
T* valuePtr;
// The pointer to the column of the first entry.
uint_fast64_t const* columnPtr;
@ -192,8 +191,45 @@ namespace storm {
uint_fast64_t entryCount;
};
typedef BaseRows<T> rows;
typedef BaseRows<T const> const_rows;
/*!
* This class represents a number of consecutive rows of the matrix.
*/
class const_rows {
public:
/*!
* Constructs an object that represents the rows defined by the value of the first entry, the column
* of the first entry and the number of entries in this row set.
*
* @param valuePtr A pointer to the value of the first entry of the rows.
* @param columnPtr A pointer to the column of the first entry of the rows.
* @param entryCount The number of entrys in the rows.
*/
const_rows(T const* valuePtr, uint_fast64_t const* columnPtr, uint_fast64_t entryCount);
/*!
* Retrieves an iterator that points to the beginning of the rows.
*
* @return An iterator that points to the beginning of the rows.
*/
const_iterator begin() const;
/*!
* Retrieves an iterator that points past the last entry of the rows.
*
* @return An iterator that points past the last entry of the rows.
*/
const_iterator end() const;
private:
// The pointer to the value of the first entry.
T const* valuePtr;
// The pointer to the column of the first entry.
uint_fast64_t const* columnPtr;
// The number of non-zero entries in the rows.
uint_fast64_t entryCount;
};
/*!
* An enum representing the internal state of the matrix. After creation, the matrix is UNINITIALIZED.
@ -217,7 +253,7 @@ namespace storm {
* @param size The number of rows and columns of the matrix.
* @param entries The number of entries of the matrix.
*/
SparseMatrix(uint_fast64_t size = 0, uint_fast64_t entries);
SparseMatrix(uint_fast64_t size = 0, uint_fast64_t entries = 0);
/*!
* Constructs a sparse matrix by performing a deep-copy of the given matrix.
@ -236,27 +272,26 @@ namespace storm {
/*!
* Constructs a sparse matrix by moving the given contents.
*
* @param colCount The number of columns of the matrix.
* @param columnCount The number of columns of the matrix.
* @param rowIndications The row indications vector of the matrix to be constructed.
* @param columnIndications The column indications vector of the matrix to be constructed.
* @param values The vector containing the values of the entries in the matrix.
*/
SparseMatrix(uint_fast64_t colCount, std::vector<uint_fast64_t>&& rowIndications,
std::vector<uint_fast64_t>&& columnIndications, std::vector<T>&& values);
SparseMatrix(uint_fast64_t columnCount, std::vector<uint_fast64_t>&& rowIndications, std::vector<uint_fast64_t>&& columnIndications, std::vector<T>&& values);
/*!
* Assigns the contents of the given matrix to the current one by deep-copying its contents.
*
* @param other The matrix from which to copy-assign.
*/
storm::storage::SparseMatrix<T>& operator=(SparseMatrix<T> const& other);
SparseMatrix<T>& operator=(SparseMatrix<T> const& other);
/*!
* Assigns the contents of the given matrix to the current one by moving its contents.
*
* @param other The matrix from which to move to contents.
*/
storm::storage::SparseMatrix<T>& operator=(SparseMatrix<T>&& other);
SparseMatrix<T>& operator=(SparseMatrix<T>&& other);
/*!
* Sets the matrix entry at the given row and column to the given value. After all entries have been added,
@ -268,15 +303,10 @@ namespace storm {
* treated as empty. If these constraints are not met, an exception is thrown.
*
* @param row The row in which the matrix entry is to be set.
* @param col The column in which the matrix entry is to be set.
* @param column The column in which the matrix entry is to be set.
* @param value The value that is to be set at the specified row and column.
*/
void addNextValue(uint_fast64_t row, uint_fast64_t col, T const& value);
/*!
* Inserts an empty row in the matrix.
*/
void insertEmptyRow();
void addNextValue(uint_fast64_t row, uint_fast64_t column, T const& value);
/*
* Finalizes the sparse matrix to indicate that initialization process has been completed and the matrix
@ -631,8 +661,8 @@ namespace storm {
#ifdef STORM_HAVE_INTELTBB
/*!
* This function is a helper for Parallel Execution of the multipliyWithVector functionality.
* It uses Intels TBB parallel_for paradigm to split up the row/vector multiplication and summation
* This function is a helper for the parallel execution of the multipliyWithVector method.
* It uses Intel's TBB parallel_for paradigm to split up the row/vector multiplication and summation.
*/
template <typename M, typename V, typename T>
class tbbHelper_MatrixRowVectorScalarProduct {
@ -645,7 +675,6 @@ namespace storm {
V * resultVector;
V const* vectorX;
M const* matrixA;
};
#endif

Loading…
Cancel
Save