Browse Source
Fixed MDP Parser, removed parsing of STATES/TRANSITIONS, see #10
Fixed MDP Parser, removed parsing of STATES/TRANSITIONS, see #10
Refactored the Sparse Adapters, see #17tempestpy_adaptions
PBerger
12 years ago
9 changed files with 452 additions and 293 deletions
-
6src/adapters/EigenAdapter.h
-
220src/adapters/StormAdapter.h
-
20src/parser/NondeterministicSparseTransitionParser.cpp
-
247src/storage/SparseMatrix.h
-
4test/parser/ParseMdpTest.cpp
-
33test/storage/SparseMatrixTest.cpp
-
0test/storage/adapters/EigenAdapterTest.cpp
-
111test/storage/adapters/GmmAdapterTest.cpp
-
104test/storage/adapters/StormAdapterTest.cpp
@ -0,0 +1,220 @@ |
|||
/* |
|||
* StormAdapter.h |
|||
* |
|||
* Created on: 02.03.2013 |
|||
* Author: Philipp Berger |
|||
*/ |
|||
|
|||
#ifndef STORM_ADAPTERS_STORMADAPTER_H_ |
|||
#define STORM_ADAPTERS_STORMADAPTER_H_ |
|||
|
|||
#include "src/storage/SparseMatrix.h" |
|||
|
|||
#include "log4cplus/logger.h" |
|||
#include "log4cplus/loggingmacros.h" |
|||
|
|||
extern log4cplus::Logger logger; |
|||
|
|||
namespace storm { |
|||
|
|||
namespace adapters { |
|||
|
|||
class StormAdapter { |
|||
public: |
|||
/*! |
|||
* Converts a sparse matrix into a sparse matrix in the storm format. |
|||
* @return A pointer to a row-major sparse matrix in storm format. |
|||
*/ |
|||
template<class T> |
|||
static storm::storage::SparseMatrix<T>* toStormSparseMatrix(gmm::csr_matrix<T> const& matrix) { |
|||
uint_fast64_t realNonZeros = gmm::nnz(matrix); |
|||
LOG4CPLUS_DEBUG(logger, "Converting matrix with " << realNonZeros << " non-zeros from gmm++ format into Storm."); |
|||
|
|||
// Prepare the resulting matrix. |
|||
storm::storage::SparseMatrix<T>* result = new storm::storage::SparseMatrix<T>(matrix.nrows(), matrix.ncols()); |
|||
|
|||
// Set internal NonZero Counter |
|||
result->nonZeroEntryCount = realNonZeros; |
|||
result->setState(result->Initialized); |
|||
|
|||
if (!result->prepareInternalStorage(false)) { |
|||
LOG4CPLUS_ERROR(logger, "Unable to allocate internal storage while converting GMM++ Matrix to Storm."); |
|||
delete result; |
|||
return nullptr; |
|||
} else { |
|||
|
|||
// Copy Row Indications |
|||
std::copy(matrix.jc.begin(), matrix.jc.end(), std::back_inserter(result->rowIndications)); |
|||
// Copy Columns Indications |
|||
std::copy(matrix.ir.begin(), matrix.ir.end(), std::back_inserter(result->columnIndications)); |
|||
// And do the same thing with the actual values. |
|||
std::copy(matrix.pr.begin(), matrix.pr.end(), std::back_inserter(result->valueStorage)); |
|||
|
|||
result->currentSize = realNonZeros; |
|||
result->lastRow = matrix.nrows() - 1; |
|||
} |
|||
|
|||
result->finalize(); |
|||
|
|||
LOG4CPLUS_DEBUG(logger, "Done converting matrix to storm format."); |
|||
|
|||
return result; |
|||
} |
|||
|
|||
/*! |
|||
* Helper function to determine whether the given Eigen matrix is in RowMajor |
|||
* format. Always returns true, but is overloaded, so the compiler will |
|||
* only call it in case the Eigen matrix is in RowMajor format. |
|||
* @return True. |
|||
*/ |
|||
template<typename _Scalar, typename _Index> |
|||
static bool isEigenRowMajor(Eigen::SparseMatrix<_Scalar, Eigen::RowMajor, _Index>) { |
|||
return true; |
|||
} |
|||
|
|||
/*! |
|||
* Helper function to determine whether the given Eigen matrix is in RowMajor |
|||
* format. Always returns false, but is overloaded, so the compiler will |
|||
* only call it in case the Eigen matrix is in ColMajor format. |
|||
* @return False. |
|||
*/ |
|||
template<typename _Scalar, typename _Index> |
|||
static bool isEigenRowMajor( |
|||
Eigen::SparseMatrix<_Scalar, Eigen::ColMajor, _Index>) { |
|||
return false; |
|||
} |
|||
|
|||
/*! |
|||
* Converts a sparse matrix in the eigen format to Storm Sparse Matrix format. |
|||
* @return A pointer to a row-major sparse matrix in our format. |
|||
*/ |
|||
template<class T, int _Options, typename _Index> |
|||
static storm::storage::SparseMatrix<T>* toStormSparseMatrix(Eigen::SparseMatrix<T, _Options, _Index> const& matrix) { |
|||
uint_fast64_t realNonZeros = matrix.nonZeros(); |
|||
LOG4CPLUS_DEBUG(logger, "Converting matrix with " << realNonZeros << " non-zeros from Eigen3 format into Storm."); |
|||
|
|||
// Throw an error in case the matrix is not in compressed format. |
|||
if (!matrix.isCompressed()) { |
|||
LOG4CPLUS_ERROR(logger, "Trying to convert from an Eigen matrix that is not in compressed form."); |
|||
return nullptr; |
|||
} |
|||
|
|||
/* |
|||
* Try to prepare the internal storage and throw an error in case of |
|||
* failure. |
|||
*/ |
|||
|
|||
// Get necessary pointers to the contents of the Eigen matrix. |
|||
const T* valuePtr = matrix.valuePtr(); |
|||
const _Index* indexPtr = matrix.innerIndexPtr(); |
|||
const _Index* outerPtr = matrix.outerIndexPtr(); |
|||
|
|||
const uint_fast64_t outerSize = matrix.outerSize(); |
|||
|
|||
storm::storage::SparseMatrix<T>* result = nullptr; |
|||
|
|||
// If the given matrix is in RowMajor format, copying can simply |
|||
// be done by adding all values in order. |
|||
// Direct copying is, however, prevented because we have to |
|||
// separate the diagonal entries from others. |
|||
if (isEigenRowMajor(matrix)) { |
|||
/* Because of the RowMajor format outerSize evaluates to the |
|||
* number of rows. |
|||
* Prepare the resulting matrix. |
|||
*/ |
|||
result = new storm::storage::SparseMatrix<T>(matrix.outerSize(), matrix.innerSize()); |
|||
|
|||
// Set internal NonZero Counter |
|||
result->nonZeroEntryCount = realNonZeros; |
|||
result->setState(result->Initialized); |
|||
|
|||
if (!result->prepareInternalStorage(false)) { |
|||
LOG4CPLUS_ERROR(logger, "Unable to allocate internal storage while converting Eigen3 RM Matrix to Storm."); |
|||
delete result; |
|||
return nullptr; |
|||
} else { |
|||
|
|||
// Copy Row Indications |
|||
std::copy(outerPtr, outerPtr + outerSize, std::back_inserter(result->rowIndications)); |
|||
// Copy Columns Indications |
|||
std::copy(indexPtr, indexPtr + realNonZeros, std::back_inserter(result->columnIndications)); |
|||
// And do the same thing with the actual values. |
|||
std::copy(valuePtr, valuePtr + realNonZeros, std::back_inserter(result->valueStorage)); |
|||
|
|||
// This is our Sentinel Element. |
|||
result->rowIndications.push_back(realNonZeros); |
|||
|
|||
result->currentSize = realNonZeros; |
|||
result->lastRow = outerSize - 1; |
|||
} |
|||
} else { |
|||
/* Because of the RowMajor format outerSize evaluates to the |
|||
* number of columns. |
|||
* Prepare the resulting matrix. |
|||
*/ |
|||
const uint_fast64_t colCount = matrix.outerSize(); |
|||
result = new storm::storage::SparseMatrix<T>(matrix.innerSize(), colCount); |
|||
|
|||
// Set internal NonZero Counter |
|||
result->nonZeroEntryCount = realNonZeros; |
|||
result->setState(result->Initialized); |
|||
if (!result->prepareInternalStorage()) { |
|||
LOG4CPLUS_ERROR(logger, "Unable to allocate internal storage while converting Eigen3 CM Matrix to Storm."); |
|||
delete result; |
|||
return nullptr; |
|||
} else { |
|||
// Set internal NonZero Counter |
|||
result->nonZeroEntryCount = realNonZeros; |
|||
result->setState(result->Initialized); |
|||
|
|||
// Create an array to remember which elements have to still |
|||
// be searched in each column and initialize it with the starting |
|||
// index for every column. |
|||
_Index* positions = new _Index[colCount](); |
|||
for (_Index i = 0; i < colCount; ++i) { |
|||
positions[i] = outerPtr[i]; |
|||
} |
|||
|
|||
// Now copy the elements. As the matrix is in ColMajor format, |
|||
// we need to iterate over the columns to find the next non-zero |
|||
// entry. |
|||
uint_fast64_t i = 0; |
|||
int currentRow = 0; |
|||
int currentColumn = 0; |
|||
while (i < realNonZeros) { |
|||
// If the current element belongs the the current column, |
|||
// add it in case it is also in the current row. |
|||
if ((positions[currentColumn] < outerPtr[currentColumn + 1]) |
|||
&& (indexPtr[positions[currentColumn]] == currentRow)) { |
|||
result->addNextValue(currentRow, currentColumn, valuePtr[positions[currentColumn]]); |
|||
// Remember that we found one more non-zero element. |
|||
++i; |
|||
// Mark this position as "used". |
|||
++positions[currentColumn]; |
|||
} |
|||
|
|||
// Now we can advance to the next column and also row, |
|||
// in case we just iterated through the last column. |
|||
++currentColumn; |
|||
if (currentColumn == colCount) { |
|||
currentColumn = 0; |
|||
++currentRow; |
|||
} |
|||
} |
|||
delete[] positions; |
|||
} |
|||
} |
|||
result->setState(result->Initialized); |
|||
result->finalize(); |
|||
|
|||
LOG4CPLUS_DEBUG(logger, "Done converting matrix to storm format."); |
|||
|
|||
return result; |
|||
} |
|||
}; |
|||
|
|||
} //namespace adapters |
|||
|
|||
} //namespace storm |
|||
|
|||
#endif /* STORM_ADAPTERS_STORMADAPTER_H_ */ |
@ -0,0 +1,111 @@ |
|||
#include "gtest/gtest.h"
|
|||
|
|||
#include "gmm/gmm_matrix.h"
|
|||
#include "src/adapters/GmmxxAdapter.h"
|
|||
#include "src/exceptions/InvalidArgumentException.h"
|
|||
#include "boost/integer/integer_mask.hpp"
|
|||
|
|||
#define STORM_GMMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE 5
|
|||
#define STORM_GMMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE 5
|
|||
|
|||
double getValue(gmm::csr_matrix<double> const& gmmSparseMatrix, uint_fast64_t row, uint_fast64_t col) { |
|||
uint_fast64_t rowStart = gmmSparseMatrix.jc.at(row); |
|||
uint_fast64_t rowEnd = gmmSparseMatrix.jc.at(row + 1); |
|||
while (rowStart < rowEnd) { |
|||
if (gmmSparseMatrix.ir.at(rowStart) == col) { |
|||
return gmmSparseMatrix.pr.at(rowStart); |
|||
} |
|||
if (gmmSparseMatrix.ir.at(rowStart) > col) { |
|||
break; |
|||
} |
|||
++rowStart; |
|||
} |
|||
|
|||
return 0.0; |
|||
} |
|||
|
|||
TEST(GmmAdapterTest, SimpleDenseSquareCopy) { |
|||
// 5 rows
|
|||
storm::storage::SparseMatrix<double> sm(STORM_GMMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE); |
|||
|
|||
double values[STORM_GMMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE * STORM_GMMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE]; |
|||
sm.initialize(STORM_GMMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE * STORM_GMMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE); |
|||
|
|||
int row = 0; |
|||
int col = 0; |
|||
for (int i = 0; i < STORM_GMMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE * STORM_GMMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE; ++i) { |
|||
values[i] = static_cast<double>(i + 1); |
|||
|
|||
sm.addNextValue(row, col, values[i]); |
|||
++col; |
|||
if (col == STORM_GMMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE) { |
|||
++row; |
|||
col = 0; |
|||
} |
|||
} |
|||
sm.finalize(); |
|||
|
|||
auto gsm = storm::adapters::GmmxxAdapter::toGmmxxSparseMatrix(sm); |
|||
|
|||
ASSERT_EQ(gsm->nrows(), STORM_GMMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE); |
|||
ASSERT_EQ(gsm->ncols(), STORM_GMMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE); |
|||
ASSERT_EQ(gmm::nnz(*gsm), STORM_GMMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE * STORM_GMMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE); |
|||
row = 0; |
|||
col = 0; |
|||
for (int i = 0; i < STORM_GMMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE * STORM_GMMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE; ++i) { |
|||
ASSERT_EQ(values[i], getValue(*gsm, row, col)); |
|||
++col; |
|||
if (col == STORM_GMMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE) { |
|||
++row; |
|||
col = 0; |
|||
} |
|||
} |
|||
} |
|||
|
|||
TEST(GmmAdapterTest, SimpleSparseSquareCopy) { |
|||
// 5 rows
|
|||
storm::storage::SparseMatrix<double> sm(STORM_GMMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE); |
|||
|
|||
double values[STORM_GMMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE * STORM_GMMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE]; |
|||
sm.initialize((STORM_GMMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE * STORM_GMMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE + 1) / 2); |
|||
|
|||
int row = 0; |
|||
int col = 0; |
|||
|
|||
bool everySecondElement = true; |
|||
|
|||
for (int i = 0; i < STORM_GMMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE * STORM_GMMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE; ++i) { |
|||
values[i] = static_cast<double>(i + 1); |
|||
if (everySecondElement) { |
|||
sm.addNextValue(row, col, values[i]); |
|||
} |
|||
everySecondElement = !everySecondElement; |
|||
++col; |
|||
if (col == STORM_GMMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE) { |
|||
++row; |
|||
col = 0; |
|||
} |
|||
} |
|||
sm.finalize(); |
|||
|
|||
auto gsm = storm::adapters::GmmxxAdapter::toGmmxxSparseMatrix(sm); |
|||
|
|||
ASSERT_EQ(gsm->nrows(), STORM_GMMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE); |
|||
ASSERT_EQ(gsm->ncols(), STORM_GMMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE); |
|||
ASSERT_EQ(gmm::nnz(*gsm), (STORM_GMMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE * STORM_GMMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE + 1) / 2); |
|||
|
|||
row = 0; |
|||
col = 0; |
|||
everySecondElement = true; |
|||
for (int i = 0; i < STORM_GMMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE * STORM_GMMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE; ++i) { |
|||
if (everySecondElement) { |
|||
ASSERT_EQ(values[i], getValue(*gsm, row, col)); |
|||
} |
|||
everySecondElement = !everySecondElement; |
|||
++col; |
|||
if (col == STORM_GMMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE) { |
|||
++row; |
|||
col = 0; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,104 @@ |
|||
#include "gtest/gtest.h"
|
|||
|
|||
#include "gmm/gmm_matrix.h"
|
|||
#include "src/adapters/StormAdapter.h"
|
|||
#include "src/exceptions/InvalidArgumentException.h"
|
|||
#include "boost/integer/integer_mask.hpp"
|
|||
|
|||
#define STORM_STORMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE 5
|
|||
#define STORM_STORMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE 5
|
|||
|
|||
TEST(StormAdapterTest, SimpleDenseSquareCopy) { |
|||
// 5 rows
|
|||
gmm::csr_matrix<double> gmmSparseMatrix; |
|||
|
|||
/*
|
|||
* As CSR_Matrix is read-only we have to prepare the data in this row_matrix and then do a copy. |
|||
*/ |
|||
gmm::row_matrix<gmm::wsvector<double>> gmmPreMatrix(STORM_STORMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE, STORM_STORMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE); |
|||
|
|||
double values[STORM_STORMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE * STORM_STORMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE]; |
|||
|
|||
int row = 0; |
|||
int col = 0; |
|||
for (int i = 0; i < STORM_STORMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE * STORM_STORMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE; ++i) { |
|||
values[i] = static_cast<double>(i + 1); |
|||
|
|||
gmmPreMatrix(row, col) = values[i]; |
|||
++col; |
|||
if (col == STORM_STORMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE) { |
|||
++row; |
|||
col = 0; |
|||
} |
|||
} |
|||
gmm::copy(gmmPreMatrix, gmmSparseMatrix); |
|||
|
|||
auto stormSparseMatrix = storm::adapters::StormAdapter::toStormSparseMatrix(gmmSparseMatrix); |
|||
|
|||
ASSERT_EQ(stormSparseMatrix->getRowCount(), STORM_STORMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE); |
|||
ASSERT_EQ(stormSparseMatrix->getColumnCount(), STORM_STORMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE); |
|||
ASSERT_EQ(stormSparseMatrix->getNonZeroEntryCount(), STORM_STORMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE * STORM_STORMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE); |
|||
row = 0; |
|||
col = 0; |
|||
for (int i = 0; i < STORM_STORMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE * STORM_STORMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE; ++i) { |
|||
ASSERT_EQ(values[i], stormSparseMatrix->getValue(row, col)); |
|||
++col; |
|||
if (col == STORM_STORMADAPTERTEST_SIMPLEDENSESQUARECOPY_SIZE) { |
|||
++row; |
|||
col = 0; |
|||
} |
|||
} |
|||
} |
|||
|
|||
TEST(StormAdapterTest, SimpleSparseSquareCopy) { |
|||
// 5 rows
|
|||
gmm::csr_matrix<double> gmmSparseMatrix; |
|||
|
|||
/*
|
|||
* As CSR_Matrix is read-only we have to prepare the data in this row_matrix and then do a copy. |
|||
*/ |
|||
gmm::row_matrix<gmm::wsvector<double>> gmmPreMatrix(STORM_STORMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE, STORM_STORMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE); |
|||
|
|||
double values[STORM_STORMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE * STORM_STORMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE]; |
|||
|
|||
int row = 0; |
|||
int col = 0; |
|||
|
|||
bool everySecondElement = true; |
|||
|
|||
for (int i = 0; i < STORM_STORMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE * STORM_STORMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE; ++i) { |
|||
values[i] = static_cast<double>(i + 1); |
|||
if (everySecondElement) { |
|||
gmmPreMatrix(row, col) = values[i]; |
|||
} |
|||
everySecondElement = !everySecondElement; |
|||
++col; |
|||
if (col == STORM_STORMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE) { |
|||
++row; |
|||
col = 0; |
|||
} |
|||
} |
|||
gmm::copy(gmmPreMatrix, gmmSparseMatrix); |
|||
|
|||
auto stormSparseMatrix = storm::adapters::StormAdapter::toStormSparseMatrix(gmmSparseMatrix); |
|||
|
|||
ASSERT_EQ(stormSparseMatrix->getRowCount(), STORM_STORMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE); |
|||
ASSERT_EQ(stormSparseMatrix->getColumnCount(), STORM_STORMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE); |
|||
ASSERT_EQ(stormSparseMatrix->getNonZeroEntryCount(), (STORM_STORMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE * STORM_STORMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE + 1) / 2); |
|||
|
|||
|
|||
row = 0; |
|||
col = 0; |
|||
everySecondElement = true; |
|||
for (int i = 0; i < STORM_STORMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE * STORM_STORMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE; ++i) { |
|||
if (everySecondElement) { |
|||
ASSERT_EQ(values[i], stormSparseMatrix->getValue(row, col)); |
|||
} |
|||
everySecondElement = !everySecondElement; |
|||
++col; |
|||
if (col == STORM_STORMADAPTERTEST_SIMPLESPARSESQUARECOPY_SIZE) { |
|||
++row; |
|||
col = 0; |
|||
} |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue