Browse Source
Refactored linear equation solvers and nondeterministic linear equation solvers. Added functional tests for both.
Refactored linear equation solvers and nondeterministic linear equation solvers. Added functional tests for both.
Former-commit-id: 0abb11828a
main
24 changed files with 1020 additions and 860 deletions
-
67resources/3rdparty/gmm-4.2/include/gmm/gmm_blas.h
-
10src/adapters/GmmxxAdapter.h
-
2src/counterexamples/PathBasedSubsystemGenerator.h
-
168src/solver/AbstractNondeterministicLinearEquationSolver.h
-
18src/solver/GmmxxLinearEquationSolver.cpp
-
6src/solver/GmmxxLinearEquationSolver.h
-
139src/solver/GmmxxNondeterministicLinearEquationSolver.cpp
-
129src/solver/GmmxxNondeterministicLinearEquationSolver.h
-
153src/solver/NativeLinearEquationSolver.cpp
-
65src/solver/NativeLinearEquationSolver.h
-
142src/solver/NativeNondeterministicLinearEquationSolver.cpp
-
50src/solver/NativeNondeterministicLinearEquationSolver.h
-
3src/storm.cpp
-
15src/utility/StormOptions.cpp
-
24src/utility/solver.cpp
-
16src/utility/vector.cpp
-
76src/utility/vector.h
-
231test/functional/modelchecker/GmmxxMdpPrctlModelCheckerTest.cpp
-
33test/functional/modelchecker/SparseMdpPrctlModelCheckerTest.cpp
-
224test/functional/solver/GmmxxLinearEquationSolverTest.cpp
-
33test/functional/solver/NativeLinearEquationSolverTest.cpp
-
212test/performance/modelchecker/GmmxxMdpPrctModelCheckerTest.cpp
-
62test/performance/modelchecker/SparseMdpPrctlModelCheckerTest.cpp
-
2test/performance/storm-performance-tests.cpp
@ -1,11 +1,144 @@ |
|||
#include "src/solver/GmmxxNondeterministicLinearEquationSolver.h"
|
|||
#include "src/settings/Settings.h"
|
|||
#include "src/adapters/GmmxxAdapter.h"
|
|||
#include "src/utility/vector.h"
|
|||
|
|||
bool GmmxxNondeterministicLinearEquationSolverOptionsRegistered = storm::settings::Settings::registerNewModule([] (storm::settings::Settings* instance) -> bool { |
|||
instance->addOption(storm::settings::OptionBuilder("GmmxxNondeterminsticLinearEquationSolver", "maxiter", "i", "The maximal number of iterations to perform before iterative solving is aborted.").addArgument(storm::settings::ArgumentBuilder::createUnsignedIntegerArgument("count", "The maximal iteration count.").setDefaultValueUnsignedInteger(10000).build()).build()); |
|||
|
|||
instance->addOption(storm::settings::OptionBuilder("GmmxxLinearEquationSolver", "precision", "", "The precision used for detecting convergence of iterative methods.").addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("value", "The precision to achieve.").setDefaultValueDouble(1e-6).addValidationFunctionDouble(storm::settings::ArgumentValidators::doubleRangeValidatorExcluding(0.0, 1.0)).build()).build()); |
|||
instance->addOption(storm::settings::OptionBuilder("GmmxxNondeterminsticLinearEquationSolver", "precision", "", "The precision used for detecting convergence of iterative methods.").addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("value", "The precision to achieve.").setDefaultValueDouble(1e-6).addValidationFunctionDouble(storm::settings::ArgumentValidators::doubleRangeValidatorExcluding(0.0, 1.0)).build()).build()); |
|||
|
|||
instance->addOption(storm::settings::OptionBuilder("GmmxxLinearEquationSolver", "absolute", "", "Whether the relative or the absolute error is considered for deciding convergence.").build()); |
|||
instance->addOption(storm::settings::OptionBuilder("GmmxxNondeterminsticLinearEquationSolver", "absolute", "", "Whether the relative or the absolute error is considered for deciding convergence.").build()); |
|||
|
|||
return true; |
|||
}); |
|||
}); |
|||
|
|||
namespace storm { |
|||
namespace solver { |
|||
|
|||
template<typename ValueType> |
|||
GmmxxNondeterministicLinearEquationSolver<ValueType>::GmmxxNondeterministicLinearEquationSolver() { |
|||
// Get the settings object to customize solving.
|
|||
storm::settings::Settings* settings = storm::settings::Settings::getInstance(); |
|||
|
|||
// Get appropriate settings.
|
|||
maximalNumberOfIterations = settings->getOptionByLongName("maxiter").getArgument(0).getValueAsUnsignedInteger(); |
|||
precision = settings->getOptionByLongName("precision").getArgument(0).getValueAsDouble(); |
|||
relative = settings->isSet("absolute"); |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
GmmxxNondeterministicLinearEquationSolver<ValueType>::GmmxxNondeterministicLinearEquationSolver(double precision, uint_fast64_t maximalNumberOfIterations, bool relative) : precision(precision), relative(relative), maximalNumberOfIterations(maximalNumberOfIterations) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
|
|||
template<typename ValueType> |
|||
AbstractNondeterministicLinearEquationSolver<ValueType>* GmmxxNondeterministicLinearEquationSolver<ValueType>::clone() const { |
|||
return new GmmxxNondeterministicLinearEquationSolver<ValueType>(*this); |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void GmmxxNondeterministicLinearEquationSolver<ValueType>::solveEquationSystem(bool minimize, storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType>& x, std::vector<ValueType> const& b, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices, std::vector<ValueType>* multiplyResult, std::vector<ValueType>* newX) const { |
|||
// Transform the transition probability matrix to the gmm++ format to use its arithmetic.
|
|||
std::unique_ptr<gmm::csr_matrix<ValueType>> gmmxxMatrix = storm::adapters::GmmxxAdapter::toGmmxxSparseMatrix<ValueType>(A); |
|||
|
|||
// Set up the environment for the power method. If scratch memory was not provided, we need to create it.
|
|||
bool multiplyResultMemoryProvided = true; |
|||
if (multiplyResult == nullptr) { |
|||
multiplyResult = new std::vector<ValueType>(A.getRowCount()); |
|||
multiplyResultMemoryProvided = false; |
|||
} |
|||
|
|||
std::vector<ValueType>* currentX = &x; |
|||
bool xMemoryProvided = true; |
|||
if (newX == nullptr) { |
|||
newX = new std::vector<ValueType>(x.size()); |
|||
xMemoryProvided = false; |
|||
} |
|||
std::vector<ValueType>* swap = nullptr; |
|||
uint_fast64_t iterations = 0; |
|||
bool converged = false; |
|||
|
|||
// Keep track of which of the vectors for x is the auxiliary copy.
|
|||
std::vector<ValueType>* copyX = newX; |
|||
|
|||
// Proceed with the iterations as long as the method did not converge or reach the user-specified maximum number
|
|||
// of iterations.
|
|||
while (!converged && iterations < maximalNumberOfIterations) { |
|||
// Compute x' = A*x + b.
|
|||
gmm::mult(*gmmxxMatrix, *currentX, *multiplyResult); |
|||
gmm::add(b, *multiplyResult); |
|||
|
|||
// Reduce the vector x by applying min/max over all nondeterministic choices.
|
|||
if (minimize) { |
|||
storm::utility::vector::reduceVectorMin(*multiplyResult, *newX, nondeterministicChoiceIndices); |
|||
} else { |
|||
storm::utility::vector::reduceVectorMax(*multiplyResult, *newX, nondeterministicChoiceIndices); |
|||
} |
|||
|
|||
// Determine whether the method converged.
|
|||
converged = storm::utility::vector::equalModuloPrecision(*currentX, *newX, this->precision, this->relative); |
|||
|
|||
// Update environment variables.
|
|||
std::swap(currentX, newX); |
|||
++iterations; |
|||
} |
|||
|
|||
// Check if the solver converged and issue a warning otherwise.
|
|||
if (converged) { |
|||
LOG4CPLUS_INFO(logger, "Iterative solver converged after " << iterations << " iterations."); |
|||
} else { |
|||
LOG4CPLUS_WARN(logger, "Iterative solver did not converge after " << iterations << " iterations."); |
|||
} |
|||
|
|||
// If we performed an odd number of iterations, we need to swap the x and currentX, because the newest result
|
|||
// is currently stored in currentX, but x is the output vector.
|
|||
if (currentX == copyX) { |
|||
std::swap(x, *currentX); |
|||
} |
|||
|
|||
if (!xMemoryProvided) { |
|||
delete copyX; |
|||
} |
|||
|
|||
if (!multiplyResultMemoryProvided) { |
|||
delete multiplyResult; |
|||
} |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void GmmxxNondeterministicLinearEquationSolver<ValueType>::performMatrixVectorMultiplication(bool minimize, storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType>& x, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices, std::vector<ValueType>* b, uint_fast64_t n, std::vector<ValueType>* multiplyResult) const { |
|||
// Transform the transition probability matrix to the gmm++ format to use its arithmetic.
|
|||
std::unique_ptr<gmm::csr_matrix<ValueType>> gmmxxMatrix = storm::adapters::GmmxxAdapter::toGmmxxSparseMatrix<ValueType>(A); |
|||
|
|||
bool multiplyResultMemoryProvided = true; |
|||
if (multiplyResult == nullptr) { |
|||
multiplyResult = new std::vector<ValueType>(A.getRowCount()); |
|||
multiplyResultMemoryProvided = false; |
|||
} |
|||
|
|||
// Now perform matrix-vector multiplication as long as we meet the bound of the formula.
|
|||
for (uint_fast64_t i = 0; i < n; ++i) { |
|||
gmm::mult(*gmmxxMatrix, x, *multiplyResult); |
|||
|
|||
if (b != nullptr) { |
|||
gmm::add(*b, *multiplyResult); |
|||
} |
|||
|
|||
if (minimize) { |
|||
storm::utility::vector::reduceVectorMin(*multiplyResult, x, nondeterministicChoiceIndices); |
|||
} else { |
|||
storm::utility::vector::reduceVectorMax(*multiplyResult, x, nondeterministicChoiceIndices); |
|||
} |
|||
} |
|||
|
|||
if (!multiplyResultMemoryProvided) { |
|||
delete multiplyResult; |
|||
} |
|||
} |
|||
|
|||
// Explicitly instantiate the solver.
|
|||
template class GmmxxNondeterministicLinearEquationSolver<double>; |
|||
} // namespace solver
|
|||
} // namespace storm
|
@ -0,0 +1,153 @@ |
|||
#include "src/solver/NativeLinearEquationSolver.h"
|
|||
#include "src/settings/Settings.h"
|
|||
#include "src/utility/vector.h"
|
|||
#include "src/exceptions/InvalidStateException.h"
|
|||
|
|||
bool NativeLinearEquationSolverOptionsRegistered = storm::settings::Settings::registerNewModule([] (storm::settings::Settings* instance) -> bool { |
|||
// Offer all available methods as a command line option.
|
|||
std::vector<std::string> methods; |
|||
methods.push_back("jacobi"); |
|||
instance->addOption(storm::settings::OptionBuilder("NativeLinearEquationSolver", "nativelin", "", "The method to be used for solving linear equation systems with the native engine. Available are: jacobi.").addArgument(storm::settings::ArgumentBuilder::createStringArgument("name", "The name of the method to use.").addValidationFunctionString(storm::settings::ArgumentValidators::stringInListValidator(methods)).setDefaultValueString("jacobi").build()).build()); |
|||
|
|||
instance->addOption(storm::settings::OptionBuilder("NativeLinearEquationSolver", "maxiter", "i", "The maximal number of iterations to perform before iterative solving is aborted.").addArgument(storm::settings::ArgumentBuilder::createUnsignedIntegerArgument("count", "The maximal iteration count.").setDefaultValueUnsignedInteger(10000).build()).build()); |
|||
|
|||
instance->addOption(storm::settings::OptionBuilder("NativeLinearEquationSolver", "precision", "", "The precision used for detecting convergence of iterative methods.").addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("value", "The precision to achieve.").setDefaultValueDouble(1e-06).addValidationFunctionDouble(storm::settings::ArgumentValidators::doubleRangeValidatorExcluding(0.0, 1.0)).build()).build()); |
|||
|
|||
instance->addOption(storm::settings::OptionBuilder("NativeLinearEquationSolver", "absolute", "", "Whether the relative or the absolute error is considered for deciding convergence.").build()); |
|||
|
|||
return true; |
|||
}); |
|||
|
|||
namespace storm { |
|||
namespace solver { |
|||
|
|||
template<typename ValueType> |
|||
NativeLinearEquationSolver<ValueType>::NativeLinearEquationSolver(SolutionMethod method, double precision, uint_fast64_t maximalNumberOfIterations, bool relative) : method(method), precision(precision), relative(relative), maximalNumberOfIterations(maximalNumberOfIterations) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<typename ValueType> |
|||
NativeLinearEquationSolver<ValueType>::NativeLinearEquationSolver() { |
|||
// Get the settings object to customize linear solving.
|
|||
storm::settings::Settings* settings = storm::settings::Settings::getInstance(); |
|||
|
|||
// Get appropriate settings.
|
|||
maximalNumberOfIterations = settings->getOptionByLongName("maxiter").getArgument(0).getValueAsUnsignedInteger(); |
|||
precision = settings->getOptionByLongName("precision").getArgument(0).getValueAsDouble(); |
|||
relative = settings->isSet("absolute"); |
|||
|
|||
// Determine the method to be used.
|
|||
std::string const& methodAsString = settings->getOptionByLongName("nativelin").getArgument(0).getValueAsString(); |
|||
if (methodAsString == "jacobi") { |
|||
method = JACOBI; |
|||
} |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
AbstractLinearEquationSolver<ValueType>* NativeLinearEquationSolver<ValueType>::clone() const { |
|||
return new NativeLinearEquationSolver<ValueType>(*this); |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void NativeLinearEquationSolver<ValueType>::solveEquationSystem(storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType>& x, std::vector<ValueType> const& b, std::vector<ValueType>* multiplyResult) const { |
|||
// Get a Jacobi decomposition of the matrix A.
|
|||
std::pair<storm::storage::SparseMatrix<ValueType>, storm::storage::SparseMatrix<ValueType>> jacobiDecomposition = A.getJacobiDecomposition(); |
|||
|
|||
// To avoid copying the contents of the vector in the loop, we create a temporary x to swap with.
|
|||
bool multiplyResultProvided = true; |
|||
std::vector<ValueType>* nextX = multiplyResult; |
|||
if (nextX == nullptr) { |
|||
nextX = new std::vector<ValueType>(x.size()); |
|||
multiplyResultProvided = false; |
|||
} |
|||
std::vector<ValueType> const* copyX = nextX; |
|||
std::vector<ValueType>* currentX = &x; |
|||
|
|||
// Target vector for precision calculation.
|
|||
std::vector<ValueType> tmpX(x.size()); |
|||
|
|||
// Set up additional environment variables.
|
|||
uint_fast64_t iterationCount = 0; |
|||
bool converged = false; |
|||
|
|||
while (!converged && iterationCount < maximalNumberOfIterations) { |
|||
// Compute D^-1 * (b - LU * x) and store result in nextX.
|
|||
jacobiDecomposition.first.multiplyWithVector(*currentX, tmpX); |
|||
storm::utility::vector::scaleVectorInPlace(tmpX, -storm::utility::constantOne<ValueType>()); |
|||
storm::utility::vector::addVectorsInPlace(tmpX, b); |
|||
jacobiDecomposition.second.multiplyWithVector(tmpX, *nextX); |
|||
|
|||
// Swap the two pointers as a preparation for the next iteration.
|
|||
std::swap(nextX, currentX); |
|||
|
|||
// Now check if the process already converged within our precision.
|
|||
converged = storm::utility::vector::equalModuloPrecision(*currentX, *nextX, precision, relative); |
|||
|
|||
// Increase iteration count so we can abort if convergence is too slow.
|
|||
++iterationCount; |
|||
} |
|||
|
|||
// If the last iteration did not write to the original x we have to swap the contents, because the
|
|||
// output has to be written to the input parameter x.
|
|||
if (currentX == copyX) { |
|||
std::swap(x, *currentX); |
|||
} |
|||
|
|||
// If the vector for the temporary multiplication result was not provided, we need to delete it.
|
|||
if (!multiplyResultProvided) { |
|||
delete copyX; |
|||
} |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void NativeLinearEquationSolver<ValueType>::performMatrixVectorMultiplication(storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType>& x, std::vector<ValueType>* b, uint_fast64_t n, std::vector<ValueType>* multiplyResult) const { |
|||
// Set up some temporary variables so that we can just swap pointers instead of copying the result after
|
|||
// each iteration.
|
|||
std::vector<ValueType>* swap = nullptr; |
|||
std::vector<ValueType>* currentX = &x; |
|||
|
|||
bool multiplyResultProvided = true; |
|||
std::vector<ValueType>* nextX = multiplyResult; |
|||
if (nextX == nullptr) { |
|||
nextX = new std::vector<ValueType>(x.size()); |
|||
multiplyResultProvided = false; |
|||
} |
|||
std::vector<ValueType> const* copyX = nextX; |
|||
|
|||
// Now perform matrix-vector multiplication as long as we meet the bound.
|
|||
for (uint_fast64_t i = 0; i < n; ++i) { |
|||
A.multiplyWithVector(*currentX, *nextX); |
|||
std::swap(nextX, currentX); |
|||
|
|||
// If requested, add an offset to the current result vector.
|
|||
if (b != nullptr) { |
|||
storm::utility::vector::addVectorsInPlace(*currentX, *b); |
|||
} |
|||
} |
|||
|
|||
// If we performed an odd number of repetitions, we need to swap the contents of currentVector and x,
|
|||
// because the output is supposed to be stored in the input vector x.
|
|||
if (currentX == copyX) { |
|||
std::swap(x, *currentX); |
|||
} |
|||
|
|||
// If the vector for the temporary multiplication result was not provided, we need to delete it.
|
|||
if (!multiplyResultProvided) { |
|||
delete copyX; |
|||
} |
|||
} |
|||
|
|||
|
|||
template<typename ValueType> |
|||
std::string NativeLinearEquationSolver<ValueType>::methodToString() const { |
|||
if (method == JACOBI) { |
|||
return "jacobi"; |
|||
} else { |
|||
throw storm::exceptions::InvalidStateException() << "Illegal method '" << method << "' set in NativeLinearEquationSolver."; |
|||
} |
|||
} |
|||
|
|||
// Explicitly instantiate the linear equation solver.
|
|||
template class NativeLinearEquationSolver<double>; |
|||
} |
|||
} |
@ -0,0 +1,65 @@ |
|||
#ifndef STORM_SOLVER_NATIVELINEAREQUATIONSOLVER_H_ |
|||
#define STORM_SOLVER_NATIVELINEAREQUATIONSOLVER_H_ |
|||
|
|||
#include "AbstractLinearEquationSolver.h" |
|||
|
|||
namespace storm { |
|||
namespace solver { |
|||
|
|||
/*! |
|||
* A class that uses StoRM's native matrix operations to implement the AbstractLinearEquationSolver interface. |
|||
*/ |
|||
template<typename ValueType> |
|||
class NativeLinearEquationSolver : public AbstractLinearEquationSolver<ValueType> { |
|||
public: |
|||
// An enumeration specifying the available solution methods. |
|||
enum SolutionMethod { |
|||
JACOBI |
|||
}; |
|||
|
|||
/*! |
|||
* Constructs a linear equation solver with parameters being set according to the settings object. |
|||
*/ |
|||
NativeLinearEquationSolver(); |
|||
|
|||
/*! |
|||
* Constructs a linear equation solver with the given parameters. |
|||
* |
|||
* @param method The method to use for linear equation solving. |
|||
* @param precision The precision to use for convergence detection. |
|||
* @param maximalNumberOfIterations The maximal number of iterations do perform before iteration is aborted. |
|||
* @param relative If set, the relative error rather than the absolute error is considered for convergence |
|||
* detection. |
|||
*/ |
|||
NativeLinearEquationSolver(SolutionMethod method, double precision, uint_fast64_t maximalNumberOfIterations, bool relative = true); |
|||
|
|||
virtual AbstractLinearEquationSolver<ValueType>* clone() const override; |
|||
|
|||
virtual void solveEquationSystem(storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType>& x, std::vector<ValueType> const& b, std::vector<ValueType>* multiplyResult = nullptr) const override; |
|||
|
|||
virtual void performMatrixVectorMultiplication(storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType>& x, std::vector<ValueType>* b, uint_fast64_t n = 1, std::vector<ValueType>* multiplyResult = nullptr) const override; |
|||
|
|||
private: |
|||
/*! |
|||
* Retrieves the string representation of the solution method associated with this solver. |
|||
* |
|||
* @return The string representation of the solution method associated with this solver. |
|||
*/ |
|||
std::string methodToString() const; |
|||
|
|||
// The method to use for solving linear equation systems. |
|||
SolutionMethod method; |
|||
|
|||
// The required precision for the iterative methods. |
|||
double precision; |
|||
|
|||
// Sets whether the relative or absolute error is to be considered for convergence detection. |
|||
bool relative; |
|||
|
|||
// The maximal number of iterations to do before iteration is aborted. |
|||
uint_fast64_t maximalNumberOfIterations; |
|||
}; |
|||
} |
|||
} |
|||
|
|||
#endif /* STORM_SOLVER_NATIVELINEAREQUATIONSOLVER_H_ */ |
@ -0,0 +1,142 @@ |
|||
#include "src/solver/NativeNondeterministicLinearEquationSolver.h"
|
|||
#include "src/settings/Settings.h"
|
|||
#include "src/utility/vector.h"
|
|||
|
|||
bool NativeNondeterministicLinearEquationSolverOptionsRegistered = storm::settings::Settings::registerNewModule([] (storm::settings::Settings* instance) -> bool { |
|||
instance->addOption(storm::settings::OptionBuilder("NativeNondeterminsticLinearEquationSolver", "maxiter", "i", "The maximal number of iterations to perform before iterative solving is aborted.").addArgument(storm::settings::ArgumentBuilder::createUnsignedIntegerArgument("count", "The maximal iteration count.").setDefaultValueUnsignedInteger(10000).build()).build()); |
|||
|
|||
instance->addOption(storm::settings::OptionBuilder("NativeNondeterminsticLinearEquationSolver", "precision", "", "The precision used for detecting convergence of iterative methods.").addArgument(storm::settings::ArgumentBuilder::createDoubleArgument("value", "The precision to achieve.").setDefaultValueDouble(1e-06).addValidationFunctionDouble(storm::settings::ArgumentValidators::doubleRangeValidatorExcluding(0.0, 1.0)).build()).build()); |
|||
|
|||
instance->addOption(storm::settings::OptionBuilder("NativeNondeterminsticLinearEquationSolver", "absolute", "", "Whether the relative or the absolute error is considered for deciding convergence.").build()); |
|||
|
|||
return true; |
|||
}); |
|||
|
|||
namespace storm { |
|||
namespace solver { |
|||
|
|||
template<typename ValueType> |
|||
NativeNondeterministicLinearEquationSolver<ValueType>::NativeNondeterministicLinearEquationSolver() { |
|||
// Get the settings object to customize solving.
|
|||
storm::settings::Settings* settings = storm::settings::Settings::getInstance(); |
|||
|
|||
// Get appropriate settings.
|
|||
maximalNumberOfIterations = settings->getOptionByLongName("maxiter").getArgument(0).getValueAsUnsignedInteger(); |
|||
precision = settings->getOptionByLongName("precision").getArgument(0).getValueAsDouble(); |
|||
relative = settings->isSet("absolute"); |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
NativeNondeterministicLinearEquationSolver<ValueType>::NativeNondeterministicLinearEquationSolver(double precision, uint_fast64_t maximalNumberOfIterations, bool relative) : precision(precision), relative(relative), maximalNumberOfIterations(maximalNumberOfIterations) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<typename ValueType> |
|||
AbstractNondeterministicLinearEquationSolver<ValueType>* NativeNondeterministicLinearEquationSolver<ValueType>::clone() const { |
|||
return new NativeNondeterministicLinearEquationSolver<ValueType>(*this); |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void NativeNondeterministicLinearEquationSolver<ValueType>::solveEquationSystem(bool minimize, storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType>& x, std::vector<ValueType> const& b, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices, std::vector<ValueType>* multiplyResult, std::vector<ValueType>* newX) const { |
|||
|
|||
// Set up the environment for the power method. If scratch memory was not provided, we need to create it.
|
|||
bool multiplyResultMemoryProvided = true; |
|||
if (multiplyResult == nullptr) { |
|||
multiplyResult = new std::vector<ValueType>(A.getRowCount()); |
|||
multiplyResultMemoryProvided = false; |
|||
} |
|||
std::vector<ValueType>* currentX = &x; |
|||
bool xMemoryProvided = true; |
|||
if (newX == nullptr) { |
|||
newX = new std::vector<ValueType>(x.size()); |
|||
xMemoryProvided = false; |
|||
} |
|||
std::vector<ValueType>* swap = nullptr; |
|||
uint_fast64_t iterations = 0; |
|||
bool converged = false; |
|||
|
|||
// Keep track of which of the vectors for x is the auxiliary copy.
|
|||
std::vector<ValueType>* copyX = newX; |
|||
|
|||
// Proceed with the iterations as long as the method did not converge or reach the
|
|||
// user-specified maximum number of iterations.
|
|||
while (!converged && iterations < maximalNumberOfIterations) { |
|||
// Compute x' = A*x + b.
|
|||
A.multiplyWithVector(*currentX, *multiplyResult); |
|||
storm::utility::vector::addVectorsInPlace(*multiplyResult, b); |
|||
|
|||
// Reduce the vector x' by applying min/max for all non-deterministic choices as given by the topmost
|
|||
// element of the min/max operator stack.
|
|||
if (minimize) { |
|||
storm::utility::vector::reduceVectorMin(*multiplyResult, *newX, nondeterministicChoiceIndices); |
|||
} else { |
|||
storm::utility::vector::reduceVectorMax(*multiplyResult, *newX, nondeterministicChoiceIndices); |
|||
} |
|||
|
|||
// Determine whether the method converged.
|
|||
converged = storm::utility::vector::equalModuloPrecision(*currentX, *newX, precision, relative); |
|||
|
|||
// Update environment variables.
|
|||
std::swap(currentX, newX); |
|||
++iterations; |
|||
} |
|||
|
|||
// Check if the solver converged and issue a warning otherwise.
|
|||
if (converged) { |
|||
LOG4CPLUS_INFO(logger, "Iterative solver converged after " << iterations << " iterations."); |
|||
} else { |
|||
LOG4CPLUS_WARN(logger, "Iterative solver did not converge after " << iterations << " iterations."); |
|||
} |
|||
|
|||
// If we performed an odd number of iterations, we need to swap the x and currentX, because the newest result
|
|||
// is currently stored in currentX, but x is the output vector.
|
|||
if (currentX == copyX) { |
|||
std::swap(x, *currentX); |
|||
} |
|||
|
|||
if (!xMemoryProvided) { |
|||
delete copyX; |
|||
} |
|||
|
|||
if (!multiplyResultMemoryProvided) { |
|||
delete multiplyResult; |
|||
} |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void NativeNondeterministicLinearEquationSolver<ValueType>::performMatrixVectorMultiplication(bool minimize, storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType>& x, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices, std::vector<ValueType>* b, uint_fast64_t n, std::vector<ValueType>* multiplyResult) const { |
|||
|
|||
// If scratch memory was not provided, we need to create it.
|
|||
bool multiplyResultMemoryProvided = true; |
|||
if (multiplyResult == nullptr) { |
|||
multiplyResult = new std::vector<ValueType>(A.getRowCount()); |
|||
multiplyResultMemoryProvided = false; |
|||
} |
|||
|
|||
// Now perform matrix-vector multiplication as long as we meet the bound of the formula.
|
|||
for (uint_fast64_t i = 0; i < n; ++i) { |
|||
A.multiplyWithVector(x, *multiplyResult); |
|||
|
|||
// Add b if it is non-null.
|
|||
if (b != nullptr) { |
|||
storm::utility::vector::addVectorsInPlace(*multiplyResult, *b); |
|||
} |
|||
|
|||
// Reduce the vector x' by applying min/max for all non-deterministic choices as given by the topmost
|
|||
// element of the min/max operator stack.
|
|||
if (minimize) { |
|||
storm::utility::vector::reduceVectorMin(*multiplyResult, x, nondeterministicChoiceIndices); |
|||
} else { |
|||
storm::utility::vector::reduceVectorMax(*multiplyResult, x, nondeterministicChoiceIndices); |
|||
} |
|||
} |
|||
|
|||
if (!multiplyResultMemoryProvided) { |
|||
delete multiplyResult; |
|||
} |
|||
} |
|||
|
|||
// Explicitly instantiate the solver.
|
|||
template class NativeNondeterministicLinearEquationSolver<double>; |
|||
} // namespace solver
|
|||
} // namespace storm
|
@ -0,0 +1,50 @@ |
|||
#ifndef STORM_SOLVER_NATIVENONDETERMINISTICLINEAREQUATIONSOLVER_H_ |
|||
#define STORM_SOLVER_NATIVENONDETERMINISTICLINEAREQUATIONSOLVER_H_ |
|||
|
|||
#include "src/solver/AbstractNondeterministicLinearEquationSolver.h" |
|||
|
|||
namespace storm { |
|||
namespace solver { |
|||
|
|||
/*! |
|||
* A class that uses the gmm++ library to implement the AbstractNondeterminsticLinearEquationSolver interface. |
|||
*/ |
|||
template<class ValueType> |
|||
class NativeNondeterministicLinearEquationSolver : public AbstractNondeterministicLinearEquationSolver<ValueType> { |
|||
public: |
|||
/*! |
|||
* Constructs a nondeterministic linear equation solver with parameters being set according to the settings |
|||
* object. |
|||
*/ |
|||
NativeNondeterministicLinearEquationSolver(); |
|||
|
|||
/*! |
|||
* Constructs a nondeterminstic linear equation solver with the given parameters. |
|||
* |
|||
* @param precision The precision to use for convergence detection. |
|||
* @param maximalNumberOfIterations The maximal number of iterations do perform before iteration is aborted. |
|||
* @param relative If set, the relative error rather than the absolute error is considered for convergence |
|||
* detection. |
|||
*/ |
|||
NativeNondeterministicLinearEquationSolver(double precision, uint_fast64_t maximalNumberOfIterations, bool relative = true); |
|||
|
|||
virtual AbstractNondeterministicLinearEquationSolver<ValueType>* clone() const override; |
|||
|
|||
virtual void performMatrixVectorMultiplication(bool minimize, storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType>& x, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices, std::vector<ValueType>* b = nullptr, uint_fast64_t n = 1, std::vector<ValueType>* newX = nullptr) const override; |
|||
|
|||
virtual void solveEquationSystem(bool minimize, storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType>& x, std::vector<ValueType> const& b, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices, std::vector<ValueType>* multiplyResult = nullptr, std::vector<ValueType>* newX = nullptr) const override; |
|||
|
|||
private: |
|||
// The required precision for the iterative methods. |
|||
double precision; |
|||
|
|||
// Sets whether the relative or absolute error is to be considered for convergence detection. |
|||
bool relative; |
|||
|
|||
// The maximal number of iterations to do before iteration is aborted. |
|||
uint_fast64_t maximalNumberOfIterations; |
|||
}; |
|||
} // namespace solver |
|||
} // namespace storm |
|||
|
|||
#endif /* STORM_SOLVER_NATIVENONDETERMINISTICLINEAREQUATIONSOLVER_H_ */ |
@ -0,0 +1,16 @@ |
|||
#include "src/utility/vector.h"
|
|||
|
|||
template<typename ValueType> |
|||
std::ostream& operator<<(std::ostream& out, std::vector<ValueType> const& vector) { |
|||
out << "vector (" << vector.size() << ") [ "; |
|||
for (uint_fast64_t i = 0; i < vector.size() - 1; ++i) { |
|||
out << vector[i] << ", "; |
|||
} |
|||
out << vector.back(); |
|||
out << " ]"; |
|||
return out; |
|||
} |
|||
|
|||
// Explicitly instantiate functions.
|
|||
template std::ostream& operator<<(std::ostream& out, std::vector<double> const& vector); |
|||
template std::ostream& operator<<(std::ostream& out, std::vector<uint_fast64_t> const& vector); |
@ -1,231 +0,0 @@ |
|||
#include "gtest/gtest.h"
|
|||
#include "storm-config.h"
|
|||
|
|||
#include "src/modelchecker/prctl/SparseMdpPrctlModelChecker.h"
|
|||
#include "src/solver/GmmxxNondeterministicLinearEquationSolver.h"
|
|||
#include "src/settings/Settings.h"
|
|||
#include "src/parser/AutoParser.h"
|
|||
|
|||
TEST(GmmxxMdpPrctlModelCheckerTest, Dice) { |
|||
storm::settings::Settings* s = storm::settings::Settings::getInstance(); |
|||
storm::parser::AutoParser<double> parser(STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.tra", STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.lab", "", STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.flip.trans.rew"); |
|||
|
|||
ASSERT_EQ(parser.getType(), storm::models::MDP); |
|||
|
|||
std::shared_ptr<storm::models::Mdp<double>> mdp = parser.getModel<storm::models::Mdp<double>>(); |
|||
|
|||
ASSERT_EQ(mdp->getNumberOfStates(), 169ull); |
|||
ASSERT_EQ(mdp->getNumberOfTransitions(), 436ull); |
|||
|
|||
storm::modelchecker::prctl::SparseMdpPrctlModelChecker<double> mc(*mdp, std::shared_ptr<storm::solver::AbstractNondeterministicLinearEquationSolver<double>>(new storm::solver::GmmxxNondeterministicLinearEquationSolver<double>())); |
|||
|
|||
storm::property::prctl::Ap<double>* apFormula = new storm::property::prctl::Ap<double>("two"); |
|||
storm::property::prctl::Eventually<double>* eventuallyFormula = new storm::property::prctl::Eventually<double>(apFormula); |
|||
storm::property::prctl::ProbabilisticNoBoundOperator<double>* probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(eventuallyFormula, true); |
|||
|
|||
std::vector<double> result = mc.checkNoBoundOperator(*probFormula); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 0.0277777612209320068), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("two"); |
|||
eventuallyFormula = new storm::property::prctl::Eventually<double>(apFormula); |
|||
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(eventuallyFormula, false); |
|||
|
|||
result = mc.checkNoBoundOperator(*probFormula); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 0.0277777612209320068), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("three"); |
|||
eventuallyFormula = new storm::property::prctl::Eventually<double>(apFormula); |
|||
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(eventuallyFormula, true); |
|||
|
|||
result = mc.checkNoBoundOperator(*probFormula); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 0.0555555224418640136), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("three"); |
|||
eventuallyFormula = new storm::property::prctl::Eventually<double>(apFormula); |
|||
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(eventuallyFormula, false); |
|||
|
|||
result = mc.checkNoBoundOperator(*probFormula); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 0.0555555224418640136), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("four"); |
|||
eventuallyFormula = new storm::property::prctl::Eventually<double>(apFormula); |
|||
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(eventuallyFormula, true); |
|||
|
|||
result = mc.checkNoBoundOperator(*probFormula); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 0.083333283662796020508), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("four"); |
|||
eventuallyFormula = new storm::property::prctl::Eventually<double>(apFormula); |
|||
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(eventuallyFormula, false); |
|||
|
|||
result = mc.checkNoBoundOperator(*probFormula); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 0.083333283662796020508), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("done"); |
|||
storm::property::prctl::ReachabilityReward<double>* reachabilityRewardFormula = new storm::property::prctl::ReachabilityReward<double>(apFormula); |
|||
storm::property::prctl::RewardNoBoundOperator<double>* rewardFormula = new storm::property::prctl::RewardNoBoundOperator<double>(reachabilityRewardFormula, true); |
|||
|
|||
result = mc.checkNoBoundOperator(*rewardFormula); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 7.3333294987678527832), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete rewardFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("done"); |
|||
reachabilityRewardFormula = new storm::property::prctl::ReachabilityReward<double>(apFormula); |
|||
rewardFormula = new storm::property::prctl::RewardNoBoundOperator<double>(reachabilityRewardFormula, false); |
|||
|
|||
result = mc.checkNoBoundOperator(*rewardFormula);; |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 7.3333294987678527832), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete rewardFormula; |
|||
|
|||
storm::parser::AutoParser<double> stateRewardParser(STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.tra", STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.lab", STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.flip.state.rew", ""); |
|||
|
|||
ASSERT_EQ(stateRewardParser.getType(), storm::models::MDP); |
|||
|
|||
std::shared_ptr<storm::models::Mdp<double>> stateRewardMdp = stateRewardParser.getModel<storm::models::Mdp<double>>(); |
|||
|
|||
storm::modelchecker::prctl::SparseMdpPrctlModelChecker<double> stateRewardModelChecker(*stateRewardMdp, std::shared_ptr<storm::solver::AbstractNondeterministicLinearEquationSolver<double>>(new storm::solver::GmmxxNondeterministicLinearEquationSolver<double>())); |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("done"); |
|||
reachabilityRewardFormula = new storm::property::prctl::ReachabilityReward<double>(apFormula); |
|||
rewardFormula = new storm::property::prctl::RewardNoBoundOperator<double>(reachabilityRewardFormula, true); |
|||
|
|||
result = stateRewardModelChecker.checkNoBoundOperator(*rewardFormula); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 7.3333294987678527832), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete rewardFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("done"); |
|||
reachabilityRewardFormula = new storm::property::prctl::ReachabilityReward<double>(apFormula); |
|||
rewardFormula = new storm::property::prctl::RewardNoBoundOperator<double>(reachabilityRewardFormula, false); |
|||
|
|||
result = stateRewardModelChecker.checkNoBoundOperator(*rewardFormula); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 7.3333294987678527832), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete rewardFormula; |
|||
|
|||
storm::parser::AutoParser<double> stateAndTransitionRewardParser(STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.tra", STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.lab", STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.flip.state.rew", STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.flip.trans.rew"); |
|||
|
|||
ASSERT_EQ(stateAndTransitionRewardParser.getType(), storm::models::MDP); |
|||
|
|||
std::shared_ptr<storm::models::Mdp<double>> stateAndTransitionRewardMdp = stateAndTransitionRewardParser.getModel<storm::models::Mdp<double>>(); |
|||
|
|||
storm::modelchecker::prctl::SparseMdpPrctlModelChecker<double> stateAndTransitionRewardModelChecker(*stateAndTransitionRewardMdp, std::shared_ptr<storm::solver::AbstractNondeterministicLinearEquationSolver<double>>(new storm::solver::GmmxxNondeterministicLinearEquationSolver<double>())); |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("done"); |
|||
reachabilityRewardFormula = new storm::property::prctl::ReachabilityReward<double>(apFormula); |
|||
rewardFormula = new storm::property::prctl::RewardNoBoundOperator<double>(reachabilityRewardFormula, true); |
|||
|
|||
result = stateAndTransitionRewardModelChecker.checkNoBoundOperator(*rewardFormula); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - (2.0 * 7.3333294987678527832)), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete rewardFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("done"); |
|||
reachabilityRewardFormula = new storm::property::prctl::ReachabilityReward<double>(apFormula); |
|||
rewardFormula = new storm::property::prctl::RewardNoBoundOperator<double>(reachabilityRewardFormula, false); |
|||
|
|||
result = stateAndTransitionRewardModelChecker.checkNoBoundOperator(*rewardFormula); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - (2.0 * 7.3333294987678527832)), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete rewardFormula; |
|||
} |
|||
|
|||
TEST(GmmxxMdpPrctlModelCheckerTest, AsynchronousLeader) { |
|||
storm::settings::Settings* s = storm::settings::Settings::getInstance(); |
|||
storm::parser::AutoParser<double> parser(STORM_CPP_BASE_PATH "/examples/mdp/asynchronous_leader/leader4.tra", STORM_CPP_BASE_PATH "/examples/mdp/asynchronous_leader/leader4.lab", "", STORM_CPP_BASE_PATH "/examples/mdp/asynchronous_leader/leader4.trans.rew"); |
|||
|
|||
ASSERT_EQ(parser.getType(), storm::models::MDP); |
|||
|
|||
std::shared_ptr<storm::models::Mdp<double>> mdp = parser.getModel<storm::models::Mdp<double>>(); |
|||
|
|||
ASSERT_EQ(mdp->getNumberOfStates(), 3172ull); |
|||
ASSERT_EQ(mdp->getNumberOfTransitions(), 7144ull); |
|||
|
|||
storm::modelchecker::prctl::SparseMdpPrctlModelChecker<double> mc(*mdp, std::shared_ptr<storm::solver::AbstractNondeterministicLinearEquationSolver<double>>(new storm::solver::GmmxxNondeterministicLinearEquationSolver<double>())); |
|||
|
|||
storm::property::prctl::Ap<double>* apFormula = new storm::property::prctl::Ap<double>("elected"); |
|||
storm::property::prctl::Eventually<double>* eventuallyFormula = new storm::property::prctl::Eventually<double>(apFormula); |
|||
storm::property::prctl::ProbabilisticNoBoundOperator<double>* probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(eventuallyFormula, true); |
|||
|
|||
std::vector<double> result = mc.checkNoBoundOperator(*probFormula); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 1.0), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("elected"); |
|||
eventuallyFormula = new storm::property::prctl::Eventually<double>(apFormula); |
|||
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(eventuallyFormula, false); |
|||
|
|||
result = mc.checkNoBoundOperator(*probFormula); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 1.0), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("elected"); |
|||
storm::property::prctl::BoundedEventually<double>* boundedEventuallyFormula = new storm::property::prctl::BoundedEventually<double>(apFormula, 25); |
|||
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(boundedEventuallyFormula, true); |
|||
|
|||
result = mc.checkNoBoundOperator(*probFormula); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 0.0625), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("elected"); |
|||
boundedEventuallyFormula = new storm::property::prctl::BoundedEventually<double>(apFormula, 25); |
|||
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(boundedEventuallyFormula, false); |
|||
|
|||
result = mc.checkNoBoundOperator(*probFormula); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 0.0625), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("elected"); |
|||
storm::property::prctl::ReachabilityReward<double>* reachabilityRewardFormula = new storm::property::prctl::ReachabilityReward<double>(apFormula); |
|||
storm::property::prctl::RewardNoBoundOperator<double>* rewardFormula = new storm::property::prctl::RewardNoBoundOperator<double>(reachabilityRewardFormula, true); |
|||
|
|||
result = mc.checkNoBoundOperator(*rewardFormula);; |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 4.28568908480604982), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete rewardFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("elected"); |
|||
reachabilityRewardFormula = new storm::property::prctl::ReachabilityReward<double>(apFormula); |
|||
rewardFormula = new storm::property::prctl::RewardNoBoundOperator<double>(reachabilityRewardFormula, false); |
|||
|
|||
result = mc.checkNoBoundOperator(*rewardFormula);; |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 4.2856904354441400784), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete rewardFormula; |
|||
} |
@ -0,0 +1,224 @@ |
|||
#include "gtest/gtest.h"
|
|||
#include "storm-config.h"
|
|||
|
|||
#include "src/solver/GmmxxLinearEquationSolver.h"
|
|||
#include "src/settings/Settings.h"
|
|||
|
|||
TEST(GmmxxLinearEquationSolver, SolveWithStandardOptions) { |
|||
ASSERT_NO_THROW(storm::storage::SparseMatrixBuilder<double> builder); |
|||
storm::storage::SparseMatrixBuilder<double> builder; |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 0, 2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 1, 4)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 2, -2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 0, 4)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 1, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 2, 5)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 0, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 1, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 2, 3)); |
|||
|
|||
storm::storage::SparseMatrix<double> A; |
|||
ASSERT_NO_THROW(A = builder.build()); |
|||
|
|||
std::vector<double> x(3); |
|||
std::vector<double> b = {16, -4, -7}; |
|||
|
|||
ASSERT_NO_THROW(storm::solver::GmmxxLinearEquationSolver<double> solver); |
|||
|
|||
storm::solver::GmmxxLinearEquationSolver<double> solver; |
|||
ASSERT_NO_THROW(solver.solveEquationSystem(A, x, b)); |
|||
ASSERT_LT(std::abs(x[0] - 1), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
ASSERT_LT(std::abs(x[1] - 3), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
ASSERT_LT(std::abs(x[2] - (-1)), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
} |
|||
|
|||
TEST(GmmxxLinearEquationSolver, gmres) { |
|||
ASSERT_NO_THROW(storm::storage::SparseMatrixBuilder<double> builder); |
|||
storm::storage::SparseMatrixBuilder<double> builder; |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 0, 2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 1, 4)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 2, -2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 0, 4)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 1, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 2, 5)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 0, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 1, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 2, 3)); |
|||
|
|||
storm::storage::SparseMatrix<double> A; |
|||
ASSERT_NO_THROW(A = builder.build()); |
|||
|
|||
std::vector<double> x(3); |
|||
std::vector<double> b = {16, -4, -7}; |
|||
|
|||
ASSERT_NO_THROW(storm::solver::GmmxxLinearEquationSolver<double> solver(storm::solver::GmmxxLinearEquationSolver<double>::GMRES, 1e-6, 10000, storm::solver::GmmxxLinearEquationSolver<double>::NONE, true, 50)); |
|||
|
|||
storm::solver::GmmxxLinearEquationSolver<double> solver(storm::solver::GmmxxLinearEquationSolver<double>::GMRES, 1e-6, 10000, storm::solver::GmmxxLinearEquationSolver<double>::NONE, true, 50); |
|||
ASSERT_NO_THROW(solver.solveEquationSystem(A, x, b)); |
|||
ASSERT_LT(std::abs(x[0] - 1), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
ASSERT_LT(std::abs(x[1] - 3), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
ASSERT_LT(std::abs(x[2] - (-1)), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
} |
|||
|
|||
TEST(GmmxxLinearEquationSolver, qmr) { |
|||
ASSERT_NO_THROW(storm::storage::SparseMatrixBuilder<double> builder); |
|||
storm::storage::SparseMatrixBuilder<double> builder; |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 0, 2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 1, 4)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 2, -2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 0, 4)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 1, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 2, 5)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 0, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 1, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 2, 3)); |
|||
|
|||
storm::storage::SparseMatrix<double> A; |
|||
ASSERT_NO_THROW(A = builder.build()); |
|||
|
|||
std::vector<double> x(3); |
|||
std::vector<double> b = {16, -4, -7}; |
|||
|
|||
ASSERT_NO_THROW(storm::solver::GmmxxLinearEquationSolver<double> solver(storm::solver::GmmxxLinearEquationSolver<double>::QMR, 1e-6, 10000, storm::solver::GmmxxLinearEquationSolver<double>::NONE)); |
|||
|
|||
storm::solver::GmmxxLinearEquationSolver<double> solver(storm::solver::GmmxxLinearEquationSolver<double>::QMR, 1e-6, 10000, storm::solver::GmmxxLinearEquationSolver<double>::NONE, 50); |
|||
ASSERT_NO_THROW(solver.solveEquationSystem(A, x, b)); |
|||
ASSERT_LT(std::abs(x[0] - 1), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
ASSERT_LT(std::abs(x[1] - 3), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
ASSERT_LT(std::abs(x[2] - (-1)), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
} |
|||
|
|||
TEST(GmmxxLinearEquationSolver, bicgstab) { |
|||
ASSERT_NO_THROW(storm::storage::SparseMatrixBuilder<double> builder); |
|||
storm::storage::SparseMatrixBuilder<double> builder; |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 0, 2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 1, 4)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 2, -2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 0, 4)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 1, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 2, 5)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 0, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 1, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 2, 3)); |
|||
|
|||
storm::storage::SparseMatrix<double> A; |
|||
ASSERT_NO_THROW(A = builder.build()); |
|||
|
|||
std::vector<double> x(3); |
|||
std::vector<double> b = {16, -4, -7}; |
|||
|
|||
ASSERT_NO_THROW(storm::solver::GmmxxLinearEquationSolver<double> solver(storm::solver::GmmxxLinearEquationSolver<double>::BICGSTAB, 1e-6, 10000, storm::solver::GmmxxLinearEquationSolver<double>::NONE)); |
|||
|
|||
storm::solver::GmmxxLinearEquationSolver<double> solver(storm::solver::GmmxxLinearEquationSolver<double>::BICGSTAB, 1e-6, 10000, storm::solver::GmmxxLinearEquationSolver<double>::NONE); |
|||
ASSERT_NO_THROW(solver.solveEquationSystem(A, x, b)); |
|||
ASSERT_LT(std::abs(x[0] - 1), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
ASSERT_LT(std::abs(x[1] - 3), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
ASSERT_LT(std::abs(x[2] - (-1)), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
} |
|||
|
|||
TEST(GmmxxLinearEquationSolver, jacobi) { |
|||
ASSERT_NO_THROW(storm::storage::SparseMatrixBuilder<double> builder); |
|||
storm::storage::SparseMatrixBuilder<double> builder; |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 0, 4)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 1, 2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 2, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 0, 1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 1, -5)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 2, 2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 0, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 1, 2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 2, 4)); |
|||
|
|||
storm::storage::SparseMatrix<double> A; |
|||
ASSERT_NO_THROW(A = builder.build()); |
|||
|
|||
std::vector<double> x(3); |
|||
std::vector<double> b = {11, -16, 1}; |
|||
|
|||
ASSERT_NO_THROW(storm::solver::GmmxxLinearEquationSolver<double> solver(storm::solver::GmmxxLinearEquationSolver<double>::JACOBI, 1e-6, 10000, storm::solver::GmmxxLinearEquationSolver<double>::NONE)); |
|||
|
|||
storm::solver::GmmxxLinearEquationSolver<double> solver(storm::solver::GmmxxLinearEquationSolver<double>::JACOBI, 1e-6, 10000, storm::solver::GmmxxLinearEquationSolver<double>::NONE); |
|||
ASSERT_NO_THROW(solver.solveEquationSystem(A, x, b)); |
|||
ASSERT_LT(std::abs(x[0] - 1), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
ASSERT_LT(std::abs(x[1] - 3), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
ASSERT_LT(std::abs(x[2] - (-1)), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
} |
|||
|
|||
TEST(GmmxxLinearEquationSolver, gmresilu) { |
|||
ASSERT_NO_THROW(storm::storage::SparseMatrixBuilder<double> builder); |
|||
storm::storage::SparseMatrixBuilder<double> builder; |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 0, 2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 1, 4)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 2, -2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 0, 4)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 1, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 2, 5)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 0, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 1, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 2, 3)); |
|||
|
|||
storm::storage::SparseMatrix<double> A; |
|||
ASSERT_NO_THROW(A = builder.build()); |
|||
|
|||
std::vector<double> x(3); |
|||
std::vector<double> b = {16, -4, -7}; |
|||
|
|||
ASSERT_NO_THROW(storm::solver::GmmxxLinearEquationSolver<double> solver(storm::solver::GmmxxLinearEquationSolver<double>::GMRES, 1e-6, 10000, storm::solver::GmmxxLinearEquationSolver<double>::ILU, true, 50)); |
|||
|
|||
storm::solver::GmmxxLinearEquationSolver<double> solver(storm::solver::GmmxxLinearEquationSolver<double>::GMRES, 1e-6, 10000, storm::solver::GmmxxLinearEquationSolver<double>::NONE, true, 50); |
|||
ASSERT_NO_THROW(solver.solveEquationSystem(A, x, b)); |
|||
ASSERT_LT(std::abs(x[0] - 1), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
ASSERT_LT(std::abs(x[1] - 3), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
ASSERT_LT(std::abs(x[2] - (-1)), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
} |
|||
|
|||
TEST(GmmxxLinearEquationSolver, gmresdiag) { |
|||
ASSERT_NO_THROW(storm::storage::SparseMatrixBuilder<double> builder); |
|||
storm::storage::SparseMatrixBuilder<double> builder; |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 0, 2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 1, 4)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 2, -2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 0, 4)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 1, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 2, 5)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 0, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 1, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 2, 3)); |
|||
|
|||
storm::storage::SparseMatrix<double> A; |
|||
ASSERT_NO_THROW(A = builder.build()); |
|||
|
|||
std::vector<double> x(3); |
|||
std::vector<double> b = {16, -4, -7}; |
|||
|
|||
ASSERT_NO_THROW(storm::solver::GmmxxLinearEquationSolver<double> solver(storm::solver::GmmxxLinearEquationSolver<double>::GMRES, 1e-6, 10000, storm::solver::GmmxxLinearEquationSolver<double>::DIAGONAL, true, 50)); |
|||
|
|||
storm::solver::GmmxxLinearEquationSolver<double> solver(storm::solver::GmmxxLinearEquationSolver<double>::GMRES, 1e-6, 10000, storm::solver::GmmxxLinearEquationSolver<double>::NONE, true, 50); |
|||
ASSERT_NO_THROW(solver.solveEquationSystem(A, x, b)); |
|||
ASSERT_LT(std::abs(x[0] - 1), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
ASSERT_LT(std::abs(x[1] - 3), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
ASSERT_LT(std::abs(x[2] - (-1)), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
} |
|||
|
|||
TEST(GmmxxLinearEquationSolver, MatrixVectorMultplication) { |
|||
ASSERT_NO_THROW(storm::storage::SparseMatrixBuilder<double> builder); |
|||
storm::storage::SparseMatrixBuilder<double> builder; |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 1, 0.5)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 4, 0.5)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 2, 0.5)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 4, 0.5)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 3, 0.5)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 4, 0.5)); |
|||
ASSERT_NO_THROW(builder.addNextValue(3, 4, 1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(4, 4, 1)); |
|||
|
|||
storm::storage::SparseMatrix<double> A; |
|||
ASSERT_NO_THROW(A = builder.build()); |
|||
|
|||
std::vector<double> x(5); |
|||
x[4] = 1; |
|||
|
|||
storm::solver::GmmxxLinearEquationSolver<double> solver; |
|||
ASSERT_NO_THROW(solver.performMatrixVectorMultiplication(A, x, nullptr, 4)); |
|||
ASSERT_LT(std::abs(x[0] - 1), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
} |
@ -0,0 +1,33 @@ |
|||
#include "gtest/gtest.h"
|
|||
#include "storm-config.h"
|
|||
|
|||
#include "src/solver/NativeLinearEquationSolver.h"
|
|||
#include "src/settings/Settings.h"
|
|||
|
|||
TEST(NativeLinearEquationSolver, SolveWithStandardOptions) { |
|||
ASSERT_NO_THROW(storm::storage::SparseMatrixBuilder<double> builder); |
|||
storm::storage::SparseMatrixBuilder<double> builder; |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 0, 4)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 1, 2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(0, 2, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 0, 1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 1, -5)); |
|||
ASSERT_NO_THROW(builder.addNextValue(1, 2, 2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 0, -1)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 1, 2)); |
|||
ASSERT_NO_THROW(builder.addNextValue(2, 2, 4)); |
|||
|
|||
storm::storage::SparseMatrix<double> A; |
|||
ASSERT_NO_THROW(A = builder.build()); |
|||
|
|||
std::vector<double> x(3); |
|||
std::vector<double> b = {11, -16, 1}; |
|||
|
|||
ASSERT_NO_THROW(storm::solver::NativeLinearEquationSolver<double> solver); |
|||
|
|||
storm::solver::NativeLinearEquationSolver<double> solver; |
|||
ASSERT_NO_THROW(solver.solveEquationSystem(A, x, b)); |
|||
ASSERT_LT(std::abs(x[0] - 1), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
ASSERT_LT(std::abs(x[1] - 3), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
ASSERT_LT(std::abs(x[2] - (-1)), storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
} |
@ -1,212 +0,0 @@ |
|||
#include "gtest/gtest.h"
|
|||
#include "storm-config.h"
|
|||
|
|||
#include "src/settings/Settings.h"
|
|||
#include "src/modelchecker/prctl/SparseMdpPrctlModelChecker.h"
|
|||
#include "src/solver/GmmxxNondeterministicLinearEquationSolver.h"
|
|||
#include "src/parser/AutoParser.h"
|
|||
|
|||
TEST(GmmxxMdpPrctlModelCheckerTest, AsynchronousLeader) { |
|||
storm::settings::Settings* s = storm::settings::Settings::getInstance(); |
|||
storm::parser::AutoParser<double> parser(STORM_CPP_BASE_PATH "/examples/mdp/asynchronous_leader/leader7.tra", STORM_CPP_BASE_PATH "/examples/mdp/asynchronous_leader/leader7.lab", "", STORM_CPP_BASE_PATH "/examples/mdp/asynchronous_leader/leader7.trans.rew"); |
|||
|
|||
ASSERT_EQ(parser.getType(), storm::models::MDP); |
|||
|
|||
std::shared_ptr<storm::models::Mdp<double>> mdp = parser.getModel<storm::models::Mdp<double>>(); |
|||
|
|||
ASSERT_EQ(mdp->getNumberOfStates(), 2095783ull); |
|||
ASSERT_EQ(mdp->getNumberOfTransitions(), 7714385ull); |
|||
|
|||
storm::modelchecker::prctl::SparseMdpPrctlModelChecker<double> mc(*mdp, std::shared_ptr<storm::solver::AbstractNondeterministicLinearEquationSolver<double>>(new storm::solver::GmmxxNondeterministicLinearEquationSolver<double>())); |
|||
|
|||
storm::property::prctl::Ap<double>* apFormula = new storm::property::prctl::Ap<double>("elected"); |
|||
storm::property::prctl::Eventually<double>* eventuallyFormula = new storm::property::prctl::Eventually<double>(apFormula); |
|||
storm::property::prctl::ProbabilisticNoBoundOperator<double>* probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(eventuallyFormula, true); |
|||
|
|||
LOG4CPLUS_WARN(logger, "Model Checking Pmin=? [F elected] on asynchronous_leader/leader7..."); |
|||
std::vector<double> result = mc.checkNoBoundOperator(*probFormula); |
|||
LOG4CPLUS_WARN(logger, "Done."); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 1.0), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("elected"); |
|||
eventuallyFormula = new storm::property::prctl::Eventually<double>(apFormula); |
|||
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(eventuallyFormula, false); |
|||
|
|||
LOG4CPLUS_WARN(logger, "Model Checking Pmax=? [F elected] on asynchronous_leader/leader7..."); |
|||
result = mc.checkNoBoundOperator(*probFormula); |
|||
LOG4CPLUS_WARN(logger, "Done."); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 1.0), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("elected"); |
|||
storm::property::prctl::BoundedEventually<double>* boundedEventuallyFormula = new storm::property::prctl::BoundedEventually<double>(apFormula, 25ull); |
|||
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(boundedEventuallyFormula, true); |
|||
|
|||
LOG4CPLUS_WARN(logger, "Model Checking Pmin=? [F<=25 elected] on asynchronous_leader/leader7..."); |
|||
result = mc.checkNoBoundOperator(*probFormula); |
|||
LOG4CPLUS_WARN(logger, "Done."); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 0.0), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("elected"); |
|||
boundedEventuallyFormula = new storm::property::prctl::BoundedEventually<double>(apFormula, 25ull); |
|||
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(boundedEventuallyFormula, false); |
|||
|
|||
LOG4CPLUS_WARN(logger, "Model Checking Pmax=? [F<=25 elected] on asynchronous_leader/leader7..."); |
|||
result = mc.checkNoBoundOperator(*probFormula); |
|||
LOG4CPLUS_WARN(logger, "Done."); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 0.0), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("elected"); |
|||
storm::property::prctl::ReachabilityReward<double>* reachabilityRewardFormula = new storm::property::prctl::ReachabilityReward<double>(apFormula); |
|||
storm::property::prctl::RewardNoBoundOperator<double>* rewardFormula = new storm::property::prctl::RewardNoBoundOperator<double>(reachabilityRewardFormula, true); |
|||
|
|||
LOG4CPLUS_WARN(logger, "Model Checking Rmin=? [F elected] on asynchronous_leader/leader7..."); |
|||
result = mc.checkNoBoundOperator(*rewardFormula); |
|||
LOG4CPLUS_WARN(logger, "Done."); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 6.172433512), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete rewardFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("elected"); |
|||
reachabilityRewardFormula = new storm::property::prctl::ReachabilityReward<double>(apFormula); |
|||
rewardFormula = new storm::property::prctl::RewardNoBoundOperator<double>(reachabilityRewardFormula, false); |
|||
|
|||
LOG4CPLUS_WARN(logger, "Model Checking Rmax=? [F elected] on asynchronous_leader/leader7..."); |
|||
result = mc.checkNoBoundOperator(*rewardFormula); |
|||
LOG4CPLUS_WARN(logger, "Done"); |
|||
|
|||
ASSERT_LT(std::abs(result[0] - 6.1724344), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete rewardFormula; |
|||
} |
|||
|
|||
TEST(GmmxxMdpPrctlModelCheckerTest, Consensus) { |
|||
storm::settings::Settings* s = storm::settings::Settings::getInstance(); |
|||
|
|||
storm::parser::AutoParser<double> parser(STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin4_6.tra", STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin4_6.lab", STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin4_6.steps.state.rew", ""); |
|||
|
|||
ASSERT_EQ(parser.getType(), storm::models::MDP); |
|||
|
|||
std::shared_ptr<storm::models::Mdp<double>> mdp = parser.getModel<storm::models::Mdp<double>>(); |
|||
|
|||
ASSERT_EQ(mdp->getNumberOfStates(), 63616ull); |
|||
ASSERT_EQ(mdp->getNumberOfTransitions(), 213472ull); |
|||
|
|||
storm::modelchecker::prctl::SparseMdpPrctlModelChecker<double> mc(*mdp, std::shared_ptr<storm::solver::AbstractNondeterministicLinearEquationSolver<double>>(new storm::solver::GmmxxNondeterministicLinearEquationSolver<double>())); |
|||
|
|||
storm::property::prctl::Ap<double>* apFormula = new storm::property::prctl::Ap<double>("finished"); |
|||
storm::property::prctl::Eventually<double>* eventuallyFormula = new storm::property::prctl::Eventually<double>(apFormula); |
|||
storm::property::prctl::ProbabilisticNoBoundOperator<double>* probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(eventuallyFormula, true); |
|||
|
|||
LOG4CPLUS_WARN(logger, "Model Checking Pmin=? [F finished] on consensus/coin4_6..."); |
|||
std::vector<double> result = mc.checkNoBoundOperator(*probFormula); |
|||
LOG4CPLUS_WARN(logger, "Done."); |
|||
|
|||
ASSERT_LT(std::abs(result[31168] - 1.0), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("finished"); |
|||
storm::property::prctl::Ap<double>* apFormula2 = new storm::property::prctl::Ap<double>("all_coins_equal_0"); |
|||
storm::property::prctl::And<double>* andFormula = new storm::property::prctl::And<double>(apFormula, apFormula2); |
|||
eventuallyFormula = new storm::property::prctl::Eventually<double>(andFormula); |
|||
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(eventuallyFormula, true); |
|||
|
|||
LOG4CPLUS_WARN(logger, "Model Checking Pmin=? [F finished & all_coins_equal_0] on consensus/coin4_6..."); |
|||
result = mc.checkNoBoundOperator(*probFormula); |
|||
LOG4CPLUS_WARN(logger, "Done."); |
|||
|
|||
ASSERT_LT(std::abs(result[31168] - 0.43742828319177884388579), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("finished"); |
|||
apFormula2 = new storm::property::prctl::Ap<double>("all_coins_equal_1"); |
|||
andFormula = new storm::property::prctl::And<double>(apFormula, apFormula2); |
|||
eventuallyFormula = new storm::property::prctl::Eventually<double>(andFormula); |
|||
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(eventuallyFormula, false); |
|||
|
|||
LOG4CPLUS_WARN(logger, "Model Checking Pmax=? [F finished & all_coins_equal_1] on consensus/coin4_6..."); |
|||
result = mc.checkNoBoundOperator(*probFormula); |
|||
LOG4CPLUS_WARN(logger, "Done."); |
|||
|
|||
ASSERT_LT(std::abs(result[31168] - 0.52932863686144482340267813924583606421947479248047), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("finished"); |
|||
apFormula2 = new storm::property::prctl::Ap<double>("agree"); |
|||
storm::property::prctl::Not<double>* notFormula = new storm::property::prctl::Not<double>(apFormula2); |
|||
andFormula = new storm::property::prctl::And<double>(apFormula, notFormula); |
|||
eventuallyFormula = new storm::property::prctl::Eventually<double>(andFormula); |
|||
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(eventuallyFormula, false); |
|||
|
|||
LOG4CPLUS_WARN(logger, "Model Checking Pmax=? [F finished & !agree] on consensus/coin4_6..."); |
|||
result = mc.checkNoBoundOperator(*probFormula); |
|||
LOG4CPLUS_WARN(logger, "Done."); |
|||
|
|||
ASSERT_LT(std::abs(result[31168] - 0.1041409700076474653673841), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("finished"); |
|||
storm::property::prctl::BoundedEventually<double>* boundedEventuallyFormula = new storm::property::prctl::BoundedEventually<double>(apFormula, 50ull); |
|||
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(boundedEventuallyFormula, true); |
|||
|
|||
LOG4CPLUS_WARN(logger, "Model Checking Pmin=? [F<=50 finished] on consensus/coin4_6..."); |
|||
result = mc.checkNoBoundOperator(*probFormula); |
|||
LOG4CPLUS_WARN(logger, "Done."); |
|||
|
|||
ASSERT_LT(std::abs(result[31168] - 0.0), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("finished"); |
|||
boundedEventuallyFormula = new storm::property::prctl::BoundedEventually<double>(apFormula, 50ull); |
|||
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(boundedEventuallyFormula, false); |
|||
|
|||
LOG4CPLUS_WARN(logger, "Model Checking Pmax=? [F<=50 finished] on consensus/coin4_6..."); |
|||
result = mc.checkNoBoundOperator(*probFormula); |
|||
LOG4CPLUS_WARN(logger, "Done."); |
|||
|
|||
ASSERT_LT(std::abs(result[31168] - 0.0), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete probFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("finished"); |
|||
storm::property::prctl::ReachabilityReward<double>* reachabilityRewardFormula = new storm::property::prctl::ReachabilityReward<double>(apFormula); |
|||
storm::property::prctl::RewardNoBoundOperator<double>* rewardFormula = new storm::property::prctl::RewardNoBoundOperator<double>(reachabilityRewardFormula, true); |
|||
|
|||
LOG4CPLUS_WARN(logger, "Model Checking Rmin=? [F finished] on consensus/coin4_6..."); |
|||
result = mc.checkNoBoundOperator(*rewardFormula); |
|||
LOG4CPLUS_WARN(logger, "Done."); |
|||
|
|||
ASSERT_LT(std::abs(result[31168] - 1725.5933133943854045), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete rewardFormula; |
|||
|
|||
apFormula = new storm::property::prctl::Ap<double>("finished"); |
|||
reachabilityRewardFormula = new storm::property::prctl::ReachabilityReward<double>(apFormula); |
|||
rewardFormula = new storm::property::prctl::RewardNoBoundOperator<double>(reachabilityRewardFormula, false); |
|||
|
|||
LOG4CPLUS_WARN(logger, "Model Checking Rmax=? [F finished] on consensus/coin4_6..."); |
|||
result = mc.checkNoBoundOperator(*rewardFormula); |
|||
LOG4CPLUS_WARN(logger, "Done."); |
|||
|
|||
ASSERT_LT(std::abs(result[31168] - 2183.1424220082612919213715), s->getOptionByLongName("precision").getArgument(0).getValueAsDouble()); |
|||
|
|||
delete rewardFormula; |
|||
|
|||
} |
Reference in new issue
xxxxxxxxxx