Browse Source

Added SparseMatrixBuilder class that actually builds the matrices. A call to build() will then generate the matrix. This eliminates superfluous checks in the matrix that slowed down performance.

Former-commit-id: af5d946fb8
tempestpy_adaptions
dehnert 11 years ago
parent
commit
81cf0e2b22
  1. 24
      src/adapters/ExplicitModelAdapter.h
  2. 7
      src/modelchecker/prctl/SparseDtmcPrctlModelChecker.h
  3. 8
      src/models/AbstractModel.h
  4. 2
      src/parser/DeterministicModelParser.cpp
  5. 19
      src/parser/DeterministicSparseTransitionParser.cpp
  6. 7
      src/parser/MarkovAutomatonSparseTransitionParser.cpp
  7. 2
      src/parser/MarkovAutomatonSparseTransitionParser.h
  8. 13
      src/parser/NondeterministicSparseTransitionParser.cpp
  9. 395
      src/storage/SparseMatrix.cpp
  10. 186
      src/storage/SparseMatrix.h
  11. 22
      src/utility/graph.h
  12. 10
      src/utility/matrix.h
  13. 757
      test/functional/storage/SparseMatrixTest.cpp
  14. 1
      test/performance/graph/GraphTest.cpp
  15. 16
      test/performance/storage/SparseMatrixTest.cpp

24
src/adapters/ExplicitModelAdapter.h

@ -455,7 +455,7 @@ namespace storm {
* @return A tuple containing a vector with all rows at which the nondeterministic choices of each state begin
* and a vector containing the labels associated with each choice.
*/
static std::pair<std::vector<uint_fast64_t>, std::vector<storm::storage::VectorSet<uint_fast64_t>>> buildMatrices(storm::ir::Program const& program, VariableInformation const& variableInformation, std::vector<storm::ir::TransitionReward> const& transitionRewards, StateInformation& stateInformation, bool deterministicModel, storm::storage::SparseMatrix<ValueType>& transitionMatrix, storm::storage::SparseMatrix<ValueType>& transitionRewardMatrix) {
static std::pair<std::vector<uint_fast64_t>, std::vector<storm::storage::VectorSet<uint_fast64_t>>> buildMatrices(storm::ir::Program const& program, VariableInformation const& variableInformation, std::vector<storm::ir::TransitionReward> const& transitionRewards, StateInformation& stateInformation, bool deterministicModel, storm::storage::SparseMatrixBuilder<ValueType>& transitionMatrixBuilder, storm::storage::SparseMatrixBuilder<ValueType>& transitionRewardMatrixBuilder) {
std::vector<uint_fast64_t> nondeterministicChoiceIndices;
std::vector<storm::storage::VectorSet<uint_fast64_t>> choiceLabels;
@ -480,7 +480,7 @@ namespace storm {
// requested and issue an error otherwise.
if (totalNumberOfChoices == 0) {
if (storm::settings::Settings::getInstance()->isSet("fixDeadlocks")) {
transitionMatrix.addNextValue(currentRow, currentState, storm::utility::constantOne<ValueType>());
transitionMatrixBuilder.addNextValue(currentRow, currentState, storm::utility::constantOne<ValueType>());
++currentRow;
} else {
LOG4CPLUS_ERROR(logger, "Error while creating sparse matrix from probabilistic program: found deadlock state. For fixing these, please provide the appropriate option.");
@ -528,13 +528,13 @@ namespace storm {
choiceLabels.push_back(globalChoice.getChoiceLabels());
for (auto const& stateProbabilityPair : globalChoice) {
transitionMatrix.addNextValue(currentRow, stateProbabilityPair.first, stateProbabilityPair.second);
transitionMatrixBuilder.addNextValue(currentRow, stateProbabilityPair.first, stateProbabilityPair.second);
}
// Add all transition rewards to the matrix and add dummy entry if there is none.
if (stateToRewardMap.size() > 0) {
for (auto const& stateRewardPair : stateToRewardMap) {
transitionRewardMatrix.addNextValue(currentRow, stateRewardPair.first, stateRewardPair.second);
transitionRewardMatrixBuilder.addNextValue(currentRow, stateRewardPair.first, stateRewardPair.second);
}
}
@ -549,7 +549,7 @@ namespace storm {
choiceLabels.emplace_back(std::move(choice.getChoiceLabels()));
for (auto const& stateProbabilityPair : choice) {
transitionMatrix.addNextValue(currentRow, stateProbabilityPair.first, stateProbabilityPair.second);
transitionMatrixBuilder.addNextValue(currentRow, stateProbabilityPair.first, stateProbabilityPair.second);
// Now add all rewards that match this choice.
for (auto const& transitionReward : transitionRewards) {
@ -563,7 +563,7 @@ namespace storm {
// Add all transition rewards to the matrix and add dummy entry if there is none.
if (stateToRewardMap.size() > 0) {
for (auto const& stateRewardPair : stateToRewardMap) {
transitionRewardMatrix.addNextValue(currentRow, stateRewardPair.first, stateRewardPair.second);
transitionRewardMatrixBuilder.addNextValue(currentRow, stateRewardPair.first, stateRewardPair.second);
}
}
@ -576,7 +576,7 @@ namespace storm {
choiceLabels.emplace_back(std::move(choice.getChoiceLabels()));
for (auto const& stateProbabilityPair : choice) {
transitionMatrix.addNextValue(currentRow, stateProbabilityPair.first, stateProbabilityPair.second);
transitionMatrixBuilder.addNextValue(currentRow, stateProbabilityPair.first, stateProbabilityPair.second);
// Now add all rewards that match this choice.
for (auto const& transitionReward : transitionRewards) {
@ -590,7 +590,7 @@ namespace storm {
// Add all transition rewards to the matrix and add dummy entry if there is none.
if (stateToRewardMap.size() > 0) {
for (auto const& stateRewardPair : stateToRewardMap) {
transitionRewardMatrix.addNextValue(currentRow, stateRewardPair.first, stateRewardPair.second);
transitionRewardMatrixBuilder.addNextValue(currentRow, stateRewardPair.first, stateRewardPair.second);
}
}
@ -631,13 +631,15 @@ namespace storm {
bool deterministicModel = program.getModelType() == storm::ir::Program::DTMC || program.getModelType() == storm::ir::Program::CTMC;
// Build the transition and reward matrices.
std::pair<std::vector<uint_fast64_t>, std::vector<storm::storage::VectorSet<uint_fast64_t>>> nondeterministicChoiceIndicesAndChoiceLabelsPair = buildMatrices(program, variableInformation, rewardModel.getTransitionRewards(), stateInformation, deterministicModel, modelComponents.transitionMatrix, modelComponents.transitionRewardMatrix);
storm::storage::SparseMatrixBuilder<ValueType> transitionMatrixBuilder;
storm::storage::SparseMatrixBuilder<ValueType> transitionRewardMatrixBuilder;
std::pair<std::vector<uint_fast64_t>, std::vector<storm::storage::VectorSet<uint_fast64_t>>> nondeterministicChoiceIndicesAndChoiceLabelsPair = buildMatrices(program, variableInformation, rewardModel.getTransitionRewards(), stateInformation, deterministicModel, transitionMatrixBuilder, transitionRewardMatrixBuilder);
modelComponents.nondeterministicChoiceIndices = std::move(nondeterministicChoiceIndicesAndChoiceLabelsPair.first);
modelComponents.choiceLabeling = std::move(nondeterministicChoiceIndicesAndChoiceLabelsPair.second);
// Finalize the resulting matrices.
modelComponents.transitionMatrix.finalize();
modelComponents.transitionRewardMatrix.finalize(modelComponents.transitionMatrix.getRowCount());
modelComponents.transitionMatrix = transitionMatrixBuilder.build();
modelComponents.transitionRewardMatrix = transitionRewardMatrixBuilder.build(modelComponents.transitionMatrix.getRowCount());
// Now build the state labeling.
modelComponents.stateLabeling = buildStateLabeling(program, variableInformation, stateInformation);

7
src/modelchecker/prctl/SparseDtmcPrctlModelChecker.h

@ -90,7 +90,6 @@ public:
return this->checkBoundedUntil(formula.getLeft().check(*this), formula.getRight().check(*this), formula.getBound(), qualitative);
}
/*!
* Computes the probability to satisfy phi until psi inside a given bound for each state in the model.
*
@ -108,7 +107,7 @@ public:
// If we identify the states that have probability 0 of reaching the target states, we can exclude them in the
// further analysis.
storm::storage::BitVector statesWithProbabilityGreater0 = storm::utility::graph::performProbGreater0(this->getModel(), phiStates, psiStates, true, stepBound);
storm::storage::BitVector statesWithProbabilityGreater0 = storm::utility::graph::performProbGreater0(this->getModel(), this->getModel().getBackwardTransitions(), phiStates, psiStates, true, stepBound);
LOG4CPLUS_INFO(logger, "Found " << statesWithProbabilityGreater0.getNumberOfSetBits() << " 'maybe' states.");
// Check if we already know the result (i.e. probability 0) for all initial states and
@ -264,9 +263,7 @@ public:
// We need to identify the states which have to be taken out of the matrix, i.e.
// all states that have probability 0 and 1 of satisfying the until-formula.
LOG4CPLUS_INFO(logger, "Running Prob01.");
std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 = storm::utility::graph::performProb01(this->getModel(), phiStates, psiStates);
LOG4CPLUS_INFO(logger, "Done running Prob01.");
storm::storage::BitVector statesWithProbability0 = std::move(statesWithProbability01.first);
storm::storage::BitVector statesWithProbability1 = std::move(statesWithProbability01.second);
@ -427,7 +424,7 @@ public:
// Determine which states have a reward of infinity by definition.
storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true);
storm::storage::BitVector infinityStates = storm::utility::graph::performProb1(this->getModel(), trueStates, targetStates);
storm::storage::BitVector infinityStates = storm::utility::graph::performProb1(this->getModel(), this->getModel().getBackwardTransitions(), trueStates, targetStates);
infinityStates.complement();
storm::storage::BitVector maybeStates = ~targetStates & ~infinityStates;
LOG4CPLUS_INFO(logger, "Found " << infinityStates.getNumberOfSetBits() << " 'infinity' states.");

8
src/models/AbstractModel.h

@ -160,7 +160,7 @@ class AbstractModel: public std::enable_shared_from_this<AbstractModel<T>> {
}
// The resulting sparse matrix will have as many rows/columns as there are blocks in the partition.
storm::storage::SparseMatrix<T> dependencyGraph(numberOfStates, numberOfStates);
storm::storage::SparseMatrixBuilder<T> dependencyGraphBuilder(numberOfStates, numberOfStates);
for (uint_fast64_t currentBlockIndex = 0; currentBlockIndex < decomposition.size(); ++currentBlockIndex) {
// Get the next block.
@ -181,13 +181,11 @@ class AbstractModel: public std::enable_shared_from_this<AbstractModel<T>> {
// Now we can just enumerate all the target SCCs and insert the corresponding transitions.
for (auto targetBlock : allTargetBlocks) {
dependencyGraph.addNextValue(currentBlockIndex, targetBlock, storm::utility::constantOne<T>());
dependencyGraphBuilder.addNextValue(currentBlockIndex, targetBlock, storm::utility::constantOne<T>());
}
}
// Finalize the matrix and return result.
dependencyGraph.finalize(true);
return dependencyGraph;
return dependencyGraphBuilder.build();
}
/*!

2
src/parser/DeterministicModelParser.cpp

@ -28,10 +28,10 @@ namespace parser {
*/
DeterministicModelParserResultContainer<double> parseDeterministicModel(std::string const & transitionSystemFile, std::string const & labelingFile,
std::string const & stateRewardFile, std::string const & transitionRewardFile) {
storm::storage::SparseMatrix<double> resultTransitionSystem(std::move(storm::parser::DeterministicSparseTransitionParser(transitionSystemFile)));
uint_fast64_t stateCount = resultTransitionSystem.getColumnCount();
uint_fast64_t rowCount = resultTransitionSystem.getRowCount();
storm::models::AtomicPropositionsLabeling resultLabeling(std::move(storm::parser::AtomicPropositionLabelingParser(stateCount, labelingFile)));

19
src/parser/DeterministicSparseTransitionParser.cpp

@ -201,7 +201,7 @@ storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser(std::st
* The number of non-zero elements is computed by firstPass().
*/
LOG4CPLUS_INFO(logger, "Attempting to create matrix of size " << (maxStateId+1) << " x " << (maxStateId+1) << ".");
storm::storage::SparseMatrix<double> resultMatrix(maxStateId + 1, maxStateId + 1, nonZeroEntryCount);
storm::storage::SparseMatrixBuilder<double> matrixBuilder(maxStateId + 1, maxStateId + 1, nonZeroEntryCount);
int_fast64_t row, lastRow = -1, col;
double val;
@ -225,7 +225,7 @@ storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser(std::st
if (lastRow != row) {
if ((lastRow != -1) && (!rowHadDiagonalEntry)) {
if (insertDiagonalEntriesIfMissing && !isRewardMatrix) {
resultMatrix.addNextValue(lastRow, lastRow, storm::utility::constantZero<double>());
matrixBuilder.addNextValue(lastRow, lastRow, storm::utility::constantZero<double>());
// LOG4CPLUS_DEBUG(logger, "While parsing " << filename << ": state " << lastRow << " has no transition to itself. Inserted a 0-transition. (1)");
} else if (!isRewardMatrix) {
// LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": state " << lastRow << " has no transition to itself.");
@ -236,7 +236,7 @@ storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser(std::st
for (int_fast64_t skippedRow = lastRow + 1; skippedRow < row; ++skippedRow) {
hadDeadlocks = true;
if (fixDeadlocks && !isRewardMatrix) {
resultMatrix.addNextValue(skippedRow, skippedRow, storm::utility::constantOne<double>());
matrixBuilder.addNextValue(skippedRow, skippedRow, storm::utility::constantOne<double>());
rowHadDiagonalEntry = true;
// LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": state " << skippedRow << " has no outgoing transitions. A self-loop was inserted.");
} else if (!isRewardMatrix) {
@ -253,20 +253,20 @@ storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser(std::st
} else if (col > row && !rowHadDiagonalEntry) {
rowHadDiagonalEntry = true;
if (insertDiagonalEntriesIfMissing && !isRewardMatrix) {
resultMatrix.addNextValue(row, row, storm::utility::constantZero<double>());
matrixBuilder.addNextValue(row, row, storm::utility::constantZero<double>());
// LOG4CPLUS_DEBUG(logger, "While parsing " << filename << ": state " << row << " has no transition to itself. Inserted a 0-transition. (2)");
} else if (!isRewardMatrix) {
// LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": state " << row << " has no transition to itself.");
}
}
resultMatrix.addNextValue(row, col, val);
matrixBuilder.addNextValue(row, col, val);
buf = trimWhitespaces(buf);
}
if (!rowHadDiagonalEntry) {
if (insertDiagonalEntriesIfMissing && !isRewardMatrix) {
resultMatrix.addNextValue(lastRow, lastRow, storm::utility::constantZero<double>());
matrixBuilder.addNextValue(lastRow, lastRow, storm::utility::constantZero<double>());
// LOG4CPLUS_DEBUG(logger, "While parsing " << filename << ": state " << lastRow << " has no transition to itself. Inserted a 0-transition. (3)");
} else if (!isRewardMatrix) {
// LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": state " << lastRow << " has no transition to itself.");
@ -275,12 +275,7 @@ storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser(std::st
if (!fixDeadlocks && hadDeadlocks) throw storm::exceptions::WrongFormatException() << "Some of the nodes had deadlocks. You can use --fixDeadlocks to insert self-loops on the fly.";
/*
* Finalize Matrix.
*/
resultMatrix.finalize();
return resultMatrix;
return matrixBuilder.build();
}
} // namespace parser

7
src/parser/MarkovAutomatonSparseTransitionParser.cpp

@ -139,6 +139,7 @@ namespace storm {
MarkovAutomatonSparseTransitionParser::ResultType MarkovAutomatonSparseTransitionParser::secondPass(char* buf, SupportedLineEndingsEnum lineEndings, FirstPassResult const& firstPassResult) {
ResultType result(firstPassResult);
storm::storage::SparseMatrixBuilder<double> matrixBuilder(firstPassResult.numberOfChoices, firstPassResult.highestStateIndex + 1, firstPassResult.numberOfNonzeroEntries);
bool fixDeadlocks = storm::settings::Settings::getInstance()->isSet("fixDeadlocks");
@ -159,7 +160,7 @@ namespace storm {
if (fixDeadlocks) {
for (uint_fast64_t index = lastsource + 1; index < source; ++index) {
result.nondeterministicChoiceIndices[index] = currentChoice;
result.transitionMatrix.addNextValue(currentChoice, index, 1);
matrixBuilder.addNextValue(currentChoice, index, 1);
++currentChoice;
}
} else {
@ -218,7 +219,7 @@ namespace storm {
double val = checked_strtod(buf, &buf);
// Record the value as well as the exit rate in case of a Markovian choice.
result.transitionMatrix.addNextValue(currentChoice, target, val);
matrixBuilder.addNextValue(currentChoice, target, val);
if (isMarkovianChoice) {
result.exitRates[source] += val;
}
@ -235,7 +236,7 @@ namespace storm {
}
// As we have added all entries at this point, we need to finalize the matrix.
result.transitionMatrix.finalize();
result.transitionMatrix = matrixBuilder.build();
// Put a sentinel element at the end.
result.nondeterministicChoiceIndices[firstPassResult.highestStateIndex + 1] = currentChoice;

2
src/parser/MarkovAutomatonSparseTransitionParser.h

@ -39,7 +39,7 @@ namespace storm {
*/
struct ResultType {
ResultType(FirstPassResult const& firstPassResult) : transitionMatrix(firstPassResult.numberOfChoices, firstPassResult.highestStateIndex + 1, firstPassResult.numberOfNonzeroEntries), nondeterministicChoiceIndices(firstPassResult.highestStateIndex + 2), markovianChoices(firstPassResult.numberOfChoices), markovianStates(firstPassResult.highestStateIndex + 1), exitRates(firstPassResult.highestStateIndex + 1) {
ResultType(FirstPassResult const& firstPassResult) : transitionMatrix(), nondeterministicChoiceIndices(firstPassResult.highestStateIndex + 2), markovianChoices(firstPassResult.numberOfChoices), markovianStates(firstPassResult.highestStateIndex + 1), exitRates(firstPassResult.highestStateIndex + 1) {
// Intentionally left empty.
}

13
src/parser/NondeterministicSparseTransitionParser.cpp

@ -264,7 +264,7 @@ NondeterministicSparseTransitionParserResult_t NondeterministicSparseTransitionP
* Those two values, as well as the number of nonzero elements, was been calculated in the first run.
*/
LOG4CPLUS_INFO(logger, "Attempting to create matrix of size " << choices << " x " << (maxnode+1) << " with " << nonzero << " entries.");
storm::storage::SparseMatrix<double> matrix(choices, maxnode + 1, nonzero);
storm::storage::SparseMatrixBuilder<double> matrixBuilder(choices, maxnode + 1, nonzero);
/*
* Create row mapping.
@ -325,7 +325,7 @@ NondeterministicSparseTransitionParserResult_t NondeterministicSparseTransitionP
hadDeadlocks = true;
if (fixDeadlocks) {
rowMapping.at(node) = curRow;
matrix.addNextValue(curRow, node, 1);
matrixBuilder.addNextValue(curRow, node, 1);
++curRow;
LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": node " << node << " has no outgoing transitions. A self-loop was inserted.");
} else {
@ -343,7 +343,7 @@ NondeterministicSparseTransitionParserResult_t NondeterministicSparseTransitionP
// Read target and value and write it to the matrix.
target = checked_strtol(buf, &buf);
val = checked_strtod(buf, &buf);
matrix.addNextValue(curRow, target, val);
matrixBuilder.addNextValue(curRow, target, val);
lastsource = source;
lastchoice = choice;
@ -379,12 +379,7 @@ NondeterministicSparseTransitionParserResult_t NondeterministicSparseTransitionP
if (!fixDeadlocks && hadDeadlocks && !isRewardFile) throw storm::exceptions::WrongFormatException() << "Some of the nodes had deadlocks. You can use --fixDeadlocks to insert self-loops on the fly.";
/*
* Finalize matrix.
*/
matrix.finalize();
return std::make_pair(std::move(matrix), std::move(rowMapping));
return std::make_pair(matrixBuilder.build(), std::move(rowMapping));
}
} // namespace parser

395
src/storage/SparseMatrix.cpp

@ -10,6 +10,127 @@ extern log4cplus::Logger logger;
namespace storm {
namespace storage {
template<typename T>
SparseMatrixBuilder<T>::SparseMatrixBuilder(uint_fast64_t rows, uint_fast64_t columns, uint_fast64_t entries) : rowCountSet(rows != 0), rowCount(rows), columnCountSet(columns != 0), columnCount(columns), entryCount(entries), storagePreallocated(rows != 0 && columns != 0 && entries != 0), columnsAndValues(), rowIndications(), currentEntryCount(0), lastRow(0), lastColumn(0) {
this->prepareInternalStorage();
}
template<typename T>
void SparseMatrixBuilder<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 SparseMatrixBuilder::addNextValue: adding entry at out-of-bounds position (" << row << ", " << column << ") in matrix of size (" << rowCount << ", " << columnCount << ").";
}
} else {
if (rowCountSet) {
if (row >= rowCount) {
throw storm::exceptions::OutOfRangeException() << "Illegal call to SparseMatrixBuilder::addNextValue: adding entry at out-of-bounds row " << row << " in matrix with " << rowCount << " rows.";
}
}
if (columnCountSet) {
if (column >= columnCount) {
throw storm::exceptions::OutOfRangeException() << "Illegal call to SparseMatrixBuilder::addNextValue: adding entry at out-of-bounds column " << column << " in matrix with " << columnCount << " columns.";
}
}
}
// Check that we did not move backwards wrt. the row.
if (row < lastRow) {
throw storm::exceptions::InvalidArgumentException() << "Illegal call to SparseMatrixBuilder::addNextValue: adding an element in row " << row << ", but an element in row " << lastRow << " has already been added.";
}
// Check that we did not move backwards wrt. to column.
if (row == lastRow && column < lastColumn) {
throw storm::exceptions::InvalidArgumentException() << "Illegal call to SparseMatrixBuilder::addNextValue: adding an element in column " << column << " in row " << row << ", but an element in column " << lastColumn << " has already been added in that row.";
}
// 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) {
rowIndications[i] = currentEntryCount;
}
} else {
// 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);
}
}
lastRow = row;
}
lastColumn = column;
// Finally, set the element and increase the current size.
if (storagePreallocated) {
columnsAndValues[currentEntryCount] = std::make_pair(column, value);
} else {
columnsAndValues.emplace_back(column, value);
if (!columnCountSet) {
columnCount = column + 1;
}
if (!rowCountSet) {
rowCount = row + 1;
}
}
++currentEntryCount;
}
template<typename T>
SparseMatrix<T> SparseMatrixBuilder<T>::build(uint_fast64_t overriddenRowCount, uint_fast64_t overriddenColumnCount) {
// Check whether it's safe to finalize the matrix and throw error otherwise.
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 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] = currentEntryCount;
}
} else {
if (!rowCountSet) {
rowCount = std::max(overriddenRowCount, rowCount);
}
for (uint_fast64_t i = lastRow + 1; i < rowCount; ++i) {
rowIndications.push_back(currentEntryCount);
}
}
// 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] = currentEntryCount;
} else {
rowIndications.push_back(currentEntryCount);
if (!columnCountSet) {
columnCount = std::max(columnCount, overriddenColumnCount);
}
}
entryCount = currentEntryCount;
}
return SparseMatrix<T>(columnCount, std::move(rowIndications), std::move(columnsAndValues));
}
template<typename T>
void SparseMatrixBuilder<T>::prepareInternalStorage() {
// Only allocate the memory if the dimensions of the matrix are already known.
if (storagePreallocated) {
columnsAndValues = std::vector<std::pair<uint_fast64_t, T>>(entryCount, std::make_pair(0, storm::utility::constantZero<T>()));
rowIndications = std::vector<uint_fast64_t>(rowCount + 1, 0);
} else {
rowIndications.push_back(0);
}
}
template<typename T>
SparseMatrix<T>::rows::rows(iterator begin, uint_fast64_t entryCount) : beginIterator(begin), entryCount(entryCount) {
// Intentionally left empty.
@ -41,37 +162,30 @@ namespace storm {
}
template<typename T>
SparseMatrix<T>::SparseMatrix(uint_fast64_t rows, uint_fast64_t columns, uint_fast64_t entries) : rowCountSet(rows != 0), rowCount(rows), columnCountSet(columns != 0), columnCount(columns), entryCount(entries), storagePreallocated(rows != 0 && columns != 0 && entries != 0), columnsAndValues(), rowIndications(), internalStatus(UNINITIALIZED), currentEntryCount(0), lastRow(0), lastColumn(0) {
prepareInternalStorage();
SparseMatrix<T>::SparseMatrix() : rowCount(0), columnCount(0), entryCount(0), columnsAndValues(), rowIndications() {
// Intentionally left empty.
}
template<typename T>
SparseMatrix<T>::SparseMatrix(SparseMatrix<T> const& other) : rowCountSet(other.rowCountSet), rowCount(other.rowCount), columnCountSet(other.columnCountSet), columnCount(other.columnCount), entryCount(other.entryCount), storagePreallocated(other.storagePreallocated), columnsAndValues(other.columnsAndValues), rowIndications(other.rowIndications), internalStatus(other.internalStatus), currentEntryCount(other.currentEntryCount), lastRow(other.lastRow), lastColumn(other.lastColumn) {
SparseMatrix<T>::SparseMatrix(SparseMatrix<T> const& other) : rowCount(other.rowCount), columnCount(other.columnCount), entryCount(other.entryCount), columnsAndValues(other.columnsAndValues), rowIndications(other.rowIndications) {
// Intentionally left empty.
}
template<typename T>
SparseMatrix<T>::SparseMatrix(SparseMatrix<T>&& other) : rowCountSet(other.rowCountSet), rowCount(other.rowCount), columnCountSet(other.columnCountSet), columnCount(other.columnCount), entryCount(other.entryCount), storagePreallocated(other.storagePreallocated), columnsAndValues(std::move(other.columnsAndValues)), rowIndications(std::move(other.rowIndications)), internalStatus(other.internalStatus), currentEntryCount(other.currentEntryCount), lastRow(other.lastRow), lastColumn(other.lastColumn) {
SparseMatrix<T>::SparseMatrix(SparseMatrix<T>&& other) : rowCount(other.rowCount), columnCount(other.columnCount), entryCount(other.entryCount), columnsAndValues(std::move(other.columnsAndValues)), rowIndications(std::move(other.rowIndications)) {
// Now update the source matrix
other.rowCountSet = false;
other.rowCount = 0;
other.columnCountSet = false;
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(uint_fast64_t columnCount, std::vector<uint_fast64_t> const& rowIndications, std::vector<std::pair<uint_fast64_t, T>> const& columnsAndValues) : rowCount(rowIndications.size() - 1), columnCount(columnCount), entryCount(columnsAndValues.size()), storagePreallocated(true), columnsAndValues(columnsAndValues), rowIndications(rowIndications), internalStatus(INITIALIZED), currentEntryCount(0), lastRow(0), lastColumn(0) {
SparseMatrix<T>::SparseMatrix(uint_fast64_t columnCount, std::vector<uint_fast64_t> const& rowIndications, std::vector<std::pair<uint_fast64_t, T>> const& columnsAndValues) : rowCount(rowIndications.size() - 1), columnCount(columnCount), entryCount(columnsAndValues.size()), columnsAndValues(columnsAndValues), rowIndications(rowIndications) {
// Intentionally left empty.
}
template<typename T>
SparseMatrix<T>::SparseMatrix(uint_fast64_t columnCount, std::vector<uint_fast64_t> const& rowIndications, std::vector<uint_fast64_t> const& columnIndications, std::vector<T> const& values) : rowCount(rowIndications.size() - 1), columnCount(columnCount), entryCount(values.size()), storagePreallocated(true), columnsAndValues(), rowIndications(rowIndications), internalStatus(INITIALIZED), currentEntryCount(0), lastRow(0), lastColumn(0) {
SparseMatrix<T>::SparseMatrix(uint_fast64_t columnCount, std::vector<uint_fast64_t> const& rowIndications, std::vector<uint_fast64_t> const& columnIndications, std::vector<T> const& values) : rowCount(rowIndications.size() - 1), columnCount(columnCount), entryCount(values.size()), columnsAndValues(), rowIndications(rowIndications) {
if (columnIndications.size() != values.size()) {
throw storm::exceptions::InvalidArgumentException() << "Illegal call to SparseMatrix::SparseMatrix: value and column vector length mismatch.";
}
@ -87,12 +201,12 @@ namespace storm {
}
template<typename T>
SparseMatrix<T>::SparseMatrix(uint_fast64_t columnCount, std::vector<uint_fast64_t>&& rowIndications, std::vector<std::pair<uint_fast64_t, T>>&& columnsAndValues) : rowCount(rowIndications.size() - 1), columnCount(columnCount), entryCount(columnsAndValues.size()), storagePreallocated(true), columnsAndValues(std::move(columnsAndValues)), rowIndications(std::move(rowIndications)), internalStatus(INITIALIZED), currentEntryCount(0), lastRow(0), lastColumn(0) {
SparseMatrix<T>::SparseMatrix(uint_fast64_t columnCount, std::vector<uint_fast64_t>&& rowIndications, std::vector<std::pair<uint_fast64_t, T>>&& columnsAndValues) : rowCount(rowIndications.size() - 1), columnCount(columnCount), entryCount(columnsAndValues.size()), columnsAndValues(std::move(columnsAndValues)), rowIndications(std::move(rowIndications)) {
// Intentionally left empty.
}
template<typename T>
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()), columnsAndValues(), rowIndications(std::move(rowIndications)), internalStatus(INITIALIZED), currentEntryCount(0), lastRow(0), lastColumn(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()), columnsAndValues(), rowIndications(std::move(rowIndications)) {
if (columnIndications.size() != values.size()) {
throw storm::exceptions::InvalidArgumentException() << "Illegal call to SparseMatrix::SparseMatrix: value and column vector length mismatch.";
}
@ -111,19 +225,12 @@ namespace storm {
SparseMatrix<T>& SparseMatrix<T>::operator=(SparseMatrix<T> const& other) {
// Only perform assignment if source and target are not the same.
if (this != &other) {
rowCountSet = other.rowCountSet;
rowCount = other.rowCount;
columnCountSet = other.columnCountSet;
columnCount = other.columnCount;
entryCount = other.entryCount;
columnsAndValues = other.columnsAndValues;
rowIndications = other.rowIndications;
internalStatus = other.internalStatus;
currentEntryCount = other.currentEntryCount;
lastRow = other.lastRow;
lastColumn = other.lastColumn;
}
return *this;
@ -133,19 +240,12 @@ namespace storm {
SparseMatrix<T>& SparseMatrix<T>::operator=(SparseMatrix<T>&& other) {
// Only perform assignment if source and target are not the same.
if (this != &other) {
rowCountSet = other.rowCountSet;
rowCount = other.rowCount;
columnCountSet = other.columnCountSet;
columnCount = other.columnCount;
entryCount = other.entryCount;
columnsAndValues = std::move(other.columnsAndValues);
rowIndications = std::move(other.rowIndications);
internalStatus = other.internalStatus;
currentEntryCount = other.currentEntryCount;
lastRow = other.lastRow;
lastColumn = other.lastColumn;
}
return *this;
@ -157,22 +257,8 @@ namespace storm {
return true;
}
if (this->isInitialized() != other.isInitialized()) {
return false;
}
bool equalityResult = true;
// If the matrix is initialized, we only care about the contents and not the auxiliary members.
if (!this->isInitialized()) {
equalityResult &= rowCountSet == other.rowCountSet;
equalityResult &= columnCountSet == other.columnCountSet;
equalityResult &= internalStatus == other.internalStatus;
equalityResult &= currentEntryCount == other.currentEntryCount;
equalityResult &= lastRow == other.lastRow;
equalityResult &= lastColumn == other.lastColumn;
}
equalityResult &= rowCount == other.rowCount;
equalityResult &= columnCount == other.columnCount;
@ -202,141 +288,23 @@ namespace storm {
return equalityResult;
}
template<typename T>
void SparseMatrix<T>::addNextValue(uint_fast64_t row, uint_fast64_t column, T const& value) {
if (this->isInitialized()) {
throw storm::exceptions::InvalidStateException() << "Illegal call to SparseMatrix::addNextValue: adding an entry to an already initialized matrix.";
}
// 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 << ").";
}
} else {
if (rowCountSet) {
if (row >= rowCount) {
throw storm::exceptions::OutOfRangeException() << "Illegal call to SparseMatrix::addNextValue: adding entry at out-of-bounds row " << row << " in matrix with " << rowCount << " rows.";
}
}
if (columnCountSet) {
if (column >= columnCount) {
throw storm::exceptions::OutOfRangeException() << "Illegal call to SparseMatrix::addNextValue: adding entry at out-of-bounds column " << column << " in matrix with " << columnCount << " columns.";
}
}
}
// 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.";
}
// 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.";
}
// 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) {
rowIndications[i] = currentEntryCount;
}
} else {
// 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);
}
}
lastRow = row;
}
lastColumn = column;
// Finally, set the element and increase the current size.
if (storagePreallocated) {
columnsAndValues[currentEntryCount] = std::make_pair(column, value);
} else {
columnsAndValues.emplace_back(column, value);
if (!columnCountSet) {
columnCount = column + 1;
}
if (!rowCountSet) {
rowCount = row + 1;
}
}
++currentEntryCount;
}
template<typename T>
void SparseMatrix<T>::finalize(uint_fast64_t overriddenRowCount, uint_fast64_t overridenColumnCount) {
// Check whether it's safe to finalize the matrix and throw error otherwise.
if (this->isInitialized()) {
throw storm::exceptions::InvalidStateException() << "Illegal call to SparseMatrix::finalize: matrix has already been initialized.";
} 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 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] = currentEntryCount;
}
} else {
if (!rowCountSet) {
rowCount = std::max(overriddenRowCount, rowCount);
}
for (uint_fast64_t i = lastRow + 1; i < rowCount; ++i) {
rowIndications.push_back(currentEntryCount);
}
}
// 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] = currentEntryCount;
} else {
rowIndications.push_back(currentEntryCount);
if (!columnCountSet) {
columnCount = std::max(columnCount, overridenColumnCount);
}
}
entryCount = currentEntryCount;
internalStatus = INITIALIZED;
}
}
template<typename T>
uint_fast64_t SparseMatrix<T>::getRowCount() const {
checkReady("getRowCount");
return rowCount;
}
template<typename T>
uint_fast64_t SparseMatrix<T>::getColumnCount() const {
checkReady("getColumnCount");
return columnCount;
}
template<typename T>
bool SparseMatrix<T>::isInitialized() const {
return internalStatus == INITIALIZED;
}
template<typename T>
uint_fast64_t SparseMatrix<T>::getEntryCount() const {
checkReady("getEntryCount");
return entryCount;
}
template<typename T>
void SparseMatrix<T>::makeRowsAbsorbing(storm::storage::BitVector const& rows) {
checkReady("makeRowsAbsorbing");
for (auto row : rows) {
makeRowAbsorbing(row, row);
}
@ -344,7 +312,6 @@ namespace storm {
template<typename T>
void SparseMatrix<T>::makeRowsAbsorbing(storm::storage::BitVector const& rowGroupConstraint, std::vector<uint_fast64_t> const& rowGroupIndices) {
checkReady("makeRowsAbsorbing");
for (auto rowGroup : rowGroupConstraint) {
for (uint_fast64_t row = rowGroupIndices[rowGroup]; row < rowGroupIndices[rowGroup + 1]; ++row) {
makeRowAbsorbing(row, rowGroup);
@ -354,7 +321,6 @@ namespace storm {
template<typename T>
void SparseMatrix<T>::makeRowAbsorbing(uint_fast64_t row, uint_fast64_t column) {
checkReady("makeRowAbsorbing");
if (row > rowCount) {
throw storm::exceptions::OutOfRangeException() << "Illegal call to SparseMatrix::makeRowAbsorbing: access to row " << row << " is out of bounds.";
}
@ -381,7 +347,6 @@ namespace storm {
template<typename T>
T SparseMatrix<T>::getConstrainedRowSum(uint_fast64_t row, storm::storage::BitVector const& constraint) const {
checkReady("getConstrainedRowSum");
T result(0);
for (const_iterator it = this->begin(row), ite = this->end(row); it != ite; ++it) {
if (constraint.get(it->first)) {
@ -393,7 +358,6 @@ namespace storm {
template<typename T>
std::vector<T> SparseMatrix<T>::getConstrainedRowSumVector(storm::storage::BitVector const& rowConstraint, storm::storage::BitVector const& columnConstraint) const {
checkReady("getConstrainedRowSumVector");
std::vector<T> result(rowConstraint.getNumberOfSetBits());
uint_fast64_t currentRowCount = 0;
for (auto row : rowConstraint) {
@ -404,7 +368,6 @@ namespace storm {
template<typename T>
std::vector<T> SparseMatrix<T>::getConstrainedRowSumVector(storm::storage::BitVector const& rowGroupConstraint, std::vector<uint_fast64_t> const& rowGroupIndices, storm::storage::BitVector const& columnConstraint) const {
checkReady("getConstrainedRowSumVector");
std::vector<T> result;
result.reserve(rowGroupConstraint.getNumberOfSetBits());
for (auto rowGroup : rowGroupConstraint) {
@ -433,7 +396,6 @@ namespace storm {
template<typename T>
SparseMatrix<T> SparseMatrix<T>::getSubmatrix(storm::storage::BitVector const& rowGroupConstraint, storm::storage::BitVector const& columnConstraint, std::vector<uint_fast64_t> const& rowGroupIndices, bool insertDiagonalEntries) const {
checkReady("getSubmatrix");
// First, we need to determine the number of entries and the number of rows of the submatrix.
uint_fast64_t subEntries = 0;
uint_fast64_t subRows = 0;
@ -460,7 +422,7 @@ namespace storm {
}
// Create and initialize resulting matrix.
SparseMatrix result(subRows, columnConstraint.getNumberOfSetBits(), subEntries);
SparseMatrixBuilder<T> matrixBuilder(subRows, columnConstraint.getNumberOfSetBits(), subEntries);
// Create a temporary vector that stores for each index whose bit is set to true the number of bits that
// were set before that particular index.
@ -496,27 +458,25 @@ namespace storm {
if (index == it->first) {
insertedDiagonalElement = true;
} else if (insertDiagonalEntries && !insertedDiagonalElement && it->first > index) {
result.addNextValue(rowCount, bitsSetBeforeIndex[index], storm::utility::constantZero<T>());
matrixBuilder.addNextValue(rowCount, bitsSetBeforeIndex[index], storm::utility::constantZero<T>());
insertedDiagonalElement = true;
}
result.addNextValue(rowCount, bitsSetBeforeIndex[it->first], it->second);
matrixBuilder.addNextValue(rowCount, bitsSetBeforeIndex[it->first], it->second);
}
}
if (insertDiagonalEntries && !insertedDiagonalElement) {
result.addNextValue(rowCount, bitsSetBeforeIndex[index], storm::utility::constantZero<T>());
matrixBuilder.addNextValue(rowCount, bitsSetBeforeIndex[index], storm::utility::constantZero<T>());
}
++rowCount;
}
}
result.finalize();
return result;
return matrixBuilder.build();
}
template<typename T>
SparseMatrix<T> SparseMatrix<T>::getSubmatrix(std::vector<uint_fast64_t> const& rowGroupToRowIndexMapping, std::vector<uint_fast64_t> const& rowGroupIndices, bool insertDiagonalEntries) const {
checkReady("getSubmatrix");
// First, we need to count how many non-zero entries the resulting matrix will have and reserve space for
// diagonal entries if requested.
uint_fast64_t subEntries = 0;
@ -538,7 +498,7 @@ namespace storm {
}
// Now create the matrix to be returned with the appropriate size.
SparseMatrix<T> submatrix(rowGroupIndices.size() - 1, columnCount, subEntries);
SparseMatrixBuilder<T> matrixBuilder(rowGroupIndices.size() - 1, columnCount, subEntries);
// Copy over the selected lines from the source matrix.
for (uint_fast64_t rowGroupIndex = 0, rowGroupIndexEnd = rowGroupToRowIndexMapping.size(); rowGroupIndex < rowGroupIndexEnd; ++rowGroupIndex) {
@ -552,25 +512,22 @@ namespace storm {
if (it->first == rowGroupIndex) {
insertedDiagonalElement = true;
} else if (insertDiagonalEntries && !insertedDiagonalElement && it->first > rowGroupIndex) {
submatrix.addNextValue(rowGroupIndex, rowGroupIndex, storm::utility::constantZero<T>());
matrixBuilder.addNextValue(rowGroupIndex, rowGroupIndex, storm::utility::constantZero<T>());
insertedDiagonalElement = true;
}
submatrix.addNextValue(rowGroupIndex, it->first, it->second);
matrixBuilder.addNextValue(rowGroupIndex, it->first, it->second);
}
if (insertDiagonalEntries && !insertedDiagonalElement) {
submatrix.addNextValue(rowGroupIndex, rowGroupIndex, storm::utility::constantZero<T>());
matrixBuilder.addNextValue(rowGroupIndex, rowGroupIndex, storm::utility::constantZero<T>());
}
}
// Finalize created matrix and return result.
submatrix.finalize();
return submatrix;
return matrixBuilder.build();
}
template <typename T>
SparseMatrix<T> SparseMatrix<T>::transpose() const {
checkReady("transpose");
uint_fast64_t rowCount = this->columnCount;
uint_fast64_t columnCount = this->rowCount;
uint_fast64_t entryCount = this->entryCount;
@ -620,8 +577,6 @@ namespace storm {
template<typename T>
void SparseMatrix<T>::invertDiagonal() {
checkReady("invertDiagonal");
// Check if the matrix is square, because only then it makes sense to perform this
// transformation.
if (this->getRowCount() != this->getColumnCount()) {
@ -649,8 +604,6 @@ namespace storm {
template<typename T>
void SparseMatrix<T>::negateAllNonDiagonalEntries() {
checkReady("negateAllNonDiagonalEntries");
// Check if the matrix is square, because only then it makes sense to perform this transformation.
if (this->getRowCount() != this->getColumnCount()) {
throw storm::exceptions::InvalidArgumentException() << "Illegal call to SparseMatrix::invertDiagonal: matrix is non-square.";
@ -668,8 +621,6 @@ namespace storm {
template<typename T>
void SparseMatrix<T>::deleteDiagonalEntries() {
checkReady("deleteDiagonalEntries");
// Check if the matrix is square, because only then it makes sense to perform this transformation.
if (this->getRowCount() != this->getColumnCount()) {
throw storm::exceptions::InvalidArgumentException() << "Illegal call to SparseMatrix::deleteDiagonalEntries: matrix is non-square.";
@ -687,15 +638,13 @@ namespace storm {
template<typename T>
typename std::pair<storm::storage::SparseMatrix<T>, storm::storage::SparseMatrix<T>> SparseMatrix<T>::getJacobiDecomposition() const {
checkReady("getJacobiDecomposition");
if (rowCount != columnCount) {
throw storm::exceptions::InvalidArgumentException() << "Illegal call to SparseMatrix::invertDiagonal: matrix is non-square.";
}
storm::storage::SparseMatrix<T> resultLU(*this);
resultLU.deleteDiagonalEntries();
storm::storage::SparseMatrix<T> resultDinv(rowCount, columnCount, rowCount);
SparseMatrixBuilder<T> dInvBuilder(rowCount, columnCount, rowCount);
// Copy entries to the appropriate matrices.
for (uint_fast64_t rowNumber = 0; rowNumber < rowCount; ++rowNumber) {
@ -710,17 +659,14 @@ namespace storm {
break;
}
}
resultDinv.addNextValue(rowNumber, rowNumber, storm::utility::constantOne<T>() / diagonalValue);
dInvBuilder.addNextValue(rowNumber, rowNumber, storm::utility::constantOne<T>() / diagonalValue);
}
resultDinv.finalize();
return std::make_pair(std::move(resultLU), std::move(resultDinv));
return std::make_pair(std::move(resultLU), dInvBuilder.build());
}
template<typename T>
std::vector<T> SparseMatrix<T>::getPointwiseProductRowSumVector(storm::storage::SparseMatrix<T> const& otherMatrix) const {
checkReady("getPointwiseProductRowSumVector");
std::vector<T> result(rowCount, storm::utility::constantZero<T>());
// Iterate over all elements of the current matrix and either continue with the next element in case the
@ -746,7 +692,6 @@ namespace storm {
template<typename T>
void SparseMatrix<T>::multiplyWithVector(std::vector<T> const& vector, std::vector<T>& result) const {
checkReady("multiplyWithVector");
#ifdef STORM_HAVE_INTELTBB
tbb::parallel_for(tbb::blocked_range<uint_fast64_t>(0, result.size()), tbbHelper_MatrixRowVectorScalarProduct<storm::storage::SparseMatrix<T>, std::vector<T>, T>(this, &vector, &result));
#else
@ -769,8 +714,6 @@ namespace storm {
template<typename T>
uint_fast64_t SparseMatrix<T>::getSizeInMemory() const {
checkReady("getSizeInMemory");
uint_fast64_t size = sizeof(*this);
// Add size of columns and values.
@ -784,67 +727,56 @@ namespace storm {
template<typename T>
typename SparseMatrix<T>::const_rows SparseMatrix<T>::getRows(uint_fast64_t startRow, uint_fast64_t endRow) const {
checkReady("getRows");
return const_rows(this->columnsAndValues.data() + this->rowIndications[startRow], this->rowIndications[endRow + 1] - this->rowIndications[startRow]);
return const_rows(this->columnsAndValues.begin() + this->rowIndications[startRow], this->rowIndications[endRow + 1] - this->rowIndications[startRow]);
}
template<typename T>
typename SparseMatrix<T>::rows SparseMatrix<T>::getRows(uint_fast64_t startRow, uint_fast64_t endRow) {
checkReady("getRows");
return rows(this->columnsAndValues.data() + this->rowIndications[startRow], this->rowIndications[endRow + 1] - this->rowIndications[startRow]);
return rows(this->columnsAndValues.begin() + this->rowIndications[startRow], this->rowIndications[endRow + 1] - this->rowIndications[startRow]);
}
template<typename T>
typename SparseMatrix<T>::const_rows SparseMatrix<T>::getRow(uint_fast64_t row) const {
checkReady("getRow");
return getRows(row, row);
}
template<typename T>
typename SparseMatrix<T>::rows SparseMatrix<T>::getRow(uint_fast64_t row) {
checkReady("getRow");
return getRows(row, row);
}
template<typename T>
typename SparseMatrix<T>::const_iterator SparseMatrix<T>::begin(uint_fast64_t row) const {
checkReady("begin");
return this->columnsAndValues.data() + this->rowIndications[row];
return this->columnsAndValues.begin() + this->rowIndications[row];
}
template<typename T>
typename SparseMatrix<T>::iterator SparseMatrix<T>::begin(uint_fast64_t row) {
checkReady("begin");
return this->columnsAndValues.data() + this->rowIndications[row];
return this->columnsAndValues.begin() + this->rowIndications[row];
}
template<typename T>
typename SparseMatrix<T>::const_iterator SparseMatrix<T>::end(uint_fast64_t row) const {
checkReady("end");
return this->columnsAndValues.data() + this->rowIndications[row + 1];
return this->columnsAndValues.begin() + this->rowIndications[row + 1];
}
template<typename T>
typename SparseMatrix<T>::iterator SparseMatrix<T>::end(uint_fast64_t row) {
checkReady("end");
return this->columnsAndValues.data() + this->rowIndications[row + 1];
return this->columnsAndValues.begin() + this->rowIndications[row + 1];
}
template<typename T>
typename SparseMatrix<T>::const_iterator SparseMatrix<T>::end() const {
checkReady("end");
return this->columnsAndValues.data() + this->rowIndications[rowCount];
return this->columnsAndValues.begin() + this->rowIndications[rowCount];
}
template<typename T>
typename SparseMatrix<T>::iterator SparseMatrix<T>::end() {
checkReady("end");
return this->columnsAndValues.data() + this->rowIndications[rowCount];
return this->columnsAndValues.begin() + this->rowIndications[rowCount];
}
template<typename T>
T SparseMatrix<T>::getRowSum(uint_fast64_t row) const {
checkReady("getRowSum");
T sum = storm::utility::constantZero<T>();
for (const_iterator it = this->begin(row), ite = this->end(row); it != ite; ++it) {
sum += it->second;
@ -854,8 +786,6 @@ namespace storm {
template<typename T>
bool SparseMatrix<T>::isSubmatrixOf(SparseMatrix<T> const& matrix) const {
checkReady("isSubmatrixOf");
// Check for matching sizes.
if (this->getRowCount() != matrix.getRowCount()) return false;
if (this->getColumnCount() != matrix.getColumnCount()) return false;
@ -877,8 +807,6 @@ namespace storm {
template<typename T>
std::ostream& operator<<(std::ostream& out, SparseMatrix<T> const& matrix) {
matrix.checkReady("operator<<");
// Print column numbers in header.
out << "\t\t";
for (uint_fast64_t i = 0; i < matrix.columnCount; ++i) {
@ -922,34 +850,17 @@ namespace storm {
boost::hash_combine(result, rowCount);
boost::hash_combine(result, columnCount);
boost::hash_combine(result, entryCount);
boost::hash_combine(result, internalStatus);
boost::hash_combine(result, boost::hash_range(columnsAndValues.begin(), columnsAndValues.end()));
boost::hash_combine(result, boost::hash_range(rowIndications.begin(), rowIndications.end()));
return result;
}
template<typename T>
void SparseMatrix<T>::prepareInternalStorage() {
// Only allocate the memory if the dimensions of the matrix are already known.
if (storagePreallocated) {
columnsAndValues = std::vector<std::pair<uint_fast64_t, T>>(entryCount, std::make_pair(0, storm::utility::constantZero<T>()));
rowIndications = std::vector<uint_fast64_t>(rowCount + 1, 0);
} else {
rowIndications.push_back(0);
}
}
template<typename T>
void SparseMatrix<T>::checkReady(std::string const& methodName) const {
if (!this->isInitialized()) {
throw storm::exceptions::InvalidStateException() << "Invalid call to SparseMatrix::" << methodName << ": matrix used for operation has not been initialized properly.";
}
}
// Explicitly instantiate the matrix and the nested classes.
// Explicitly instantiate the builder and the matrix.
template class SparseMatrixBuilder<double>;
template class SparseMatrix<double>;
template std::ostream& operator<<(std::ostream& out, SparseMatrix<double> const& matrix);
template class SparseMatrixBuilder<int>;
template class SparseMatrix<int>;
template std::ostream& operator<<(std::ostream& out, SparseMatrix<int> const& matrix);

186
src/storage/SparseMatrix.h

@ -40,6 +40,103 @@ namespace storm {
class tbbHelper_MatrixRowVectorScalarProduct;
#endif
// Forward declare matrix class.
template<typename T> class SparseMatrix;
/*!
* A class that can be used to build a sparse matrix by adding value by value.
*/
template<typename T>
class SparseMatrixBuilder {
public:
/*!
* Constructs a sparse matrix builder producing a matrix with the given number of rows, columns and entries.
*
* @param rows The number of rows of the resulting matrix.
* @param columns The number of columns of the resulting matrix.
* @param entries The number of entries of the resulting matrix.
*/
SparseMatrixBuilder(uint_fast64_t rows = 0, uint_fast64_t columns = 0, uint_fast64_t entries = 0);
/*!
* Sets the matrix entry at the given row and column to the given value. After all entries have been added,
* a call to finalize(false) is mandatory.
*
* Note: this is a linear setter. That is, it must be called consecutively for each entry, row by row and
* column by column. As multiple entries per column are admitted, consecutive calls to this method are
* admitted to mention the same row-column-pair. If rows are skipped entirely, the corresponding rows are
* 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 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 column, T const& value);
/*
* Finalizes the sparse matrix to indicate that initialization process has been completed and the matrix
* may now be used. This must be called after all entries have been added to the matrix via addNextValue.
*
* @param overriddenRowCount If this is set to a value that is greater than the current number of rows,
* this will cause the finalize method to add empty rows at the end of the matrix until the given row count
* has been matched. Note that this will *not* override the row count that has been given upon construction
* (if any), but will only take effect if the matrix has been created without the number of rows given.
* @param overriddenColumnCount If this is set to a value that is greater than the current number of columns,
* this will cause the finalize method to set the number of columns to the given value. Note that this will
* *not* override the column count that has been given upon construction (if any), but will only take effect
* if the matrix has been created without the number of columns given. By construction, the matrix will have
* no entries in the columns that have been added this way.
*/
SparseMatrix<T> build(uint_fast64_t overriddenRowCount = 0, uint_fast64_t overriddenColumnCount = 0);
private:
/*!
* Prepares the internal storage of the builder. This relies on the number of entries and the number of rows
* being set correctly. They may, however, be zero, in which case the insertion of elements in the builder
* will cause occasional reallocations.
*/
void prepareInternalStorage();
// A flag indicating whether the number of rows was set upon construction.
bool rowCountSet;
// The number of rows of the matrix.
uint_fast64_t rowCount;
// A flag indicating whether the number of columns was set upon construction.
bool columnCountSet;
// The number of columns of the matrix.
uint_fast64_t columnCount;
// The number of entries in the matrix.
uint_fast64_t entryCount;
// Stores whether the storage of the matrix was preallocated or not.
bool storagePreallocated;
// The storage for the columns and values of all entries in the matrix.
std::vector<std::pair<uint_fast64_t, T>> columnsAndValues;
// A vector containing the indices at which each given row begins. This index is to be interpreted as an
// index in the valueStorage and the columnIndications vectors. Put differently, the values of the entries
// in row i are valueStorage[rowIndications[i]] to valueStorage[rowIndications[i + 1]] where the last
// entry is not included anymore.
std::vector<uint_fast64_t> rowIndications;
// Stores the current number of entries in the matrix. This is used for inserting an entry into a matrix
// with preallocated storage.
uint_fast64_t currentEntryCount;
// Stores the row of the last entry in the matrix. This is used for correctly inserting an entry into a
// matrix.
uint_fast64_t lastRow;
// Stores the column of the currently last entry in the matrix. This is used for correctly inserting an
// entry into a matrix.
uint_fast64_t lastColumn;
};
/*!
* A class that holds a possibly non-square matrix in the compressed row storage format. That is, it is supposed
* to store non-zero entries only, but zeros may be explicitly stored if necessary for certain operations.
@ -68,8 +165,8 @@ namespace storm {
friend class tbbHelper_MatrixRowVectorScalarProduct;
#endif
typedef std::pair<uint_fast64_t, T>* iterator;
typedef std::pair<uint_fast64_t, T> const* const_iterator;
typedef typename std::vector<std::pair<uint_fast64_t, T>>::iterator iterator;
typedef typename std::vector<std::pair<uint_fast64_t, T> const>::const_iterator const_iterator;
/*!
* This class represents a number of consecutive rows of the matrix.
@ -151,14 +248,10 @@ namespace storm {
enum MatrixStatus { UNINITIALIZED, INITIALIZED };
/*!
* Constructs a sparse matrix object with the given number of rows, columns and number of entries.
*
* @param rows The number of rows of the matrix.
* @param columns The number of columns of the matrix.
* @param entries The number of entries of the matrix.
* Constructs an empty sparse matrix.
*/
SparseMatrix(uint_fast64_t rows = 0, uint_fast64_t columns = 0, uint_fast64_t entries = 0);
SparseMatrix();
/*!
* Constructs a sparse matrix by performing a deep-copy of the given matrix.
*
@ -233,37 +326,6 @@ namespace storm {
*/
bool operator==(SparseMatrix<T> const& other) const;
/*!
* Sets the matrix entry at the given row and column to the given value. After all entries have been added,
* a call to finalize(false) is mandatory.
*
* Note: this is a linear setter. That is, it must be called consecutively for each entry, row by row and
* column by column. As multiple entries per column are admitted, consecutive calls to this method are
* admitted to mention the same row-column-pair. If rows are skipped entirely, the corresponding rows are
* 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 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 column,T const& value);
/*
* Finalizes the sparse matrix to indicate that initialization process has been completed and the matrix
* may now be used. This must be called after all entries have been added to the matrix via addNextValue.
*
* @param overriddenRowCount If this is set to a value that is greater than the current number of rows,
* this will cause the finalize method to add empty rows at the end of the matrix until the given row count
* has been matched. Note that this will *not* override the row count that has been given upon construction
* (if any), but will only take effect if the matrix has been created without the number of rows given.
* @param overriddenColumnCount If this is set to a value that is greater than the current number of columns,
* this will cause the finalize method to set the number of columns to the given value. Note that this will
* *not* override the column count that has been given upon construction (if any), but will only take effect
* if the matrix has been created without the number of columns given. By construction, the matrix will have
* no entries in the columns that have been added this way.
*/
void finalize(uint_fast64_t overriddenRowCount = 0, uint_fast64_t overriddenColumnCount = 0);
/*!
* Returns the number of rows of the matrix.
*
@ -285,13 +347,6 @@ namespace storm {
*/
uint_fast64_t getEntryCount() const;
/*!
* Checks whether the matrix was initialized properly and is ready for further use.
*
* @return True iff the matrix was initialized properly and is ready for further use.
*/
bool isInitialized() const;
/*!
* This function makes the given rows absorbing.
*
@ -566,36 +621,15 @@ namespace storm {
std::size_t hash() const;
private:
/*!
* Prepares the internal storage of the matrix. This relies on the number of entries and the number of rows
* being set correctly. They may, however, be zero, in which case the insertion of elements in the matrix
* will cause occasional reallocations.
*/
void prepareInternalStorage();
/*!
* Checks whether the matrix is properly initialized and throws an exception otherwise.
*/
void checkReady(std::string const& methodName) const;
// A flag indicating whether the number of rows was set upon construction.
bool rowCountSet;
// The number of rows of the matrix.
uint_fast64_t rowCount;
// A flag indicating whether the number of columns was set upon construction.
bool columnCountSet;
// The number of columns of the matrix.
uint_fast64_t columnCount;
// The number of entries in the matrix.
uint_fast64_t entryCount;
// Stores whether the storage of the matrix was preallocated or not.
bool storagePreallocated;
// The storage for the columns and values of all entries in the matrix.
std::vector<std::pair<uint_fast64_t, T>> columnsAndValues;
@ -604,22 +638,6 @@ namespace storm {
// in row i are valueStorage[rowIndications[i]] to valueStorage[rowIndications[i + 1]] where the last
// entry is not included anymore.
std::vector<uint_fast64_t> rowIndications;
// The internal status of the matrix.
MatrixStatus internalStatus;
// Stores the current number of entries in the matrix. This is used for inserting an entry into a matrix
// with preallocated storage.
uint_fast64_t currentEntryCount;
// Stores the row of the last entry in the matrix. This is used for correctly inserting an entry into a
// matrix.
uint_fast64_t lastRow;
// Stores the column of the currently last entry in the matrix. This is used for correctly inserting an
// entry into a matrix.
uint_fast64_t lastColumn;
};
#ifdef STORM_HAVE_INTELTBB

22
src/utility/graph.h

@ -45,13 +45,10 @@ namespace storm {
* @return A bit vector with all indices of states that have a probability greater than 0.
*/
template <typename T>
storm::storage::BitVector performProbGreater0(storm::models::AbstractDeterministicModel<T> const& model, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool useStepBound = false, uint_fast64_t maximalSteps = 0) {
storm::storage::BitVector performProbGreater0(storm::models::AbstractDeterministicModel<T> const& model, storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, bool useStepBound = false, uint_fast64_t maximalSteps = 0) {
// Prepare the resulting bit vector.
storm::storage::BitVector statesWithProbabilityGreater0(model.getNumberOfStates());
// Get the backwards transition relation from the model to ease the search.
storm::storage::SparseMatrix<T> backwardTransitions = model.getBackwardTransitions();
// Add all psi states as the already satisfy the condition.
statesWithProbabilityGreater0 |= psiStates;
@ -82,7 +79,7 @@ namespace storm {
}
for (typename storm::storage::SparseMatrix<T>::const_iterator entryIt = backwardTransitions.begin(currentState), entryIte = backwardTransitions.end(currentState); entryIt != entryIte; ++entryIt) {
if (phiStates.get(entryIt->first) && (!statesWithProbabilityGreater0.get(entryIt->first) || (useStepBound && remainingSteps[entryIt->first] < currentStepBound - 1))) {
if (phiStates[entryIt->first] && (!statesWithProbabilityGreater0.get(entryIt->first) || (useStepBound && remainingSteps[entryIt->first] < currentStepBound - 1))) {
// If we don't have a bound on the number of steps to take, just add the state to the stack.
if (!useStepBound) {
statesWithProbabilityGreater0.set(entryIt->first, true);
@ -117,8 +114,8 @@ namespace storm {
* @return A bit vector with all indices of states that have a probability greater than 1.
*/
template <typename T>
storm::storage::BitVector performProb1(storm::models::AbstractDeterministicModel<T> const& model, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, storm::storage::BitVector const& statesWithProbabilityGreater0) {
storm::storage::BitVector statesWithProbability1 = performProbGreater0(model, ~psiStates, ~statesWithProbabilityGreater0);
storm::storage::BitVector performProb1(storm::models::AbstractDeterministicModel<T> const& model, storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates, storm::storage::BitVector const& statesWithProbabilityGreater0) {
storm::storage::BitVector statesWithProbability1 = performProbGreater0(model, backwardTransitions, ~psiStates, ~statesWithProbabilityGreater0);
statesWithProbability1.complement();
return statesWithProbability1;
}
@ -136,9 +133,9 @@ namespace storm {
* @return A bit vector with all indices of states that have a probability greater than 1.
*/
template <typename T>
storm::storage::BitVector performProb1(storm::models::AbstractDeterministicModel<T> const& model, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
storm::storage::BitVector statesWithProbabilityGreater0 = performProbGreater0(model, phiStates, psiStates);
storm::storage::BitVector statesWithProbability1 = performProbGreater0(model, ~psiStates, ~(statesWithProbabilityGreater0));
storm::storage::BitVector performProb1(storm::models::AbstractDeterministicModel<T> const& model, storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
storm::storage::BitVector statesWithProbabilityGreater0 = performProbGreater0(model, backwardTransitions, phiStates, psiStates);
storm::storage::BitVector statesWithProbability1 = performProbGreater0(model, backwardTransitions, ~psiStates, ~(statesWithProbabilityGreater0));
statesWithProbability1.complement();
return statesWithProbability1;
}
@ -156,8 +153,9 @@ namespace storm {
template <typename T>
static std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(storm::models::AbstractDeterministicModel<T> const& model, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
result.first = performProbGreater0(model, phiStates, psiStates);
result.second = performProb1(model, phiStates, psiStates, result.first);
storm::storage::SparseMatrix<T> backwardTransitions = model.getBackwardTransitions();
result.first = performProbGreater0(model, backwardTransitions, phiStates, psiStates);
result.second = performProb1(model, backwardTransitions, phiStates, psiStates, result.first);
result.first.complement();
return result;
}

10
src/utility/matrix.h

@ -20,7 +20,7 @@ namespace storm {
*/
template <typename T>
storm::storage::SparseMatrix<T> applyScheduler(storm::storage::SparseMatrix<T> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices, storm::storage::Scheduler const& scheduler) {
storm::storage::SparseMatrix<T> result(nondeterministicChoiceIndices.size() - 1, transitionMatrix.getColumnCount());
storm::storage::SparseMatrixBuilder<T> matrixBuilder(nondeterministicChoiceIndices.size() - 1, transitionMatrix.getColumnCount());
for (uint_fast64_t state = 0; state < nondeterministicChoiceIndices.size() - 1; ++state) {
if (scheduler.isChoiceDefined(state)) {
@ -33,17 +33,15 @@ namespace storm {
// If a valid choice for this state is defined, we copy over the corresponding entries.
typename storm::storage::SparseMatrix<T>::const_rows selectedRow = transitionMatrix.getRow(choice);
for (auto const& entry : selectedRow) {
result.addNextValue(state, entry.first, entry.second);
matrixBuilder.addNextValue(state, entry.first, entry.second);
}
} else {
// If no valid choice for the state is defined, we insert a self-loop.
result.addNextValue(state, state, storm::utility::constantOne<T>());
matrixBuilder.addNextValue(state, state, storm::utility::constantOne<T>());
}
}
// Finalize the matrix creation and return result.
result.finalize();
return result;
return matrixBuilder.build();
}
}
}

757
test/functional/storage/SparseMatrixTest.cpp

@ -3,218 +3,228 @@
#include "src/exceptions/InvalidArgumentException.h"
#include "src/exceptions/OutOfRangeException.h"
TEST(SparseMatrix, SimpleCreation) {
ASSERT_NO_THROW(storm::storage::SparseMatrix<double> matrix);
ASSERT_NO_THROW(storm::storage::SparseMatrix<double> matrix(3));
ASSERT_NO_THROW(storm::storage::SparseMatrix<double> matrix(3, 4));
ASSERT_NO_THROW(storm::storage::SparseMatrix<double> matrix(3, 4, 5));
}
TEST(SparseMatrix, CreationWithMovingContents) {
ASSERT_NO_THROW(storm::storage::SparseMatrix<double> matrix(4, {0, 2, 5, 5}, {1, 2, 0, 1, 3}, {1.0, 1.2, 0.5, 0.7, 0.2}));
storm::storage::SparseMatrix<double> matrix(4, {0, 2, 5, 5}, {1, 2, 0, 1, 3}, {1.0, 1.2, 0.5, 0.7, 0.2});
ASSERT_EQ(3, matrix.getRowCount());
ASSERT_EQ(4, matrix.getColumnCount());
ASSERT_EQ(5, matrix.getEntryCount());
}
TEST(SparseMatrix, CreationWithDimensions) {
storm::storage::SparseMatrix<double> matrix(3, 4, 5);
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(1, 3, 0.2));
ASSERT_NO_THROW(matrix.finalize());
TEST(SparseMatrixBuilder, CreationWithDimensions) {
storm::storage::SparseMatrixBuilder<double> matrixBuilder(3, 4, 5);
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 3, 0.2));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
ASSERT_EQ(3, matrix.getRowCount());
ASSERT_EQ(4, matrix.getColumnCount());
ASSERT_EQ(5, matrix.getEntryCount());
}
TEST(SparseMatrix, CreationWithoutNumberOfEntries) {
storm::storage::SparseMatrix<double> matrix(3, 4);
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(1, 3, 0.2));
ASSERT_NO_THROW(matrix.finalize());
TEST(SparseMatrixBuilder, CreationWithoutNumberOfEntries) {
storm::storage::SparseMatrixBuilder<double> matrixBuilder(3, 4);
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 3, 0.2));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
ASSERT_EQ(3, matrix.getRowCount());
ASSERT_EQ(4, matrix.getColumnCount());
ASSERT_EQ(5, matrix.getEntryCount());
}
TEST(SparseMatrix, CreationWithNumberOfRows) {
storm::storage::SparseMatrix<double> matrix(3);
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(1, 3, 0.2));
ASSERT_NO_THROW(matrix.finalize());
TEST(SparseMatrixBuilder, CreationWithNumberOfRows) {
storm::storage::SparseMatrixBuilder<double> matrixBuilder(3);
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 3, 0.2));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
ASSERT_EQ(3, matrix.getRowCount());
ASSERT_EQ(4, matrix.getColumnCount());
ASSERT_EQ(5, matrix.getEntryCount());
}
TEST(SparseMatrix, CreationWithoutDimensions) {
TEST(SparseMatrixBuilder, CreationWithoutDimensions) {
storm::storage::SparseMatrixBuilder<double> matrixBuilder;
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 3, 0.2));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(1, 3, 0.2));
ASSERT_NO_THROW(matrix.finalize());
ASSERT_NO_THROW(matrix = matrixBuilder.build());
ASSERT_EQ(2, matrix.getRowCount());
ASSERT_EQ(4, matrix.getColumnCount());
ASSERT_EQ(5, matrix.getEntryCount());
}
TEST(SparseMatrix, CopyConstruct) {
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(1, 3, 0.2));
ASSERT_NO_THROW(matrix.finalize());
ASSERT_NO_THROW(storm::storage::SparseMatrix<double> copy(matrix));
storm::storage::SparseMatrix<double> copy(matrix);
ASSERT_TRUE(matrix == copy);
TEST(SparseMatrixBuilder, AddNextValue) {
storm::storage::SparseMatrixBuilder<double> matrixBuilder1(3, 4, 5);
ASSERT_NO_THROW(matrixBuilder1.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder1.addNextValue(0, 2, 1.2));
ASSERT_THROW(matrixBuilder1.addNextValue(0, 4, 0.5), storm::exceptions::OutOfRangeException);
ASSERT_THROW(matrixBuilder1.addNextValue(3, 1, 0.5), storm::exceptions::OutOfRangeException);
storm::storage::SparseMatrixBuilder<double> matrixBuilder2(3, 4);
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 2, 1.2));
ASSERT_THROW(matrixBuilder2.addNextValue(0, 4, 0.5), storm::exceptions::OutOfRangeException);
ASSERT_THROW(matrixBuilder2.addNextValue(3, 1, 0.5), storm::exceptions::OutOfRangeException);
storm::storage::SparseMatrixBuilder<double> matrixBuilder3(3);
ASSERT_NO_THROW(matrixBuilder3.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder3.addNextValue(1, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder3.addNextValue(2, 4, 0.5));
ASSERT_THROW(matrixBuilder3.addNextValue(3, 1, 0.2), storm::exceptions::OutOfRangeException);
storm::storage::SparseMatrixBuilder<double> matrixBuilder4;
ASSERT_NO_THROW(matrixBuilder4.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder4.addNextValue(1, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder4.addNextValue(2, 4, 0.5));
ASSERT_NO_THROW(matrixBuilder4.addNextValue(3, 1, 0.2));
}
TEST(SparseMatrix, CopyAssign) {
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(1, 3, 0.2));
ASSERT_NO_THROW(matrix.finalize());
ASSERT_NO_THROW(storm::storage::SparseMatrix<double> copy = matrix);
storm::storage::SparseMatrix<double> copy = matrix;
ASSERT_TRUE(matrix == copy);
}
TEST(SparseMatrix, AddNextValue) {
storm::storage::SparseMatrix<double> matrix(3, 4, 5);
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_THROW(matrix.addNextValue(0, 4, 0.5), storm::exceptions::OutOfRangeException);
ASSERT_THROW(matrix.addNextValue(3, 1, 0.5), storm::exceptions::OutOfRangeException);
storm::storage::SparseMatrix<double> matrix2(3, 4);
ASSERT_NO_THROW(matrix2.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix2.addNextValue(0, 2, 1.2));
ASSERT_THROW(matrix2.addNextValue(0, 4, 0.5), storm::exceptions::OutOfRangeException);
ASSERT_THROW(matrix.addNextValue(3, 1, 0.5), storm::exceptions::OutOfRangeException);
storm::storage::SparseMatrix<double> matrix3(3);
ASSERT_NO_THROW(matrix3.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix3.addNextValue(1, 2, 1.2));
ASSERT_NO_THROW(matrix3.addNextValue(2, 4, 0.5));
ASSERT_THROW(matrix3.addNextValue(3, 1, 0.2), storm::exceptions::OutOfRangeException);
storm::storage::SparseMatrix<double> matrix4;
ASSERT_NO_THROW(matrix4.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix4.addNextValue(1, 2, 1.2));
ASSERT_NO_THROW(matrix4.addNextValue(2, 4, 0.5));
ASSERT_NO_THROW(matrix4.addNextValue(3, 1, 0.2));
}
TEST(SparseMatrix, Finalize) {
storm::storage::SparseMatrix<double> matrix(3, 4, 5);
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(1, 3, 0.2));
ASSERT_FALSE(matrix.isInitialized());
ASSERT_NO_THROW(matrix.finalize());
ASSERT_TRUE(matrix.isInitialized());
storm::storage::SparseMatrix<double> matrix2(3, 4, 5);
ASSERT_NO_THROW(matrix2.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix2.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix2.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix2.addNextValue(1, 1, 0.7));
ASSERT_THROW(matrix2.finalize(), storm::exceptions::InvalidStateException);
TEST(SparseMatrix, Build) {
storm::storage::SparseMatrixBuilder<double> matrixBuilder1(3, 4, 5);
ASSERT_NO_THROW(matrixBuilder1.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder1.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder1.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder1.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder1.addNextValue(1, 3, 0.2));
ASSERT_NO_THROW(matrixBuilder1.build());
storm::storage::SparseMatrixBuilder<double> matrixBuilder2(3, 4, 5);
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 1, 0.7));
ASSERT_THROW(matrixBuilder2.build(), storm::exceptions::InvalidStateException);
storm::storage::SparseMatrixBuilder<double> matrixBuilder3;
ASSERT_NO_THROW(matrixBuilder3.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder3.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder3.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder3.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder3.addNextValue(1, 3, 0.2));
storm::storage::SparseMatrix<double> matrix3;
ASSERT_NO_THROW(matrix3.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix3.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix3.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix3.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix3.addNextValue(1, 3, 0.2));
ASSERT_NO_THROW(matrix3.finalize());
ASSERT_NO_THROW(matrix3 = matrixBuilder3.build());
ASSERT_EQ(2, matrix3.getRowCount());
ASSERT_EQ(4, matrix3.getColumnCount());
ASSERT_EQ(5, matrix3.getEntryCount());
storm::storage::SparseMatrixBuilder<double> matrixBuilder4;
ASSERT_NO_THROW(matrixBuilder4.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder4.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder4.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder4.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder4.addNextValue(1, 3, 0.2));
storm::storage::SparseMatrix<double> matrix4;
ASSERT_NO_THROW(matrix4.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix4.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix4.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix4.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix4.addNextValue(1, 3, 0.2));
ASSERT_NO_THROW(matrix4.finalize(4));
ASSERT_NO_THROW(matrix4 = matrixBuilder4.build(4));
ASSERT_EQ(4, matrix4.getRowCount());
ASSERT_EQ(4, matrix4.getColumnCount());
ASSERT_EQ(5, matrix4.getEntryCount());
storm::storage::SparseMatrixBuilder<double> matrixBuilder5;
ASSERT_NO_THROW(matrixBuilder5.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder5.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder5.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder5.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder5.addNextValue(1, 3, 0.2));
storm::storage::SparseMatrix<double> matrix5;
ASSERT_NO_THROW(matrix5.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix5.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix5.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix5.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix5.addNextValue(1, 3, 0.2));
ASSERT_NO_THROW(matrix5.finalize(0, 6));
ASSERT_NO_THROW(matrix5 = matrixBuilder5.build(0, 6));
ASSERT_EQ(2, matrix5.getRowCount());
ASSERT_EQ(6, matrix5.getColumnCount());
ASSERT_EQ(5, matrix5.getEntryCount());
}
TEST(SparseMatrix, MakeAbsorbing) {
storm::storage::SparseMatrix<double> matrix(3, 4, 5);
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(1, 3, 0.2));
ASSERT_NO_THROW(matrix.finalize());
TEST(SparseMatrix, CreationWithMovingContents) {
ASSERT_NO_THROW(storm::storage::SparseMatrix<double> matrix(4, {0, 2, 5, 5}, {1, 2, 0, 1, 3}, {1.0, 1.2, 0.5, 0.7, 0.2}));
storm::storage::SparseMatrix<double> matrix(4, {0, 2, 5, 5}, {1, 2, 0, 1, 3}, {1.0, 1.2, 0.5, 0.7, 0.2});
ASSERT_EQ(3, matrix.getRowCount());
ASSERT_EQ(4, matrix.getColumnCount());
ASSERT_EQ(5, matrix.getEntryCount());
}
TEST(SparseMatrix, CopyConstruct) {
storm::storage::SparseMatrixBuilder<double> matrixBuilder;
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 3, 0.2));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
ASSERT_NO_THROW(storm::storage::SparseMatrix<double> copy(matrix));
storm::storage::SparseMatrix<double> copy(matrix);
ASSERT_TRUE(matrix == copy);
}
TEST(SparseMatrix, CopyAssign) {
storm::storage::SparseMatrixBuilder<double> matrixBuilder;
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 3, 0.2));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
ASSERT_NO_THROW(storm::storage::SparseMatrix<double> copy = matrix);
storm::storage::SparseMatrix<double> copy = matrix;
ASSERT_TRUE(matrix == copy);
}
TEST(SparseMatrix, MakeAbsorbing) {
storm::storage::SparseMatrixBuilder<double> matrixBuilder(3, 4, 5);
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 3, 0.2));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
storm::storage::BitVector absorbingRows(3);
absorbingRows.set(1);
ASSERT_NO_THROW(matrix.makeRowsAbsorbing(absorbingRows));
storm::storage::SparseMatrix<double> matrix2(3, 4, 3);
ASSERT_NO_THROW(matrix2.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix2.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix2.addNextValue(1, 1, 1));
ASSERT_NO_THROW(matrix2.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder2(3, 4, 3);
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 1, 1));
storm::storage::SparseMatrix<double> matrix2;
ASSERT_NO_THROW(matrix2 = matrixBuilder2.build());
ASSERT_TRUE(matrix == matrix2);
}
TEST(SparseMatrix, MakeRowGroupAbsorbing) {
storm::storage::SparseMatrix<double> matrix(5, 4, 9);
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrix.addNextValue(4, 3, 0.3));
ASSERT_NO_THROW(matrix.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder(5, 4, 9);
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 3, 0.3));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
std::vector<uint_fast64_t> rowGroupIndices = {0, 2, 4, 5};
@ -223,33 +233,35 @@ TEST(SparseMatrix, MakeRowGroupAbsorbing) {
ASSERT_NO_THROW(matrix.makeRowsAbsorbing(absorbingRowGroups, rowGroupIndices));
storm::storage::SparseMatrixBuilder<double> matrixBuilder2;
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(2, 1, 1));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(3, 1, 1));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(4, 3, 0.3));
storm::storage::SparseMatrix<double> matrix2;
ASSERT_NO_THROW(matrix2.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix2.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix2.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix2.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix2.addNextValue(2, 1, 1));
ASSERT_NO_THROW(matrix2.addNextValue(3, 1, 1));
ASSERT_NO_THROW(matrix2.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrix2.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrix2.addNextValue(4, 3, 0.3));
ASSERT_NO_THROW(matrix2.finalize());
ASSERT_NO_THROW(matrix2 = matrixBuilder2.build());
ASSERT_TRUE(matrix == matrix2);
}
TEST(SparseMatrix, ConstrainedRowSumVector) {
storm::storage::SparseMatrix<double> matrix(5, 4, 9);
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrix.addNextValue(4, 3, 0.3));
ASSERT_NO_THROW(matrix.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder(5, 4, 9);
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 3, 0.3));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
storm::storage::BitVector columnConstraint(4);
columnConstraint.set(1);
@ -259,17 +271,18 @@ TEST(SparseMatrix, ConstrainedRowSumVector) {
std::vector<double> constrainedRowSum = matrix.getConstrainedRowSumVector(storm::storage::BitVector(5, true), columnConstraint);
ASSERT_TRUE(constrainedRowSum == std::vector<double>({1.0, 0.7, 0, 0, 0.5}));
storm::storage::SparseMatrix<double> matrix2(5, 4, 9);
ASSERT_NO_THROW(matrix2.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix2.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix2.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix2.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix2.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrix2.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrix2.addNextValue(3, 3, 1.2));
ASSERT_NO_THROW(matrix2.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrix2.addNextValue(4, 3, 0.3));
ASSERT_NO_THROW(matrix2.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder2(5, 4, 9);
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(3, 3, 1.2));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(4, 3, 0.3));
storm::storage::SparseMatrix<double> matrix2;
ASSERT_NO_THROW(matrix2 = matrixBuilder2.build());
std::vector<uint_fast64_t> rowGroupIndices = {0, 2, 4, 5};
@ -286,17 +299,18 @@ TEST(SparseMatrix, ConstrainedRowSumVector) {
}
TEST(SparseMatrix, Submatrix) {
storm::storage::SparseMatrix<double> matrix(5, 4, 9);
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrix.addNextValue(4, 3, 0.3));
ASSERT_NO_THROW(matrix.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder(5, 4, 9);
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 3, 0.3));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
std::vector<uint_fast64_t> rowGroupIndices = {0, 1, 2, 4, 5};
@ -311,11 +325,12 @@ TEST(SparseMatrix, Submatrix) {
ASSERT_NO_THROW(storm::storage::SparseMatrix<double> matrix2 = matrix.getSubmatrix(rowGroupConstraint, columnConstraint, rowGroupIndices, false));
storm::storage::SparseMatrix<double> matrix2 = matrix.getSubmatrix(rowGroupConstraint, columnConstraint, rowGroupIndices, false);
storm::storage::SparseMatrix<double> matrix3(3, 2, 3);
ASSERT_NO_THROW(matrix3.addNextValue(0, 0, 0.5));
ASSERT_NO_THROW(matrix3.addNextValue(2, 0, 0.1));
ASSERT_NO_THROW(matrix3.addNextValue(2, 1, 0.3));
ASSERT_NO_THROW(matrix3.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder3(3, 2, 3);
ASSERT_NO_THROW(matrixBuilder3.addNextValue(0, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder3.addNextValue(2, 0, 0.1));
ASSERT_NO_THROW(matrixBuilder3.addNextValue(2, 1, 0.3));
storm::storage::SparseMatrix<double> matrix3;
ASSERT_NO_THROW(matrix3 = matrixBuilder3.build());
ASSERT_TRUE(matrix2 == matrix3);
@ -324,132 +339,142 @@ TEST(SparseMatrix, Submatrix) {
ASSERT_NO_THROW(storm::storage::SparseMatrix<double> matrix4 = matrix.getSubmatrix(rowGroupToIndexMapping, rowGroupIndices));
storm::storage::SparseMatrix<double> matrix4 = matrix.getSubmatrix(rowGroupToIndexMapping, rowGroupIndices);
storm::storage::SparseMatrix<double> matrix5(4, 4, 8);
ASSERT_NO_THROW(matrix5.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix5.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix5.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix5.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix5.addNextValue(2, 2, 1.1));
ASSERT_NO_THROW(matrix5.addNextValue(3, 0, 0.1));
ASSERT_NO_THROW(matrix5.addNextValue(3, 1, 0.2));
ASSERT_NO_THROW(matrix5.addNextValue(3, 3, 0.3));
ASSERT_NO_THROW(matrix5.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder5(4, 4, 8);
ASSERT_NO_THROW(matrixBuilder5.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder5.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder5.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder5.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder5.addNextValue(2, 2, 1.1));
ASSERT_NO_THROW(matrixBuilder5.addNextValue(3, 0, 0.1));
ASSERT_NO_THROW(matrixBuilder5.addNextValue(3, 1, 0.2));
ASSERT_NO_THROW(matrixBuilder5.addNextValue(3, 3, 0.3));
storm::storage::SparseMatrix<double> matrix5;
ASSERT_NO_THROW(matrix5 = matrixBuilder5.build());
ASSERT_TRUE(matrix4 == matrix5);
}
TEST(SparseMatrix, Transpose) {
storm::storage::SparseMatrix<double> matrix(5, 4, 9);
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrix.addNextValue(4, 3, 0.3));
ASSERT_NO_THROW(matrix.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder(5, 4, 9);
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 3, 0.3));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
ASSERT_NO_THROW(storm::storage::SparseMatrix<double> transposeResult = matrix.transpose());
storm::storage::SparseMatrix<double> transposeResult = matrix.transpose();
storm::storage::SparseMatrix<double> matrix2(4, 5, 9);
ASSERT_NO_THROW(matrix2.addNextValue(0, 1, 0.5));
ASSERT_NO_THROW(matrix2.addNextValue(0, 2, 0.5));
ASSERT_NO_THROW(matrix2.addNextValue(0, 4, 0.1));
ASSERT_NO_THROW(matrix2.addNextValue(1, 0, 1.0));
ASSERT_NO_THROW(matrix2.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix2.addNextValue(1, 4, 0.2));
ASSERT_NO_THROW(matrix2.addNextValue(2, 0, 1.2));
ASSERT_NO_THROW(matrix2.addNextValue(2, 3, 1.1));
ASSERT_NO_THROW(matrix2.addNextValue(3, 4, 0.3));
ASSERT_NO_THROW(matrix2.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder2(4, 5, 9);
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 1, 0.5));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 2, 0.5));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 4, 0.1));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 0, 1.0));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 4, 0.2));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(2, 0, 1.2));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(2, 3, 1.1));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(3, 4, 0.3));
storm::storage::SparseMatrix<double> matrix2;
ASSERT_NO_THROW(matrix2 = matrixBuilder2.build());
ASSERT_TRUE(transposeResult == matrix2);
}
TEST(SparseMatrix, EquationSystem) {
storm::storage::SparseMatrix<double> matrix(4, 4, 7);
ASSERT_NO_THROW(matrix.addNextValue(0, 0, 1.1));
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 3, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(2, 2, 0.99));
ASSERT_NO_THROW(matrix.addNextValue(3, 3, 0.11));
ASSERT_NO_THROW(matrix.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder(4, 4, 7);
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 0, 1.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 3, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(2, 2, 0.99));
ASSERT_NO_THROW(matrixBuilder.addNextValue(3, 3, 0.11));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
ASSERT_NO_THROW(matrix.convertToEquationSystem());
storm::storage::SparseMatrix<double> matrix2(4, 4, 7);
ASSERT_NO_THROW(matrix2.addNextValue(0, 0, 1 - 1.1));
ASSERT_NO_THROW(matrix2.addNextValue(0, 1, -1.2));
ASSERT_NO_THROW(matrix2.addNextValue(1, 1, 1 - 0.5));
ASSERT_NO_THROW(matrix2.addNextValue(1, 3, -0.7));
ASSERT_NO_THROW(matrix2.addNextValue(2, 0, -0.5));
ASSERT_NO_THROW(matrix2.addNextValue(2, 2, 1 - 0.99));
ASSERT_NO_THROW(matrix2.addNextValue(3, 3, 1 - 0.11));
ASSERT_NO_THROW(matrix2.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder2(4, 4, 7);
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 0, 1 - 1.1));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 1, -1.2));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 1, 1 - 0.5));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 3, -0.7));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(2, 0, -0.5));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(2, 2, 1 - 0.99));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(3, 3, 1 - 0.11));
storm::storage::SparseMatrix<double> matrix2;
ASSERT_NO_THROW(matrix2 = matrixBuilder2.build());
ASSERT_TRUE(matrix == matrix2);
}
TEST(SparseMatrix, JacobiDecomposition) {
storm::storage::SparseMatrix<double> matrix(4, 4, 7);
ASSERT_NO_THROW(matrix.addNextValue(0, 0, 1.1));
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 3, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(2, 2, 0.99));
ASSERT_NO_THROW(matrix.addNextValue(3, 3, 0.11));
ASSERT_NO_THROW(matrix.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder(4, 4, 7);
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 0, 1.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 3, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(2, 2, 0.99));
ASSERT_NO_THROW(matrixBuilder.addNextValue(3, 3, 0.11));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
ASSERT_NO_THROW(matrix.getJacobiDecomposition());
std::pair<storm::storage::SparseMatrix<double>, storm::storage::SparseMatrix<double>> jacobiDecomposition = matrix.getJacobiDecomposition();
storm::storage::SparseMatrix<double> LU(4, 4, 3);
ASSERT_NO_THROW(LU.addNextValue(0, 1, 1.2));
ASSERT_NO_THROW(LU.addNextValue(1, 3, 0.7));
ASSERT_NO_THROW(LU.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(LU.finalize());
storm::storage::SparseMatrix<double> Dinv(4, 4, 4);
ASSERT_NO_THROW(Dinv.addNextValue(0, 0, 1 / 1.1));
ASSERT_NO_THROW(Dinv.addNextValue(1, 1, 1 / 0.5));
ASSERT_NO_THROW(Dinv.addNextValue(2, 2, 1 / 0.99));
ASSERT_NO_THROW(Dinv.addNextValue(3, 3, 1 / 0.11));
ASSERT_NO_THROW(Dinv.finalize());
ASSERT_TRUE(LU == jacobiDecomposition.first);
ASSERT_TRUE(Dinv == jacobiDecomposition.second);
storm::storage::SparseMatrixBuilder<double> luBuilder(4, 4, 3);
ASSERT_NO_THROW(luBuilder.addNextValue(0, 1, 1.2));
ASSERT_NO_THROW(luBuilder.addNextValue(1, 3, 0.7));
ASSERT_NO_THROW(luBuilder.addNextValue(2, 0, 0.5));
storm::storage::SparseMatrix<double> lu;
ASSERT_NO_THROW(lu = luBuilder.build());
storm::storage::SparseMatrixBuilder<double> dinvBuilder(4, 4, 4);
ASSERT_NO_THROW(dinvBuilder.addNextValue(0, 0, 1 / 1.1));
ASSERT_NO_THROW(dinvBuilder.addNextValue(1, 1, 1 / 0.5));
ASSERT_NO_THROW(dinvBuilder.addNextValue(2, 2, 1 / 0.99));
ASSERT_NO_THROW(dinvBuilder.addNextValue(3, 3, 1 / 0.11));
storm::storage::SparseMatrix<double> dinv;
ASSERT_NO_THROW(dinv = dinvBuilder.build());
ASSERT_TRUE(lu == jacobiDecomposition.first);
ASSERT_TRUE(dinv == jacobiDecomposition.second);
}
TEST(SparseMatrix, PointwiseMultiplicationVector) {
storm::storage::SparseMatrix<double> matrix(5, 4, 9);
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrix.addNextValue(4, 3, 0.3));
ASSERT_NO_THROW(matrix.finalize());
storm::storage::SparseMatrix<double> matrix2(5, 4, 9);
ASSERT_NO_THROW(matrix2.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix2.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix2.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix2.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix2.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrix2.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrix2.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrix2.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrix2.addNextValue(4, 3, 0.3));
ASSERT_NO_THROW(matrix2.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder(5, 4, 9);
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 3, 0.3));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
storm::storage::SparseMatrixBuilder<double> matrixBuilder2(5, 4, 9);
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(4, 3, 0.3));
storm::storage::SparseMatrix<double> matrix2;
ASSERT_NO_THROW(matrix2 = matrixBuilder2.build());
ASSERT_NO_THROW(std::vector<double> pointwiseProductRowSums = matrix.getPointwiseProductRowSumVector(matrix2));
std::vector<double> pointwiseProductRowSums = matrix.getPointwiseProductRowSumVector(matrix2);
@ -459,17 +484,18 @@ TEST(SparseMatrix, PointwiseMultiplicationVector) {
}
TEST(SparseMatrix, MatrixVectorMultiply) {
storm::storage::SparseMatrix<double> matrix(5, 4, 9);
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrix.addNextValue(4, 3, 0.3));
ASSERT_NO_THROW(matrix.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder(5, 4, 9);
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 3, 0.3));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
std::vector<double> x = {1, 0.3, 1.4, 7.1};
std::vector<double> result(matrix.getRowCount());
@ -481,17 +507,18 @@ TEST(SparseMatrix, MatrixVectorMultiply) {
}
TEST(SparseMatrix, Iteration) {
storm::storage::SparseMatrix<double> matrix(5, 4, 9);
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrix.addNextValue(4, 3, 0.3));
ASSERT_NO_THROW(matrix.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder(5, 4, 9);
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(2, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 3, 0.3));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
for (auto const& entry : matrix.getRow(4)) {
if (entry.first == 0) {
@ -519,50 +546,54 @@ TEST(SparseMatrix, Iteration) {
}
TEST(SparseMatrix, RowSum) {
storm::storage::SparseMatrix<double> matrix(5, 4, 8);
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrix.addNextValue(4, 3, 0.3));
ASSERT_NO_THROW(matrix.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder(5, 4, 8);
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 3, 0.3));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
ASSERT_EQ(0, matrix.getRowSum(2));
ASSERT_EQ(0.1+0.2+0.3, matrix.getRowSum(4));
}
TEST(SparseMatrix, IsSubmatrix) {
storm::storage::SparseMatrix<double> matrix(5, 4, 8);
ASSERT_NO_THROW(matrix.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrix.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrix.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrix.addNextValue(4, 3, 0.3));
ASSERT_NO_THROW(matrix.finalize());
storm::storage::SparseMatrix<double> matrix2(5, 4, 5);
ASSERT_NO_THROW(matrix2.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrix2.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix2.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix2.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrix2.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrix2.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder(5, 4, 8);
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder.addNextValue(0, 2, 1.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder.addNextValue(3, 2, 1.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrixBuilder.addNextValue(4, 3, 0.3));
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
storm::storage::SparseMatrixBuilder<double> matrixBuilder2(5, 4, 5);
ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 1, 1.0));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrixBuilder2.addNextValue(4, 1, 0.2));
storm::storage::SparseMatrix<double> matrix2;
ASSERT_NO_THROW(matrix2 = matrixBuilder2.build());
ASSERT_TRUE(matrix2.isSubmatrixOf(matrix));
storm::storage::SparseMatrix<double> matrix3(5, 4, 5);
ASSERT_NO_THROW(matrix3.addNextValue(0, 3, 1.0));
ASSERT_NO_THROW(matrix3.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrix3.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrix3.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrix3.addNextValue(4, 1, 0.2));
ASSERT_NO_THROW(matrix3.finalize());
storm::storage::SparseMatrixBuilder<double> matrixBuilder3(5, 4, 5);
ASSERT_NO_THROW(matrixBuilder3.addNextValue(0, 3, 1.0));
ASSERT_NO_THROW(matrixBuilder3.addNextValue(1, 0, 0.5));
ASSERT_NO_THROW(matrixBuilder3.addNextValue(1, 1, 0.7));
ASSERT_NO_THROW(matrixBuilder3.addNextValue(4, 0, 0.1));
ASSERT_NO_THROW(matrixBuilder3.addNextValue(4, 1, 0.2));
storm::storage::SparseMatrix<double> matrix3;
ASSERT_NO_THROW(matrix3 = matrixBuilder3.build());
ASSERT_FALSE(matrix3.isSubmatrixOf(matrix));
ASSERT_FALSE(matrix3.isSubmatrixOf(matrix2));

1
test/performance/graph/GraphTest.cpp

@ -12,6 +12,7 @@ TEST(GraphTest, PerformProb01) {
storm::storage::BitVector trueStates(dtmc->getNumberOfStates(), true);
LOG4CPLUS_WARN(logger, "Computing prob01 (3 times) for crowds/crowds20_5...");
std::pair<storm::storage::BitVector, storm::storage::BitVector> prob01(storm::utility::graph::performProb01(*dtmc, trueStates, storm::storage::BitVector(dtmc->getLabeledStates("observe0Greater1"))));
ASSERT_EQ(prob01.first.getNumberOfSetBits(), 1724414ull);

16
test/performance/storage/SparseMatrixTest.cpp

@ -2,13 +2,15 @@
#include "src/storage/SparseMatrix.h"
TEST(SparseMatrix, Iteration) {
storm::storage::SparseMatrix<double> matrix;
storm::storage::SparseMatrixBuilder<double> matrixBuilder;
for (uint_fast64_t row = 0; row < 10000; ++row) {
for (uint_fast64_t column = 0; column < row; ++column) {
ASSERT_NO_THROW(matrix.addNextValue(row, column, row+column));
ASSERT_NO_THROW(matrixBuilder.addNextValue(row, column, row+column));
}
}
ASSERT_NO_THROW(matrix.finalize());
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
for (uint_fast64_t row = 0; row < matrix.getRowCount(); ++row) {
for (auto const& entry : matrix.getRow(row)) {
@ -21,13 +23,15 @@ TEST(SparseMatrix, Iteration) {
}
TEST(SparseMatrix, Multiplication) {
storm::storage::SparseMatrix<double> matrix;
storm::storage::SparseMatrixBuilder<double> matrixBuilder;
for (uint_fast64_t row = 0; row < 2000; ++row) {
for (uint_fast64_t column = 0; column < row; ++column) {
ASSERT_NO_THROW(matrix.addNextValue(row, column, row+column));
ASSERT_NO_THROW(matrixBuilder.addNextValue(row, column, row+column));
}
}
ASSERT_NO_THROW(matrix.finalize());
storm::storage::SparseMatrix<double> matrix;
ASSERT_NO_THROW(matrix = matrixBuilder.build());
std::vector<double> x(matrix.getColumnCount(), 1.0);
std::vector<double> result(matrix.getRowCount());

Loading…
Cancel
Save