gereon 12 years ago
parent
commit
131e10545b
  1. 54
      CMakeLists.txt
  2. 3
      examples/dtmc/synchronous_leader/leader.pctl
  3. 6
      examples/mdp/asynchronous_leader/leader.pctl
  4. 4
      examples/mdp/consensus/coin.pctl
  5. 2
      examples/mdp/two_dice/two_dice.nm
  6. 2
      resources/3rdparty/cudd-2.5.0/Makefile
  7. 2
      src/formula/abstract/PathBoundOperator.h
  8. 1
      src/modelchecker/EigenDtmcPrctlModelChecker.h
  9. 2
      src/modelchecker/GmmxxMdpPrctlModelChecker.h
  10. 14
      src/modelchecker/SparseDtmcPrctlModelChecker.h
  11. 12
      src/modelchecker/SparseMdpPrctlModelChecker.h
  12. 6
      src/modelchecker/TopologicalValueIterationMdpPrctlModelChecker.h
  13. 52
      src/models/AbstractDeterministicModel.h
  14. 118
      src/models/AbstractModel.h
  15. 66
      src/models/AbstractNondeterministicModel.h
  16. 258
      src/models/GraphTransitions.h
  17. 40
      src/parser/CslParser.cpp
  18. 30
      src/parser/LtlParser.cpp
  19. 6
      src/parser/PrctlFileParser.cpp
  20. 88
      src/parser/PrctlParser.cpp
  21. 10
      src/parser/PrctlParser.h
  22. 26
      src/storage/SparseMatrix.h
  23. 15
      src/utility/Settings.h
  24. 368
      src/utility/graph.h
  25. 3
      storm-config.h.in
  26. 4
      test/functional/die/testFormulas.prctl
  27. 2
      test/functional/eigen/EigenSparseMatrixTest.cpp
  28. 6
      test/functional/modelchecker/EigenDtmcPrctModelCheckerTest.cpp
  29. 6
      test/functional/modelchecker/GmmxxDtmcPrctModelCheckerTest.cpp
  30. 130
      test/functional/modelchecker/GmmxxMdpPrctModelCheckerTest.cpp
  31. 0
      test/functional/parser/.gitignore
  32. 9
      test/functional/parser/CslParserTest.cpp
  33. 4
      test/functional/parser/LtlParserTest.cpp
  34. 4
      test/functional/parser/ParseMdpTest.cpp
  35. 0
      test/functional/parser/ParsePrismTest.cpp
  36. 0
      test/functional/parser/PrctlParserTest.cpp
  37. 8
      test/functional/parser/ReadLabFileTest.cpp
  38. 8
      test/functional/parser/ReadTraFileTest.cpp
  39. 0
      test/functional/parser/prctl_files/apOnly.prctl
  40. 0
      test/functional/parser/prctl_files/complexFormula.prctl
  41. 0
      test/functional/parser/prctl_files/probabilisticFormula.prctl
  42. 0
      test/functional/parser/prctl_files/probabilisticNoBoundFormula.prctl
  43. 0
      test/functional/parser/prctl_files/propositionalFormula.prctl
  44. 0
      test/functional/parser/prctl_files/rewardFormula.prctl
  45. 0
      test/functional/parser/prctl_files/rewardNoBoundFormula.prctl
  46. 0
      test/functional/parser/readme.txt
  47. 0
      test/functional/storage/BitVectorTest.cpp
  48. 0
      test/functional/storage/SparseMatrixTest.cpp
  49. 0
      test/functional/storage/adapters/EigenAdapterTest.cpp
  50. 0
      test/functional/storage/adapters/GmmAdapterTest.cpp
  51. 0
      test/functional/storage/adapters/StormAdapterTest.cpp
  52. 13
      test/functional/storm-functional-tests.cpp
  53. 153
      test/performance/graph/GraphTest.cpp
  54. 126
      test/performance/modelchecker/GmmxxDtmcPrctModelCheckerTest.cpp
  55. 246
      test/performance/modelchecker/GmmxxMdpPrctModelCheckerTest.cpp
  56. 70
      test/performance/storm-performance-tests.cpp

54
CMakeLists.txt

@ -20,7 +20,7 @@ else()
set (STORM_LIB_SUFFIX a)
set (GTEST_LIBRARY ${PROJECT_SOURCE_DIR}/resources/3rdparty/gtest-1.6.0/libgtest.${STORM_LIB_SUFFIX})
set (GTEST_MAIN_LIBRARY ${PROJECT_SOURCE_DIR}/resources/3rdparty/gtest-1.6.0/libgtest_main.${STORM_LIB_SUFFIX})
set (GTEST_LIBRARIES ${GTEST_LIBRARY}) # as we dont use FindGTest anymore
set (GTEST_LIBRARIES ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY}) # as we dont use FindGTest anymore
endif()
message(STATUS "GTEST_INCLUDE_DIR is ${GTEST_INCLUDE_DIR}")
message(STATUS "GTEST_LIBRARY is ${GTEST_LIBRARY}")
@ -95,7 +95,7 @@ else(CLANG)
# As CLANG is not set as a variable, we need to set it in case we have not matched another compiler.
set (CLANG ON)
# Set standard flags for clang
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -funroll-loops -O4")
set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -funroll-loops -O3")
set (CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ -Wall -Werror -pedantic -Wno-unused-variable -DBOOST_RESULT_OF_USE_TR1 -DBOOST_NO_DECLTYPE")
set (CMAKE_CXX_FLAGS_DEBUG "-g")
@ -126,10 +126,12 @@ file(GLOB_RECURSE STORM_MODELS_FILES ${PROJECT_SOURCE_DIR}/src/models/*.h ${PROJ
file(GLOB_RECURSE STORM_PARSER_FILES ${PROJECT_SOURCE_DIR}/src/parser/*.h ${PROJECT_SOURCE_DIR}/src/parser/*.cpp)
file(GLOB_RECURSE STORM_STORAGE_FILES ${PROJECT_SOURCE_DIR}/src/storage/*.h ${PROJECT_SOURCE_DIR}/src/storage/*.cpp)
file(GLOB_RECURSE STORM_UTILITY_FILES ${PROJECT_SOURCE_DIR}/src/utility/*.h ${PROJECT_SOURCE_DIR}/src/utility/*.cpp)
file(GLOB_RECURSE STORM_IR_FILES ${PROJECT_SOURCE_DIR}/src/ir/*.h ${PROJECT_SOURCE_DIR}/src/ir/*.cpp)
# Test Sources
# Note that the tests also need the source files, except for the main file
file(GLOB_RECURSE STORM_TEST_FILES ${PROJECT_SOURCE_DIR}/test/*.h ${PROJECT_SOURCE_DIR}/test/*.cpp)
file(GLOB_RECURSE STORM_FUNCTIONAL_TEST_FILES ${STORM_CPP_TESTS_BASE_PATH}/functional/*.h ${STORM_CPP_TESTS_BASE_PATH}/functional/*.cpp)
file(GLOB_RECURSE STORM_PERFORMANCE_TEST_FILES ${STORM_CPP_TESTS_BASE_PATH}/performance/*.h ${STORM_CPP_TESTS_BASE_PATH}/performance/*.cpp)
# Group the headers and sources
source_group(main FILES ${STORM_MAIN_FILE})
@ -141,7 +143,9 @@ source_group(models FILES ${STORM_MODELS_FILES})
source_group(parser FILES ${STORM_PARSER_FILES})
source_group(storage FILES ${STORM_STORAGE_FILES})
source_group(utility FILES ${STORM_UTILITY_FILES})
source_group(test FILES ${STORM_TEST_FILES})
source_group(ir FILES ${STORM_IR_FILES})
source_group(functional-test FILES ${STORM_FUNCTIONAL_TEST_FILES})
source_group(performance-test FILES ${STORM_PERFORMANCE_TEST_FILES})
# Add base folder for better inclusion paths
include_directories("${PROJECT_SOURCE_DIR}")
@ -224,15 +228,18 @@ endif(CUDD_LIBRARY_DIRS)
# Add the executables
# Must be created *after* Boost was added because of LINK_DIRECTORIES
add_executable(storm ${STORM_SOURCES} ${STORM_HEADERS})
add_executable(storm-tests ${STORM_TEST_FILES} ${STORM_SOURCES_WITHOUT_MAIN} ${STORM_HEADERS})
add_executable(storm-functional-tests ${STORM_FUNCTIONAL_TEST_FILES} ${STORM_SOURCES_WITHOUT_MAIN} ${STORM_HEADERS})
add_executable(storm-performance-tests ${STORM_PERFORMANCE_TEST_FILES} ${STORM_SOURCES_WITHOUT_MAIN} ${STORM_HEADERS})
# Add target link deps for Boost program options
target_link_libraries(storm ${Boost_LIBRARIES})
target_link_libraries(storm-tests ${Boost_LIBRARIES})
target_link_libraries(storm-functional-tests ${Boost_LIBRARIES})
target_link_libraries(storm-performance-tests ${Boost_LIBRARIES})
if (USE_INTELTBB)
target_link_libraries(storm tbb tbbmalloc)
target_link_libraries(storm-tests tbb tbbmalloc)
target_link_libraries(storm-functional-tests tbb tbbmalloc)
target_link_libraries(storm-performance-tests tbb tbbmalloc)
endif(USE_INTELTBB)
if (APPLE)
@ -253,14 +260,16 @@ if (STORM_USE_COTIRE)
cotire(storm)
target_link_libraries(storm_unity ${Boost_LIBRARIES})
#cotire(storm-tests)
#cotire(storm-functional-tests)
#cotire(storm-performance-tests)
endif()
# Link against libc++abi if requested. May be needed to build on Linux systems using clang.
if (LINK_LIBCXXABI)
message (STATUS "Linking against libc++abi.")
target_link_libraries(storm "c++abi")
target_link_libraries(storm-tests "c++abi")
target_link_libraries(storm-functional-tests "c++abi")
target_link_libraries(storm-performance-tests "c++abi")
endif(LINK_LIBCXXABI)
# Add a target to generate API documentation with Doxygen
@ -279,9 +288,11 @@ if (GTEST_INCLUDE_DIR)
enable_testing()
include_directories(${GTEST_INCLUDE_DIR})
target_link_libraries(storm-tests ${GTEST_LIBRARIES})
target_link_libraries(storm-functional-tests ${GTEST_LIBRARIES})
target_link_libraries(storm-performance-tests ${GTEST_LIBRARIES})
add_test(NAME storm-tests COMMAND storm-tests)
add_test(NAME storm-functional-tests COMMAND storm-functional-tests)
add_test(NAME storm-performance-tests COMMAND storm-performance-tests)
if(MSVC) # VS2012 doesn't support correctly the tuples yet
add_definitions( /D _VARIADIC_MAX=10 )
endif()
@ -293,20 +304,23 @@ if (LOG4CPLUS_INCLUDE_DIR)
if (STORM_USE_COTIRE)
target_link_libraries(storm_unity ${LOG4CPLUS_LIBRARIES})
endif(STORM_USE_COTIRE)
target_link_libraries(storm-tests ${LOG4CPLUS_LIBRARIES})
target_link_libraries(storm-functional-tests ${LOG4CPLUS_LIBRARIES})
target_link_libraries(storm-performance-tests ${LOG4CPLUS_LIBRARIES})
# On Linux, we have to link against librt
if (UNIX AND NOT APPLE)
target_link_libraries(storm rt)
if (STORM_USE_COTIRE)
target_link_libraries(storm_unity rt)
endif(STORM_USE_COTIRE)
target_link_libraries(storm-tests rt)
target_link_libraries(storm-functional-tests rt)
target_link_libraries(storm-performance-tests rt)
endif(UNIX AND NOT APPLE)
endif(LOG4CPLUS_INCLUDE_DIR)
if (CUDD_LIBRARY_DIRS)
target_link_libraries(storm "-lobj -lcudd -lmtr -lst -lutil -lepd")
target_link_libraries(storm-tests "-lobj -lcudd -lmtr -lst -lutil -lepd")
target_link_libraries(storm-functional-tests "-lobj -lcudd -lmtr -lst -lutil -lepd")
target_link_libraries(storm-performance-tests "-lobj -lcudd -lmtr -lst -lutil -lepd")
endif(CUDD_LIBRARY_DIRS)
if (THREADS_FOUND)
@ -315,7 +329,8 @@ if (THREADS_FOUND)
if (STORM_USE_COTIRE)
target_link_libraries(storm_unity ${CMAKE_THREAD_LIBS_INIT})
endif(STORM_USE_COTIRE)
target_link_libraries(storm-tests ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(storm-functional-tests ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(storm-performance-tests ${CMAKE_THREAD_LIBS_INIT})
endif(THREADS_FOUND)
# Configure a header file to pass some of the CMake settings to the source code
@ -324,10 +339,9 @@ configure_file (
"${PROJECT_BINARY_DIR}/storm-config.h"
)
add_custom_target(memcheck valgrind --leak-check=full --show-reachable=yes ${PROJECT_BINARY_DIR}/storm -v --fix-deadlocks ${PROJECT_SOURCE_DIR}/examples/dtmc/crowds/crowds5_5.tra examples/dtmc/crowds/crowds5_5.lab
DEPENDS storm)
add_custom_target(memcheck-tests valgrind --leak-check=full --show-reachable=yes ${PROJECT_BINARY_DIR}/storm-tests -v --fix-deadlocks
DEPENDS storm-tests)
add_custom_target(memcheck valgrind --leak-check=full --show-reachable=yes ${PROJECT_BINARY_DIR}/storm -v --fix-deadlocks ${PROJECT_SOURCE_DIR}/examples/dtmc/crowds/crowds5_5.tra examples/dtmc/crowds/crowds5_5.lab DEPENDS storm)
add_custom_target(memcheck-functional-tests valgrind --leak-check=full --show-reachable=yes ${PROJECT_BINARY_DIR}/storm-functional-tests -v --fix-deadlocks DEPENDS storm-functional-tests)
add_custom_target(memcheck-performance-tests valgrind --leak-check=full --show-reachable=yes ${PROJECT_BINARY_DIR}/storm-performance-tests -v --fix-deadlocks DEPENDS storm-performance-tests)
set (CPPLINT_ARGS --filter=-whitespace/tab,-whitespace/line_length,-legal/copyright,-readability/streams)
add_custom_target(style python cpplint.py ${CPPLINT_ARGS} `find ./src/ -iname "*.h" -or -iname "*.cpp"`)

3
examples/dtmc/synchronous_leader/leader.pctl

@ -1,3 +1,4 @@
P=? [ F elected ]
P=? [ F<=(4*(N+1)) elected ]
// P=? [ F<=(4*(N+1)) elected ]
P=? [ F<=28 elected ]
R=? [ F elected ]

6
examples/mdp/asynchronous_leader/leader.pctl

@ -1,8 +1,8 @@
Pmin=? [ F elected ]
const int K = 25;
Pmin=? [ F<=K elected ]
Pmax=? [ F<=K elected ]
// const int K = 25;
Pmin=? [ F<=25 elected ]
Pmax=? [ F<=25 elected ]
Rmin=? [ F elected ]
Rmax=? [ F elected ]

4
examples/mdp/consensus/coin.pctl

@ -11,8 +11,8 @@ Pmin=? [ F finished & all_coins_equal_1 ]
Pmax=? [ F finished & !agree ]
// Min/max probability of finishing within k steps
Pmin=? [ F<=k finished ]
Pmax=? [ F<=k finished ]
Pmin=? [ F<=50 finished ]
Pmax=? [ F<=50 finished ]
// Min/max expected steps to finish
Rmin=? [ F finished ]

2
examples/mdp/two_dice/two_dice.nm

@ -17,7 +17,7 @@ module die1
[] s1=4 -> 0.5 : (s1'=7) & (d1'=2) + 0.5 : (s1'=7) & (d1'=3);
[] s1=5 -> 0.5 : (s1'=7) & (d1'=4) + 0.5 : (s1'=7) & (d1'=5);
[] s1=6 -> 0.5 : (s1'=2) + 0.5 : (s1'=7) & (d1'=6);
[] s1=7 & s2=7 -> (s1'=7);
[] s1=7 & s2=7 -> 1: (s1'=7);
endmodule
module die2 = die1 [ s1=s2, s2=s1, d1=d2 ] endmodule

2
resources/3rdparty/cudd-2.5.0/Makefile

@ -51,7 +51,7 @@ RANLIB = ranlib
#ICFLAGS =
# These two are typical settings for optimized code with gcc.
#ICFLAGS = -g -O3 -Wall
ICFLAGS = -O3
ICFLAGS = -O4
# Use XCFLAGS to specify machine-dependent compilation flags.
# For some platforms no special flags are needed.

2
src/formula/abstract/PathBoundOperator.h

@ -70,7 +70,7 @@ public:
* @param minimumOperator Indicator, if operator should be minimum or maximum operator.
*/
PathBoundOperator(storm::property::ComparisonType comparisonOperator, T bound, FormulaType* pathFormula, bool minimumOperator)
: comparisonOperator(comparisonOperator), bound(bound), pathFormula(pathFormula), OptimizingOperator(minimumOperator) {
: OptimizingOperator(minimumOperator), comparisonOperator(comparisonOperator), bound(bound), pathFormula(pathFormula) {
// Intentionally left empty
}

1
src/modelchecker/EigenDtmcPrctlModelChecker.h

@ -12,7 +12,6 @@
#include "src/models/Dtmc.h"
#include "src/modelchecker/SparseDtmcPrctlModelChecker.h"
#include "src/utility/GraphAnalyzer.h"
#include "src/utility/ConstTemplates.h"
#include "src/exceptions/NoConvergenceException.h"

2
src/modelchecker/GmmxxMdpPrctlModelChecker.h

@ -151,7 +151,7 @@ private:
if (converged) {
LOG4CPLUS_INFO(logger, "Iterative solver converged after " << iterations << " iterations.");
} else {
LOG4CPLUS_WARN(logger, "Iterative solver did not converge.");
LOG4CPLUS_WARN(logger, "Iterative solver did not converge after " << iterations << " iterations.");
}
}
};

14
src/modelchecker/SparseDtmcPrctlModelChecker.h

@ -11,7 +11,7 @@
#include "src/modelchecker/AbstractModelChecker.h"
#include "src/models/Dtmc.h"
#include "src/utility/Vector.h"
#include "src/utility/GraphAnalyzer.h"
#include "src/utility/graph.h"
#include <vector>
@ -94,10 +94,6 @@ public:
// Make all rows absorbing that violate both sub-formulas or satisfy the second sub-formula.
tmpMatrix.makeRowsAbsorbing(~(*leftStates | *rightStates) | *rightStates);
// Delete obsolete intermediates.
delete leftStates;
delete rightStates;
// Create the vector with which to multiply.
std::vector<Type>* result = new std::vector<Type>(this->getModel().getNumberOfStates());
storm::utility::setVectorValues(result, *rightStates, storm::utility::constGetOne<Type>());
@ -105,7 +101,9 @@ public:
// Perform the matrix vector multiplication as often as required by the formula bound.
this->performMatrixVectorMultiplication(tmpMatrix, *result, nullptr, formula.getBound());
// Return result.
// Delete obsolete intermediates and return result.
delete leftStates;
delete rightStates;
return result;
}
@ -211,7 +209,7 @@ public:
// Then, 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.
std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 = storm::utility::GraphAnalyzer::performProb01(this->getModel(), *leftStates, *rightStates);
std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 = storm::utility::graph::performProb01(this->getModel(), *leftStates, *rightStates);
storm::storage::BitVector statesWithProbability0 = std::move(statesWithProbability01.first);
storm::storage::BitVector statesWithProbability1 = std::move(statesWithProbability01.second);
@ -359,7 +357,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::GraphAnalyzer::performProb1(this->getModel(), trueStates, *targetStates);
storm::storage::BitVector infinityStates = storm::utility::graph::performProb1(this->getModel(), trueStates, *targetStates);
infinityStates.complement();
// Create resulting vector.

12
src/modelchecker/SparseMdpPrctlModelChecker.h

@ -11,7 +11,7 @@
#include "src/modelchecker/AbstractModelChecker.h"
#include "src/models/Mdp.h"
#include "src/utility/Vector.h"
#include "src/utility/GraphAnalyzer.h"
#include "src/utility/graph.h"
#include <vector>
#include <stack>
@ -99,7 +99,7 @@ public:
// Make all rows absorbing that violate both sub-formulas or satisfy the second sub-formula.
tmpMatrix.makeRowsAbsorbing(~(*leftStates | *rightStates) | *rightStates, *this->getModel().getNondeterministicChoiceIndices());
// Create the vector with which to multiply.
std::vector<Type>* result = new std::vector<Type>(this->getModel().getNumberOfStates());
storm::utility::setVectorValues(result, *rightStates, storm::utility::constGetOne<Type>());
@ -215,9 +215,9 @@ public:
// all states that have probability 0 and 1 of satisfying the until-formula.
std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01;
if (this->minimumOperatorStack.top()) {
statesWithProbability01 = storm::utility::GraphAnalyzer::performProb01Min(this->getModel(), *leftStates, *rightStates);
statesWithProbability01 = storm::utility::graph::performProb01Min(this->getModel(), *leftStates, *rightStates);
} else {
statesWithProbability01 = storm::utility::GraphAnalyzer::performProb01Max(this->getModel(), *leftStates, *rightStates);
statesWithProbability01 = storm::utility::graph::performProb01Max(this->getModel(), *leftStates, *rightStates);
}
storm::storage::BitVector statesWithProbability0 = std::move(statesWithProbability01.first);
storm::storage::BitVector statesWithProbability1 = std::move(statesWithProbability01.second);
@ -360,9 +360,9 @@ public:
storm::storage::BitVector infinityStates;
storm::storage::BitVector trueStates(this->getModel().getNumberOfStates(), true);
if (this->minimumOperatorStack.top()) {
infinityStates = storm::utility::GraphAnalyzer::performProb1A(this->getModel(), trueStates, *targetStates);
infinityStates = storm::utility::graph::performProb1A(this->getModel(), this->getModel().getBackwardTransitions(), trueStates, *targetStates);
} else {
infinityStates = storm::utility::GraphAnalyzer::performProb1E(this->getModel(), trueStates, *targetStates);
infinityStates = storm::utility::graph::performProb1E(this->getModel(), this->getModel().getBackwardTransitions(), trueStates, *targetStates);
}
infinityStates.complement();

6
src/modelchecker/TopologicalValueIterationMdpPrctlModelChecker.h

@ -67,10 +67,8 @@ private:
bool relative = s->get<bool>("relative");
// Now, we need to determine the SCCs of the MDP and a topological sort.
std::pair<std::vector<std::vector<uint_fast64_t>>, storm::models::GraphTransitions<Type>> sccDecomposition = storm::utility::GraphAnalyzer::performSccDecomposition(this->getModel(), stronglyConnectedComponents, stronglyConnectedComponentsDependencyGraph);
std::vector<std::vector<uint_fast64_t>> stronglyConnectedComponents = std::move(sccDecomposition.first);
storm::models::GraphTransitions<Type> stronglyConnectedComponentsDependencyGraph = std::move(sccDecomposition.second);
std::vector<std::vector<uint_fast64_t>> stronglyConnectedComponents = storm::utility::GraphAnalyzer::performSccDecomposition(this->getModel(), stronglyConnectedComponents, stronglyConnectedComponentsDependencyGraph);
storm::storage::SparseMatrix<bool> stronglyConnectedComponentsDependencyGraph = this->getModel().extractSccDependencyGraph(stronglyConnectedComponents);
std::vector<uint_fast64_t> topologicalSort = storm::utility::GraphAnalyzer::getTopologicalSort(stronglyConnectedComponentsDependencyGraph);
// Set up the environment for the power method.

52
src/models/AbstractDeterministicModel.h

@ -2,7 +2,6 @@
#define STORM_MODELS_ABSTRACTDETERMINISTICMODEL_H_
#include "AbstractModel.h"
#include "GraphTransitions.h"
#include <memory>
@ -47,44 +46,23 @@ class AbstractDeterministicModel: public AbstractModel<T> {
}
/*!
* Extracts the SCC dependency graph from the model according to the given SCC decomposition.
* Returns an iterator to the successors of the given state.
*
* @param stronglyConnectedComponents A vector containing the SCCs of the system.
* @param stateToSccMap A mapping from state indices to
* @param state The state for which to return the iterator.
* @return An iterator to the successors of the given state.
*/
virtual storm::storage::SparseMatrix<bool> extractSccDependencyGraph(std::vector<std::vector<uint_fast64_t>> const& stronglyConnectedComponents, std::map<uint_fast64_t, uint_fast64_t> const& stateToSccMap) {
// The resulting sparse matrix will have as many rows/columns as there are SCCs.
uint_fast64_t numberOfStates = stronglyConnectedComponents.size();
storm::storage::SparseMatrix<bool> sccDependencyGraph(numberOfStates);
sccDependencyGraph.initialize();
for (uint_fast64_t currentSccIndex = 0; currentSccIndex < stronglyConnectedComponents.size(); ++currentSccIndex) {
// Get the actual SCC.
std::vector<uint_fast64_t> const& scc = stronglyConnectedComponents[currentSccIndex];
// Now, we determine the SCCs which are reachable (in one step) from the current SCC.
std::set<uint_fast64_t> allTargetSccs;
for (auto state : scc) {
for (typename storm::storage::SparseMatrix<T>::ConstIndexIterator succIt = this->getTransitionMatrix()->constColumnIteratorBegin(state), succIte = this->getTransitionMatrix()->constColumnIteratorEnd(state); succIt != succIte; ++succIt) {
uint_fast64_t targetScc = stateToSccMap.find(*succIt)->second;
// We only need to consider transitions that are actually leaving the SCC.
if (targetScc != currentSccIndex) {
allTargetSccs.insert(targetScc);
}
}
}
// Now we can just enumerate all the target SCCs and insert the corresponding transitions.
for (auto targetScc : allTargetSccs) {
sccDependencyGraph.insertNextValue(currentSccIndex, targetScc, true);
}
}
// Finalize the matrix.
sccDependencyGraph.finalize(true);
return sccDependencyGraph;
virtual typename storm::storage::SparseMatrix<T>::ConstIndexIterator constStateSuccessorIteratorBegin(uint_fast64_t state) const {
return this->transitionMatrix->constColumnIteratorBegin(state);
}
/*!
* Returns an iterator pointing to the element past the successors of the given state.
*
* @param state The state for which to return the iterator.
* @return An iterator pointing to the element past the successors of the given state.
*/
virtual typename storm::storage::SparseMatrix<T>::ConstIndexIterator constStateSuccessorIteratorEnd(uint_fast64_t state) const {
return this->transitionMatrix->constColumnIteratorEnd(state);
}
};

118
src/models/AbstractModel.h

@ -91,7 +91,120 @@ class AbstractModel: public std::enable_shared_from_this<AbstractModel<T>> {
* @param stronglyConnectedComponents A vector containing the SCCs of the system.
* @param stateToSccMap A mapping from state indices to
*/
virtual storm::storage::SparseMatrix<bool> extractSccDependencyGraph(std::vector<std::vector<uint_fast64_t>> const& stronglyConnectedComponents, std::map<uint_fast64_t, uint_fast64_t> const& stateToSccMap) = 0;
storm::storage::SparseMatrix<bool> extractSccDependencyGraph(std::vector<std::vector<uint_fast64_t>> const& stronglyConnectedComponents) const {
uint_fast64_t numberOfStates = stronglyConnectedComponents.size();
// First, we need to create a mapping of states to their SCC index, to ease the computation
// of dependency transitions later.
std::vector<uint_fast64_t> stateToSccMap(this->getNumberOfStates());
for (uint_fast64_t i = 0; i < numberOfStates; ++i) {
for (uint_fast64_t j = 0; j < stronglyConnectedComponents[i].size(); ++j) {
stateToSccMap[stronglyConnectedComponents[i][j]] = i;
}
}
// The resulting sparse matrix will have as many rows/columns as there are SCCs.
storm::storage::SparseMatrix<bool> sccDependencyGraph(numberOfStates);
sccDependencyGraph.initialize();
for (uint_fast64_t currentSccIndex = 0; currentSccIndex < stronglyConnectedComponents.size(); ++currentSccIndex) {
// Get the actual SCC.
std::vector<uint_fast64_t> const& scc = stronglyConnectedComponents[currentSccIndex];
// Now, we determine the SCCs which are reachable (in one step) from the current SCC.
std::set<uint_fast64_t> allTargetSccs;
for (auto state : scc) {
for (typename storm::storage::SparseMatrix<T>::ConstIndexIterator succIt = this->constStateSuccessorIteratorBegin(state), succIte = this->constStateSuccessorIteratorEnd(state); succIt != succIte; ++succIt) {
uint_fast64_t targetScc = stateToSccMap[*succIt];
// We only need to consider transitions that are actually leaving the SCC.
if (targetScc != currentSccIndex) {
allTargetSccs.insert(targetScc);
}
}
}
// Now we can just enumerate all the target SCCs and insert the corresponding transitions.
for (auto targetScc : allTargetSccs) {
sccDependencyGraph.insertNextValue(currentSccIndex, targetScc, true);
}
}
// Finalize the matrix.
sccDependencyGraph.finalize(true);
return sccDependencyGraph;
}
/*!
* Retrieves the backward transition relation of the model, i.e. a set of transitions
* between states that correspond to the reversed transition relation of this model.
*
* @return A sparse matrix that represents the backward transitions of this model.
*/
virtual storm::storage::SparseMatrix<bool> getBackwardTransitions() const {
uint_fast64_t numberOfStates = this->getNumberOfStates();
uint_fast64_t numberOfTransitions = this->getNumberOfTransitions();
std::vector<uint_fast64_t> rowIndications(numberOfStates + 1);
std::vector<uint_fast64_t> columnIndications(numberOfTransitions);
std::vector<bool> values(numberOfTransitions, true);
// First, we need to count how many backward transitions each state has.
for (uint_fast64_t i = 0; i < numberOfStates; ++i) {
for (auto rowIt = this->constStateSuccessorIteratorBegin(i), rowIte = this->constStateSuccessorIteratorEnd(i); rowIt != rowIte; ++rowIt) {
rowIndications[*rowIt + 1]++;
}
}
// Now compute the accumulated offsets.
for (uint_fast64_t i = 1; i < numberOfStates; ++i) {
rowIndications[i] = rowIndications[i - 1] + rowIndications[i];
}
// Put a sentinel element at the end of the indices list. This way,
// for each state i the range of indices can be read off between
// state_indices_list[i] and state_indices_list[i + 1].
// FIXME: This should not be necessary and already be implied by the first steps.
rowIndications[numberOfStates] = numberOfTransitions;
// Create an array that stores the next index for each state. Initially
// this corresponds to the previously computed accumulated offsets.
std::vector<uint_fast64_t> nextIndices = rowIndications;
// Now we are ready to actually fill in the list of predecessors for
// every state. Again, we start by considering all but the last row.
for (uint_fast64_t i = 0; i < numberOfStates; ++i) {
for (auto rowIt = this->constStateSuccessorIteratorBegin(i), rowIte = this->constStateSuccessorIteratorEnd(i); rowIt != rowIte; ++rowIt) {
columnIndications[nextIndices[*rowIt]++] = i;
}
}
storm::storage::SparseMatrix<bool> backwardTransitionMatrix(numberOfStates, numberOfStates,
numberOfTransitions,
std::move(rowIndications),
std::move(columnIndications),
std::move(values));
return backwardTransitionMatrix;
}
/*!
* Returns an iterator to the successors of the given state.
*
* @param state The state for which to return the iterator.
* @return An iterator to the successors of the given state.
*/
virtual typename storm::storage::SparseMatrix<T>::ConstIndexIterator constStateSuccessorIteratorBegin(uint_fast64_t state) const = 0;
/*!
* Returns an iterator pointing to the element past the successors of the given state.
*
* @param state The state for which to return the iterator.
* @return An iterator pointing to the element past the successors of the given state.
*/
virtual typename storm::storage::SparseMatrix<T>::ConstIndexIterator constStateSuccessorIteratorEnd(uint_fast64_t state) const = 0;
/*!
* Returns the state space size of the model.
@ -220,10 +333,11 @@ class AbstractModel: public std::enable_shared_from_this<AbstractModel<T>> {
<< std::endl;
}
private:
protected:
/*! A matrix representing the likelihoods of moving between states. */
std::shared_ptr<storm::storage::SparseMatrix<T>> transitionMatrix;
private:
/*! The labeling of the states of the model. */
std::shared_ptr<storm::models::AtomicPropositionsLabeling> stateLabeling;

66
src/models/AbstractNondeterministicModel.h

@ -2,7 +2,6 @@
#define STORM_MODELS_ABSTRACTNONDETERMINISTICMODEL_H_
#include "AbstractModel.h"
#include "GraphTransitions.h"
#include <memory>
@ -56,51 +55,8 @@ class AbstractNondeterministicModel: public AbstractModel<T> {
* @return The number of choices for all states of the MDP.
*/
uint_fast64_t getNumberOfChoices() const {
return this->getTransitionMatrix()->getRowCount();
return this->transitionMatrix->getRowCount();
}
/*!
* Extracts the SCC dependency graph from the model according to the given SCC decomposition.
*
* @param stronglyConnectedComponents A vector containing the SCCs of the system.
* @param stateToSccMap A mapping from state indices to
*/
virtual storm::storage::SparseMatrix<bool> extractSccDependencyGraph(std::vector<std::vector<uint_fast64_t>> const& stronglyConnectedComponents, std::map<uint_fast64_t, uint_fast64_t> const& stateToSccMap) {
// The resulting sparse matrix will have as many rows/columns as there are SCCs.
uint_fast64_t numberOfStates = stronglyConnectedComponents.size();
storm::storage::SparseMatrix<bool> sccDependencyGraph(numberOfStates);
sccDependencyGraph.initialize();
for (uint_fast64_t currentSccIndex = 0; currentSccIndex < stronglyConnectedComponents.size(); ++currentSccIndex) {
// Get the actual SCC.
std::vector<uint_fast64_t> const& scc = stronglyConnectedComponents[currentSccIndex];
// Now, we determine the SCCs which are reachable (in one step) from the current SCC.
std::set<uint_fast64_t> allTargetSccs;
for (auto state : scc) {
for (uint_fast64_t rowIndex = (*nondeterministicChoiceIndices)[state]; rowIndex < (*nondeterministicChoiceIndices)[state + 1]; ++rowIndex) {
for (typename storm::storage::SparseMatrix<T>::ConstIndexIterator succIt = this->getTransitionMatrix()->constColumnIteratorBegin(rowIndex), succIte = this->getTransitionMatrix()->constColumnIteratorEnd(rowIndex); succIt != succIte; ++succIt) {
uint_fast64_t targetScc = stateToSccMap.find(*succIt)->second;
// We only need to consider transitions that are actually leaving the SCC.
if (targetScc != currentSccIndex) {
allTargetSccs.insert(targetScc);
}
}
}
}
// Now we can just enumerate all the target SCCs and insert the corresponding transitions.
for (auto targetScc : allTargetSccs) {
sccDependencyGraph.insertNextValue(currentSccIndex, targetScc, true);
}
}
// Finalize the matrix.
sccDependencyGraph.finalize(true);
return sccDependencyGraph;
}
/*!
* Retrieves the size of the internal representation of the model in memory.
@ -120,6 +76,26 @@ class AbstractNondeterministicModel: public AbstractModel<T> {
std::shared_ptr<std::vector<uint_fast64_t>> getNondeterministicChoiceIndices() const {
return nondeterministicChoiceIndices;
}
/*!
* Returns an iterator to the successors of the given state.
*
* @param state The state for which to return the iterator.
* @return An iterator to the successors of the given state.
*/
virtual typename storm::storage::SparseMatrix<T>::ConstIndexIterator constStateSuccessorIteratorBegin(uint_fast64_t state) const {
return this->transitionMatrix->constColumnIteratorBegin((*nondeterministicChoiceIndices)[state]);
}
/*!
* Returns an iterator pointing to the element past the successors of the given state.
*
* @param state The state for which to return the iterator.
* @return An iterator pointing to the element past the successors of the given state.
*/
virtual typename storm::storage::SparseMatrix<T>::ConstIndexIterator constStateSuccessorIteratorEnd(uint_fast64_t state) const {
return this->transitionMatrix->constColumnIteratorEnd((*nondeterministicChoiceIndices)[state + 1] - 1);
}
private:
/*! A vector of indices mapping states to the choices (rows) in the transition matrix. */

258
src/models/GraphTransitions.h

@ -1,258 +0,0 @@
/*
* GraphTransitions.h
*
* Created on: 17.11.2012
* Author: Christian Dehnert
*/
#ifndef STORM_MODELS_GRAPHTRANSITIONS_H_
#define STORM_MODELS_GRAPHTRANSITIONS_H_
#include "src/storage/SparseMatrix.h"
#include <algorithm>
#include <memory>
namespace storm {
namespace models {
/*!
* This class stores the successors of all states in a state space of the
* given size.
*/
template <class T>
class GraphTransitions {
public:
/*!
* Just typedef the iterator as a pointer to the index type.
*/
typedef const uint_fast64_t * stateSuccessorIterator;
//! Constructor
/*!
* Constructs an object representing the graph structure of the given
* transition relation, which is given by a sparse matrix.
* @param transitionMatrix The (0-based) matrix representing the transition
* relation.
* @param forward If set to true, this objects will store the graph structure
* of the backwards transition relation.
*/
GraphTransitions(storm::storage::SparseMatrix<T> const& transitionMatrix, bool forward)
: numberOfStates(transitionMatrix.getColumnCount()), numberOfTransitions(transitionMatrix.getNonZeroEntryCount()), successorList(numberOfTransitions), stateIndications(numberOfStates + 1) {
if (forward) {
this->initializeForward(transitionMatrix);
} else {
this->initializeBackward(transitionMatrix);
}
}
GraphTransitions(storm::storage::SparseMatrix<T> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices, bool forward)
: numberOfStates(transitionMatrix.getColumnCount()), numberOfTransitions(transitionMatrix.getNonZeroEntryCount()), successorList(numberOfTransitions), stateIndications(numberOfStates + 1) {
if (forward) {
this->initializeForward(transitionMatrix, nondeterministicChoiceIndices);
} else {
this->initializeBackward(transitionMatrix, nondeterministicChoiceIndices);
}
}
GraphTransitions(GraphTransitions<T> const& transitions, std::vector<std::vector<std::uint_fast64_t>> const& stronglyConnectedComponents, std::map<uint_fast64_t, uint_fast64_t> const& stateToSccMap)
: numberOfStates(stronglyConnectedComponents.size()), numberOfTransitions(0), successorList(), stateIndications(numberOfStates + 1) {
this->initializeFromSccDecomposition(transitions, stronglyConnectedComponents, stateToSccMap);
}
GraphTransitions() : numberOfStates(0), numberOfTransitions(0), successorList(), stateIndications() {
// Intentionally left empty.
}
/*!
* Retrieves the size of the internal representation of the graph transitions in memory.
* @return the size of the internal representation of the graph transitions in memory
* measured in bytes.
*/
virtual uint_fast64_t getSizeInMemory() const {
uint_fast64_t result = sizeof(this) + (numberOfStates + numberOfTransitions + 1) * sizeof(uint_fast64_t);
return result;
}
uint_fast64_t getNumberOfStates() const {
return numberOfStates;
}
uint_fast64_t getNumberOfTransitions() const {
return numberOfTransitions;
}
/*!
* Returns an iterator to the successors of the given state.
* @param state The state for which to get the successor iterator.
* @return An iterator to the predecessors of the given states.
*/
stateSuccessorIterator beginStateSuccessorsIterator(uint_fast64_t state) const {
return &(this->successorList[0]) + this->stateIndications[state];
}
/*!
* Returns an iterator referring to the element after the successors of
* the given state.
* @param state The state for which to get the iterator.
* @return An iterator referring to the element after the successors of
* the given state.
*/
stateSuccessorIterator endStateSuccessorsIterator(uint_fast64_t state) const {
return &(this->successorList[0]) + this->stateIndications[state + 1];
}
/*!
* Returns a (naive) string representation of the transitions in this object.
* @returns a (naive) string representation of the transitions in this object.
*/
std::string toString() const {
std::stringstream stream;
for (uint_fast64_t state = 0; state < numberOfStates; ++state) {
for (auto succIt = this->beginStateSuccessorsIterator(state), succIte = this->endStateSuccessorsIterator(state); succIt != succIte; ++succIt) {
stream << state << " -> " << *succIt << std::endl;
}
}
return stream.str();
}
private:
/*!
* Initializes this graph transitions object using the forward transition
* relation given by means of a sparse matrix.
*/
void initializeForward(storm::storage::SparseMatrix<T> const& transitionMatrix) {
// First, we copy the index list from the sparse matrix as this will
// stay the same.
std::copy(transitionMatrix.constColumnIteratorBegin(), transitionMatrix.constColumnIteratorEnd(), this->stateIndications.begin());
// Now we can iterate over all rows of the transition matrix and record the target state.
for (uint_fast64_t i = 0, currentNonZeroElement = 0; i < numberOfStates; i++) {
for (auto rowIt = transitionMatrix.constColumnIteratorBegin(i); rowIt != transitionMatrix.constColumnIteratorEnd(i); ++rowIt) {
this->successorList[currentNonZeroElement++] = *rowIt;
}
}
}
void initializeForward(storm::storage::SparseMatrix<T> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices) {
// We can directly copy the starting indices from the transition matrix as we do not
// eliminate duplicate transitions and therefore will have as many non-zero entries as this
// matrix.
typename storm::storage::SparseMatrix<T>::ConstRowsIterator rowsIt(transitionMatrix);
for (uint_fast64_t i = 0; i < numberOfStates; ++i) {
rowsIt.moveToRow(nondeterministicChoiceIndices[i]);
this->stateIndications[i] = rowsIt.index();
}
this->stateIndications[numberOfStates] = numberOfTransitions;
// Now we can iterate over all rows of the transition matrix and record
// the target state.
for (uint_fast64_t i = 0, currentNonZeroElement = 0; i < numberOfStates; i++) {
for (uint_fast64_t j = nondeterministicChoiceIndices[i]; j < nondeterministicChoiceIndices[i + 1]; ++j) {
for (auto rowIt = transitionMatrix.constColumnIteratorBegin(j); rowIt != transitionMatrix.constColumnIteratorEnd(j); ++rowIt) {
this->successorList[currentNonZeroElement++] = *rowIt;
}
}
}
}
/*!
* Initializes this graph transitions object using the backwards transition
* relation, whose forward transition relation is given by means of a sparse
* matrix.
*/
void initializeBackward(storm::storage::SparseMatrix<T> const& transitionMatrix) {
// First, we need to count how many backward transitions each state has.
for (uint_fast64_t i = 0; i < numberOfStates; ++i) {
for (auto rowIt = transitionMatrix.constColumnIteratorBegin(i); rowIt != transitionMatrix.constColumnIteratorEnd(i); ++rowIt) {
this->stateIndications[*rowIt + 1]++;
}
}
// Now compute the accumulated offsets.
for (uint_fast64_t i = 1; i < numberOfStates; ++i) {
this->stateIndications[i] = this->stateIndications[i - 1] + this->stateIndications[i];
}
// Put a sentinel element at the end of the indices list. This way,
// for each state i the range of indices can be read off between
// state_indices_list[i] and state_indices_list[i + 1].
this->stateIndications[numberOfStates] = numberOfTransitions;
// Create an array that stores the next index for each state. Initially
// this corresponds to the previously computed accumulated offsets.
std::vector<uint_fast64_t> nextIndices = stateIndications;
// Now we are ready to actually fill in the list of predecessors for
// every state. Again, we start by considering all but the last row.
for (uint_fast64_t i = 0; i < numberOfStates; ++i) {
for (auto rowIt = transitionMatrix.constColumnIteratorBegin(i); rowIt != transitionMatrix.constColumnIteratorEnd(i); ++rowIt) {
this->successorList[nextIndices[*rowIt]++] = i;
}
}
}
void initializeBackward(storm::storage::SparseMatrix<T> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices) {
// First, we need to count how many backward transitions each state has.
for (uint_fast64_t i = 0; i < numberOfStates; ++i) {
for (uint_fast64_t j = nondeterministicChoiceIndices[i]; j < nondeterministicChoiceIndices[i + 1]; ++j) {
for (auto rowIt = transitionMatrix.constColumnIteratorBegin(j); rowIt != transitionMatrix.constColumnIteratorEnd(j); ++rowIt) {
this->stateIndications[*rowIt + 1]++;
}
}
}
// Now compute the accumulated offsets.
for (uint_fast64_t i = 1; i < numberOfStates; i++) {
this->stateIndications[i] = this->stateIndications[i - 1] + this->stateIndications[i];
}
// Put a sentinel element at the end of the indices list. This way,
// for each state i the range of indices can be read off between
// state_indices_list[i] and state_indices_list[i + 1].
this->stateIndications[numberOfStates] = numberOfTransitions;
// Create an array that stores the next index for each state. Initially
// this corresponds to the previously computed accumulated offsets.
std::vector<uint_fast64_t> nextIndices = stateIndications;
// Now we are ready to actually fill in the list of predecessors for
// every state. Again, we start by considering all but the last row.
for (uint_fast64_t i = 0; i < numberOfStates; i++) {
for (uint_fast64_t j = nondeterministicChoiceIndices[i]; j < nondeterministicChoiceIndices[i + 1]; ++j) {
for (auto rowIt = transitionMatrix.constColumnIteratorBegin(j); rowIt != transitionMatrix.constColumnIteratorEnd(j); ++rowIt) {
this->successorList[nextIndices[*rowIt]++] = i;
}
}
}
}
/*!
* Store the number of states to determine the highest index at which the
* state_indices_list may be accessed.
*/
uint_fast64_t numberOfStates;
/*!
* Store the number of non-zero transition entries to determine the highest
* index at which the predecessor_list may be accessed.
*/
uint_fast64_t numberOfTransitions;
/*! A list of successors for *all* states. */
std::vector<uint_fast64_t> successorList;
/*!
* A list of indices indicating at which position in the global array the
* successors of a state can be found.
*/
std::vector<uint_fast64_t> stateIndications;
};
} // namespace models
} // namespace storm
#endif /* STORM_MODELS_GRAPHTRANSITIONS_H_ */

40
src/parser/CslParser.cpp

@ -40,7 +40,15 @@ namespace parser {
template<typename Iterator, typename Skipper>
struct CslParser::CslGrammar : qi::grammar<Iterator, storm::property::csl::AbstractCslFormula<double>*(), Skipper > {
CslGrammar() : CslGrammar::base_type(start) {
freeIdentifierName = qi::lexeme[+(qi::alpha | qi::char_('_'))];
//This block contains helper rules that may be used several times
freeIdentifierName = qi::lexeme[qi::alpha >> *(qi::alnum | qi::char_('_'))];
comparisonType = (
(qi::lit(">="))[qi::_val = storm::property::GREATER_EQUAL] |
(qi::lit(">"))[qi::_val = storm::property::GREATER] |
(qi::lit("<="))[qi::_val = storm::property::LESS_EQUAL] |
(qi::lit("<"))[qi::_val = storm::property::LESS]);
//Comment: Empty line or line starting with "//"
comment = (qi::lit("//") >> *(qi::char_))[qi::_val = nullptr];
//This block defines rules for parsing state formulas
stateFormula %= orFormula;
@ -63,25 +71,13 @@ struct CslParser::CslGrammar : qi::grammar<Iterator, storm::property::csl::Abstr
phoenix::new_<storm::property::csl::Ap<double>>(qi::_1)];
atomicProposition.name("state formula");
probabilisticBoundOperator = (
(qi::lit("P") >> qi::lit(">") >> qi::double_ > qi::lit("[") > pathFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::csl::ProbabilisticBoundOperator<double> >(storm::property::GREATER, qi::_1, qi::_2)] |
(qi::lit("P") >> qi::lit(">=") > qi::double_ > qi::lit("[") > pathFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::csl::ProbabilisticBoundOperator<double> >(storm::property::GREATER_EQUAL, qi::_1, qi::_2)] |
(qi::lit("P") >> qi::lit("<") >> qi::double_ > qi::lit("[") > pathFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::csl::ProbabilisticBoundOperator<double> >(storm::property::LESS, qi::_1, qi::_2)] |
(qi::lit("P") > qi::lit("<=") > qi::double_ > qi::lit("[") > pathFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::csl::ProbabilisticBoundOperator<double> >(storm::property::LESS_EQUAL, qi::_1, qi::_2)]
(qi::lit("P") >> comparisonType > qi::double_ > qi::lit("[") > pathFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::csl::ProbabilisticBoundOperator<double> >(qi::_1, qi::_2, qi::_3)]
);
probabilisticBoundOperator.name("state formula");
steadyStateBoundOperator = (
(qi::lit("S") >> qi::lit(">") >> qi::double_ > qi::lit("[") > stateFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::csl::SteadyStateBoundOperator<double> >(storm::property::GREATER, qi::_1, qi::_2)] |
(qi::lit("S") >> qi::lit(">=") >> qi::double_ > qi::lit("[") > stateFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::csl::SteadyStateBoundOperator<double> >(storm::property::GREATER_EQUAL, qi::_1, qi::_2)] |
(qi::lit("S") >> qi::lit("<") >> qi::double_ > qi::lit("[") > stateFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::csl::SteadyStateBoundOperator<double> >(storm::property::LESS, qi::_1, qi::_2)] |
(qi::lit("S") > qi::lit("<=") >> qi::double_ > qi::lit("[") > stateFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::csl::SteadyStateBoundOperator<double> >(storm::property::LESS_EQUAL, qi::_1, qi::_2)]
(qi::lit("S") >> comparisonType > qi::double_ > qi::lit("[") > stateFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::csl::SteadyStateBoundOperator<double> >(qi::_1, qi::_2, qi::_3)]
);
steadyStateBoundOperator.name("state formula");
@ -126,11 +122,18 @@ struct CslParser::CslGrammar : qi::grammar<Iterator, storm::property::csl::Abstr
phoenix::new_<storm::property::csl::Until<double>>(phoenix::bind(&storm::property::csl::AbstractStateFormula<double>::clone, phoenix::bind(&std::shared_ptr<storm::property::csl::AbstractStateFormula<double>>::get, qi::_a)), qi::_2)];
until.name("path formula (for probabilistic operator)");
start = (noBoundOperator | stateFormula);
formula = (noBoundOperator | stateFormula);
formula.name("CSL formula");
start = (((formula) > (comment | qi::eps))[qi::_val = qi::_1] |
comment
) > qi::eoi;
start.name("CSL formula");
}
qi::rule<Iterator, storm::property::csl::AbstractCslFormula<double>*(), Skipper> start;
qi::rule<Iterator, storm::property::csl::AbstractCslFormula<double>*(), Skipper> formula;
qi::rule<Iterator, storm::property::csl::AbstractCslFormula<double>*(), Skipper> comment;
qi::rule<Iterator, storm::property::csl::AbstractStateFormula<double>*(), Skipper> stateFormula;
qi::rule<Iterator, storm::property::csl::AbstractStateFormula<double>*(), Skipper> atomicStateFormula;
@ -155,6 +158,7 @@ struct CslParser::CslGrammar : qi::grammar<Iterator, storm::property::csl::Abstr
qi::rule<Iterator, std::string(), Skipper> freeIdentifierName;
qi::rule<Iterator, storm::property::ComparisonType(), Skipper> comparisonType;
};

30
src/parser/LtlParser.cpp

@ -43,6 +43,11 @@ namespace parser {
template<typename Iterator, typename Skipper>
struct LtlParser::LtlGrammar : qi::grammar<Iterator, storm::property::ltl::AbstractLtlFormula<double>*(), Skipper > {
LtlGrammar() : LtlGrammar::base_type(start) {
//This block contains helper rules that may be used several times
freeIdentifierName = qi::lexeme[qi::alpha >> *(qi::alnum | qi::char_('_'))];
//Comment: Empty line or line starting with "//"
comment = (qi::lit("//") >> *(qi::char_))[qi::_val = nullptr];
freeIdentifierName = qi::lexeme[+(qi::alpha | qi::char_('_'))];
//This block defines rules for parsing state formulas
@ -68,27 +73,9 @@ struct LtlParser::LtlGrammar : qi::grammar<Iterator, storm::property::ltl::Abstr
atomicProposition = (freeIdentifierName)[qi::_val =
phoenix::new_<storm::property::ltl::Ap<double>>(qi::_1)];
atomicProposition.name("LTL formula");
/*probabilisticBoundOperator = (
(qi::lit("P") >> qi::lit(">") >> qi::double_ > qi::lit("[") > LtlFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::ltl::ProbabilisticBoundOperator<double> >(storm::property::GREATER, qi::_1, qi::_2)] |
(qi::lit("P") >> qi::lit(">=") > qi::double_ > qi::lit("[") > LtlFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::ltl::ProbabilisticBoundOperator<double> >(storm::property::GREATER_EQUAL, qi::_1, qi::_2)] |
(qi::lit("P") >> qi::lit("<") >> qi::double_ > qi::lit("[") > LtlFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::ltl::ProbabilisticBoundOperator<double> >(storm::property::LESS, qi::_1, qi::_2)] |
(qi::lit("P") >> qi::lit("<=") > qi::double_ > qi::lit("[") > LtlFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::ltl::ProbabilisticBoundOperator<double> >(storm::property::LESS_EQUAL, qi::_1, qi::_2)]
);
probabilisticBoundOperator.name("state formula");*/
//This block defines rules for parsing formulas with noBoundOperators
/*noBoundOperator = (probabilisticNoBoundOperator | rewardNoBoundOperator);
noBoundOperator.name("no bound operator");
probabilisticNoBoundOperator = (qi::lit("P") >> qi::lit("=") >> qi::lit("?") >> qi::lit("[") >> LtlFormula >> qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::ltl::ProbabilisticNoBoundOperator<double> >(qi::_1)];
probabilisticNoBoundOperator.name("no bound operator");*/
//This block defines rules for parsing probabilistic path formulas
pathFormula = (boundedEventually | eventually | globally);//(boundedEventually | eventually | globally | boundedUntil | until);
pathFormula = (boundedEventually | eventually | globally);
pathFormula.name("LTL formula");
boundedEventually = (qi::lit("F") >> qi::lit("<=") > qi::int_ > ltlFormula)[qi::_val =
phoenix::new_<storm::property::ltl::BoundedEventually<double>>(qi::_2, qi::_1)];
@ -100,11 +87,14 @@ struct LtlParser::LtlGrammar : qi::grammar<Iterator, storm::property::ltl::Abstr
phoenix::new_<storm::property::ltl::Globally<double> >(qi::_1)];
globally.name("LTL formula");
start = ltlFormula;
start = (((ltlFormula) > (comment | qi::eps))[qi::_val = qi::_1] |
comment
) > qi::eoi;
start.name("LTL formula");
}
qi::rule<Iterator, storm::property::ltl::AbstractLtlFormula<double>*(), Skipper> start;
qi::rule<Iterator, storm::property::ltl::AbstractLtlFormula<double>*(), Skipper> comment;
qi::rule<Iterator, storm::property::ltl::AbstractLtlFormula<double>*(), Skipper> ltlFormula;
qi::rule<Iterator, storm::property::ltl::AbstractLtlFormula<double>*(), Skipper> atomicLtlFormula;

6
src/parser/PrctlFileParser.cpp

@ -40,7 +40,11 @@ std::list<storm::property::prctl::AbstractPrctlFormula<double>*> PrctlFileParser
//The while loop reads the input file line by line
while (std::getline(inputFileStream, line)) {
PrctlParser parser(line);
result.push_back(parser.getFormula());
if (!parser.parsedComment()) {
//lines containing comments will be skipped.
LOG4CPLUS_INFO(logger, "Parsed formula \"" + line + "\" into \"" + parser.getFormula()->toString() + "\"");
result.push_back(parser.getFormula());
}
}
}

88
src/parser/PrctlParser.cpp

@ -35,7 +35,15 @@ namespace parser {
template<typename Iterator, typename Skipper>
struct PrctlParser::PrctlGrammar : qi::grammar<Iterator, storm::property::prctl::AbstractPrctlFormula<double>*(), Skipper > {
PrctlGrammar() : PrctlGrammar::base_type(start) {
freeIdentifierName = qi::lexeme[+(qi::alpha | qi::char_('_'))];
//This block contains helper rules that may be used several times
freeIdentifierName = qi::lexeme[qi::alpha >> *(qi::alnum | qi::char_('_'))];
comparisonType = (
(qi::lit(">="))[qi::_val = storm::property::GREATER_EQUAL] |
(qi::lit(">"))[qi::_val = storm::property::GREATER] |
(qi::lit("<="))[qi::_val = storm::property::LESS_EQUAL] |
(qi::lit("<"))[qi::_val = storm::property::LESS]);
//Comment: Empty line or line starting with "//"
comment = (qi::lit("//") >> *(qi::char_))[qi::_val = nullptr];
//This block defines rules for parsing state formulas
stateFormula %= orFormula;
@ -58,36 +66,47 @@ struct PrctlParser::PrctlGrammar : qi::grammar<Iterator, storm::property::prctl:
phoenix::new_<storm::property::prctl::Ap<double>>(qi::_1)];
atomicProposition.name("state formula");
probabilisticBoundOperator = (
(qi::lit("P") >> qi::lit(">") >> qi::double_ > qi::lit("[") > pathFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::ProbabilisticBoundOperator<double> >(storm::property::GREATER, qi::_1, qi::_2)] |
(qi::lit("P") >> qi::lit(">=") > qi::double_ > qi::lit("[") > pathFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::ProbabilisticBoundOperator<double> >(storm::property::GREATER_EQUAL, qi::_1, qi::_2)] |
(qi::lit("P") >> qi::lit("<") >> qi::double_ > qi::lit("[") > pathFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::ProbabilisticBoundOperator<double> >(storm::property::LESS, qi::_1, qi::_2)] |
(qi::lit("P") >> qi::lit("<=") > qi::double_ > qi::lit("[") > pathFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::ProbabilisticBoundOperator<double> >(storm::property::LESS_EQUAL, qi::_1, qi::_2)]
(qi::lit("P") >> qi::lit("min") > comparisonType > qi::double_ > qi::lit("[") > pathFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::ProbabilisticBoundOperator<double> >(qi::_1, qi::_2, qi::_3, true)] |
(qi::lit("P") >> qi::lit("max") > comparisonType > qi::double_ > qi::lit("[") > pathFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::ProbabilisticBoundOperator<double> >(qi::_1, qi::_2, qi::_3, false)] |
(qi::lit("P") >> comparisonType > qi::double_ > qi::lit("[") > pathFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::ProbabilisticBoundOperator<double> >(qi::_1, qi::_2, qi::_3)]
);
probabilisticBoundOperator.name("state formula");
rewardBoundOperator = (
(qi::lit("R") >> qi::lit(">") >> qi::double_ >> qi::lit("[") >> rewardPathFormula >> qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::RewardBoundOperator<double> >(storm::property::GREATER, qi::_1, qi::_2)] |
(qi::lit("R") >> qi::lit(">=") >> qi::double_ >> qi::lit("[") >> rewardPathFormula >> qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::RewardBoundOperator<double> >(storm::property::GREATER_EQUAL, qi::_1, qi::_2)] |
(qi::lit("R") >> qi::lit("<") >> qi::double_ >> qi::lit("[") >> rewardPathFormula >> qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::RewardBoundOperator<double> >(storm::property::LESS, qi::_1, qi::_2)] |
(qi::lit("R") >> qi::lit("<=")>> qi::double_ >> qi::lit("[") >> rewardPathFormula >> qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::RewardBoundOperator<double> >(storm::property::LESS_EQUAL, qi::_1, qi::_2)]
(qi::lit("R") >> qi::lit("min") > comparisonType > qi::double_ > qi::lit("[") > rewardPathFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::RewardBoundOperator<double> >(qi::_1, qi::_2, qi::_3, true)] |
(qi::lit("R") >> qi::lit("max") > comparisonType > qi::double_ > qi::lit("[") > rewardPathFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::RewardBoundOperator<double> >(qi::_1, qi::_2, qi::_3, false)] |
(qi::lit("R") >> comparisonType > qi::double_ > qi::lit("[") > rewardPathFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::RewardBoundOperator<double> >(qi::_1, qi::_2, qi::_3)]
);
rewardBoundOperator.name("state formula");
//This block defines rules for parsing formulas with noBoundOperators
noBoundOperator = (probabilisticNoBoundOperator | rewardNoBoundOperator);
noBoundOperator.name("no bound operator");
probabilisticNoBoundOperator = (qi::lit("P") >> qi::lit("=") >> qi::lit("?") >> qi::lit("[") >> pathFormula >> qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::ProbabilisticNoBoundOperator<double> >(qi::_1)];
probabilisticNoBoundOperator = (
(qi::lit("P") >> qi::lit("min") >> qi::lit("=") >> qi::lit("?") >> qi::lit("[") >> pathFormula >> qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::ProbabilisticNoBoundOperator<double> >(qi::_1, true)] |
(qi::lit("P") >> qi::lit("max") >> qi::lit("=") >> qi::lit("?") >> qi::lit("[") >> pathFormula >> qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::ProbabilisticNoBoundOperator<double> >(qi::_1, false)] |
(qi::lit("P") >> qi::lit("=") >> qi::lit("?") > qi::lit("[") > pathFormula > qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::ProbabilisticNoBoundOperator<double> >(qi::_1)]
);
probabilisticNoBoundOperator.name("no bound operator");
rewardNoBoundOperator = (qi::lit("R") >> qi::lit("=") >> qi::lit("?") >> qi::lit("[") >> rewardPathFormula >> qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::RewardNoBoundOperator<double> >(qi::_1)];
rewardNoBoundOperator = (
(qi::lit("R") >> qi::lit("min") >> qi::lit("=") >> qi::lit("?") >> qi::lit("[") >> rewardPathFormula >> qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::RewardNoBoundOperator<double> >(qi::_1, true)] |
(qi::lit("R") >> qi::lit("max") >> qi::lit("=") >> qi::lit("?") >> qi::lit("[") >> rewardPathFormula >> qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::RewardNoBoundOperator<double> >(qi::_1, false)] |
(qi::lit("R") >> qi::lit("=") >> qi::lit("?") >> qi::lit("[") >> rewardPathFormula >> qi::lit("]"))[qi::_val =
phoenix::new_<storm::property::prctl::RewardNoBoundOperator<double> >(qi::_1)]
);
rewardNoBoundOperator.name("no bound operator");
//This block defines rules for parsing probabilistic path formulas
@ -95,19 +114,19 @@ struct PrctlParser::PrctlGrammar : qi::grammar<Iterator, storm::property::prctl:
pathFormula.name("path formula");
boundedEventually = (qi::lit("F") >> qi::lit("<=") > qi::int_ > stateFormula)[qi::_val =
phoenix::new_<storm::property::prctl::BoundedEventually<double>>(qi::_2, qi::_1)];
boundedEventually.name("path formula (for probablistic operator)");
boundedEventually.name("path formula (for probabilistic operator)");
eventually = (qi::lit("F") > stateFormula)[qi::_val =
phoenix::new_<storm::property::prctl::Eventually<double> >(qi::_1)];
eventually.name("path formula (for probablistic operator)");
eventually.name("path formula (for probabilistic operator)");
globally = (qi::lit("G") > stateFormula)[qi::_val =
phoenix::new_<storm::property::prctl::Globally<double> >(qi::_1)];
globally.name("path formula (for probablistic operator)");
globally.name("path formula (for probabilistic operator)");
boundedUntil = (stateFormula[qi::_a = phoenix::construct<std::shared_ptr<storm::property::prctl::AbstractStateFormula<double>>>(qi::_1)] >> qi::lit("U") >> qi::lit("<=") > qi::int_ > stateFormula)
[qi::_val = phoenix::new_<storm::property::prctl::BoundedUntil<double>>(phoenix::bind(&storm::property::prctl::AbstractStateFormula<double>::clone, phoenix::bind(&std::shared_ptr<storm::property::prctl::AbstractStateFormula<double>>::get, qi::_a)), qi::_3, qi::_2)];
boundedUntil.name("path formula (for probablistic operator)");
boundedUntil.name("path formula (for probabilistic operator)");
until = (stateFormula[qi::_a = phoenix::construct<std::shared_ptr<storm::property::prctl::AbstractStateFormula<double>>>(qi::_1)] >> qi::lit("U") > stateFormula)[qi::_val =
phoenix::new_<storm::property::prctl::Until<double>>(phoenix::bind(&storm::property::prctl::AbstractStateFormula<double>::clone, phoenix::bind(&std::shared_ptr<storm::property::prctl::AbstractStateFormula<double>>::get, qi::_a)), qi::_2)];
until.name("path formula (for probablistic operator)");
until.name("path formula (for probabilistic operator)");
//This block defines rules for parsing reward path formulas
rewardPathFormula = (cumulativeReward | reachabilityReward | instantaneousReward | steadyStateReward);
@ -123,11 +142,18 @@ struct PrctlParser::PrctlGrammar : qi::grammar<Iterator, storm::property::prctl:
instantaneousReward.name("path formula (for reward operator)");
steadyStateReward = (qi::lit("S"))[qi::_val = phoenix::new_<storm::property::prctl::SteadyStateReward<double>>()];
start = (noBoundOperator | stateFormula);
formula = (noBoundOperator | stateFormula);
formula.name("PRCTL formula");
start = (((formula) > (comment | qi::eps))[qi::_val = qi::_1] |
comment
) > qi::eoi;
start.name("PRCTL formula");
}
qi::rule<Iterator, storm::property::prctl::AbstractPrctlFormula<double>*(), Skipper> start;
qi::rule<Iterator, storm::property::prctl::AbstractPrctlFormula<double>*(), Skipper> formula;
qi::rule<Iterator, storm::property::prctl::AbstractPrctlFormula<double>*(), Skipper> comment;
qi::rule<Iterator, storm::property::prctl::AbstractStateFormula<double>*(), Skipper> stateFormula;
qi::rule<Iterator, storm::property::prctl::AbstractStateFormula<double>*(), Skipper> atomicStateFormula;
@ -158,6 +184,7 @@ struct PrctlParser::PrctlGrammar : qi::grammar<Iterator, storm::property::prctl:
qi::rule<Iterator, std::string(), Skipper> freeIdentifierName;
qi::rule<Iterator, storm::property::ComparisonType(), Skipper> comparisonType;
};
@ -207,12 +234,5 @@ storm::parser::PrctlParser::PrctlParser(std::string formulaString) {
throw storm::exceptions::WrongFormatException() << msg.str();
}
// The syntax can be so wrong that no rule can be matched at all
// In that case, no expectation failure is thrown, but the parser just returns nullptr
// Then, of course the result is not usable, hence we throw a WrongFormatException, too.
if (result_pointer == nullptr) {
throw storm::exceptions::WrongFormatException() << "Syntax error in formula";
}
formula = result_pointer;
}

10
src/parser/PrctlParser.h

@ -38,6 +38,16 @@ class PrctlParser : Parser {
return this->formula;
}
/*!
* Checks whether the line which was parsed was a comment line; also returns true if the line was empty (as the semantics are
* the same)
*
* @return True if the parsed line consisted completely of a (valid) comment, false otherwise.
*/
bool parsedComment() {
return (formula == nullptr);
}
private:
storm::property::prctl::AbstractPrctlFormula<double>* formula;

26
src/storage/SparseMatrix.h

@ -211,7 +211,7 @@ public:
*/
SparseMatrix(uint_fast64_t rows, uint_fast64_t cols) : rowCount(rows), colCount(cols),
nonZeroEntryCount(0), internalStatus(MatrixStatus::UnInitialized), currentSize(0), lastRow(0) {
// Intentionally left empty.
}
/*!
@ -219,11 +219,31 @@ public:
*
* @param size The number of rows and columns of the matrix.
*/
SparseMatrix(uint_fast64_t size)
SparseMatrix(uint_fast64_t size = 0)
: rowCount(size), colCount(size), nonZeroEntryCount(0),
internalStatus(MatrixStatus::UnInitialized), currentSize(0), lastRow(0) {
// Intentionally left empty.
}
/*!
* Constructs a sparse matrix object with the given (moved) contents.
*
* @param rowCount The number of rows.
* @param colCount The number of columns.
* @param nonZeroEntryCount The number of non-zero entries.
* @param rowIndications The vector indicating where the rows start.
* @param columnIndications The vector indicating the column for each non-zero element.
* @param values The vector containing the non-zero values.
*/
SparseMatrix(uint_fast64_t rowCount, uint_fast64_t colCount, uint_fast64_t nonZeroEntryCount,
std::vector<uint_fast64_t>&& rowIndications,
std::vector<uint_fast64_t>&& columnIndications, std::vector<T>&& values)
: rowCount(rowCount), colCount(colCount), nonZeroEntryCount(nonZeroEntryCount),
valueStorage(values), columnIndications(columnIndications),
rowIndications(rowIndications), internalStatus(MatrixStatus::Initialized),
currentSize(0), lastRow(0) {
// Intentionally left empty.
}
/*!
* Initializes the sparse matrix with the given number of non-zero entries

15
src/utility/Settings.h

@ -52,7 +52,7 @@ namespace settings {
* @brief Get value of a generic option.
*/
template <typename T>
inline const T& get( std::string const & name) const {
const T& get(std::string const& name) const {
if (this->vm.count(name) == 0) throw storm::exceptions::InvalidSettingsException() << "Could not read option " << name << ".";
return this->vm[name].as<T>();
}
@ -60,32 +60,33 @@ namespace settings {
/*!
* @brief Get value of string option.
*/
inline const std::string& getString(std::string const & name) const {
const std::string& getString(std::string const& name) const {
return this->get<std::string>(name);
}
/*!
* @brief Check if an option is set.
*/
inline const bool isSet(std::string const & name) const {
const bool isSet(std::string const& name) const {
return this->vm.count(name) > 0;
}
/*!
* @brief Set an option.
*/
inline void set(std::string const & name) {
void set(std::string const& name) {
bpo::variable_value val;
this->vm.insert( std::make_pair(name, val) );
this->vm.insert(std::make_pair(name, val));
}
/*!
* @brief Set value for an option.
*/
template <typename T>
inline void set(std::string const & name, T const & value) {
void set(std::string const& name, T const& value) {
bpo::variable_value val(value, false);
this->vm.insert( std::make_pair(name, val) );
this->vm.erase(name);
this->vm.insert(std::make_pair(name, val));
}
/*!

368
src/utility/GraphAnalyzer.h → src/utility/graph.h

@ -5,8 +5,8 @@
* Author: Christian Dehnert
*/
#ifndef STORM_UTILITY_GRAPHANALYZER_H_
#define STORM_UTILITY_GRAPHANALYZER_H_
#ifndef STORM_UTILITY_GRAPH_H_
#define STORM_UTILITY_GRAPH_H_
#include "src/models/AbstractDeterministicModel.h"
#include "src/models/AbstractNondeterministicModel.h"
@ -20,27 +20,8 @@ extern log4cplus::Logger logger;
namespace storm {
namespace utility {
class GraphAnalyzer {
public:
/*!
* Computes the sets of states that have probability 0 or 1, respectively, of satisfying phi until psi in a
* deterministic model.
*
* @param model The model whose graph structure to search.
* @param phiStates The set of all states satisfying phi.
* @param psiStates The set of all states satisfying psi.
* @return A pair of bit vectors such that the first bit vector stores the indices of all states
* with probability 0 and the second stores all indices of states with probability 1.
*/
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 = GraphAnalyzer::performProbGreater0(model, phiStates, psiStates);
result.second = GraphAnalyzer::performProb1(model, phiStates, psiStates, result.first);
result.first.complement();
return result;
}
namespace graph {
/*!
* Performs a backwards breadt-first search trough the underlying graph structure
@ -53,12 +34,12 @@ public:
* @return A bit vector with all indices of states that have a probability greater than 0.
*/
template <typename T>
static storm::storage::BitVector performProbGreater0(storm::models::AbstractDeterministicModel<T> const& model, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
storm::storage::BitVector performProbGreater0(storm::models::AbstractDeterministicModel<T> const& model, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
// Prepare the resulting bit vector.
storm::storage::BitVector statesWithProbabilityGreater0(model.getNumberOfStates());
// Get the backwards transition relation from the model to ease the search.
storm::models::GraphTransitions<T> backwardTransitions(*model.getTransitionMatrix(), false);
storm::storage::SparseMatrix<bool> backwardTransitions = model.getBackwardTransitions();
// Add all psi states as the already satisfy the condition.
statesWithProbabilityGreater0 |= psiStates;
@ -73,7 +54,7 @@ public:
uint_fast64_t currentState = stack.back();
stack.pop_back();
for(auto it = backwardTransitions.beginStateSuccessorsIterator(currentState); it != backwardTransitions.endStateSuccessorsIterator(currentState); ++it) {
for(auto it = backwardTransitions.constColumnIteratorBegin(currentState); it != backwardTransitions.constColumnIteratorEnd(currentState); ++it) {
if (phiStates.get(*it) && !statesWithProbabilityGreater0.get(*it)) {
statesWithProbabilityGreater0.set(*it, true);
stack.push_back(*it);
@ -100,8 +81,8 @@ public:
* @return A bit vector with all indices of states that have a probability greater than 1.
*/
template <typename T>
static 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 = GraphAnalyzer::performProbGreater0(model, ~psiStates, ~statesWithProbabilityGreater0);
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);
statesWithProbability1.complement();
return statesWithProbability1;
}
@ -119,28 +100,29 @@ public:
* @return A bit vector with all indices of states that have a probability greater than 1.
*/
template <typename T>
static storm::storage::BitVector performProb1(storm::models::AbstractDeterministicModel<T> const& model, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
storm::storage::BitVector statesWithProbabilityGreater0 = GraphAnalyzer::performProbGreater0(model, phiStates, psiStates);
storm::storage::BitVector statesWithProbability1 = GraphAnalyzer::performProbGreater0(model, ~psiStates, ~(statesWithProbabilityGreater0));
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));
statesWithProbability1.complement();
return statesWithProbability1;
}
/*!
* Computes the sets of states that have probability 0 or 1, respectively, of satisfying phi
* until psi in a non-deterministic model in which all non-deterministic choices are resolved
* such that the probability is maximized.
/*!
* Computes the sets of states that have probability 0 or 1, respectively, of satisfying phi until psi in a
* deterministic model.
*
* @param model The model whose graph structure to search.
* @param phiStates The set of all states satisfying phi.
* @param psiStates The set of all states satisfying psi.
* @return A pair of bit vectors that represent all states with probability 0 and 1, respectively.
* @return A pair of bit vectors such that the first bit vector stores the indices of all states
* with probability 0 and the second stores all indices of states with probability 1.
*/
template <typename T>
static std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(storm::models::AbstractNondeterministicModel<T> const& model, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
result.first = GraphAnalyzer::performProb0A(model, phiStates, psiStates);
result.second = GraphAnalyzer::performProb1E(model, phiStates, psiStates);
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);
result.first.complement();
return result;
}
@ -151,17 +133,15 @@ public:
* scheduler tries to maximize this probability.
*
* @param model The model whose graph structure to search.
* @param backwardTransitions The reversed transition relation of the model.
* @param phiStates The set of all states satisfying phi.
* @param psiStates The set of all states satisfying psi.
* @return A bit vector that represents all states with probability 0.
*/
template <typename T>
static storm::storage::BitVector performProb0A(storm::models::AbstractNondeterministicModel<T> const& model, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
storm::storage::BitVector performProb0A(storm::models::AbstractNondeterministicModel<T> const& model, storm::storage::SparseMatrix<bool> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
// Prepare the resulting bit vector.
storm::storage::BitVector statesWithProbability0(model.getNumberOfStates());
// Get the backwards transition relation from the model to ease the search.
storm::models::GraphTransitions<T> backwardTransitions(*model.getTransitionMatrix(), *model.getNondeterministicChoiceIndices(), false);
// Add all psi states as the already satisfy the condition.
statesWithProbability0 |= psiStates;
@ -176,7 +156,7 @@ public:
uint_fast64_t currentState = stack.back();
stack.pop_back();
for(auto it = backwardTransitions.beginStateSuccessorsIterator(currentState); it != backwardTransitions.endStateSuccessorsIterator(currentState); ++it) {
for(auto it = backwardTransitions.constColumnIteratorBegin(currentState), ite = backwardTransitions.constColumnIteratorEnd(currentState); it != ite; ++it) {
if (phiStates.get(*it) && !statesWithProbability0.get(*it)) {
statesWithProbability0.set(*it, true);
stack.push_back(*it);
@ -196,19 +176,17 @@ public:
* scheduler tries to maximize this probability.
*
* @param model The model whose graph structure to search.
* @param backwardTransitions The reversed transition relation of the model.
* @param phiStates The set of all states satisfying phi.
* @param psiStates The set of all states satisfying psi.
* @return A bit vector that represents all states with probability 1.
*/
template <typename T>
static storm::storage::BitVector performProb1E(storm::models::AbstractNondeterministicModel<T> const& model, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
storm::storage::BitVector performProb1E(storm::models::AbstractNondeterministicModel<T> const& model, storm::storage::SparseMatrix<bool> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
// Get some temporaries for convenience.
std::shared_ptr<storm::storage::SparseMatrix<T>> transitionMatrix = model.getTransitionMatrix();
std::shared_ptr<std::vector<uint_fast64_t>> nondeterministicChoiceIndices = model.getNondeterministicChoiceIndices();
// Get the backwards transition relation from the model to ease the search.
storm::models::GraphTransitions<T> backwardTransitions(*model.getTransitionMatrix(), *model.getNondeterministicChoiceIndices(), false);
storm::storage::BitVector currentStates(model.getNumberOfStates(), true);
std::vector<uint_fast64_t> stack;
@ -225,7 +203,7 @@ public:
uint_fast64_t currentState = stack.back();
stack.pop_back();
for(auto it = backwardTransitions.beginStateSuccessorsIterator(currentState); it != backwardTransitions.endStateSuccessorsIterator(currentState); ++it) {
for(auto it = backwardTransitions.constColumnIteratorBegin(currentState), ite = backwardTransitions.constColumnIteratorEnd(currentState); it != ite; ++it) {
if (phiStates.get(*it) && !nextStates.get(*it)) {
// Check whether the predecessor has only successors in the current state set for one of the
// nondeterminstic choices.
@ -261,21 +239,26 @@ public:
return currentStates;
}
/*!
/*!
* Computes the sets of states that have probability 0 or 1, respectively, of satisfying phi
* until psi in a non-deterministic model in which all non-deterministic choices are resolved
* such that the probability is minimized.
* such that the probability is maximized.
*
* @param model The model whose graph structure to search.
* @param phiStates The set of all states satisfying phi.
* @param psiStates The set of all states satisfying psi.
* @return A pair of bit vectors that represent all states with probability 0 and 1, respectively.
*/
template <typename T>
static std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(storm::models::AbstractNondeterministicModel<T> const& model, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
template <typename T>
std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(storm::models::AbstractNondeterministicModel<T> const& model, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
result.first = GraphAnalyzer::performProb0E(model, phiStates, psiStates);
result.second = GraphAnalyzer::performProb1A(model, phiStates, psiStates);
// Get the backwards transition relation from the model to ease the search.
storm::storage::SparseMatrix<bool> backwardTransitions = model.getBackwardTransitions();
result.first = performProb0A(model, backwardTransitions, phiStates, psiStates);
result.second = performProb1E(model, backwardTransitions, phiStates, psiStates);
return result;
}
@ -286,12 +269,13 @@ public:
* scheduler tries to minimize this probability.
*
* @param model The model whose graph structure to search.
* @param backwardTransitions The reversed transition relation of the model.
* @param phiStates The set of all states satisfying phi.
* @param psiStates The set of all states satisfying psi.
* @return A bit vector that represents all states with probability 0.
*/
template <typename T>
static storm::storage::BitVector performProb0E(storm::models::AbstractNondeterministicModel<T> const& model, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
storm::storage::BitVector performProb0E(storm::models::AbstractNondeterministicModel<T> const& model, storm::storage::SparseMatrix<bool> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
// Prepare resulting bit vector.
storm::storage::BitVector statesWithProbability0(model.getNumberOfStates());
@ -299,9 +283,6 @@ public:
std::shared_ptr<storm::storage::SparseMatrix<T>> transitionMatrix = model.getTransitionMatrix();
std::shared_ptr<std::vector<uint_fast64_t>> nondeterministicChoiceIndices = model.getNondeterministicChoiceIndices();
// Get the backwards transition relation from the model to ease the search.
storm::models::GraphTransitions<T> backwardTransitions(*transitionMatrix, *nondeterministicChoiceIndices, false);
// Add all psi states as the already satisfy the condition.
statesWithProbability0 |= psiStates;
@ -315,7 +296,7 @@ public:
uint_fast64_t currentState = stack.back();
stack.pop_back();
for(auto it = backwardTransitions.beginStateSuccessorsIterator(currentState); it != backwardTransitions.endStateSuccessorsIterator(currentState); ++it) {
for(auto it = backwardTransitions.constColumnIteratorBegin(currentState), ite = backwardTransitions.constColumnIteratorEnd(currentState); it != ite; ++it) {
if (phiStates.get(*it) && !statesWithProbability0.get(*it)) {
// Check whether the predecessor has at least one successor in the current state
// set for every nondeterministic choice.
@ -355,19 +336,17 @@ public:
* scheduler tries to minimize this probability.
*
* @param model The model whose graph structure to search.
* @param backwardTransitions The reversed transition relation of the model.
* @param phiStates The set of all states satisfying phi.
* @param psiStates The set of all states satisfying psi.
* @return A bit vector that represents all states with probability 0.
*/
template <typename T>
static storm::storage::BitVector performProb1A(storm::models::AbstractNondeterministicModel<T> const& model, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
storm::storage::BitVector performProb1A(storm::models::AbstractNondeterministicModel<T> const& model, storm::storage::SparseMatrix<bool> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
// Get some temporaries for convenience.
std::shared_ptr<storm::storage::SparseMatrix<T>> transitionMatrix = model.getTransitionMatrix();
std::shared_ptr<std::vector<uint_fast64_t>> nondeterministicChoiceIndices = model.getNondeterministicChoiceIndices();
// Get the backwards transition relation from the model to ease the search.
storm::models::GraphTransitions<T> backwardTransitions(*model.getTransitionMatrix(), *model.getNondeterministicChoiceIndices(), false);
storm::storage::BitVector currentStates(model.getNumberOfStates(), true);
std::vector<uint_fast64_t> stack;
@ -384,7 +363,7 @@ public:
uint_fast64_t currentState = stack.back();
stack.pop_back();
for(auto it = backwardTransitions.beginStateSuccessorsIterator(currentState); it != backwardTransitions.endStateSuccessorsIterator(currentState); ++it) {
for(auto it = backwardTransitions.constColumnIteratorBegin(currentState), ite = backwardTransitions.constColumnIteratorEnd(currentState); it != ite; ++it) {
if (phiStates.get(*it) && !nextStates.get(*it)) {
// Check whether the predecessor has only successors in the current state set for all of the
// nondeterminstic choices.
@ -421,17 +400,142 @@ public:
}
/*!
* Performs a decomposition of the given nondeterministic model into its SCCs.
* Computes the sets of states that have probability 0 or 1, respectively, of satisfying phi
* until psi in a non-deterministic model in which all non-deterministic choices are resolved
* such that the probability is minimized.
*
* @param model The model whose graph structure to search.
* @param phiStates The set of all states satisfying phi.
* @param psiStates The set of all states satisfying psi.
* @return A pair of bit vectors that represent all states with probability 0 and 1, respectively.
*/
template <typename T>
std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(storm::models::AbstractNondeterministicModel<T> const& model, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
// Get the backwards transition relation from the model to ease the search.
storm::storage::SparseMatrix<bool> backwardTransitions = model.getBackwardTransitions();
result.first = performProb0E(model, backwardTransitions, phiStates, psiStates);
result.second = performProb1A(model, backwardTransitions, phiStates, psiStates);
return result;
}
/*!
* Performs an SCC decomposition using Tarjan's algorithm.
*
* @param startState The state at which the search is started.
* @param currentIndex The index that is to be used as the next free index.
* @param stateIndices The vector that stores the index for each state.
* @param lowlinks A vector that stores the lowlink of each state, i.e. the lowest index of a state reachable from
* a particular state.
* @param tarjanStack A stack used for Tarjan's algorithm.
* @param tarjanStackStates A bit vector that represents all states that are currently contained in tarjanStack.
* @param visitedStates A bit vector that stores all states that have already been visited.
* @param matrix The transition matrix representing the graph structure.
* @param stronglyConnectedComponents A vector of strongly connected components to which newly found SCCs are added.
*/
template <typename T>
void performSccDecompositionHelper(uint_fast64_t startState, uint_fast64_t& currentIndex, std::vector<uint_fast64_t>& stateIndices, std::vector<uint_fast64_t>& lowlinks, std::vector<uint_fast64_t>& tarjanStack, storm::storage::BitVector& tarjanStackStates, storm::storage::BitVector& visitedStates, storm::storage::SparseMatrix<T> const& matrix, std::vector<std::vector<uint_fast64_t>>& stronglyConnectedComponents) {
// Create the stacks needed for turning the recursive formulation of Tarjan's algorithm
// into an iterative version. In particular, we keep one stack for states and one stack
// for the iterators. The last one is not strictly needed, but reduces iteration work when
// all successors of a particular state are considered.
std::vector<uint_fast64_t> recursionStateStack;
recursionStateStack.reserve(lowlinks.size());
std::vector<typename storm::storage::SparseMatrix<T>::ConstIndexIterator> recursionIteratorStack;
recursionIteratorStack.reserve(lowlinks.size());
std::vector<bool> statesInStack(lowlinks.size());
// Initialize the recursion stacks with the given initial state (and its successor iterator).
recursionStateStack.push_back(startState);
recursionIteratorStack.push_back(matrix.constColumnIteratorBegin(startState));
recursionStepForward:
while (!recursionStateStack.empty()) {
uint_fast64_t currentState = recursionStateStack.back();
typename storm::storage::SparseMatrix<T>::ConstIndexIterator currentIt = recursionIteratorStack.back();
// Perform the treatment of newly discovered state as defined by Tarjan's algorithm
visitedStates.set(currentState, true);
stateIndices[currentState] = currentIndex;
lowlinks[currentState] = currentIndex;
++currentIndex;
tarjanStack.push_back(currentState);
tarjanStackStates.set(currentState, true);
// Now, traverse all successors of the current state.
for(; currentIt != matrix.constColumnIteratorEnd(currentState); ++currentIt) {
// If we have not visited the successor already, we need to perform the procedure
// recursively on the newly found state.
if (!visitedStates.get(*currentIt)) {
// Save current iterator position so we can continue where we left off later.
recursionIteratorStack.pop_back();
recursionIteratorStack.push_back(currentIt);
// Put unvisited successor on top of our recursion stack and remember that.
recursionStateStack.push_back(*currentIt);
statesInStack[*currentIt] = true;
// Also, put initial value for iterator on corresponding recursion stack.
recursionIteratorStack.push_back(matrix.constColumnIteratorBegin(*currentIt));
// Perform the actual recursion step in an iterative way.
goto recursionStepForward;
recursionStepBackward:
lowlinks[currentState] = std::min(lowlinks[currentState], lowlinks[*currentIt]);
} else if (tarjanStackStates.get(*currentIt)) {
// Update the lowlink of the current state.
lowlinks[currentState] = std::min(lowlinks[currentState], stateIndices[*currentIt]);
}
}
// If the current state is the root of a SCC, we need to pop all states of the SCC from
// the algorithm's stack.
if (lowlinks[currentState] == stateIndices[currentState]) {
stronglyConnectedComponents.push_back(std::vector<uint_fast64_t>());
uint_fast64_t lastState = 0;
do {
// Pop topmost state from the algorithm's stack.
lastState = tarjanStack.back();
tarjanStack.pop_back();
tarjanStackStates.set(lastState, false);
// Add the state to the current SCC.
stronglyConnectedComponents.back().push_back(lastState);
} while (lastState != currentState);
}
// If we reach this point, we have completed the recursive descent for the current state.
// That is, we need to pop it from the recursion stacks.
recursionStateStack.pop_back();
recursionIteratorStack.pop_back();
// If there is at least one state under the current one in our recursion stack, we need
// to restore the topmost state as the current state and jump to the part after the
// original recursive call.
if (recursionStateStack.size() > 0) {
currentState = recursionStateStack.back();
currentIt = recursionIteratorStack.back();
goto recursionStepBackward;
}
}
}
/*!
* Performs a decomposition of the given model into its SCCs.
*
* @param model The nondeterminstic model to decompose.
* @return A pair whose first component represents the SCCs and whose second component represents the dependency
* graph of the SCCs.
* @return A vector of SCCs of the model.
*/
template <typename T>
static std::pair<std::vector<std::vector<uint_fast64_t>>, storm::models::GraphTransitions<T>> performSccDecomposition(storm::models::AbstractNondeterministicModel<T> const& model) {
std::vector<std::vector<uint_fast64_t>> performSccDecomposition(storm::models::AbstractModel<T> const& model) {
LOG4CPLUS_INFO(logger, "Computing SCC decomposition.");
std::pair<std::vector<std::vector<uint_fast64_t>>, storm::models::GraphTransitions<T>> sccDecomposition;
std::vector<std::vector<uint_fast64_t>> scc;
uint_fast64_t numberOfStates = model.getNumberOfStates();
// Set up the environment of Tarjan's algorithm.
@ -441,21 +545,17 @@ public:
std::vector<uint_fast64_t> stateIndices(numberOfStates);
std::vector<uint_fast64_t> lowlinks(numberOfStates);
storm::storage::BitVector visitedStates(numberOfStates);
std::map<uint_fast64_t, uint_fast64_t> stateToSccMap;
// Start the search for SCCs from every vertex in the graph structure, because there is.
uint_fast64_t currentIndex = 0;
for (uint_fast64_t state = 0; state < numberOfStates; ++state) {
if (!visitedStates.get(state)) {
performSccDecompositionHelper(state, currentIndex, stateIndices, lowlinks, tarjanStack, tarjanStackStates, visitedStates, model.getTransitionMatrix(), sccDecomposition.first, stateToSccMap);
performSccDecompositionHelper(state, currentIndex, stateIndices, lowlinks, tarjanStack, tarjanStackStates, visitedStates, *model.getTransitionMatrix(), scc);
}
}
// Finally, determine the dependency graph over the SCCs and return result.
sccDecomposition.second = model.extractSccDependencyGraph(sccDecomposition.first, stateToSccMap);
LOG4CPLUS_INFO(logger, "Done computing SCC decomposition.");
return sccDecomposition;
return scc;
}
/*!
@ -465,7 +565,7 @@ public:
* @return A vector of indices that is a topological sort of the states.
*/
template <typename T>
static std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<T> const& matrix) {
std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<T> const& matrix) {
if (matrix.getRowCount() != matrix.getColumnCount()) {
LOG4CPLUS_ERROR(logger, "Provided matrix is required to be square.");
throw storm::exceptions::InvalidArgumentException() << "Provided matrix is required to be square.";
@ -536,117 +636,11 @@ public:
return topologicalSort;
}
private:
/*!
* Performs an SCC decomposition using Tarjan's algorithm.
*
* @param startState The state at which the search is started.
* @param currentIndex The index that is to be used as the next free index.
* @param stateIndices The vector that stores the index for each state.
* @param lowlinks A vector that stores the lowlink of each state, i.e. the lowest index of a state reachable from
* a particular state.
* @param tarjanStack A stack used for Tarjan's algorithm.
* @param tarjanStackStates A bit vector that represents all states that are currently contained in tarjanStack.
* @param visitedStates A bit vector that stores all states that have already been visited.
* @param matrix The transition matrix representing the graph structure.
* @param stronglyConnectedComponents A vector of strongly connected components to which newly found SCCs are added.
* @param stateToSccMap A mapping from state indices to SCC indices that maps each state to its SCC.
*/
template <typename T>
static void performSccDecompositionHelper(uint_fast64_t startState, uint_fast64_t& currentIndex, std::vector<uint_fast64_t>& stateIndices, std::vector<uint_fast64_t>& lowlinks, std::vector<uint_fast64_t>& tarjanStack, storm::storage::BitVector& tarjanStackStates, storm::storage::BitVector& visitedStates, storm::storage::SparseMatrix<T> const& matrix, std::vector<std::vector<uint_fast64_t>>& stronglyConnectedComponents, std::map<uint_fast64_t, uint_fast64_t>& stateToSccMap) {
// Create the stacks needed for turning the recursive formulation of Tarjan's algorithm
// into an iterative version. In particular, we keep one stack for states and one stack
// for the iterators. The last one is not strictly needed, but reduces iteration work when
// all successors of a particular state are considered.
std::vector<uint_fast64_t> recursionStateStack;
recursionStateStack.reserve(lowlinks.size());
std::vector<typename storm::storage::SparseMatrix<T>::ConstIndexIterator> recursionIteratorStack;
recursionIteratorStack.reserve(lowlinks.size());
std::vector<bool> statesInStack(lowlinks.size());
// Initialize the recursion stacks with the given initial state (and its successor iterator).
recursionStateStack.push_back(startState);
recursionIteratorStack.push_back(matrix.constColumnIteratorBegin(startState));
recursionStepForward:
while (!recursionStateStack.empty()) {
uint_fast64_t currentState = recursionStateStack.back();
typename storm::storage::SparseMatrix<T>::ConstIndexIterator currentIt = recursionIteratorStack.back();
// Perform the treatment of newly discovered state as defined by Tarjan's algorithm
visitedStates.set(currentState, true);
stateIndices[currentState] = currentIndex;
lowlinks[currentState] = currentIndex;
++currentIndex;
tarjanStack.push_back(currentState);
tarjanStackStates.set(currentState, true);
// Now, traverse all successors of the current state.
for(; currentIt != matrix.constColumnIteratorEnd(currentState); ++currentIt) {
// If we have not visited the successor already, we need to perform the procedure
// recursively on the newly found state.
if (!visitedStates.get(*currentIt)) {
// Save current iterator position so we can continue where we left off later.
recursionIteratorStack.pop_back();
recursionIteratorStack.push_back(currentIt);
// Put unvisited successor on top of our recursion stack and remember that.
recursionStateStack.push_back(*currentIt);
statesInStack[*currentIt] = true;
// Also, put initial value for iterator on corresponding recursion stack.
recursionIteratorStack.push_back(matrix.constColumnIteratorBegin(*currentIt));
// Perform the actual recursion step in an iterative way.
goto recursionStepForward;
recursionStepBackward:
lowlinks[currentState] = std::min(lowlinks[currentState], lowlinks[*currentIt]);
} else if (tarjanStackStates.get(*currentIt)) {
// Update the lowlink of the current state.
lowlinks[currentState] = std::min(lowlinks[currentState], stateIndices[*currentIt]);
}
}
// If the current state is the root of a SCC, we need to pop all states of the SCC from
// the algorithm's stack.
if (lowlinks[currentState] == stateIndices[currentState]) {
stronglyConnectedComponents.push_back(std::vector<uint_fast64_t>());
uint_fast64_t lastState = 0;
do {
// Pop topmost state from the algorithm's stack.
lastState = tarjanStack.back();
tarjanStack.pop_back();
tarjanStackStates.set(lastState, false);
// Add the state to the current SCC.
stronglyConnectedComponents.back().push_back(lastState);
stateToSccMap[lastState] = stronglyConnectedComponents.size() - 1;
} while (lastState != currentState);
}
// If we reach this point, we have completed the recursive descent for the current state.
// That is, we need to pop it from the recursion stacks.
recursionStateStack.pop_back();
recursionIteratorStack.pop_back();
// If there is at least one state under the current one in our recursion stack, we need
// to restore the topmost state as the current state and jump to the part after the
// original recursive call.
if (recursionStateStack.size() > 0) {
currentState = recursionStateStack.back();
currentIt = recursionIteratorStack.back();
goto recursionStepBackward;
}
}
}
};
} // namespace graph
} // namespace utility
} // namespace storm
#endif /* STORM_UTILITY_GRAPHANALYZER_H_ */
#endif /* STORM_UTILITY_GRAPH_H_ */

3
storm-config.h.in

@ -1,4 +1,5 @@
// the configured options and settings for STORM
#define STORM_CPP_VERSION_MAJOR @STORM_CPP_VERSION_MAJOR@
#define STORM_CPP_VERSION_MINOR @STORM_CPP_VERSION_MINOR@
#define STORM_CPP_TESTS_BASE_PATH "@STORM_CPP_TESTS_BASE_PATH@"
#define STORM_CPP_BASE_PATH "@PROJECT_SOURCE_DIR@"
#define STORM_CPP_TESTS_BASE_PATH "@STORM_CPP_TESTS_BASE_PATH@"

4
test/functional/die/testFormulas.prctl

@ -1,4 +0,0 @@
P=? [ F one ]
P=? [ F two ]
P=? [ F three ]
R=? [ F done ]

2
test/eigen/EigenSparseMatrixTest.cpp → test/functional/eigen/EigenSparseMatrixTest.cpp

@ -18,7 +18,7 @@ TEST(EigenSparseMatrixTest, BasicReadWriteTest) {
int position_row[50] = {
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, /* first row empty, one full row ��� 25 minus the diagonal entry */
2, 2, 2, 2, /* first row empty, one full row 25 minus the diagonal entry */
4, 4, /* one empty row, then first and last column */
13, 13, 13, 13, /* a few empty rows, middle columns */
24, 24, 24, 24, 24, 24, 24, 24, 24, 24,

6
test/functional/EigenDtmcPrctModelCheckerTest.cpp → test/functional/modelchecker/EigenDtmcPrctModelCheckerTest.cpp

@ -9,7 +9,7 @@
TEST(EigenDtmcPrctModelCheckerTest, Die) {
storm::settings::Settings* s = storm::settings::instance();
s->set("fix-deadlocks");
storm::parser::AutoParser<double> parser(STORM_CPP_TESTS_BASE_PATH "/functional/die/die.tra", STORM_CPP_TESTS_BASE_PATH "/functional/die/die.lab", "", STORM_CPP_TESTS_BASE_PATH "/functional/die/die.coin_flips.trans.rew");
storm::parser::AutoParser<double> parser(STORM_CPP_TESTS_BASE_PATH "/functional/modelchecker/die/die.tra", STORM_CPP_TESTS_BASE_PATH "/functional/modelchecker/die/die.lab", "", STORM_CPP_TESTS_BASE_PATH "/functional/modelchecker/die/die.coin_flips.trans.rew");
ASSERT_EQ(parser.getType(), storm::models::DTMC);
@ -69,7 +69,7 @@ TEST(EigenDtmcPrctModelCheckerTest, Die) {
TEST(EigenDtmcPrctModelCheckerTest, Crowds) {
storm::settings::Settings* s = storm::settings::instance();
s->set("fix-deadlocks");
storm::parser::AutoParser<double> parser(STORM_CPP_TESTS_BASE_PATH "/functional/crowds/crowds5_5.tra", STORM_CPP_TESTS_BASE_PATH "/functional/crowds/crowds5_5.lab", "", "");
storm::parser::AutoParser<double> parser(STORM_CPP_TESTS_BASE_PATH "/functional/modelchecker/crowds/crowds5_5.tra", STORM_CPP_TESTS_BASE_PATH "/functional/modelchecker/crowds/crowds5_5.lab", "", "");
ASSERT_EQ(parser.getType(), storm::models::DTMC);
@ -117,7 +117,7 @@ TEST(EigenDtmcPrctModelCheckerTest, Crowds) {
TEST(EigenDtmcPrctModelCheckerTest, SynchronousLeader) {
storm::settings::Settings* s = storm::settings::instance();
s->set("fix-deadlocks");
storm::parser::AutoParser<double> parser(STORM_CPP_TESTS_BASE_PATH "/functional/synchronous_leader/leader4_8.tra", STORM_CPP_TESTS_BASE_PATH "/functional/synchronous_leader/leader4_8.lab", "", STORM_CPP_TESTS_BASE_PATH "/functional/synchronous_leader/leader4_8.pick.trans.rew");
storm::parser::AutoParser<double> parser(STORM_CPP_TESTS_BASE_PATH "/functional/modelchecker/synchronous_leader/leader4_8.tra", STORM_CPP_TESTS_BASE_PATH "/functional/modelchecker/synchronous_leader/leader4_8.lab", "", STORM_CPP_TESTS_BASE_PATH "/functional/modelchecker/synchronous_leader/leader4_8.pick.trans.rew");
ASSERT_EQ(parser.getType(), storm::models::DTMC);

6
test/functional/GmmxxDtmcPrctModelCheckerTest.cpp → test/functional/modelchecker/GmmxxDtmcPrctModelCheckerTest.cpp

@ -8,7 +8,7 @@
TEST(GmmxxDtmcPrctModelCheckerTest, Die) {
storm::settings::Settings* s = storm::settings::instance();
s->set("fix-deadlocks");
storm::parser::AutoParser<double> parser(STORM_CPP_TESTS_BASE_PATH "/functional/die/die.tra", STORM_CPP_TESTS_BASE_PATH "/functional/die/die.lab", "", STORM_CPP_TESTS_BASE_PATH "/functional/die/die.coin_flips.trans.rew");
storm::parser::AutoParser<double> parser(STORM_CPP_BASE_PATH "/examples/dtmc/die/die.tra", STORM_CPP_BASE_PATH "/examples/dtmc/die/die.lab", "", STORM_CPP_BASE_PATH "/examples/dtmc/die/die.coin_flips.trans.rew");
ASSERT_EQ(parser.getType(), storm::models::DTMC);
@ -75,7 +75,7 @@ TEST(GmmxxDtmcPrctModelCheckerTest, Die) {
TEST(GmmxxDtmcPrctModelCheckerTest, Crowds) {
storm::settings::Settings* s = storm::settings::instance();
s->set("fix-deadlocks");
storm::parser::AutoParser<double> parser(STORM_CPP_TESTS_BASE_PATH "/functional/crowds/crowds5_5.tra", STORM_CPP_TESTS_BASE_PATH "/functional/crowds/crowds5_5.lab", "", "");
storm::parser::AutoParser<double> parser(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.tra", STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.lab", "", "");
ASSERT_EQ(parser.getType(), storm::models::DTMC);
@ -129,7 +129,7 @@ TEST(GmmxxDtmcPrctModelCheckerTest, Crowds) {
TEST(GmmxxDtmcPrctModelCheckerTest, SynchronousLeader) {
storm::settings::Settings* s = storm::settings::instance();
s->set("fix-deadlocks");
storm::parser::AutoParser<double> parser(STORM_CPP_TESTS_BASE_PATH "/functional/synchronous_leader/leader4_8.tra", STORM_CPP_TESTS_BASE_PATH "/functional/synchronous_leader/leader4_8.lab", "", STORM_CPP_TESTS_BASE_PATH "/functional/synchronous_leader/leader4_8.pick.trans.rew");
storm::parser::AutoParser<double> parser(STORM_CPP_BASE_PATH "/examples/dtmc/synchronous_leader/leader4_8.tra", STORM_CPP_BASE_PATH "/examples/dtmc/synchronous_leader/leader4_8.lab", "", STORM_CPP_BASE_PATH "/examples/dtmc/synchronous_leader/leader4_8.pick.trans.rew");
ASSERT_EQ(parser.getType(), storm::models::DTMC);

130
test/functional/GmmxxMdpPrctModelCheckerTest.cpp → test/functional/modelchecker/GmmxxMdpPrctModelCheckerTest.cpp

@ -7,171 +7,171 @@
TEST(GmmxxMdpPrctModelCheckerTest, Dice) {
storm::settings::Settings* s = storm::settings::instance();
storm::parser::AutoParser<double> parser(STORM_CPP_TESTS_BASE_PATH "/functional/two_dice/two_dice.tra", STORM_CPP_TESTS_BASE_PATH "/functional/two_dice/two_dice.lab", "", STORM_CPP_TESTS_BASE_PATH "/functional/two_dice/two_dice.flip.trans.rew");
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(), 169u);
ASSERT_EQ(mdp->getNumberOfTransitions(), 436u);
storm::modelchecker::GmmxxMdpPrctlModelChecker<double> mc(*mdp);
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_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[0] - 0.0277777612209320068), s->get<double>("precision"));
delete probFormula;
delete result;
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->get<double>("precision"));
delete probFormula;
delete result;
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->get<double>("precision"));
delete probFormula;
delete result;
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->get<double>("precision"));
delete probFormula;
delete result;
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->get<double>("precision"));
delete probFormula;
delete result;
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->get<double>("precision"));
delete probFormula;
delete result;
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->get<double>("precision"));
delete rewardFormula;
delete result;
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->get<double>("precision"));
delete rewardFormula;
delete result;
storm::parser::AutoParser<double> stateRewardParser(STORM_CPP_TESTS_BASE_PATH "/functional/two_dice/two_dice.tra", STORM_CPP_TESTS_BASE_PATH "/functional/two_dice/two_dice.lab", STORM_CPP_TESTS_BASE_PATH "/functional/two_dice/two_dice.flip.state.rew", "");
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::GmmxxMdpPrctlModelChecker<double> stateRewardModelChecker(*stateRewardMdp);
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->get<double>("precision"));
delete rewardFormula;
delete result;
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->get<double>("precision"));
delete rewardFormula;
delete result;
storm::parser::AutoParser<double> stateAndTransitionRewardParser(STORM_CPP_TESTS_BASE_PATH "/functional/two_dice/two_dice.tra", STORM_CPP_TESTS_BASE_PATH "/functional/two_dice/two_dice.lab", STORM_CPP_TESTS_BASE_PATH "/functional/two_dice/two_dice.flip.state.rew", STORM_CPP_TESTS_BASE_PATH "/functional/two_dice/two_dice.flip.trans.rew");
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::GmmxxMdpPrctlModelChecker<double> stateAndTransitionRewardModelChecker(*stateAndTransitionRewardMdp);
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 * 7.3333294987678527832)), s->get<double>("precision"));
delete rewardFormula;
delete result;
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 * 7.3333294987678527832)), s->get<double>("precision"));
delete rewardFormula;
delete result;
}
TEST(GmmxxMdpPrctModelCheckerTest, AsynchronousLeader) {
storm::settings::Settings* s = storm::settings::instance();
storm::parser::AutoParser<double> parser(STORM_CPP_TESTS_BASE_PATH "/functional/asynchronous_leader/leader4.tra", STORM_CPP_TESTS_BASE_PATH "/functional/asynchronous_leader/leader4.lab", "", STORM_CPP_TESTS_BASE_PATH "/functional/asynchronous_leader/leader4.trans.rew");
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);

0
test/parser/.gitignore → test/functional/parser/.gitignore

9
test/parser/CslParserTest.cpp → test/functional/parser/CslParserTest.cpp

@ -116,7 +116,7 @@ TEST(CslParserTest, parseProbabilisticNoBoundFormulaTest) {
TEST(CslParserTest, parseComplexFormulaTest) {
storm::parser::CslParser* cslParser = nullptr;
ASSERT_NO_THROW(
cslParser = new storm::parser::CslParser("S<=0.5 [ P <= 0.5 [ a U c ] ] & (P > 0.5 [ G b] | !P < 0.4 [ G P>0.9 [F >=7 a & b] ])")
cslParser = new storm::parser::CslParser("S<=0.5 [ P <= 0.5 [ a U c ] ] & (P > 0.5 [ G b] | !P < 0.4 [ G P>0.9 [F >=7 a & b] ]) //and a comment")
);
ASSERT_NE(cslParser->getFormula(), nullptr);
@ -127,14 +127,9 @@ TEST(CslParserTest, parseComplexFormulaTest) {
}
TEST(CslParserTest, wrongProbabilisticFormulaTest) {
storm::parser::CslParser* cslParser = nullptr;
ASSERT_THROW(
cslParser = new storm::parser::CslParser("P > 0.5 [ a ]"),
storm::exceptions::WrongFormatException
);
ASSERT_THROW(cslParser = new storm::parser::CslParser("P > 0.5 [ a ]"), storm::exceptions::WrongFormatException);
delete cslParser;
}

4
test/parser/LtlParserTest.cpp → test/functional/parser/LtlParserTest.cpp

@ -132,7 +132,7 @@ TEST(LtlParserTest, parseComplexUntilTest) {
TEST(LtlParserTest, parseComplexFormulaTest) {
storm::parser::LtlParser* ltlParser = nullptr;
ASSERT_NO_THROW(
ltlParser = new storm::parser::LtlParser("a U F b | G a & F<=3 a U<=7 b")
ltlParser = new storm::parser::LtlParser("a U F b | G a & F<=3 a U<=7 b //and a comment :P")
);
ASSERT_NE(ltlParser->getFormula(), nullptr);
@ -145,7 +145,7 @@ TEST(LtlParserTest, parseComplexFormulaTest) {
TEST(LtlParserTest, wrongFormulaTest) {
storm::parser::LtlParser* ltlParser = nullptr;
ASSERT_THROW(
ltlParser = new storm::parser::LtlParser("(a | b) & +"),
ltlParser = new storm::parser::LtlParser("(a | c) & +"),
storm::exceptions::WrongFormatException
);
delete ltlParser;

4
test/parser/ParseMdpTest.cpp → test/functional/parser/ParseMdpTest.cpp

@ -13,8 +13,8 @@
TEST(ParseMdpTest, parseAndOutput) {
storm::parser::NondeterministicModelParser* mdpParser = nullptr;
ASSERT_NO_THROW(mdpParser = new storm::parser::NondeterministicModelParser(
STORM_CPP_TESTS_BASE_PATH "/parser/tra_files/mdp_general_input_01.tra",
STORM_CPP_TESTS_BASE_PATH "/parser/lab_files/pctl_general_input_01.lab"));
STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general_input_01.tra",
STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/pctl_general_input_01.lab"));
std::shared_ptr<storm::models::Mdp<double>> mdp = mdpParser->getMdp();
std::shared_ptr<storm::storage::SparseMatrix<double>> matrix = mdp->getTransitionMatrix();

0
test/parser/ParsePrismTest.cpp → test/functional/parser/ParsePrismTest.cpp

0
test/parser/PrctlParserTest.cpp → test/functional/parser/PrctlParserTest.cpp

8
test/parser/ReadLabFileTest.cpp → test/functional/parser/ReadLabFileTest.cpp

@ -25,7 +25,7 @@ TEST(ReadLabFileTest, ParseTest) {
storm::parser::AtomicPropositionLabelingParser* parser = nullptr;
//Parsing the file
ASSERT_NO_THROW(parser = new storm::parser::AtomicPropositionLabelingParser(12, STORM_CPP_TESTS_BASE_PATH "/parser/lab_files/pctl_general_input_01.lab"));
ASSERT_NO_THROW(parser = new storm::parser::AtomicPropositionLabelingParser(12, STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/pctl_general_input_01.lab"));
std::shared_ptr<storm::models::AtomicPropositionsLabeling> labeling(parser->getLabeling());
//Checking whether all propositions are in the labelling
@ -89,14 +89,14 @@ TEST(ReadLabFileTest, ParseTest) {
}
TEST(ReadLabFileTest, WrongHeaderTest1) {
ASSERT_THROW(storm::parser::AtomicPropositionLabelingParser(3, STORM_CPP_TESTS_BASE_PATH "/parser/lab_files/wrong_format_header1.lab"), storm::exceptions::WrongFormatException);
ASSERT_THROW(storm::parser::AtomicPropositionLabelingParser(3, STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/wrong_format_header1.lab"), storm::exceptions::WrongFormatException);
}
TEST(ReadLabFileTest, WrongHeaderTest2) {
ASSERT_THROW(storm::parser::AtomicPropositionLabelingParser(3, STORM_CPP_TESTS_BASE_PATH "/parser/lab_files/wrong_format_header2.lab"), storm::exceptions::WrongFormatException);
ASSERT_THROW(storm::parser::AtomicPropositionLabelingParser(3, STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/wrong_format_header2.lab"), storm::exceptions::WrongFormatException);
}
TEST(ReadLabFileTest, WrongPropositionTest) {
ASSERT_THROW(storm::parser::AtomicPropositionLabelingParser(3, STORM_CPP_TESTS_BASE_PATH "/parser/lab_files/wrong_format_proposition.lab"), storm::exceptions::WrongFormatException);
ASSERT_THROW(storm::parser::AtomicPropositionLabelingParser(3, STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/wrong_format_proposition.lab"), storm::exceptions::WrongFormatException);
}

8
test/parser/ReadTraFileTest.cpp → test/functional/parser/ReadTraFileTest.cpp

@ -21,7 +21,7 @@ TEST(ReadTraFileTest, NonExistingFileTest) {
*/
TEST(ReadTraFileTest, ParseFileTest1) {
storm::parser::DeterministicSparseTransitionParser* parser = nullptr;
ASSERT_NO_THROW(parser = new storm::parser::DeterministicSparseTransitionParser(STORM_CPP_TESTS_BASE_PATH "/parser/tra_files/csl_general_input_01.tra"));
ASSERT_NO_THROW(parser = new storm::parser::DeterministicSparseTransitionParser(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/csl_general_input_01.tra"));
std::shared_ptr<storm::storage::SparseMatrix<double>> result = parser->getMatrix();
if (result != nullptr) {
@ -73,13 +73,13 @@ TEST(ReadTraFileTest, ParseFileTest1) {
}
TEST(ReadTraFileTest, WrongFormatTestHeader1) {
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser(STORM_CPP_TESTS_BASE_PATH "/parser/tra_files/wrong_format_header1.tra"), storm::exceptions::WrongFormatException);
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/wrong_format_header1.tra"), storm::exceptions::WrongFormatException);
}
TEST(ReadTraFileTest, WrongFormatTestHeader2) {
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser(STORM_CPP_TESTS_BASE_PATH "/parser/tra_files/wrong_format_header2.tra"), storm::exceptions::WrongFormatException);
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/wrong_format_header2.tra"), storm::exceptions::WrongFormatException);
}
TEST(ReadTraFileTest, WrongFormatTestTransition) {
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser(STORM_CPP_TESTS_BASE_PATH "/parser/tra_files/wrong_format_transition.tra"), storm::exceptions::WrongFormatException);
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/wrong_format_transition.tra"), storm::exceptions::WrongFormatException);
}

0
test/parser/prctl_files/apOnly.prctl → test/functional/parser/prctl_files/apOnly.prctl

0
test/parser/prctl_files/complexFormula.prctl → test/functional/parser/prctl_files/complexFormula.prctl

0
test/parser/prctl_files/probabilisticFormula.prctl → test/functional/parser/prctl_files/probabilisticFormula.prctl

0
test/parser/prctl_files/probabilisticNoBoundFormula.prctl → test/functional/parser/prctl_files/probabilisticNoBoundFormula.prctl

0
test/parser/prctl_files/propositionalFormula.prctl → test/functional/parser/prctl_files/propositionalFormula.prctl

0
test/parser/prctl_files/rewardFormula.prctl → test/functional/parser/prctl_files/rewardFormula.prctl

0
test/parser/prctl_files/rewardNoBoundFormula.prctl → test/functional/parser/prctl_files/rewardNoBoundFormula.prctl

0
test/parser/readme.txt → test/functional/parser/readme.txt

0
test/storage/BitVectorTest.cpp → test/functional/storage/BitVectorTest.cpp

0
test/storage/SparseMatrixTest.cpp → test/functional/storage/SparseMatrixTest.cpp

0
test/storage/adapters/EigenAdapterTest.cpp → test/functional/storage/adapters/EigenAdapterTest.cpp

0
test/storage/adapters/GmmAdapterTest.cpp → test/functional/storage/adapters/GmmAdapterTest.cpp

0
test/storage/adapters/StormAdapterTest.cpp → test/functional/storage/adapters/StormAdapterTest.cpp

13
test/storm-tests.cpp → test/functional/storm-functional-tests.cpp

@ -15,10 +15,12 @@ log4cplus::Logger logger;
* Initializes the logging framework.
*/
void setUpLogging() {
log4cplus::SharedAppenderPtr fileLogAppender(new log4cplus::FileAppender("storm-tests.log"));
logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("main"));
logger.setLogLevel(log4cplus::ERROR_LOG_LEVEL);
log4cplus::SharedAppenderPtr fileLogAppender(new log4cplus::FileAppender("storm-functional-tests.log"));
fileLogAppender->setName("mainFileAppender");
fileLogAppender->setThreshold(log4cplus::FATAL_LOG_LEVEL);
fileLogAppender->setLayout(std::auto_ptr<log4cplus::Layout>(new log4cplus::PatternLayout("%-5p - %D{%H:%M} (%r ms) - %F:%L : %m%n")));
logger = log4cplus::Logger::getInstance("mainLogger");
logger.addAppender(fileLogAppender);
// Uncomment these lines to enable console logging output
@ -58,9 +60,12 @@ int main(int argc, char* argv[]) {
if (!parseOptions(argc, argv)) {
return 0;
}
std::cout << "STORM Testing Suite" << std::endl;
std::cout << "StoRM (Functional) Testing Suite" << std::endl;
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
int result = RUN_ALL_TESTS();
logger.closeNestedAppenders();
return result;
}

153
test/performance/graph/GraphTest.cpp

@ -0,0 +1,153 @@
#include "gtest/gtest.h"
#include "storm-config.h"
#include "src/utility/Settings.h"
#include "src/parser/AutoParser.h"
#include "src/utility/graph.h"
TEST(GraphTest, PerformProb01) {
storm::parser::AutoParser<double> parser(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds20_5.tra", STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds20_5.lab", "", "");
std::shared_ptr<storm::models::Dtmc<double>> dtmc = parser.getModel<storm::models::Dtmc<double>>();
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, storm::storage::BitVector(dtmc->getNumberOfStates(), true), storm::storage::BitVector(dtmc->getLabeledStates("observe0Greater1")));
ASSERT_EQ(prob01.first.getNumberOfSetBits(), 1724414u);
ASSERT_EQ(prob01.second.getNumberOfSetBits(), 46046u);
prob01 = storm::utility::graph::performProb01(*dtmc, storm::storage::BitVector(dtmc->getNumberOfStates(), true), storm::storage::BitVector(dtmc->getLabeledStates("observeIGreater1")));
ASSERT_EQ(prob01.first.getNumberOfSetBits(), 574016u);
ASSERT_EQ(prob01.second.getNumberOfSetBits(), 825797u);
prob01 = storm::utility::graph::performProb01(*dtmc, storm::storage::BitVector(dtmc->getNumberOfStates(), true), storm::storage::BitVector(dtmc->getLabeledStates("observeOnlyTrueSender")));
ASSERT_EQ(prob01.first.getNumberOfSetBits(), 1785309u);
ASSERT_EQ(prob01.second.getNumberOfSetBits(), 40992u);
LOG4CPLUS_WARN(logger, "Done.");
dtmc = nullptr;
storm::parser::AutoParser<double> parser2(STORM_CPP_BASE_PATH "/examples/dtmc/synchronous_leader/leader6_8.tra", STORM_CPP_BASE_PATH "/examples/dtmc/synchronous_leader/leader6_8.lab", "", "");
std::shared_ptr<storm::models::Dtmc<double>> dtmc2 = parser2.getModel<storm::models::Dtmc<double>>();
LOG4CPLUS_WARN(logger, "Computing prob01 for synchronous_leader/leader6_8...");
prob01 = storm::utility::graph::performProb01(*dtmc2, storm::storage::BitVector(dtmc2->getNumberOfStates(), true), storm::storage::BitVector(dtmc2->getLabeledStates("elected")));
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_EQ(prob01.first.getNumberOfSetBits(), 0u);
ASSERT_EQ(prob01.second.getNumberOfSetBits(), 1312334u);
dtmc2 = nullptr;
}
TEST(GraphTest, PerformProb01MinMax) {
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", "", "");
std::shared_ptr<storm::models::Mdp<double>> mdp = parser.getModel<storm::models::Mdp<double>>();
LOG4CPLUS_WARN(logger, "Computing prob01min for asynchronous_leader/leader7...");
std::pair<storm::storage::BitVector, storm::storage::BitVector> prob01 = storm::utility::graph::performProb01Min(*mdp, storm::storage::BitVector(mdp->getNumberOfStates(), true), mdp->getLabeledStates("elected"));
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_EQ(prob01.first.getNumberOfSetBits(), 0u);
ASSERT_EQ(prob01.second.getNumberOfSetBits(), 2095783u);
LOG4CPLUS_WARN(logger, "Computing prob01max for asynchronous_leader/leader7...");
prob01 = storm::utility::graph::performProb01Max(*mdp, storm::storage::BitVector(mdp->getNumberOfStates(), true), mdp->getLabeledStates("elected"));
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_EQ(prob01.first.getNumberOfSetBits(), 0u);
ASSERT_EQ(prob01.second.getNumberOfSetBits(), 2095783u);
mdp = nullptr;
storm::parser::AutoParser<double> parser2(STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin4_6.tra", STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin4_6.lab", "", "");
std::shared_ptr<storm::models::Mdp<double>> mdp2 = parser2.getModel<storm::models::Mdp<double>>();
LOG4CPLUS_WARN(logger, "Computing prob01min for consensus/coin4_6...");
prob01 = storm::utility::graph::performProb01Min(*mdp2, storm::storage::BitVector(mdp2->getNumberOfStates(), true), mdp2->getLabeledStates("finished"));
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_EQ(prob01.first.getNumberOfSetBits(), 0u);
ASSERT_EQ(prob01.second.getNumberOfSetBits(), 63616u);
LOG4CPLUS_WARN(logger, "Computing prob01max for consensus/coin4_6...");
prob01 = storm::utility::graph::performProb01Max(*mdp2, storm::storage::BitVector(mdp2->getNumberOfStates(), true), mdp2->getLabeledStates("finished"));
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_EQ(prob01.first.getNumberOfSetBits(), 0u);
ASSERT_EQ(prob01.second.getNumberOfSetBits(), 63616u);
mdp2 = nullptr;
}
TEST(GraphTest, PerformSCCDecompositionAndGetDependencyGraph) {
storm::parser::AutoParser<double> parser(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds20_5.tra", STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds20_5.lab", "", "");
std::shared_ptr<storm::models::Dtmc<double>> dtmc = parser.getModel<storm::models::Dtmc<double>>();
LOG4CPLUS_WARN(logger, "Computing SCC decomposition of crowds/crowds20_5...");
std::vector<std::vector<uint_fast64_t>> sccDecomposition = storm::utility::graph::performSccDecomposition(*dtmc);
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_EQ(sccDecomposition.size(), 1290297u);
LOG4CPLUS_WARN(logger, "Extracting SCC dependency graph of crowds/crowds20_5...");
storm::storage::SparseMatrix<bool> sccDependencyGraph = dtmc->extractSccDependencyGraph(sccDecomposition);
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_EQ(sccDependencyGraph.getNonZeroEntryCount(), 1371253u);
dtmc = nullptr;
storm::parser::AutoParser<double> parser2(STORM_CPP_BASE_PATH "/examples/dtmc/synchronous_leader/leader6_8.tra", STORM_CPP_BASE_PATH "/examples/dtmc/synchronous_leader/leader6_8.lab", "", "");
std::shared_ptr<storm::models::Dtmc<double>> dtmc2 = parser2.getModel<storm::models::Dtmc<double>>();
LOG4CPLUS_WARN(logger, "Computing SCC decomposition of synchronous_leader/leader6_8...");
sccDecomposition = storm::utility::graph::performSccDecomposition(*dtmc2);
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_EQ(sccDecomposition.size(), 1279673u);
LOG4CPLUS_WARN(logger, "Extracting SCC dependency graph of synchronous_leader/leader6_8...");
sccDependencyGraph = dtmc2->extractSccDependencyGraph(sccDecomposition);
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_EQ(sccDependencyGraph.getNonZeroEntryCount(), 1535367u);
dtmc2 = nullptr;
storm::parser::AutoParser<double> parser3(STORM_CPP_BASE_PATH "/examples/mdp/asynchronous_leader/leader6.tra", STORM_CPP_BASE_PATH "/examples/mdp/asynchronous_leader/leader6.lab", "", "");
std::shared_ptr<storm::models::Mdp<double>> mdp = parser3.getModel<storm::models::Mdp<double>>();
LOG4CPLUS_WARN(logger, "Computing SCC decomposition of asynchronous_leader/leader6...");
sccDecomposition = storm::utility::graph::performSccDecomposition(*mdp);
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_EQ(sccDecomposition.size(), 214675);
LOG4CPLUS_WARN(logger, "Extracting SCC dependency graph of asynchronous_leader/leader6...");
sccDependencyGraph = mdp->extractSccDependencyGraph(sccDecomposition);
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_EQ(sccDependencyGraph.getNonZeroEntryCount(), 684093u);
mdp = nullptr;
storm::parser::AutoParser<double> parser4(STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin4_6.tra", STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin4_6.lab", "", "");
std::shared_ptr<storm::models::Mdp<double>> mdp2 = parser4.getModel<storm::models::Mdp<double>>();
LOG4CPLUS_WARN(logger, "Computing SCC decomposition of consensus/coin4_6...");
sccDecomposition = storm::utility::graph::performSccDecomposition(*mdp2);
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_EQ(sccDecomposition.size(), 63611u);
LOG4CPLUS_WARN(logger, "Extracting SCC dependency graph of consensus/coin4_6...");
sccDependencyGraph = mdp2->extractSccDependencyGraph(sccDecomposition);
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_EQ(sccDependencyGraph.getNonZeroEntryCount(), 213400u);
mdp2 = nullptr;
}

126
test/performance/modelchecker/GmmxxDtmcPrctModelCheckerTest.cpp

@ -0,0 +1,126 @@
#include "gtest/gtest.h"
#include "storm-config.h"
#include "src/utility/Settings.h"
#include "src/modelchecker/GmmxxDtmcPrctlModelChecker.h"
#include "src/parser/AutoParser.h"
TEST(GmmxxDtmcPrctModelCheckerTest, Crowds) {
storm::settings::Settings* s = storm::settings::instance();
s->set("fix-deadlocks");
storm::parser::AutoParser<double> parser(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds20_5.tra", STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds20_5.lab", "", "");
ASSERT_EQ(parser.getType(), storm::models::DTMC);
std::shared_ptr<storm::models::Dtmc<double>> dtmc = parser.getModel<storm::models::Dtmc<double>>();
ASSERT_EQ(dtmc->getNumberOfStates(), 2036647u);
ASSERT_EQ(dtmc->getNumberOfTransitions(), 8973900u);
storm::modelchecker::GmmxxDtmcPrctlModelChecker<double> mc(*dtmc);
storm::property::prctl::Ap<double>* apFormula = new storm::property::prctl::Ap<double>("observe0Greater1");
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);
LOG4CPLUS_WARN(logger, "Model Checking P=? [F observe0Greater1] on crowds/crowds20_5...");
std::vector<double>* result = probFormula->check(mc);
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[0] - 0.2296803699), s->get<double>("precision"));
delete probFormula;
delete result;
apFormula = new storm::property::prctl::Ap<double>("observeIGreater1");
eventuallyFormula = new storm::property::prctl::Eventually<double>(apFormula);
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(eventuallyFormula);
LOG4CPLUS_WARN(logger, "Model Checking P=? [F observeIGreater1] on crowds/crowds20_5...");
result = probFormula->check(mc);
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[0] - 0.05072232915), s->get<double>("precision"));
delete probFormula;
delete result;
apFormula = new storm::property::prctl::Ap<double>("observeOnlyTrueSender");
eventuallyFormula = new storm::property::prctl::Eventually<double>(apFormula);
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(eventuallyFormula);
LOG4CPLUS_WARN(logger, "Model Checking P=? [F observeOnlyTrueSender] on crowds/crowds20_5...");
result = probFormula->check(mc);
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[0] - 0.2274230551), s->get<double>("precision"));
delete probFormula;
delete result;
}
TEST(GmmxxDtmcPrctModelCheckerTest, SynchronousLeader) {
storm::settings::Settings* s = storm::settings::instance();
s->set("fix-deadlocks");
storm::parser::AutoParser<double> parser(STORM_CPP_BASE_PATH "/examples/dtmc/synchronous_leader/leader6_8.tra", STORM_CPP_BASE_PATH "/examples/dtmc/synchronous_leader/leader6_8.lab", "", STORM_CPP_BASE_PATH "/examples/dtmc/synchronous_leader/leader6_8.pick.trans.rew");
ASSERT_EQ(parser.getType(), storm::models::DTMC);
std::shared_ptr<storm::models::Dtmc<double>> dtmc = parser.getModel<storm::models::Dtmc<double>>();
ASSERT_EQ(dtmc->getNumberOfStates(), 1312334u);
ASSERT_EQ(dtmc->getNumberOfTransitions(), 2886810u);
storm::modelchecker::GmmxxDtmcPrctlModelChecker<double> mc(*dtmc);
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);
LOG4CPLUS_WARN(logger, "Model Checking P=? [F elected] on synchronous_leader/leader6_8...");
std::vector<double>* result = probFormula->check(mc);
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[0] - 1), s->get<double>("precision"));
delete probFormula;
delete result;
apFormula = new storm::property::prctl::Ap<double>("elected");
storm::property::prctl::BoundedUntil<double>* boundedUntilFormula = new storm::property::prctl::BoundedUntil<double>(new storm::property::prctl::Ap<double>("true"), apFormula, 20);
probFormula = new storm::property::prctl::ProbabilisticNoBoundOperator<double>(boundedUntilFormula);
LOG4CPLUS_WARN(logger, "Model Checking P=? [F<=20 elected] on synchronous_leader/leader6_8...");
result = probFormula->check(mc);
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[0] - 0.999394979327824395376467), s->get<double>("precision"));
delete probFormula;
delete result;
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);
LOG4CPLUS_WARN(logger, "Model Checking R=? [F elected] on synchronous_leader/leader6_8...");
result = rewardFormula->check(mc);
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[0] - 1.02521744572240791626427), s->get<double>("precision"));
delete rewardFormula;
delete result;
}

246
test/performance/modelchecker/GmmxxMdpPrctModelCheckerTest.cpp

@ -0,0 +1,246 @@
#include "gtest/gtest.h"
#include "storm-config.h"
#include "src/utility/Settings.h"
#include "src/modelchecker/GmmxxMdpPrctlModelChecker.h"
#include "src/parser/AutoParser.h"
TEST(GmmxxMdpPrctModelCheckerTest, AsynchronousLeader) {
storm::settings::Settings* s = storm::settings::instance();
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(), 2095783u);
ASSERT_EQ(mdp->getNumberOfTransitions(), 7714385u);
storm::modelchecker::GmmxxMdpPrctlModelChecker<double> mc(*mdp);
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_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[0] - 1), s->get<double>("precision"));
delete probFormula;
delete result;
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_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[0] - 1), s->get<double>("precision"));
delete probFormula;
delete result;
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);
LOG4CPLUS_WARN(logger, "Model Checking Pmin=? [F<=25 elected] on asynchronous_leader/leader7...");
result = mc.checkNoBoundOperator(*probFormula);
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[0] - 0), s->get<double>("precision"));
delete probFormula;
delete result;
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);
LOG4CPLUS_WARN(logger, "Model Checking Pmax=? [F<=25 elected] on asynchronous_leader/leader7...");
result = mc.checkNoBoundOperator(*probFormula);
LOG4CPLUS_WARN(logger, "Done.");
ASSERT_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[0] - 0), s->get<double>("precision"));
delete probFormula;
delete result;
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->get<double>("precision"));
delete rewardFormula;
delete result;
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_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[0] - 6.1724344), s->get<double>("precision"));
delete rewardFormula;
delete result;
}
TEST(GmmxxMdpPrctModelCheckerTest, Consensus) {
storm::settings::Settings* s = storm::settings::instance();
s->set<unsigned>("maxiter", 20000);
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(), 63616u);
ASSERT_EQ(mdp->getNumberOfTransitions(), 213472u);
storm::modelchecker::GmmxxMdpPrctlModelChecker<double> mc(*mdp);
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_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[31168] - 1), s->get<double>("precision"));
delete probFormula;
delete result;
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_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[31168] - 0.43742828319177884388579), s->get<double>("precision"));
delete probFormula;
delete result;
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_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[31168] - 0.5282872761373342829216), s->get<double>("precision"));
delete probFormula;
delete result;
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_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[31168] - 0.10343451035775527713), s->get<double>("precision"));
delete probFormula;
delete result;
apFormula = new storm::property::prctl::Ap<double>("finished");
storm::property::prctl::BoundedEventually<double>* boundedEventuallyFormula = new storm::property::prctl::BoundedEventually<double>(apFormula, 50);
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_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[31168] - 0), s->get<double>("precision"));
delete probFormula;
delete result;
apFormula = new storm::property::prctl::Ap<double>("finished");
boundedEventuallyFormula = new storm::property::prctl::BoundedEventually<double>(apFormula, 50);
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_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[31168] - 0), s->get<double>("precision"));
delete probFormula;
delete result;
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_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[31168] - 1725.5933133943854045), s->get<double>("precision"));
delete rewardFormula;
delete result;
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_NE(nullptr, result);
ASSERT_LT(std::abs((*result)[31168] - 2179.014847073392047605011), s->get<double>("precision"));
delete rewardFormula;
delete result;
}

70
test/performance/storm-performance-tests.cpp

@ -0,0 +1,70 @@
#include <iostream>
#include "gtest/gtest.h"
#include "log4cplus/logger.h"
#include "log4cplus/loggingmacros.h"
#include "log4cplus/consoleappender.h"
#include "log4cplus/fileappender.h"
#include "src/utility/Settings.h"
#include "src/modelchecker/GmmxxDtmcPrctlModelChecker.h"
log4cplus::Logger logger;
/*!
* Initializes the logging framework.
*/
void setUpLogging() {
logger = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("main"));
logger.setLogLevel(log4cplus::WARN_LOG_LEVEL);
log4cplus::SharedAppenderPtr fileLogAppender(new log4cplus::FileAppender("storm-performance-tests.log"));
fileLogAppender->setName("mainFileAppender");
fileLogAppender->setThreshold(log4cplus::WARN_LOG_LEVEL);
fileLogAppender->setLayout(std::auto_ptr<log4cplus::Layout>(new log4cplus::PatternLayout("%-5p - %D{%H:%M} (%r ms) - %F:%L : %m%n")));
logger.addAppender(fileLogAppender);
// Uncomment these lines to enable console logging output
// log4cplus::SharedAppenderPtr consoleLogAppender(new log4cplus::ConsoleAppender());
// consoleLogAppender->setName("mainConsoleAppender");
// consoleLogAppender->setLayout(std::auto_ptr<log4cplus::Layout>(new log4cplus::PatternLayout("%-5p - %D{%H:%M:%s} (%r ms) - %F:%L : %m%n")));
// logger.addAppender(consoleLogAppender);
}
/*!
* Function that parses the command line options.
* @param argc The argc argument of main().
* @param argv The argv argument of main().
* @return True iff the program should continue to run after parsing the options.
*/
bool parseOptions(int const argc, char const * const argv[]) {
storm::settings::Settings* s = nullptr;
try {
storm::settings::Settings::registerModule<storm::modelchecker::GmmxxDtmcPrctlModelChecker<double>>();
s = storm::settings::newInstance(argc, argv, nullptr, true);
} catch (storm::exceptions::InvalidSettingsException& e) {
// Ignore this case.
return true;
}
if (s->isSet("help")) {
std::cout << storm::settings::help;
return false;
}
return true;
}
int main(int argc, char* argv[]) {
setUpLogging();
if (!parseOptions(argc, argv)) {
return 0;
}
std::cout << "StoRM (Performance) Testing Suite" << std::endl;
testing::InitGoogleTest(&argc, argv);
int result = RUN_ALL_TESTS();
logger.closeNestedAppenders();
return result;
}
Loading…
Cancel
Save