Browse Source

Merge branch 'master' of https://sselab.de/lab9/private/git/storm

Former-commit-id: 31a498b9a5
main
sjunges 10 years ago
parent
commit
1250b842b1
  1. 2
      CMakeLists.txt
  2. 4
      examples/mdp/tiny/tiny.clab
  3. 3
      src/models/sparse/Model.cpp
  4. 146
      src/parser/AutoParser.cpp
  5. 99
      src/parser/AutoParser.h
  6. 69
      src/parser/DeterministicModelParser.cpp
  7. 64
      src/parser/DeterministicModelParser.h
  8. 524
      src/parser/DeterministicSparseTransitionParser.cpp
  9. 139
      src/parser/DeterministicSparseTransitionParser.h
  10. 53
      src/parser/MarkovAutomatonParser.cpp
  11. 3
      src/parser/MarkovAutomatonParser.h
  12. 533
      src/parser/MarkovAutomatonSparseTransitionParser.cpp
  13. 187
      src/parser/MarkovAutomatonSparseTransitionParser.h
  14. 74
      src/parser/NondeterministicModelParser.cpp
  15. 197
      src/parser/NondeterministicModelParser.h
  16. 643
      src/parser/NondeterministicSparseTransitionParser.cpp
  17. 173
      src/parser/NondeterministicSparseTransitionParser.h
  18. 73
      src/parser/SparseChoiceLabelingParser.cpp
  19. 27
      src/parser/SparseChoiceLabelingParser.h
  20. 126
      src/parser/SparseStateRewardParser.cpp
  21. 33
      src/parser/SparseStateRewardParser.h
  22. 11
      src/settings/modules/GeneralSettings.cpp
  23. 129
      src/settings/modules/GeneralSettings.h
  24. 257
      src/storage/BitVector.cpp
  25. 12
      src/utility/storm.h
  26. 166
      test/functional/modelchecker/GmmxxDtmcPrctlModelCheckerTest.cpp
  27. 152
      test/functional/modelchecker/GmmxxMdpPrctlModelCheckerTest.cpp
  28. 6
      test/functional/modelchecker/NativeDtmcPrctlModelCheckerTest.cpp
  29. 656
      test/functional/modelchecker/NativeMdpPrctlModelCheckerTest.cpp
  30. 104
      test/functional/modelchecker/SparseDtmcEliminationModelCheckerTest.cpp
  31. 160
      test/functional/modelchecker/TopologicalValueIterationMdpPrctlModelCheckerTest.cpp
  32. 76
      test/functional/parser/AutoParserTest.cpp
  33. 117
      test/functional/parser/DeterministicModelParserTest.cpp
  34. 361
      test/functional/parser/DeterministicSparseTransitionParserTest.cpp
  35. 82
      test/functional/parser/MarkovAutomatonParserTest.cpp
  36. 336
      test/functional/parser/MarkovAutomatonSparseTransitionParserTest.cpp
  37. 81
      test/functional/parser/NondeterministicModelParserTest.cpp
  38. 39
      test/functional/parser/NondeterministicSparseTransitionParserTest.cpp
  39. 44
      test/functional/parser/SparseStateRewardParserTest.cpp
  40. 68
      test/functional/storage/DeterministicModelBisimulationDecompositionTest.cpp
  41. 6
      test/functional/storage/MaximalEndComponentDecompositionTest.cpp
  42. 4
      test/functional/storage/StronglyConnectedComponentDecompositionTest.cpp
  43. 8
      test/performance/graph/GraphTest.cpp
  44. 4
      test/performance/modelchecker/GmmxxDtmcPrctModelCheckerTest.cpp
  45. 4
      test/performance/modelchecker/GmmxxMdpPrctlModelCheckerTest.cpp
  46. 4
      test/performance/modelchecker/NativeDtmcPrctlModelCheckerTest.cpp
  47. 4
      test/performance/modelchecker/NativeMdpPrctlModelCheckerTest.cpp
  48. 4
      test/performance/modelchecker/TopologicalValueIterationMdpPrctlModelCheckerTest.cpp
  49. 4
      test/performance/storage/MaximalEndComponentDecompositionTest.cpp
  50. 8
      test/performance/storage/StronglyConnectedComponentDecompositionTest.cpp

2
CMakeLists.txt

@ -28,7 +28,7 @@ option(STORM_USE_COTIRE "Sets whether Cotire should be used (for building precom
option(LINK_LIBCXXABI "Sets whether libc++abi should be linked." OFF)
option(USE_LIBCXX "Sets whether the standard library is libc++." OFF)
option(USE_CARL "Sets whether carl should be included." ON)
option(FORCE_COLOR "Force color output" ON)
option(FORCE_COLOR "Force color output" OFF)
set(GUROBI_ROOT "" CACHE STRING "A hint to the root directory of Gurobi (optional).")
set(Z3_ROOT "" CACHE STRING "A hint to the root directory of Z3 (optional).")
set(CUDA_ROOT "" CACHE STRING "The root directory of CUDA.")

4
examples/mdp/tiny/tiny.clab

@ -0,0 +1,4 @@
0 0 3
0 1 1
1 0 2
2 0 0

3
src/models/sparse/Model.cpp

@ -182,7 +182,8 @@ namespace storm {
void Model<ValueType, RewardModelType>::printModelInformationFooterToStream(std::ostream& out) const {
this->printRewardModelsInformationToStream(out);
this->getStateLabeling().printLabelingInformationToStream(out);
out << "Size in memory: \t" << (this->getSizeInBytes())/1024 << " kbytes" << std::endl;
out << "choice labels: \t" << (this->hasChoiceLabeling() ? "yes" : "no") << std::noboolalpha << std::endl;
out << "Size in memory: " << (this->getSizeInBytes())/1024 << " kbytes" << std::endl;
out << "-------------------------------------------------------------- " << std::endl;
}

146
src/parser/AutoParser.cpp

@ -14,76 +14,86 @@
#include "src/utility/OsDetection.h"
namespace storm {
namespace parser {
using namespace storm::utility::cstring;
std::shared_ptr<storm::models::sparse::Model<double>> AutoParser::parseModel(std::string const & transitionsFilename,
std::string const & labelingFilename,
std::string const & stateRewardFilename,
std::string const & transitionRewardFilename) {
// Find and parse the model type hint.
storm::models::ModelType type = AutoParser::analyzeHint(transitionsFilename);
// Do the actual parsing.
std::shared_ptr<storm::models::sparse::Model<double>> model;
switch (type) {
case storm::models::ModelType::Dtmc: {
model.reset(new storm::models::sparse::Dtmc<double>(std::move(DeterministicModelParser::parseDtmc(transitionsFilename, labelingFilename, stateRewardFilename, transitionRewardFilename))));
break;
}
case storm::models::ModelType::Ctmc: {
model.reset(new storm::models::sparse::Ctmc<double>(std::move(DeterministicModelParser::parseCtmc(transitionsFilename, labelingFilename, stateRewardFilename, transitionRewardFilename))));
break;
}
case storm::models::ModelType::Mdp: {
model.reset(new storm::models::sparse::Mdp<double>(std::move(NondeterministicModelParser::parseMdp(transitionsFilename, labelingFilename, stateRewardFilename, transitionRewardFilename))));
break;
}
case storm::models::ModelType::MarkovAutomaton: {
model.reset(new storm::models::sparse::MarkovAutomaton<double>(storm::parser::MarkovAutomatonParser::parseMarkovAutomaton(transitionsFilename, labelingFilename, stateRewardFilename, transitionRewardFilename)));
break;
}
default:
LOG4CPLUS_WARN(logger, "Unknown/Unhandled Model Type which cannot be parsed."); // Unknown
}
return model;
}
storm::models::ModelType AutoParser::analyzeHint(std::string const & filename) {
storm::models::ModelType hintType = storm::models::ModelType::Dtmc;
// Open the file.
MappedFile file(filename.c_str());
STORM_LOG_THROW(file.getDataSize() >= STORM_PARSER_AUTOPARSER_HINT_LENGTH, storm::exceptions::WrongFormatException, "File too short to be readable.");
char const* fileData = file.getData();
char filehintBuffer[STORM_PARSER_AUTOPARSER_HINT_LENGTH + 1];
memcpy(filehintBuffer, fileData, STORM_PARSER_AUTOPARSER_HINT_LENGTH);
filehintBuffer[STORM_PARSER_AUTOPARSER_HINT_LENGTH] = 0;
// Find and read in the hint.
std::string formatString = "%" + std::to_string(STORM_PARSER_AUTOPARSER_HINT_LENGTH) + "s";
namespace parser {
using namespace storm::utility::cstring;
template<typename ValueType, typename RewardValueType>
std::shared_ptr<storm::models::sparse::Model<double>> AutoParser<ValueType, RewardValueType>::parseModel(std::string const& transitionsFilename,
std::string const& labelingFilename,
std::string const& stateRewardFilename,
std::string const& transitionRewardFilename,
std::string const& choiceLabelingFilename) {
// Find and parse the model type hint.
storm::models::ModelType type = AutoParser::analyzeHint(transitionsFilename);
// Do the actual parsing.
std::shared_ptr<storm::models::sparse::Model<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>>> model;
switch (type) {
case storm::models::ModelType::Dtmc:
{
model.reset(new storm::models::sparse::Dtmc<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>>(std::move(DeterministicModelParser<ValueType, RewardValueType>::parseDtmc(transitionsFilename, labelingFilename, stateRewardFilename, transitionRewardFilename))));
break;
}
case storm::models::ModelType::Ctmc:
{
model.reset(new storm::models::sparse::Ctmc<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>>(std::move(DeterministicModelParser<ValueType, RewardValueType>::parseCtmc(transitionsFilename, labelingFilename, stateRewardFilename, transitionRewardFilename))));
break;
}
case storm::models::ModelType::Mdp:
{
model.reset(new storm::models::sparse::Mdp<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>>(std::move(NondeterministicModelParser<ValueType, RewardValueType>::parseMdp(transitionsFilename, labelingFilename, stateRewardFilename, transitionRewardFilename, choiceLabelingFilename))));
break;
}
case storm::models::ModelType::MarkovAutomaton:
{
model.reset(new storm::models::sparse::MarkovAutomaton<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>>(storm::parser::MarkovAutomatonParser<ValueType, RewardValueType>::parseMarkovAutomaton(transitionsFilename, labelingFilename, stateRewardFilename, transitionRewardFilename)));
break;
}
default:
LOG4CPLUS_WARN(logger, "Unknown/Unhandled Model Type which cannot be parsed."); // Unknown
}
return model;
}
template<typename ValueType, typename RewardValueType>
storm::models::ModelType AutoParser<ValueType, RewardValueType>::analyzeHint(std::string const & filename) {
storm::models::ModelType hintType = storm::models::ModelType::Dtmc;
// Open the file.
MappedFile file(filename.c_str());
STORM_LOG_THROW(file.getDataSize() >= STORM_PARSER_AUTOPARSER_HINT_LENGTH, storm::exceptions::WrongFormatException, "File too short to be readable.");
char const* fileData = file.getData();
char filehintBuffer[STORM_PARSER_AUTOPARSER_HINT_LENGTH + 1];
memcpy(filehintBuffer, fileData, STORM_PARSER_AUTOPARSER_HINT_LENGTH);
filehintBuffer[STORM_PARSER_AUTOPARSER_HINT_LENGTH] = 0;
// Find and read in the hint.
std::string formatString = "%" + std::to_string(STORM_PARSER_AUTOPARSER_HINT_LENGTH) + "s";
char hint[STORM_PARSER_AUTOPARSER_HINT_LENGTH + 1];
#ifdef WINDOWS
sscanf_s(filehintBuffer, formatString.c_str(), hint, STORM_PARSER_AUTOPARSER_HINT_LENGTH + 1);
#else
sscanf(filehintBuffer, formatString.c_str(), hint);
#endif
for (char* c = hint; *c != '\0'; c++) *c = toupper(*c);
// Check if the hint value is known and store the appropriate enum value.
if (strcmp(hint, "DTMC") == 0) hintType = storm::models::ModelType::Dtmc;
else if (strcmp(hint, "CTMC") == 0) hintType = storm::models::ModelType::Ctmc;
else if (strcmp(hint, "MDP") == 0) hintType = storm::models::ModelType::Mdp;
else if (strcmp(hint, "MA") == 0) hintType = storm::models::ModelType::MarkovAutomaton;
#ifdef WINDOWS
sscanf_s(filehintBuffer, formatString.c_str(), hint, STORM_PARSER_AUTOPARSER_HINT_LENGTH + 1);
#else
sscanf(filehintBuffer, formatString.c_str(), hint);
#endif
for (char* c = hint; *c != '\0'; c++) *c = toupper(*c);
// Check if the hint value is known and store the appropriate enum value.
if (strcmp(hint, "DTMC") == 0) hintType = storm::models::ModelType::Dtmc;
else if (strcmp(hint, "CTMC") == 0) hintType = storm::models::ModelType::Ctmc;
else if (strcmp(hint, "MDP") == 0) hintType = storm::models::ModelType::Mdp;
else if (strcmp(hint, "MA") == 0) hintType = storm::models::ModelType::MarkovAutomaton;
else STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Unable to find model hint in explicit input.");
return hintType;
}
return hintType;
}
} // namespace parser
// Explicitly instantiate the parser.
template class AutoParser<double, double>;
} // namespace parser
} // namespace storm

99
src/parser/AutoParser.h

@ -9,59 +9,64 @@
namespace storm {
/*!
* Contains all file parsers and helper classes.
*
* This namespace contains everything needed to load data files (like
* atomic propositions, transition systems, formulas, etc.) including
* methods for efficient file access (see MappedFile).
*/
namespace parser {
/*!
* Contains all file parsers and helper classes.
*
* This namespace contains everything needed to load data files (like
* atomic propositions, transition systems, formulas, etc.) including
* methods for efficient file access (see MappedFile).
*/
namespace parser {
/*!
* This class automatically chooses the correct parser for the given files and returns the corresponding model.
* The choice of the parser is made using the model hint at the beginning of the given transition file.
*/
class AutoParser {
public:
/*!
* This class automatically chooses the correct parser for the given files and returns the corresponding model.
* The choice of the parser is made using the model hint at the beginning of the given transition file.
*/
template<typename ValueType = double, typename RewardValueType = double>
class AutoParser {
public:
/*!
* Checks the given files and parses the model within these files.
*
* This parser analyzes the format hint in the first line of the transition file.
* If this is a valid format, it will use the parser for this format, otherwise it will throw an exception.
*
* When the files are parsed successfully, a shared pointer owning the resulting model is returned.
* The concrete model can be obtained using the as<Type>() member of the AbstractModel class.
*
* @note The number of states of the model is determined by the transitions file.
* The labeling file may therefore not contain labels of states that are not contained in the transitions file.
*
* @param transitionsFilename The path and name of the file containing the transitions of the model.
* @param labelingFilename The path and name of the file containing the labels for the states of the model.
* @param stateRewardFilename The path and name of the file that contains the state reward of the model. This file is optional.
* @param transitionRewardFilename The path and name of the file that contains the transition rewards of the model. This file is optional.
* @return A shared_ptr containing the resulting model.
*/
static std::shared_ptr<storm::models::sparse::Model<double>> parseModel(std::string const & transitionsFilename,
std::string const & labelingFilename,
std::string const & stateRewardFilename = "",
std::string const & transitionRewardFilename = "");
/*!
* Checks the given files and parses the model within these files.
*
* This parser analyzes the format hint in the first line of the transition file.
* If this is a valid format, it will use the parser for this format, otherwise it will throw an exception.
*
* When the files are parsed successfully, a shared pointer owning the resulting model is returned.
* The concrete model can be obtained using the as<Type>() member of the AbstractModel class.
*
* @note The number of states of the model is determined by the transitions file.
* The labeling file may therefore not contain labels of states that are not contained in the transitions file.
*
* @param transitionsFilename The path and name of the file containing the transitions of the model.
* @param labelingFilename The path and name of the file containing the labels for the states of the model.
* @param stateRewardFilename The path and name of the file that contains the state reward of the model. This file is optional.
* @param transitionRewardFilename The path and name of the file that contains the transition rewards of the model. This file is optional.
* @param choiceLabelingFilename The path and name of the file that contains the choice labeling of the model. This file is optional.
* Note: this file is only meaningful for certain models (currently only MDPs). If the model is not of a type for which this input
* is meaningful, this file will not be parsed.
* @return A shared_ptr containing the resulting model.
*/
static std::shared_ptr<storm::models::sparse::Model<double>> parseModel(std::string const& transitionsFilename,
std::string const& labelingFilename,
std::string const& stateRewardFilename = "",
std::string const& transitionRewardFilename = "",
std::string const& choiceLabelingFilename = "");
private:
private:
// Define the maximal length of a hint in the file.
static uint_fast64_t hintLength;
/*!
* Opens the given file and parses the file format hint.
*
* @param filename The path and name of the file that is to be analysed.
* @return The type of the model as an enum value.
*/
static storm::models::ModelType analyzeHint(std::string const & filename);
};
} // namespace parser
/*!
* Opens the given file and parses the file format hint.
*
* @param filename The path and name of the file that is to be analysed.
* @return The type of the model as an enum value.
*/
static storm::models::ModelType analyzeHint(std::string const & filename);
};
} // namespace parser
} // namespace storm
#endif /* STORM_PARSER_AUTOPARSER_H_ */

69
src/parser/DeterministicModelParser.cpp

@ -10,53 +10,58 @@
#include "src/parser/SparseStateRewardParser.h"
namespace storm {
namespace parser {
namespace parser {
DeterministicModelParser::Result DeterministicModelParser::parseDeterministicModel(std::string const & transitionsFilename, std::string const & labelingFilename, std::string const & stateRewardFilename, std::string const & transitionRewardFilename) {
template<typename ValueType, typename RewardValueType>
typename DeterministicModelParser<ValueType, RewardValueType>::Result DeterministicModelParser<ValueType, RewardValueType>::parseDeterministicModel(std::string const& transitionsFilename, std::string const& labelingFilename, std::string const& stateRewardFilename, std::string const& transitionRewardFilename) {
// Parse the transitions.
storm::storage::SparseMatrix<double> transitions(std::move(storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitions(transitionsFilename)));
// Parse the transitions.
storm::storage::SparseMatrix<ValueType> transitions(std::move(storm::parser::DeterministicSparseTransitionParser<ValueType>::parseDeterministicTransitions(transitionsFilename)));
uint_fast64_t stateCount = transitions.getColumnCount();
uint_fast64_t stateCount = transitions.getColumnCount();
// Parse the state labeling.
storm::models::sparse::StateLabeling labeling(std::move(storm::parser::AtomicPropositionLabelingParser::parseAtomicPropositionLabeling(stateCount, labelingFilename)));
// Parse the state labeling.
storm::models::sparse::StateLabeling labeling(std::move(storm::parser::AtomicPropositionLabelingParser::parseAtomicPropositionLabeling(stateCount, labelingFilename)));
// Construct the result.
DeterministicModelParser::Result result(std::move(transitions), std::move(labeling));
// Construct the result.
DeterministicModelParser<ValueType, RewardValueType>::Result result(std::move(transitions), std::move(labeling));
// Only parse state rewards if a file is given.
if (stateRewardFilename != "") {
result.stateRewards = storm::parser::SparseStateRewardParser::parseSparseStateReward(stateCount, stateRewardFilename);
}
// Only parse state rewards if a file is given.
if (stateRewardFilename != "") {
result.stateRewards = storm::parser::SparseStateRewardParser<RewardValueType>::parseSparseStateReward(stateCount, stateRewardFilename);
}
// Only parse transition rewards if a file is given.
if (transitionRewardFilename != "") {
result.transitionRewards = storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitionRewards(transitionRewardFilename, result.transitionSystem);
}
// Only parse transition rewards if a file is given.
if (transitionRewardFilename != "") {
result.transitionRewards = storm::parser::DeterministicSparseTransitionParser<RewardValueType>::parseDeterministicTransitionRewards(transitionRewardFilename, result.transitionSystem);
}
return result;
}
return result;
}
storm::models::sparse::Dtmc<double> DeterministicModelParser::parseDtmc(std::string const & transitionsFilename, std::string const & labelingFilename, std::string const& stateRewardFilename, std::string const& transitionRewardFilename) {
DeterministicModelParser::Result parserResult(std::move(parseDeterministicModel(transitionsFilename, labelingFilename, stateRewardFilename, transitionRewardFilename)));
template<typename ValueType, typename RewardValueType>
storm::models::sparse::Dtmc<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>> DeterministicModelParser<ValueType, RewardValueType>::parseDtmc(std::string const & transitionsFilename, std::string const & labelingFilename, std::string const& stateRewardFilename, std::string const& transitionRewardFilename) {
typename DeterministicModelParser<ValueType, RewardValueType>::Result parserResult(std::move(parseDeterministicModel(transitionsFilename, labelingFilename, stateRewardFilename, transitionRewardFilename)));
std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<double>> rewardModels;
std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<RewardValueType>> rewardModels;
if (!stateRewardFilename.empty() || !transitionRewardFilename.empty()) {
rewardModels.insert(std::make_pair("", storm::models::sparse::StandardRewardModel<double>(parserResult.stateRewards, boost::optional<std::vector<double>>(), parserResult.transitionRewards)));
rewardModels.insert(std::make_pair("", storm::models::sparse::StandardRewardModel<RewardValueType>(parserResult.stateRewards, boost::optional<std::vector<RewardValueType>>(), parserResult.transitionRewards)));
}
return storm::models::sparse::Dtmc<double>(std::move(parserResult.transitionSystem), std::move(parserResult.labeling), std::move(rewardModels), boost::optional<std::vector<boost::container::flat_set<uint_fast64_t>>>());
}
return storm::models::sparse::Dtmc<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>>(std::move(parserResult.transitionSystem), std::move(parserResult.labeling), std::move(rewardModels));
}
storm::models::sparse::Ctmc<double> DeterministicModelParser::parseCtmc(std::string const & transitionsFilename, std::string const & labelingFilename, std::string const & stateRewardFilename, std::string const & transitionRewardFilename) {
DeterministicModelParser::Result parserResult(std::move(parseDeterministicModel(transitionsFilename, labelingFilename, stateRewardFilename, transitionRewardFilename)));
template<typename ValueType, typename RewardValueType>
storm::models::sparse::Ctmc<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>> DeterministicModelParser<ValueType, RewardValueType>::parseCtmc(std::string const& transitionsFilename, std::string const& labelingFilename, std::string const& stateRewardFilename, std::string const& transitionRewardFilename) {
typename DeterministicModelParser<ValueType, RewardValueType>::Result parserResult(std::move(parseDeterministicModel(transitionsFilename, labelingFilename, stateRewardFilename, transitionRewardFilename)));
std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<double>> rewardModels;
std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<RewardValueType>> rewardModels;
if (!stateRewardFilename.empty() || !transitionRewardFilename.empty()) {
rewardModels.insert(std::make_pair("", storm::models::sparse::StandardRewardModel<double>(parserResult.stateRewards, boost::optional<std::vector<double>>(), parserResult.transitionRewards)));
rewardModels.insert(std::make_pair("", storm::models::sparse::StandardRewardModel<RewardValueType>(parserResult.stateRewards, boost::optional<std::vector<RewardValueType>>(), parserResult.transitionRewards)));
}
return storm::models::sparse::Ctmc<double>(std::move(parserResult.transitionSystem), std::move(parserResult.labeling), std::move(rewardModels), boost::optional<std::vector<boost::container::flat_set<uint_fast64_t>>>());
}
return storm::models::sparse::Ctmc<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>>(std::move(parserResult.transitionSystem), std::move(parserResult.labeling), std::move(rewardModels), boost::optional<std::vector<boost::container::flat_set < uint_fast64_t>>>());
}
} /* namespace parser */
template class DeterministicModelParser<double, double>;
} /* namespace parser */
} /* namespace storm */

64
src/parser/DeterministicModelParser.h

@ -6,56 +6,56 @@
namespace storm {
namespace parser {
/*!
* Loads a deterministic model (Dtmc or Ctmc) from files.
*
* Given the file paths of the files holding the transitions, the atomic propositions and optionally the state- and transition rewards
* it loads the files, parses them and returns the desired model.
*/
template<typename ValueType = double, typename RewardValueType = double>
class DeterministicModelParser {
public:
/*!
* A structure containing the parsed components of a deterministic model.
*/
struct Result {
/*!
* The copy constructor.
*
* @param transitionSystem The transition system to be contained in the Result.
* @param labeling The the labeling of the transition system to be contained in the Result.
*/
Result(storm::storage::SparseMatrix<double>& transitionSystem, storm::models::sparse::StateLabeling& labeling) : transitionSystem(transitionSystem), labeling(labeling) {
Result(storm::storage::SparseMatrix<ValueType>& transitionSystem, storm::models::sparse::StateLabeling& labeling) : transitionSystem(transitionSystem), labeling(labeling) {
// Intentionally left empty.
}
/*!
* The move constructor.
*
* @param transitionSystem The transition system to be contained in the Result.
* @param labeling The the labeling of the transition system to be contained in the Result.
*/
Result(storm::storage::SparseMatrix<double>&& transitionSystem, storm::models::sparse::StateLabeling&& labeling) : transitionSystem(std::move(transitionSystem)), labeling(std::move(labeling)) {
Result(storm::storage::SparseMatrix<ValueType>&& transitionSystem, storm::models::sparse::StateLabeling&& labeling) : transitionSystem(std::move(transitionSystem)), labeling(std::move(labeling)) {
// Intentionally left empty.
}
//! A matrix representing the transitions of the model
storm::storage::SparseMatrix<double> transitionSystem;
storm::storage::SparseMatrix<ValueType> transitionSystem;
//! The labels of each state.
storm::models::sparse::StateLabeling labeling;
//! Optional rewards for each state.
boost::optional<std::vector<double>> stateRewards;
boost::optional<std::vector<RewardValueType>> stateRewards;
//! Optional rewards for each transition.
boost::optional<storm::storage::SparseMatrix<double>> transitionRewards;
boost::optional<storm::storage::SparseMatrix<RewardValueType>> transitionRewards;
};
/*!
* Parse a Dtmc.
*
@ -71,11 +71,11 @@ namespace storm {
* @param transitionRewardFilename The path and name of the file containing the transition rewards of the model. This file is optional.
* @return The parsed Dtmc.
*/
static storm::models::sparse::Dtmc<double> parseDtmc(std::string const & transitionsFilename,
std::string const & labelingFilename,
std::string const & stateRewardFilename = "",
std::string const & transitionRewardFilename = "");
static storm::models::sparse::Dtmc<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>> parseDtmc(std::string const& transitionsFilename,
std::string const & labelingFilename,
std::string const & stateRewardFilename = "",
std::string const & transitionRewardFilename = "");
/*!
* Parse a Ctmc.
*
@ -91,13 +91,13 @@ namespace storm {
* @param transitionRewardFilename The path and name of the file containing the transition rewards of the model. This file is optional.
* @return The parsed Ctmc.
*/
static storm::models::sparse::Ctmc<double> parseCtmc(std::string const & transitionsFilename,
std::string const & labelingFilename,
std::string const & stateRewardFilename = "",
std::string const & transitionRewardFilename = "");
static storm::models::sparse::Ctmc<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>> parseCtmc(std::string const& transitionsFilename,
std::string const & labelingFilename,
std::string const & stateRewardFilename = "",
std::string const & transitionRewardFilename = "");
private:
/*!
* Parses a deterministic model from the given files.
* Calls sub-parsers on the given files and fills the container with the results.
@ -111,12 +111,12 @@ namespace storm {
* @param transitionRewardFilename The path and name of the file containing the transition rewards of the model. This file is optional.
* @return The parsed model encapsulated in a Result structure.
*/
static Result parseDeterministicModel(std::string const & transitionsFilename,
std::string const & labelingFilename,
std::string const & stateRewardFilename = "",
std::string const & transitionRewardFilename = "");
static Result parseDeterministicModel(std::string const& transitionsFilename,
std::string const& labelingFilename,
std::string const& stateRewardFilename = "",
std::string const& transitionRewardFilename = "");
};
} /* namespace parser */
} /* namespace storm */

524
src/parser/DeterministicSparseTransitionParser.cpp

@ -1,10 +1,3 @@
/*!
* TraParser.cpp
*
* Created on: 20.11.2012
* Author: Gereon Kremer
*/
#include "src/parser/DeterministicSparseTransitionParser.h"
#include <cstdio>
@ -28,204 +21,206 @@
extern log4cplus::Logger logger;
namespace storm {
namespace parser {
using namespace storm::utility::cstring;
storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser::parseDeterministicTransitions(std::string const& filename) {
storm::storage::SparseMatrix<double> emptyMatrix;
return DeterministicSparseTransitionParser::parse(filename, false, emptyMatrix);
}
storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser::parseDeterministicTransitionRewards(std::string const& filename, storm::storage::SparseMatrix<double> const & transitionMatrix) {
return DeterministicSparseTransitionParser::parse(filename, true, transitionMatrix);
}
storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser::parse(std::string const& filename, bool isRewardFile, storm::storage::SparseMatrix<double> const & transitionMatrix) {
// Enforce locale where decimal point is '.'.
setlocale(LC_NUMERIC, "C");
if (!MappedFile::fileExistsAndIsReadable(filename.c_str())) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": File does not exist or is not readable.");
throw storm::exceptions::FileIoException() << "The supplied Transition input file \"" << filename << "\" does not exist or is not readable by this process.";
}
// Open file.
MappedFile file(filename.c_str());
char const* buf = file.getData();
// Perform first pass, i.e. count entries that are not zero.
bool insertDiagonalEntriesIfMissing = !isRewardFile;
DeterministicSparseTransitionParser::FirstPassResult firstPass = DeterministicSparseTransitionParser::firstPass(file.getData(), insertDiagonalEntriesIfMissing);
LOG4CPLUS_INFO(logger, "First pass on " << filename << " shows " << firstPass.numberOfNonzeroEntries << " NonZeros.");
// If first pass returned zero, the file format was wrong.
if (firstPass.numberOfNonzeroEntries == 0) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": empty or erroneous file format.");
throw storm::exceptions::WrongFormatException();
}
// Perform second pass.
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if(buf[0] < '0' || buf[0] > '9') {
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
if(isRewardFile) {
// The reward matrix should match the size of the transition matrix.
if (firstPass.highestStateIndex + 1 > transitionMatrix.getRowCount() || firstPass.highestStateIndex + 1 > transitionMatrix.getColumnCount()) {
LOG4CPLUS_ERROR(logger, "Reward matrix has more rows or columns than transition matrix.");
throw storm::exceptions::WrongFormatException() << "Reward matrix has more rows or columns than transition matrix.";
} else {
// If we found the right number of states or less, we set it to the number of states represented by the transition matrix.
firstPass.highestStateIndex = transitionMatrix.getRowCount() - 1;
}
}
// Creating matrix builder here.
// The actual matrix will be build once all contents are inserted.
storm::storage::SparseMatrixBuilder<double> resultMatrix(firstPass.highestStateIndex + 1, firstPass.highestStateIndex + 1, firstPass.numberOfNonzeroEntries);
uint_fast64_t row, col, lastRow = 0;
double val;
bool dontFixDeadlocks = storm::settings::generalSettings().isDontFixDeadlocksSet();
bool hadDeadlocks = false;
bool rowHadDiagonalEntry = false;
// Read all transitions from file. Note that we assume that the
// transitions are listed in canonical order, otherwise this will not
// work, i.e. the values in the matrix will be at wrong places.
// Different parsing routines for transition systems and transition rewards.
if(isRewardFile) {
while (buf[0] != '\0') {
// Read next transition.
row = checked_strtol(buf, &buf);
col = checked_strtol(buf, &buf);
val = checked_strtod(buf, &buf);
resultMatrix.addNextValue(row, col, val);
buf = trimWhitespaces(buf);
}
} else {
// Read first row and add self-loops if necessary.
char const* tmp;
row = checked_strtol(buf, &tmp);
if (row > 0) {
for (uint_fast64_t skippedRow = 0; skippedRow < row; ++skippedRow) {
namespace parser {
using namespace storm::utility::cstring;
template<typename ValueType>
storm::storage::SparseMatrix<ValueType> DeterministicSparseTransitionParser<ValueType>::parseDeterministicTransitions(std::string const& filename) {
storm::storage::SparseMatrix<ValueType> emptyMatrix;
return DeterministicSparseTransitionParser<ValueType>::parse(filename, false, emptyMatrix);
}
template<typename ValueType>
template<typename MatrixValueType>
storm::storage::SparseMatrix<ValueType> DeterministicSparseTransitionParser<ValueType>::parseDeterministicTransitionRewards(std::string const& filename, storm::storage::SparseMatrix<MatrixValueType> const& transitionMatrix) {
return DeterministicSparseTransitionParser<ValueType>::parse(filename, true, transitionMatrix);
}
template<typename ValueType>
template<typename MatrixValueType>
storm::storage::SparseMatrix<ValueType> DeterministicSparseTransitionParser<ValueType>::parse(std::string const& filename, bool isRewardFile, storm::storage::SparseMatrix<MatrixValueType> const& transitionMatrix) {
// Enforce locale where decimal point is '.'.
setlocale(LC_NUMERIC, "C");
if (!MappedFile::fileExistsAndIsReadable(filename.c_str())) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": File does not exist or is not readable.");
throw storm::exceptions::FileIoException() << "The supplied Transition input file \"" << filename << "\" does not exist or is not readable by this process.";
}
// Open file.
MappedFile file(filename.c_str());
char const* buf = file.getData();
// Perform first pass, i.e. count entries that are not zero.
bool insertDiagonalEntriesIfMissing = !isRewardFile;
DeterministicSparseTransitionParser<ValueType>::FirstPassResult firstPass = DeterministicSparseTransitionParser<ValueType>::firstPass(file.getData(), insertDiagonalEntriesIfMissing);
LOG4CPLUS_INFO(logger, "First pass on " << filename << " shows " << firstPass.numberOfNonzeroEntries << " NonZeros.");
// If first pass returned zero, the file format was wrong.
if (firstPass.numberOfNonzeroEntries == 0) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": empty or erroneous file format.");
throw storm::exceptions::WrongFormatException();
}
// Perform second pass.
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if (buf[0] < '0' || buf[0] > '9') {
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
if (isRewardFile) {
// The reward matrix should match the size of the transition matrix.
if (firstPass.highestStateIndex + 1 > transitionMatrix.getRowCount() || firstPass.highestStateIndex + 1 > transitionMatrix.getColumnCount()) {
LOG4CPLUS_ERROR(logger, "Reward matrix has more rows or columns than transition matrix.");
throw storm::exceptions::WrongFormatException() << "Reward matrix has more rows or columns than transition matrix.";
} else {
// If we found the right number of states or less, we set it to the number of states represented by the transition matrix.
firstPass.highestStateIndex = transitionMatrix.getRowCount() - 1;
}
}
// Creating matrix builder here.
// The actual matrix will be build once all contents are inserted.
storm::storage::SparseMatrixBuilder<ValueType> resultMatrix(firstPass.highestStateIndex + 1, firstPass.highestStateIndex + 1, firstPass.numberOfNonzeroEntries);
uint_fast64_t row, col, lastRow = 0;
double val;
bool dontFixDeadlocks = storm::settings::generalSettings().isDontFixDeadlocksSet();
bool hadDeadlocks = false;
bool rowHadDiagonalEntry = false;
// Read all transitions from file. Note that we assume that the
// transitions are listed in canonical order, otherwise this will not
// work, i.e. the values in the matrix will be at wrong places.
// Different parsing routines for transition systems and transition rewards.
if (isRewardFile) {
while (buf[0] != '\0') {
// Read next transition.
row = checked_strtol(buf, &buf);
col = checked_strtol(buf, &buf);
val = checked_strtod(buf, &buf);
resultMatrix.addNextValue(row, col, val);
buf = trimWhitespaces(buf);
}
} else {
// Read first row and add self-loops if necessary.
char const* tmp;
row = checked_strtol(buf, &tmp);
if (row > 0) {
for (uint_fast64_t skippedRow = 0; skippedRow < row; ++skippedRow) {
hadDeadlocks = true;
if (!dontFixDeadlocks) {
resultMatrix.addNextValue(skippedRow, skippedRow, storm::utility::one<ValueType>());
LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": state " << skippedRow << " has no outgoing transitions. A self-loop was inserted.");
} else {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": state " << skippedRow << " has no outgoing transitions.");
// Before throwing the appropriate exception we will give notice of all deadlock states.
}
}
}
while (buf[0] != '\0') {
// Read next transition.
row = checked_strtol(buf, &buf);
col = checked_strtol(buf, &buf);
val = checked_strtod(buf, &buf);
// Test if we moved to a new row.
// Handle all incomplete or skipped rows.
if (lastRow != row) {
if (!rowHadDiagonalEntry) {
if (insertDiagonalEntriesIfMissing) {
resultMatrix.addNextValue(lastRow, lastRow, storm::utility::zero<ValueType>());
LOG4CPLUS_DEBUG(logger, "While parsing " << filename << ": state " << lastRow << " has no transition to itself. Inserted a 0-transition. (1)");
} else {
LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": state " << lastRow << " has no transition to itself.");
}
// No increment for lastRow.
rowHadDiagonalEntry = true;
}
for (uint_fast64_t skippedRow = lastRow + 1; skippedRow < row; ++skippedRow) {
hadDeadlocks = true;
if (!dontFixDeadlocks) {
resultMatrix.addNextValue(skippedRow, skippedRow, storm::utility::one<double>());
resultMatrix.addNextValue(skippedRow, skippedRow, storm::utility::one<ValueType>());
LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": state " << skippedRow << " has no outgoing transitions. A self-loop was inserted.");
} else {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": state " << skippedRow << " has no outgoing transitions.");
// Before throwing the appropriate exception we will give notice of all deadlock states.
}
}
lastRow = row;
rowHadDiagonalEntry = false;
}
if (col == row) {
rowHadDiagonalEntry = true;
}
if (col > row && !rowHadDiagonalEntry) {
if (insertDiagonalEntriesIfMissing) {
resultMatrix.addNextValue(row, row, storm::utility::zero<ValueType>());
LOG4CPLUS_DEBUG(logger, "While parsing " << filename << ": state " << row << " has no transition to itself. Inserted a 0-transition. (2)");
} else {
LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": state " << row << " has no transition to itself.");
}
rowHadDiagonalEntry = true;
}
resultMatrix.addNextValue(row, col, val);
buf = trimWhitespaces(buf);
}
if (!rowHadDiagonalEntry) {
if (insertDiagonalEntriesIfMissing) {
resultMatrix.addNextValue(lastRow, lastRow, storm::utility::zero<ValueType>());
LOG4CPLUS_DEBUG(logger, "While parsing " << filename << ": state " << lastRow << " has no transition to itself. Inserted a 0-transition. (3)");
} else {
LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": state " << lastRow << " has no transition to itself.");
}
while (buf[0] != '\0') {
// Read next transition.
row = checked_strtol(buf, &buf);
col = checked_strtol(buf, &buf);
val = checked_strtod(buf, &buf);
// Test if we moved to a new row.
// Handle all incomplete or skipped rows.
if (lastRow != row) {
if (!rowHadDiagonalEntry) {
if (insertDiagonalEntriesIfMissing) {
resultMatrix.addNextValue(lastRow, lastRow, storm::utility::zero<double>());
LOG4CPLUS_DEBUG(logger, "While parsing " << filename << ": state " << lastRow << " has no transition to itself. Inserted a 0-transition. (1)");
} else {
LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": state " << lastRow << " has no transition to itself.");
}
// No increment for lastRow.
rowHadDiagonalEntry = true;
}
for (uint_fast64_t skippedRow = lastRow + 1; skippedRow < row; ++skippedRow) {
hadDeadlocks = true;
if (!dontFixDeadlocks) {
resultMatrix.addNextValue(skippedRow, skippedRow, storm::utility::one<double>());
LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": state " << skippedRow << " has no outgoing transitions. A self-loop was inserted.");
} else {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": state " << skippedRow << " has no outgoing transitions.");
// Before throwing the appropriate exception we will give notice of all deadlock states.
}
}
lastRow = row;
rowHadDiagonalEntry = false;
}
if (col == row) {
rowHadDiagonalEntry = true;
}
if (col > row && !rowHadDiagonalEntry) {
if (insertDiagonalEntriesIfMissing) {
resultMatrix.addNextValue(row, row, storm::utility::zero<double>());
LOG4CPLUS_DEBUG(logger, "While parsing " << filename << ": state " << row << " has no transition to itself. Inserted a 0-transition. (2)");
} else {
LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": state " << row << " has no transition to itself.");
}
rowHadDiagonalEntry = true;
}
resultMatrix.addNextValue(row, col, val);
buf = trimWhitespaces(buf);
}
if (!rowHadDiagonalEntry) {
if (insertDiagonalEntriesIfMissing) {
resultMatrix.addNextValue(lastRow, lastRow, storm::utility::zero<double>());
LOG4CPLUS_DEBUG(logger, "While parsing " << filename << ": state " << lastRow << " has no transition to itself. Inserted a 0-transition. (3)");
} else {
LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": state " << lastRow << " has no transition to itself.");
}
}
// If we encountered deadlock and did not fix them, now is the time to throw the exception.
if (dontFixDeadlocks && hadDeadlocks) throw storm::exceptions::WrongFormatException() << "Some of the states do not have outgoing transitions.";
}
// Finally, build the actual matrix, test and return it.
storm::storage::SparseMatrix<double> result = resultMatrix.build();
// Since we cannot do the testing if each transition for which there is a reward in the reward file also exists in the transition matrix during parsing, we have to do it afterwards.
if(isRewardFile && !result.isSubmatrixOf(transitionMatrix)) {
LOG4CPLUS_ERROR(logger, "There are rewards for non existent transitions given in the reward file.");
throw storm::exceptions::WrongFormatException() << "There are rewards for non existent transitions given in the reward file.";
}
return result;
}
DeterministicSparseTransitionParser::FirstPassResult DeterministicSparseTransitionParser::firstPass(char const* buf, bool insertDiagonalEntriesIfMissing) {
DeterministicSparseTransitionParser::FirstPassResult result;
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if(buf[0] < '0' || buf[0] > '9') {
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
// Check all transitions for non-zero diagonal entries and deadlock states.
uint_fast64_t row, col, lastRow = 0, lastCol = -1;
bool rowHadDiagonalEntry = false;
}
// If we encountered deadlock and did not fix them, now is the time to throw the exception.
if (dontFixDeadlocks && hadDeadlocks) throw storm::exceptions::WrongFormatException() << "Some of the states do not have outgoing transitions.";
}
// Finally, build the actual matrix, test and return it.
storm::storage::SparseMatrix<ValueType> result = resultMatrix.build();
// Since we cannot check if each transition for which there is a reward in the reward file also exists in the transition matrix during parsing, we have to do it afterwards.
if (isRewardFile && !result.isSubmatrixOf(transitionMatrix)) {
LOG4CPLUS_ERROR(logger, "There are rewards for non existent transitions given in the reward file.");
throw storm::exceptions::WrongFormatException() << "There are rewards for non existent transitions given in the reward file.";
}
return result;
}
template<typename ValueType>
typename DeterministicSparseTransitionParser<ValueType>::FirstPassResult DeterministicSparseTransitionParser<ValueType>::firstPass(char const* buf, bool insertDiagonalEntriesIfMissing) {
DeterministicSparseTransitionParser<ValueType>::FirstPassResult result;
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if (buf[0] < '0' || buf[0] > '9') {
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
// Check all transitions for non-zero diagonal entries and deadlock states.
uint_fast64_t row, col, lastRow = 0, lastCol = -1;
bool rowHadDiagonalEntry = false;
// Read first row and reserve space for self-loops if necessary.
char const* tmp;
row = checked_strtol(buf, &tmp);
@ -234,70 +229,73 @@ namespace storm {
++result.numberOfNonzeroEntries;
}
}
while (buf[0] != '\0') {
// Read the transition.
row = checked_strtol(buf, &buf);
col = checked_strtol(buf, &buf);
// The actual read value is not needed here.
checked_strtod(buf, &buf);
// Compensate for missing diagonal entries if desired.
if (insertDiagonalEntriesIfMissing) {
if (lastRow != row) {
if(!rowHadDiagonalEntry) {
++result.numberOfNonzeroEntries;
}
// Compensate for missing rows.
for (uint_fast64_t skippedRow = lastRow + 1; skippedRow < row; ++skippedRow) {
++result.numberOfNonzeroEntries;
}
rowHadDiagonalEntry = false;
}
if (col == row) {
rowHadDiagonalEntry = true;
}
if (col > row && !rowHadDiagonalEntry) {
rowHadDiagonalEntry = true;
++result.numberOfNonzeroEntries;
}
}
// Check if a higher state id was found.
if (row > result.highestStateIndex) result.highestStateIndex = row;
if (col > result.highestStateIndex) result.highestStateIndex = col;
++result.numberOfNonzeroEntries;
// Have we already seen this transition?
if (row == lastRow && col == lastCol) {
LOG4CPLUS_ERROR(logger, "The same transition (" << row << ", " << col << ") is given twice.");
throw storm::exceptions::InvalidArgumentException() << "The same transition (" << row << ", " << col << ") is given twice.";
}
lastRow = row;
lastCol = col;
buf = trimWhitespaces(buf);
}
if(insertDiagonalEntriesIfMissing) {
if (!rowHadDiagonalEntry) {
++result.numberOfNonzeroEntries;
}
//Compensate for missing rows at the end of the file.
for (uint_fast64_t skippedRow = (uint_fast64_t)(lastRow + 1); skippedRow <= result.highestStateIndex; ++skippedRow) {
++result.numberOfNonzeroEntries;
}
}
return result;
}
} // namespace parser
} // namespace storm
while (buf[0] != '\0') {
// Read the transition.
row = checked_strtol(buf, &buf);
col = checked_strtol(buf, &buf);
// The actual read value is not needed here.
checked_strtod(buf, &buf);
// Compensate for missing diagonal entries if desired.
if (insertDiagonalEntriesIfMissing) {
if (lastRow != row) {
if (!rowHadDiagonalEntry) {
++result.numberOfNonzeroEntries;
}
// Compensate for missing rows.
for (uint_fast64_t skippedRow = lastRow + 1; skippedRow < row; ++skippedRow) {
++result.numberOfNonzeroEntries;
}
rowHadDiagonalEntry = false;
}
if (col == row) {
rowHadDiagonalEntry = true;
}
if (col > row && !rowHadDiagonalEntry) {
rowHadDiagonalEntry = true;
++result.numberOfNonzeroEntries;
}
}
// Check if a higher state id was found.
if (row > result.highestStateIndex) result.highestStateIndex = row;
if (col > result.highestStateIndex) result.highestStateIndex = col;
++result.numberOfNonzeroEntries;
// Have we already seen this transition?
if (row == lastRow && col == lastCol) {
LOG4CPLUS_ERROR(logger, "The same transition (" << row << ", " << col << ") is given twice.");
throw storm::exceptions::InvalidArgumentException() << "The same transition (" << row << ", " << col << ") is given twice.";
}
lastRow = row;
lastCol = col;
buf = trimWhitespaces(buf);
}
if (insertDiagonalEntriesIfMissing) {
if (!rowHadDiagonalEntry) {
++result.numberOfNonzeroEntries;
}
//Compensate for missing rows at the end of the file.
for (uint_fast64_t skippedRow = (uint_fast64_t) (lastRow + 1); skippedRow <= result.highestStateIndex; ++skippedRow) {
++result.numberOfNonzeroEntries;
}
}
return result;
}
template class DeterministicSparseTransitionParser<double>;
template storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser<double>::parseDeterministicTransitionRewards(std::string const& filename, storm::storage::SparseMatrix<double> const& transitionMatrix);
template storm::storage::SparseMatrix<double> DeterministicSparseTransitionParser<double>::parse(std::string const& filename, bool isRewardFile, storm::storage::SparseMatrix<double> const& transitionMatrix);
} // namespace parser
} // namespace storm

139
src/parser/DeterministicSparseTransitionParser.h

@ -4,87 +4,88 @@
#include "src/storage/SparseMatrix.h"
namespace storm {
namespace parser {
namespace parser {
/*!
* This class can be used to parse a file containing either transitions or transition rewards of a deterministic model.
*
* The file is parsed in two passes.
* The first pass tests the file format and collects statistical data needed for the second pass.
* The second pass then parses the file data and constructs a SparseMatrix representing it.
*/
class DeterministicSparseTransitionParser {
public:
/*!
* This class can be used to parse a file containing either transitions or transition rewards of a deterministic model.
*
* The file is parsed in two passes.
* The first pass tests the file format and collects statistical data needed for the second pass.
* The second pass then parses the file data and constructs a SparseMatrix representing it.
*/
template<typename ValueType = double>
class DeterministicSparseTransitionParser {
public:
/*!
* A structure representing the result of the first pass of this parser. It contains the number of non-zero entries in the model and the highest state index.
*/
struct FirstPassResult {
/*!
* A structure representing the result of the first pass of this parser. It contains the number of non-zero entries in the model and the highest state index.
*/
struct FirstPassResult {
/*!
* The default constructor.
* Constructs an empty FirstPassResult.
*/
FirstPassResult() : numberOfNonzeroEntries(0), highestStateIndex(0) {
// Intentionally left empty.
}
/*!
* The default constructor.
* Constructs an empty FirstPassResult.
*/
FirstPassResult() : numberOfNonzeroEntries(0), highestStateIndex(0) {
// Intentionally left empty.
}
//! The total number of non-zero entries of the model.
uint_fast64_t numberOfNonzeroEntries;
//! The total number of non-zero entries of the model.
uint_fast64_t numberOfNonzeroEntries;
//! The highest state index that appears in the model.
uint_fast64_t highestStateIndex;
};
//! The highest state index that appears in the model.
uint_fast64_t highestStateIndex;
};
/*!
* Load a deterministic transition system from file and create a
* sparse adjacency matrix whose entries represent the weights of the edges.
*
* @param filename The path and name of the file to be parsed.
* @param insertDiagonalEntriesIfMissing A flag set iff entries on the primary diagonal of the matrix should be added in case they are missing in the parsed file.
* @return A SparseMatrix containing the parsed transition system.
*/
static storm::storage::SparseMatrix<double> parseDeterministicTransitions(std::string const& filename);
/*!
* Load a deterministic transition system from file and create a
* sparse adjacency matrix whose entries represent the weights of the edges.
*
* @param filename The path and name of the file to be parsed.
* @param insertDiagonalEntriesIfMissing A flag set iff entries on the primary diagonal of the matrix should be added in case they are missing in the parsed file.
* @return A SparseMatrix containing the parsed transition system.
*/
static storm::storage::SparseMatrix<ValueType> parseDeterministicTransitions(std::string const& filename);
/*!
* Load the transition rewards for a deterministic transition system from file and create a
* sparse adjacency matrix whose entries represent the rewards of the respective transitions.
*
* @param filename The path and name of the file to be parsed.
* @param transitionMatrix The transition matrix of the model in which the reward matrix is to be used in.
* The dimensions (rows and columns) of the two matrices should match.
* @return A SparseMatrix containing the parsed transition rewards.
*/
static storm::storage::SparseMatrix<double> parseDeterministicTransitionRewards(std::string const& filename, storm::storage::SparseMatrix<double> const & transitionMatrix);
/*!
* Load the transition rewards for a deterministic transition system from file and create a
* sparse adjacency matrix whose entries represent the rewards of the respective transitions.
*
* @param filename The path and name of the file to be parsed.
* @param transitionMatrix The transition matrix of the system.
* @return A SparseMatrix containing the parsed transition rewards.
*/
template<typename MatrixValueType>
static storm::storage::SparseMatrix<ValueType> parseDeterministicTransitionRewards(std::string const& filename, storm::storage::SparseMatrix<MatrixValueType> const& transitionMatrix);
private:
private:
/*
* Performs the first pass on the input pointed to by the given buffer to obtain the number of
* transitions and the maximum node id.
*
* @param buffer The buffer that contains the input.
* @param insertDiagonalEntriesIfMissing A flag set iff entries on the primary diagonal of the matrix should be added in case they are missing in the parsed file.
* @return A structure representing the result of the first pass.
*/
static FirstPassResult firstPass(char const* buffer, bool insertDiagonalEntriesIfMissing = true);
/*
* Performs the first pass on the input pointed to by the given buffer to obtain the number of
* transitions and the maximum node id.
*
* @param buffer The buffer that contains the input.
* @param insertDiagonalEntriesIfMissing A flag set iff entries on the primary diagonal of the matrix should be added in case they are missing in the parsed file.
* @return A structure representing the result of the first pass.
*/
static FirstPassResult firstPass(char const* buffer, bool insertDiagonalEntriesIfMissing = true);
/*
* The main parsing routine.
* Opens the given file, calls the first pass and performs the second pass, parsing the content of the file into a SparseMatrix.
*
* @param filename The path and name of the file to be parsed.
* @param rewardFile A flag set iff the file to be parsed contains transition rewards.
* @param insertDiagonalEntriesIfMissing A flag set iff entries on the primary diagonal of the matrix should be added in case they are missing in the parsed file.
* @param transitionMatrix The transition matrix of the model in which the reward matrix is to be used in.
* The dimensions (rows and columns) of the two matrices should match.
* @return A SparseMatrix containing the parsed file contents.
*/
static storm::storage::SparseMatrix<double> parse(std::string const& filename, bool isRewardFile, storm::storage::SparseMatrix<double> const & transitionMatrix);
/*
* The main parsing routine.
* Opens the given file, calls the first pass and performs the second pass, parsing the content of the file into a SparseMatrix.
*
* @param filename The path and name of the file to be parsed.
* @param rewardFile A flag set iff the file to be parsed contains transition rewards.
* @param insertDiagonalEntriesIfMissing A flag set iff entries on the primary diagonal of the matrix should be added in case they are missing in the parsed file.
* @param transitionMatrix The transition matrix of the system (this is only meaningful if isRewardFile is set to true).
* @return A SparseMatrix containing the parsed file contents.
*/
template<typename MatrixValueType>
static storm::storage::SparseMatrix<ValueType> parse(std::string const& filename, bool isRewardFile, storm::storage::SparseMatrix<MatrixValueType> const& transitionMatrix);
};
};
} // namespace parser
} // namespace parser
} // namespace storm
#endif /* STORM_PARSER_DETERMINISTICSPARSETRANSITIONPARSER_H_ */

53
src/parser/MarkovAutomatonParser.cpp

@ -11,38 +11,41 @@
extern log4cplus::Logger logger;
namespace storm {
namespace parser {
namespace parser {
storm::models::sparse::MarkovAutomaton<double> MarkovAutomatonParser::parseMarkovAutomaton(std::string const& transitionsFilename, std::string const& labelingFilename, std::string const& stateRewardFilename, std::string const& transitionRewardFilename) {
template<typename ValueType, typename RewardValueType>
storm::models::sparse::MarkovAutomaton<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>> MarkovAutomatonParser<ValueType, RewardValueType>::parseMarkovAutomaton(std::string const& transitionsFilename, std::string const& labelingFilename, std::string const& stateRewardFilename, std::string const& transitionRewardFilename) {
// Parse the transitions of the Markov Automaton.
storm::parser::MarkovAutomatonSparseTransitionParser::Result transitionResult(storm::parser::MarkovAutomatonSparseTransitionParser::parseMarkovAutomatonTransitions(transitionsFilename));
// Parse the transitions of the Markov Automaton.
typename storm::parser::MarkovAutomatonSparseTransitionParser<ValueType>::Result transitionResult(storm::parser::MarkovAutomatonSparseTransitionParser<ValueType>::parseMarkovAutomatonTransitions(transitionsFilename));
// Build the actual transition matrix using the MatrixBuilder provided by the transitionResult.
storm::storage::SparseMatrix<double> transitionMatrix(transitionResult.transitionMatrixBuilder.build());
// Build the actual transition matrix using the MatrixBuilder provided by the transitionResult.
storm::storage::SparseMatrix<ValueType> transitionMatrix(transitionResult.transitionMatrixBuilder.build());
// Parse the state labeling.
storm::models::sparse::StateLabeling resultLabeling(storm::parser::AtomicPropositionLabelingParser::parseAtomicPropositionLabeling(transitionMatrix.getColumnCount(), labelingFilename));
// Parse the state labeling.
storm::models::sparse::StateLabeling resultLabeling(storm::parser::AtomicPropositionLabelingParser::parseAtomicPropositionLabeling(transitionMatrix.getColumnCount(), labelingFilename));
// If given, parse the state rewards file.
boost::optional<std::vector<double>> stateRewards;
if (stateRewardFilename != "") {
stateRewards.reset(storm::parser::SparseStateRewardParser::parseSparseStateReward(transitionMatrix.getColumnCount(), stateRewardFilename));
}
std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<double>> rewardModels;
rewardModels.insert(std::make_pair("", storm::models::sparse::StandardRewardModel<double>(stateRewards, boost::optional<std::vector<double>>(), boost::optional<storm::storage::SparseMatrix<double>>())));
// If given, parse the state rewards file.
boost::optional<std::vector<RewardValueType>> stateRewards;
if (stateRewardFilename != "") {
stateRewards.reset(storm::parser::SparseStateRewardParser<RewardValueType>::parseSparseStateReward(transitionMatrix.getColumnCount(), stateRewardFilename));
}
std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<RewardValueType>> rewardModels;
rewardModels.insert(std::make_pair("", storm::models::sparse::StandardRewardModel<RewardValueType>(stateRewards, boost::optional<std::vector<double>>(), boost::optional<storm::storage::SparseMatrix<double>>())));
// Since Markov Automata do not support transition rewards no path should be given here.
if (transitionRewardFilename != "") {
LOG4CPLUS_ERROR(logger, "Transition rewards are unsupported for Markov automata.");
throw storm::exceptions::WrongFormatException() << "Transition rewards are unsupported for Markov automata.";
}
// Since Markov Automata do not support transition rewards no path should be given here.
if (transitionRewardFilename != "") {
LOG4CPLUS_ERROR(logger, "Transition rewards are unsupported for Markov automata.");
throw storm::exceptions::WrongFormatException() << "Transition rewards are unsupported for Markov automata.";
}
// Put the pieces together to generate the Markov Automaton.
storm::models::sparse::MarkovAutomaton<double> resultingAutomaton(std::move(transitionMatrix), std::move(resultLabeling), std::move(transitionResult.markovianStates), std::move(transitionResult.exitRates), rewardModels, boost::optional<std::vector<boost::container::flat_set<uint_fast64_t>>>());
// Put the pieces together to generate the Markov Automaton.
storm::models::sparse::MarkovAutomaton<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>> resultingAutomaton(std::move(transitionMatrix), std::move(resultLabeling), std::move(transitionResult.markovianStates), std::move(transitionResult.exitRates), rewardModels);
return resultingAutomaton;
}
return resultingAutomaton;
}
} // namespace parser
template class MarkovAutomatonParser<double, double>;
} // namespace parser
} // namespace storm

3
src/parser/MarkovAutomatonParser.h

@ -13,6 +13,7 @@ namespace storm {
* Given the file paths of the files holding the transitions, the atomic propositions and optionally the state rewards
* it loads the files, parses them and returns the desired model.
*/
template<typename ValueType = double, typename RewardValueType = double>
class MarkovAutomatonParser {
public:
@ -28,7 +29,7 @@ namespace storm {
* @param transitionRewardFilename The name of the file that contains the transition rewards of the Markov automaton. This should be empty as transition rewards are not supported by Markov Automata.
* @return The parsed MarkovAutomaton.
*/
static storm::models::sparse::MarkovAutomaton<double> parseMarkovAutomaton(std::string const& transitionsFilename, std::string const& labelingFilename, std::string const& stateRewardFilename = "", std::string const& transitionRewardFilename = "");
static storm::models::sparse::MarkovAutomaton<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>> parseMarkovAutomaton(std::string const& transitionsFilename, std::string const& labelingFilename, std::string const& stateRewardFilename = "", std::string const& transitionRewardFilename = "");
};
} // namespace parser

533
src/parser/MarkovAutomatonSparseTransitionParser.cpp

@ -10,273 +10,278 @@
namespace storm {
namespace parser {
namespace parser {
using namespace storm::utility::cstring;
using namespace storm::utility::cstring;
MarkovAutomatonSparseTransitionParser::FirstPassResult MarkovAutomatonSparseTransitionParser::firstPass(char const* buf) {
MarkovAutomatonSparseTransitionParser::FirstPassResult result;
template<typename ValueType>
typename MarkovAutomatonSparseTransitionParser<ValueType>::FirstPassResult MarkovAutomatonSparseTransitionParser<ValueType>::firstPass(char const* buf) {
MarkovAutomatonSparseTransitionParser::FirstPassResult result;
bool dontFixDeadlocks = storm::settings::generalSettings().isDontFixDeadlocksSet();
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if(buf[0] < '0' || buf[0] > '9') {
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
// Now read the transitions.
uint_fast64_t source, target = 0;
uint_fast64_t lastsource = 0;
bool encounteredEOF = false;
bool stateHasMarkovianChoice = false;
bool stateHasProbabilisticChoice = false;
while (buf[0] != '\0' && !encounteredEOF) {
// At the current point, the next thing to read is the source state of the next choice to come.
source = checked_strtol(buf, &buf);
// Check if we encountered a state index that is bigger than all previously seen ones and record it if necessary.
if (source > result.highestStateIndex) {
result.highestStateIndex = source;
}
// If we have skipped some states, we need to reserve the space for the self-loop insertion in the second pass.
if (source > lastsource + 1) {
if (!dontFixDeadlocks) {
result.numberOfNonzeroEntries += source - lastsource - 1;
result.numberOfChoices += source - lastsource - 1;
} else {
LOG4CPLUS_ERROR(logger, "Found deadlock states (e.g. " << lastsource + 1 << ") during parsing. Please fix them or set the appropriate flag.");
throw storm::exceptions::WrongFormatException() << "Found deadlock states (e.g. " << lastsource + 1 << ") during parsing. Please fix them or set the appropriate flag.";
}
} else if (source < lastsource) {
LOG4CPLUS_ERROR(logger, "Illegal state choice order. A choice of state " << source << " appears at an illegal position.");
throw storm::exceptions::WrongFormatException() << "Illegal state choice order. A choice of state " << source << " appears at an illegal position.";
}
++result.numberOfChoices;
// If we have moved to the next state, we need to clear the flag that stores whether or not the source has a Markovian or probabilistic choice.
if (source != lastsource) {
stateHasMarkovianChoice = false;
stateHasProbabilisticChoice = false;
}
// Record that the current source was the last source.
lastsource = source;
buf = trimWhitespaces(buf);
// Depending on the action name, the choice is either a probabilitic one or a markovian one.
bool isMarkovianChoice = false;
if (buf[0] == '!' && skipWord(buf) - buf == 1) {
isMarkovianChoice = true;
}else {
isMarkovianChoice = false;
}
buf = skipWord(buf);
if (isMarkovianChoice) {
if (stateHasMarkovianChoice) {
LOG4CPLUS_ERROR(logger, "The state " << source << " has multiple Markovian choices.");
throw storm::exceptions::WrongFormatException() << "The state " << source << " has multiple Markovian choices.";
}
if (stateHasProbabilisticChoice) {
LOG4CPLUS_ERROR(logger, "The state " << source << " has a probabilistic choice preceding a Markovian choice. The Markovian choice must be the first choice listed.");
throw storm::exceptions::WrongFormatException() << "The state " << source << " has a probabilistic choice preceding a Markovian choice. The Markovian choice must be the first choice listed.";
}
stateHasMarkovianChoice = true;
} else {
stateHasProbabilisticChoice = true;
}
// Go to the next line where the transitions start.
buf = forwardToNextLine(buf);
// Now that we have the source state and the information whether or not the current choice is probabilistic or Markovian, we need to read the list of successors and the probabilities/rates.
bool hasSuccessorState = false;
bool encounteredNewDistribution = false;
uint_fast64_t lastSuccessorState = 0;
// At this point, we need to check whether there is an additional successor or we have reached the next choice for the same or a different state.
do {
buf = trimWhitespaces(buf);
// If the end of the file was reached, we need to abort and check whether we are in a legal state.
if (buf[0] == '\0') {
if (!hasSuccessorState) {
LOG4CPLUS_ERROR(logger, "Premature end-of-file. Expected at least one successor state for state " << source << ".");
throw storm::exceptions::WrongFormatException() << "Premature end-of-file. Expected at least one successor state for state " << source << ".";
} else {
// If there was at least one successor for the current choice, this is legal and we need to move on.
encounteredEOF = true;
}
} else if (buf[0] == '*') {
// As we have encountered a "*", we know that there is an additional successor state for the current choice.
buf= skipWord(buf);
// Now we need to read the successor state and check if we already saw a higher state index.
target = checked_strtol(buf, &buf);
if (target > result.highestStateIndex) {
result.highestStateIndex = target;
}
if (hasSuccessorState && target <= lastSuccessorState) {
LOG4CPLUS_ERROR(logger, "Illegal transition order for source state " << source << ".");
throw storm::exceptions::WrongFormatException() << "Illegal transition order for source state " << source << ".";
}
// And the corresponding probability/rate.
double val = checked_strtod(buf, &buf);
if (val < 0.0) {
LOG4CPLUS_ERROR(logger, "Illegal negative probability/rate value for transition from " << source << " to " << target << ": " << val << ".");
throw storm::exceptions::WrongFormatException() << "Illegal negative probability/rate value for transition from " << source << " to " << target << ": " << val << ".";
}
if (!isMarkovianChoice && val > 1.0) {
LOG4CPLUS_ERROR(logger, "Illegal probability value for transition from " << source << " to " << target << ": " << val << ".");
throw storm::exceptions::WrongFormatException() << "Illegal probability value for transition from " << source << " to " << target << ": " << val << ".";
}
// We need to record that we found at least one successor state for the current choice.
hasSuccessorState = true;
lastSuccessorState = target;
// As we found a new successor, we need to increase the number of nonzero entries.
++result.numberOfNonzeroEntries;
buf = forwardToNextLine(buf);
} else {
// If it was not a "*", we have to assume that we encountered the beginning of a new choice definition. In this case, we don't move the pointer
// to the buffer, because we still need to read the new source state.
encounteredNewDistribution = true;
}
} while (!encounteredEOF && !encounteredNewDistribution);
}
return result;
}
MarkovAutomatonSparseTransitionParser::Result MarkovAutomatonSparseTransitionParser::secondPass(char const* buf, FirstPassResult const& firstPassResult) {
Result result(firstPassResult);
bool dontFixDeadlocks = storm::settings::generalSettings().isDontFixDeadlocksSet();
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if(buf[0] < '0' || buf[0] > '9') {
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
// Now read the transitions.
uint_fast64_t source, target = 0;
uint_fast64_t lastsource = 0;
bool encounteredEOF = false;
uint_fast64_t currentChoice = 0;
// The first choice of the first state already starts a new row group of the matrix.
result.transitionMatrixBuilder.newRowGroup(0);
while (buf[0] != '\0' && !encounteredEOF) {
// At the current point, the next thing to read is the source state of the next choice to come.
source = checked_strtol(buf, &buf);
// If we have skipped some states, we need to insert self-loops if requested.
if (source > lastsource + 1) {
if (!dontFixDeadlocks) {
for (uint_fast64_t index = lastsource + 1; index < source; ++index) {
result.transitionMatrixBuilder.newRowGroup(currentChoice);
result.transitionMatrixBuilder.addNextValue(currentChoice, index, 1);
++currentChoice;
}
} else {
LOG4CPLUS_ERROR(logger, "Found deadlock states (e.g. " << lastsource + 1 << ") during parsing. Please fix them or set the appropriate flag.");
throw storm::exceptions::WrongFormatException() << "Found deadlock states (e.g. " << lastsource + 1 << ") during parsing. Please fix them or set the appropriate flag.";
}
}
if (source != lastsource) {
// If we skipped to a new state we need to create a new row group for the choices of the new state.
result.transitionMatrixBuilder.newRowGroup(currentChoice);
}
// Record that the current source was the last source.
lastsource = source;
buf = trimWhitespaces(buf);
// Depending on the action name, the choice is either a probabilitic one or a markovian one.
bool isMarkovianChoice = false;
if (buf[0] == '!' && skipWord(buf) - buf == 1) {
isMarkovianChoice = true;
// Mark the current state as a Markovian one.
result.markovianStates.set(source, true);
} else {
isMarkovianChoice = false;
}
// Go to the next line where the transitions start.
buf = forwardToNextLine(buf);
// Now that we have the source state and the information whether or not the current choice is probabilistic or Markovian, we need to read the list of successors and the probabilities/rates.
bool encounteredNewDistribution = false;
// At this point, we need to check whether there is an additional successor or we have reached the next choice for the same or a different state.
do {
buf = trimWhitespaces(buf);
// If the end of the file was reached, we need to abort and check whether we are in a legal state.
if (buf[0] == '\0') {
// Under the assumption that the currently open choice has at least one successor (which is given after the first run)
// we may legally stop reading here.
encounteredEOF = true;
} else if (buf[0] == '*') {
// As we have encountered a "*", we know that there is an additional successor state for the current choice.
buf = skipWord(buf);
// Now we need to read the successor state and check if we already saw a higher state index.
target = checked_strtol(buf, &buf);
// And the corresponding probability/rate.
double val = checked_strtod(buf, &buf);
// Record the value as well as the exit rate in case of a Markovian choice.
result.transitionMatrixBuilder.addNextValue(currentChoice, target, val);
if (isMarkovianChoice) {
result.exitRates[source] += val;
}
buf = forwardToNextLine(buf);
} else {
// If it was not a "*", we have to assume that we encountered the beginning of a new choice definition. In this case, we don't move the pointer
// to the buffer, because we still need to read the new source state.
encounteredNewDistribution = true;
}
} while (!encounteredEOF && !encounteredNewDistribution);
++currentChoice;
}
return result;
}
MarkovAutomatonSparseTransitionParser::Result MarkovAutomatonSparseTransitionParser::parseMarkovAutomatonTransitions(std::string const& filename) {
// Set the locale to correctly recognize floating point numbers.
setlocale(LC_NUMERIC, "C");
if (!MappedFile::fileExistsAndIsReadable(filename.c_str())) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": File does not exist or is not readable.");
throw storm::exceptions::FileIoException() << "Error while parsing " << filename << ": File does not exist or is not readable.";
}
// Open file and prepare pointer to buffer.
MappedFile file(filename.c_str());
char const* buf = file.getData();
return secondPass(buf, firstPass(buf));
}
} // namespace parser
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if (buf[0] < '0' || buf[0] > '9') {
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
// Now read the transitions.
uint_fast64_t source, target = 0;
uint_fast64_t lastsource = 0;
bool encounteredEOF = false;
bool stateHasMarkovianChoice = false;
bool stateHasProbabilisticChoice = false;
while (buf[0] != '\0' && !encounteredEOF) {
// At the current point, the next thing to read is the source state of the next choice to come.
source = checked_strtol(buf, &buf);
// Check if we encountered a state index that is bigger than all previously seen ones and record it if necessary.
if (source > result.highestStateIndex) {
result.highestStateIndex = source;
}
// If we have skipped some states, we need to reserve the space for the self-loop insertion in the second pass.
if (source > lastsource + 1) {
if (!dontFixDeadlocks) {
result.numberOfNonzeroEntries += source - lastsource - 1;
result.numberOfChoices += source - lastsource - 1;
} else {
LOG4CPLUS_ERROR(logger, "Found deadlock states (e.g. " << lastsource + 1 << ") during parsing. Please fix them or set the appropriate flag.");
throw storm::exceptions::WrongFormatException() << "Found deadlock states (e.g. " << lastsource + 1 << ") during parsing. Please fix them or set the appropriate flag.";
}
} else if (source < lastsource) {
LOG4CPLUS_ERROR(logger, "Illegal state choice order. A choice of state " << source << " appears at an illegal position.");
throw storm::exceptions::WrongFormatException() << "Illegal state choice order. A choice of state " << source << " appears at an illegal position.";
}
++result.numberOfChoices;
// If we have moved to the next state, we need to clear the flag that stores whether or not the source has a Markovian or probabilistic choice.
if (source != lastsource) {
stateHasMarkovianChoice = false;
stateHasProbabilisticChoice = false;
}
// Record that the current source was the last source.
lastsource = source;
buf = trimWhitespaces(buf);
// Depending on the action name, the choice is either a probabilitic one or a markovian one.
bool isMarkovianChoice = false;
if (buf[0] == '!' && skipWord(buf) - buf == 1) {
isMarkovianChoice = true;
} else {
isMarkovianChoice = false;
}
buf = skipWord(buf);
if (isMarkovianChoice) {
if (stateHasMarkovianChoice) {
LOG4CPLUS_ERROR(logger, "The state " << source << " has multiple Markovian choices.");
throw storm::exceptions::WrongFormatException() << "The state " << source << " has multiple Markovian choices.";
}
if (stateHasProbabilisticChoice) {
LOG4CPLUS_ERROR(logger, "The state " << source << " has a probabilistic choice preceding a Markovian choice. The Markovian choice must be the first choice listed.");
throw storm::exceptions::WrongFormatException() << "The state " << source << " has a probabilistic choice preceding a Markovian choice. The Markovian choice must be the first choice listed.";
}
stateHasMarkovianChoice = true;
} else {
stateHasProbabilisticChoice = true;
}
// Go to the next line where the transitions start.
buf = forwardToNextLine(buf);
// Now that we have the source state and the information whether or not the current choice is probabilistic or Markovian, we need to read the list of successors and the probabilities/rates.
bool hasSuccessorState = false;
bool encounteredNewDistribution = false;
uint_fast64_t lastSuccessorState = 0;
// At this point, we need to check whether there is an additional successor or we have reached the next choice for the same or a different state.
do {
buf = trimWhitespaces(buf);
// If the end of the file was reached, we need to abort and check whether we are in a legal state.
if (buf[0] == '\0') {
if (!hasSuccessorState) {
LOG4CPLUS_ERROR(logger, "Premature end-of-file. Expected at least one successor state for state " << source << ".");
throw storm::exceptions::WrongFormatException() << "Premature end-of-file. Expected at least one successor state for state " << source << ".";
} else {
// If there was at least one successor for the current choice, this is legal and we need to move on.
encounteredEOF = true;
}
} else if (buf[0] == '*') {
// As we have encountered a "*", we know that there is an additional successor state for the current choice.
buf = skipWord(buf);
// Now we need to read the successor state and check if we already saw a higher state index.
target = checked_strtol(buf, &buf);
if (target > result.highestStateIndex) {
result.highestStateIndex = target;
}
if (hasSuccessorState && target <= lastSuccessorState) {
LOG4CPLUS_ERROR(logger, "Illegal transition order for source state " << source << ".");
throw storm::exceptions::WrongFormatException() << "Illegal transition order for source state " << source << ".";
}
// And the corresponding probability/rate.
double val = checked_strtod(buf, &buf);
if (val < 0.0) {
LOG4CPLUS_ERROR(logger, "Illegal negative probability/rate value for transition from " << source << " to " << target << ": " << val << ".");
throw storm::exceptions::WrongFormatException() << "Illegal negative probability/rate value for transition from " << source << " to " << target << ": " << val << ".";
}
if (!isMarkovianChoice && val > 1.0) {
LOG4CPLUS_ERROR(logger, "Illegal probability value for transition from " << source << " to " << target << ": " << val << ".");
throw storm::exceptions::WrongFormatException() << "Illegal probability value for transition from " << source << " to " << target << ": " << val << ".";
}
// We need to record that we found at least one successor state for the current choice.
hasSuccessorState = true;
lastSuccessorState = target;
// As we found a new successor, we need to increase the number of nonzero entries.
++result.numberOfNonzeroEntries;
buf = forwardToNextLine(buf);
} else {
// If it was not a "*", we have to assume that we encountered the beginning of a new choice definition. In this case, we don't move the pointer
// to the buffer, because we still need to read the new source state.
encounteredNewDistribution = true;
}
} while (!encounteredEOF && !encounteredNewDistribution);
}
return result;
}
template<typename ValueType>
typename MarkovAutomatonSparseTransitionParser<ValueType>::Result MarkovAutomatonSparseTransitionParser<ValueType>::secondPass(char const* buf, FirstPassResult const& firstPassResult) {
Result result(firstPassResult);
bool dontFixDeadlocks = storm::settings::generalSettings().isDontFixDeadlocksSet();
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if (buf[0] < '0' || buf[0] > '9') {
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
// Now read the transitions.
uint_fast64_t source, target = 0;
uint_fast64_t lastsource = 0;
bool encounteredEOF = false;
uint_fast64_t currentChoice = 0;
// The first choice of the first state already starts a new row group of the matrix.
result.transitionMatrixBuilder.newRowGroup(0);
while (buf[0] != '\0' && !encounteredEOF) {
// At the current point, the next thing to read is the source state of the next choice to come.
source = checked_strtol(buf, &buf);
// If we have skipped some states, we need to insert self-loops if requested.
if (source > lastsource + 1) {
if (!dontFixDeadlocks) {
for (uint_fast64_t index = lastsource + 1; index < source; ++index) {
result.transitionMatrixBuilder.newRowGroup(currentChoice);
result.transitionMatrixBuilder.addNextValue(currentChoice, index, 1);
++currentChoice;
}
} else {
LOG4CPLUS_ERROR(logger, "Found deadlock states (e.g. " << lastsource + 1 << ") during parsing. Please fix them or set the appropriate flag.");
throw storm::exceptions::WrongFormatException() << "Found deadlock states (e.g. " << lastsource + 1 << ") during parsing. Please fix them or set the appropriate flag.";
}
}
if (source != lastsource) {
// If we skipped to a new state we need to create a new row group for the choices of the new state.
result.transitionMatrixBuilder.newRowGroup(currentChoice);
}
// Record that the current source was the last source.
lastsource = source;
buf = trimWhitespaces(buf);
// Depending on the action name, the choice is either a probabilitic one or a markovian one.
bool isMarkovianChoice = false;
if (buf[0] == '!' && skipWord(buf) - buf == 1) {
isMarkovianChoice = true;
// Mark the current state as a Markovian one.
result.markovianStates.set(source, true);
} else {
isMarkovianChoice = false;
}
// Go to the next line where the transitions start.
buf = forwardToNextLine(buf);
// Now that we have the source state and the information whether or not the current choice is probabilistic or Markovian, we need to read the list of successors and the probabilities/rates.
bool encounteredNewDistribution = false;
// At this point, we need to check whether there is an additional successor or we have reached the next choice for the same or a different state.
do {
buf = trimWhitespaces(buf);
// If the end of the file was reached, we need to abort and check whether we are in a legal state.
if (buf[0] == '\0') {
// Under the assumption that the currently open choice has at least one successor (which is given after the first run)
// we may legally stop reading here.
encounteredEOF = true;
} else if (buf[0] == '*') {
// As we have encountered a "*", we know that there is an additional successor state for the current choice.
buf = skipWord(buf);
// Now we need to read the successor state and check if we already saw a higher state index.
target = checked_strtol(buf, &buf);
// And the corresponding probability/rate.
double val = checked_strtod(buf, &buf);
// Record the value as well as the exit rate in case of a Markovian choice.
result.transitionMatrixBuilder.addNextValue(currentChoice, target, val);
if (isMarkovianChoice) {
result.exitRates[source] += val;
}
buf = forwardToNextLine(buf);
} else {
// If it was not a "*", we have to assume that we encountered the beginning of a new choice definition. In this case, we don't move the pointer
// to the buffer, because we still need to read the new source state.
encounteredNewDistribution = true;
}
} while (!encounteredEOF && !encounteredNewDistribution);
++currentChoice;
}
return result;
}
template<typename ValueType>
typename MarkovAutomatonSparseTransitionParser<ValueType>::Result MarkovAutomatonSparseTransitionParser<ValueType>::parseMarkovAutomatonTransitions(std::string const& filename) {
// Set the locale to correctly recognize floating point numbers.
setlocale(LC_NUMERIC, "C");
if (!MappedFile::fileExistsAndIsReadable(filename.c_str())) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": File does not exist or is not readable.");
throw storm::exceptions::FileIoException() << "Error while parsing " << filename << ": File does not exist or is not readable.";
}
// Open file and prepare pointer to buffer.
MappedFile file(filename.c_str());
char const* buf = file.getData();
return secondPass(buf, firstPass(buf));
}
template class MarkovAutomatonSparseTransitionParser<double>;
} // namespace parser
} // namespace storm

187
src/parser/MarkovAutomatonSparseTransitionParser.h

@ -5,99 +5,100 @@
#include "src/storage/BitVector.h"
namespace storm {
namespace parser {
/*!
* A class providing the functionality to parse the transitions of a Markov automaton.
*
* The file is parsed in two passes.
* The first pass tests the file format and collects statistical data needed for the second pass.
* The second pass then collects the actual file data and compiles it into a Result.
*/
class MarkovAutomatonSparseTransitionParser {
public:
/*!
* A structure representing the result of the first pass of this parser. It contains the number of non-zero entries in the model, the highest state index
* and the total number of choices.
*/
struct FirstPassResult {
/*!
* The default constructor.
* Constructs an empty FirstPassResult.
*/
FirstPassResult() : numberOfNonzeroEntries(0), highestStateIndex(0), numberOfChoices(0) {
// Intentionally left empty.
}
//! The total number of non-zero entries of the model.
uint_fast64_t numberOfNonzeroEntries;
//! The highest state index that appears in the model.
uint_fast64_t highestStateIndex;
//! The total number of nondeterministic choices in the model.
uint_fast64_t numberOfChoices;
};
/*!
* A structure representing the result of the parser. It contains the sparse matrix that represents the transitions (along with a vector indicating
* at which index the choices of a given state begin) as well as the exit rates for all Markovian choices.
*/
struct Result {
/*!
* Creates a new instance of the struct using the result of the first pass to correctly initialize the container.
*
* @param firstPassResult A reference to the result of the first pass.
*/
Result(FirstPassResult const& firstPassResult) : transitionMatrixBuilder(firstPassResult.numberOfChoices, firstPassResult.highestStateIndex + 1, firstPassResult.numberOfNonzeroEntries, true, firstPassResult.highestStateIndex + 1), markovianChoices(firstPassResult.numberOfChoices), markovianStates(firstPassResult.highestStateIndex + 1), exitRates(firstPassResult.highestStateIndex + 1) {
// Intentionally left empty.
}
//! A matrix representing the transitions of the model.
storm::storage::SparseMatrixBuilder<double> transitionMatrixBuilder;
//! A bit vector indicating which choices are Markovian. By duality, all other choices are probabilitic.
storm::storage::BitVector markovianChoices;
//! A bit vector indicating which states possess a Markovian choice.
storm::storage::BitVector markovianStates;
//! A vector that stores the exit rates for each state. For all states that do not possess Markovian choices this is equal to 0.
std::vector<double> exitRates;
};
/*!
* Parses the given file under the assumption that it contains a Markov automaton specified in the appropriate format.
*
* @param filename The name of the file to parse.
* @return A structure representing the result of the parser.
*/
static Result parseMarkovAutomatonTransitions(std::string const& filename);
private:
/*!
* Performs the first pass on the input pointed to by the given buffer.
*
* @param buffer The buffer that cointains the input.
* @return A structure representing the result of the first pass.
*/
static FirstPassResult firstPass(char const* buffer);
/*!
* Performs the second pass on the input pointed to by the given buffer with the information of the first pass.
*
* @param buffer The buffer that cointains the input.
* @param firstPassResult The result of the first pass performed on the same input.
* @return A structure representing the result of the second pass.
*/
static Result secondPass(char const* buffer, FirstPassResult const& firstPassResult);
};
} // namespace parser
namespace parser {
/*!
* A class providing the functionality to parse the transitions of a Markov automaton.
*
* The file is parsed in two passes.
* The first pass tests the file format and collects statistical data needed for the second pass.
* The second pass then collects the actual file data and compiles it into a Result.
*/
template<typename ValueType = double>
class MarkovAutomatonSparseTransitionParser {
public:
/*!
* A structure representing the result of the first pass of this parser. It contains the number of non-zero entries in the model, the highest state index
* and the total number of choices.
*/
struct FirstPassResult {
/*!
* The default constructor.
* Constructs an empty FirstPassResult.
*/
FirstPassResult() : numberOfNonzeroEntries(0), highestStateIndex(0), numberOfChoices(0) {
// Intentionally left empty.
}
//! The total number of non-zero entries of the model.
uint_fast64_t numberOfNonzeroEntries;
//! The highest state index that appears in the model.
uint_fast64_t highestStateIndex;
//! The total number of nondeterministic choices in the model.
uint_fast64_t numberOfChoices;
};
/*!
* A structure representing the result of the parser. It contains the sparse matrix that represents the transitions (along with a vector indicating
* at which index the choices of a given state begin) as well as the exit rates for all Markovian choices.
*/
struct Result {
/*!
* Creates a new instance of the struct using the result of the first pass to correctly initialize the container.
*
* @param firstPassResult A reference to the result of the first pass.
*/
Result(FirstPassResult const& firstPassResult) : transitionMatrixBuilder(firstPassResult.numberOfChoices, firstPassResult.highestStateIndex + 1, firstPassResult.numberOfNonzeroEntries, true, firstPassResult.highestStateIndex + 1), markovianChoices(firstPassResult.numberOfChoices), markovianStates(firstPassResult.highestStateIndex + 1), exitRates(firstPassResult.highestStateIndex + 1) {
// Intentionally left empty.
}
//! A matrix representing the transitions of the model.
storm::storage::SparseMatrixBuilder<ValueType> transitionMatrixBuilder;
//! A bit vector indicating which choices are Markovian. By duality, all other choices are probabilitic.
storm::storage::BitVector markovianChoices;
//! A bit vector indicating which states possess a Markovian choice.
storm::storage::BitVector markovianStates;
//! A vector that stores the exit rates for each state. For all states that do not possess Markovian choices this is equal to 0.
std::vector<ValueType> exitRates;
};
/*!
* Parses the given file under the assumption that it contains a Markov automaton specified in the appropriate format.
*
* @param filename The name of the file to parse.
* @return A structure representing the result of the parser.
*/
static Result parseMarkovAutomatonTransitions(std::string const& filename);
private:
/*!
* Performs the first pass on the input pointed to by the given buffer.
*
* @param buffer The buffer that cointains the input.
* @return A structure representing the result of the first pass.
*/
static FirstPassResult firstPass(char const* buffer);
/*!
* Performs the second pass on the input pointed to by the given buffer with the information of the first pass.
*
* @param buffer The buffer that cointains the input.
* @param firstPassResult The result of the first pass performed on the same input.
* @return A structure representing the result of the second pass.
*/
static Result secondPass(char const* buffer, FirstPassResult const& firstPassResult);
};
} // namespace parser
} // namespace storm
#endif /* STORM_PARSER_MARKOVAUTOMATONSPARSETRANSITIONPARSER_H_ */

74
src/parser/NondeterministicModelParser.cpp

@ -8,47 +8,59 @@
#include "src/parser/NondeterministicSparseTransitionParser.h"
#include "src/parser/AtomicPropositionLabelingParser.h"
#include "src/parser/SparseStateRewardParser.h"
#include "src/parser/SparseChoiceLabelingParser.h"
namespace storm {
namespace parser {
namespace parser {
NondeterministicModelParser::Result NondeterministicModelParser::parseNondeterministicModel(std::string const & transitionsFilename, std::string const & labelingFilename, std::string const & stateRewardFilename, std::string const & transitionRewardFilename) {
template<typename ValueType, typename RewardValueType>
typename NondeterministicModelParser<ValueType, RewardValueType>::Result NondeterministicModelParser<ValueType, RewardValueType>::parseNondeterministicModel(std::string const& transitionsFilename, std::string const& labelingFilename, std::string const& stateRewardFilename, std::string const& transitionRewardFilename, std::string const& choiceLabelingFilename) {
// Parse the transitions.
storm::storage::SparseMatrix<double> transitions(std::move(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitions(transitionsFilename)));
// Parse the transitions.
storm::storage::SparseMatrix<ValueType> transitions(std::move(storm::parser::NondeterministicSparseTransitionParser<ValueType>::parseNondeterministicTransitions(transitionsFilename)));
uint_fast64_t stateCount = transitions.getColumnCount();
uint_fast64_t stateCount = transitions.getColumnCount();
// Parse the state labeling.
storm::models::sparse::StateLabeling labeling(std::move(storm::parser::AtomicPropositionLabelingParser::parseAtomicPropositionLabeling(stateCount, labelingFilename)));
// Parse the state labeling.
storm::models::sparse::StateLabeling labeling(std::move(storm::parser::AtomicPropositionLabelingParser::parseAtomicPropositionLabeling(stateCount, labelingFilename)));
// Only parse state rewards if a file is given.
boost::optional<std::vector<double>> stateRewards;
if (stateRewardFilename != "") {
stateRewards = storm::parser::SparseStateRewardParser::parseSparseStateReward(stateCount, stateRewardFilename);
}
// Only parse state rewards if a file is given.
boost::optional<std::vector<RewardValueType>> stateRewards;
if (!stateRewardFilename.empty()) {
stateRewards = std::move(storm::parser::SparseStateRewardParser<RewardValueType>::parseSparseStateReward(stateCount, stateRewardFilename));
}
// Only parse transition rewards if a file is given.
boost::optional<storm::storage::SparseMatrix<double>> transitionRewards;
if (transitionRewardFilename != "") {
transitionRewards = storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitionRewards(transitionRewardFilename, transitions);
}
// Only parse transition rewards if a file is given.
boost::optional<storm::storage::SparseMatrix<double>> transitionRewards;
if (!transitionRewardFilename.empty()) {
transitionRewards = std::move(storm::parser::NondeterministicSparseTransitionParser<RewardValueType>::parseNondeterministicTransitionRewards(transitionRewardFilename, transitions));
}
// Construct the result.
Result result(std::move(transitions), std::move(labeling));
result.stateRewards = stateRewards;
result.transitionRewards = transitionRewards;
// Only parse choice labeling if a file is given.
boost::optional<std::vector < storm::models::sparse::LabelSet>> choiceLabeling;
if (!choiceLabelingFilename.empty()) {
choiceLabeling = std::move(storm::parser::SparseChoiceLabelingParser::parseChoiceLabeling(transitions.getRowGroupIndices(), choiceLabelingFilename));
}
return result;
}
// Construct the result.
Result result(std::move(transitions), std::move(labeling));
result.stateRewards = std::move(stateRewards);
result.transitionRewards = std::move(transitionRewards);
result.choiceLabeling = std::move(choiceLabeling);
storm::models::sparse::Mdp<double> NondeterministicModelParser::parseMdp(std::string const & transitionsFilename, std::string const & labelingFilename, std::string const & stateRewardFilename, std::string const & transitionRewardFilename) {
Result parserResult = parseNondeterministicModel(transitionsFilename, labelingFilename, stateRewardFilename, transitionRewardFilename);
std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<double>> rewardModels;
rewardModels.insert(std::make_pair("", storm::models::sparse::StandardRewardModel<double>(parserResult.stateRewards, boost::optional<std::vector<double>>(), parserResult.transitionRewards)));
return storm::models::sparse::Mdp<double>(std::move(parserResult.transitionSystem), std::move(parserResult.labeling), std::move(rewardModels), boost::optional<std::vector<boost::container::flat_set<uint_fast64_t>>>());
}
return result;
}
} /* namespace parser */
template<typename ValueType, typename RewardValueType>
storm::models::sparse::Mdp<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>> NondeterministicModelParser<ValueType, RewardValueType>::parseMdp(std::string const& transitionsFilename, std::string const& labelingFilename, std::string const& stateRewardFilename, std::string const& transitionRewardFilename, std::string const& choiceLabelingFilename) {
Result parserResult = parseNondeterministicModel(transitionsFilename, labelingFilename, stateRewardFilename, transitionRewardFilename, choiceLabelingFilename);
std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<RewardValueType>> rewardModels;
rewardModels.insert(std::make_pair("", storm::models::sparse::StandardRewardModel<RewardValueType>(parserResult.stateRewards, boost::optional<std::vector<RewardValueType>>(), parserResult.transitionRewards)));
return storm::models::sparse::Mdp<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>>(std::move(parserResult.transitionSystem), std::move(parserResult.labeling), std::move(rewardModels), std::move(parserResult.choiceLabeling));
}
template class NondeterministicModelParser<double, double>;
} /* namespace parser */
} /* namespace storm */

197
src/parser/NondeterministicModelParser.h

@ -4,101 +4,108 @@
#include "src/models/sparse/Mdp.h"
namespace storm {
namespace parser {
/*!
* Loads a nondeterministic model (Mdp or Ctmdp) from files.
*
* Given the file paths of the files holding the transitions, the atomic propositions and optionally the state- and transition rewards
* it loads the files, parses them and returns the desired model.
*/
class NondeterministicModelParser {
public:
/*!
* A structure containing the parsed components of a nondeterministic model.
*/
struct Result {
/*!
* The copy constructor.
*
* @param transitionSystem The transition system to be contained in the Result.
* @param labeling The the labeling of the transition system to be contained in the Result.
*/
Result(storm::storage::SparseMatrix<double>& transitionSystem, storm::models::sparse::StateLabeling& labeling) : transitionSystem(transitionSystem), labeling(labeling) {
// Intentionally left empty.
}
/*!
* The move constructor.
*
* @param transitionSystem The transition system to be contained in the Result.
* @param labeling The the labeling of the transition system to be contained in the Result.
*/
Result(storm::storage::SparseMatrix<double>&& transitionSystem, storm::models::sparse::StateLabeling&& labeling) : transitionSystem(std::move(transitionSystem)), labeling(std::move(labeling)) {
// Intentionally left empty.
}
/*!
* A matrix representing the transitions of the model
*/
storm::storage::SparseMatrix<double> transitionSystem;
/*!
* The labels of each state.
*/
storm::models::sparse::StateLabeling labeling;
/*!
* Optional rewards for each state.
*/
boost::optional<std::vector<double>> stateRewards;
/*!
* Optional rewards for each transition.
*/
boost::optional<storm::storage::SparseMatrix<double>> transitionRewards;
};
/*!
* Parse a Mdp.
*
* This method is an adapter to the actual parsing function.
* I.e. it uses @parseNondeterministicModel internally to parse the given input files, takes its result and compiles it into a Dtmc.
*
* @note The number of states of the model is determined by the transitions file.
* The labeling file may therefore not contain labels of states that are not contained in the transitions file.
*
* @param transitionsFilename The path and name of the file containing the transitions of the model.
* @param labelingFilename The path and name of the file containing the labels for the states of the model.
* @param stateRewardFilename The path and name of the file containing the state reward of the model. This file is optional.
* @param transitionRewardFilename The path and name of the file containing the transition rewards of the model. This file is optional.
* @return The parsed Mdp.
*/
static storm::models::sparse::Mdp<double> parseMdp(std::string const & transitionsFilename, std::string const & labelingFilename, std::string const & stateRewardFilename = "", std::string const & transitionRewardFilename = "");
private:
/*!
* Parses a nondeterministic model from the given files.
* Calls sub-parsers on the given files and fills the container with the results.
*
* @note The number of states of the model is determined by the transitions file.
* The labeling file may therefore not contain labels of states that are not contained in the transitions file.
*
* @param transitionsFilename The path and name of the file containing the transitions of the model.
* @param labelingFilename The path and name of the file containing the labels for the states of the model.
* @param stateRewardFilename The path and name of the file containing the state reward of the model. This file is optional.
* @param transitionRewardFilename The path and name of the file containing the transition rewards of the model. This file is optional.
* @return The parsed model encapsulated in a Result structure.
*/
static Result parseNondeterministicModel(std::string const & transitionsFilename, std::string const & labelingFilename, std::string const & stateRewardFilename = "", std::string const & transitionRewardFilename = "");
};
} /* namespace parser */
namespace parser {
/*!
* Loads a nondeterministic model (Mdp or Ctmdp) from files.
*
* Given the file paths of the files holding the transitions, the atomic propositions and optionally the state- and transition rewards
* it loads the files, parses them and returns the desired model.
*/
template<typename ValueType = double, typename RewardValueType = double>
class NondeterministicModelParser {
public:
/*!
* A structure containing the parsed components of a nondeterministic model.
*/
struct Result {
/*!
* The copy constructor.
*
* @param transitionSystem The transition system to be contained in the Result.
* @param labeling The the labeling of the transition system to be contained in the Result.
*/
Result(storm::storage::SparseMatrix<ValueType>& transitionSystem, storm::models::sparse::StateLabeling& labeling) : transitionSystem(transitionSystem), labeling(labeling) {
// Intentionally left empty.
}
/*!
* The move constructor.
*
* @param transitionSystem The transition system to be contained in the Result.
* @param labeling The the labeling of the transition system to be contained in the Result.
*/
Result(storm::storage::SparseMatrix<ValueType>&& transitionSystem, storm::models::sparse::StateLabeling&& labeling) : transitionSystem(std::move(transitionSystem)), labeling(std::move(labeling)) {
// Intentionally left empty.
}
/*!
* A matrix representing the transitions of the model
*/
storm::storage::SparseMatrix<ValueType> transitionSystem;
/*!
* The labels of each state.
*/
storm::models::sparse::StateLabeling labeling;
/*!
* Optional rewards for each state.
*/
boost::optional<std::vector<RewardValueType>> stateRewards;
/*!
* Optional rewards for each transition.
*/
boost::optional<storm::storage::SparseMatrix<RewardValueType>> transitionRewards;
/*!
* Optional choice labeling.
*/
boost::optional<std::vector<storm::models::sparse::LabelSet>> choiceLabeling;
};
/*!
* Parse a Mdp.
*
* This method is an adapter to the actual parsing function.
* I.e. it uses @parseNondeterministicModel internally to parse the given input files, takes its result and compiles it into a Dtmc.
*
* @note The number of states of the model is determined by the transitions file.
* The labeling file may therefore not contain labels of states that are not contained in the transitions file.
*
* @param transitionsFilename The path and name of the file containing the transitions of the model.
* @param labelingFilename The path and name of the file containing the labels for the states of the model.
* @param stateRewardFilename The path and name of the file containing the state reward of the model. This file is optional.
* @param transitionRewardFilename The path and name of the file containing the transition rewards of the model. This file is optional.
* @param choiceLabelingFilename The path and name of the file containing the choice labeling of the model. This file is optional.
* @return The parsed Mdp.
*/
static storm::models::sparse::Mdp<ValueType, storm::models::sparse::StandardRewardModel<RewardValueType>> parseMdp(std::string const& transitionsFilename, std::string const& labelingFilename, std::string const& stateRewardFilename = "", std::string const& transitionRewardFilename = "", std::string const& choiceLabelingFilename = "");
private:
/*!
* Parses a nondeterministic model from the given files.
* Calls sub-parsers on the given files and fills the container with the results.
*
* @note The number of states of the model is determined by the transitions file.
* The labeling file may therefore not contain labels of states that are not contained in the transitions file.
*
* @param transitionsFilename The path and name of the file containing the transitions of the model.
* @param labelingFilename The path and name of the file containing the labels for the states of the model.
* @param stateRewardFilename The path and name of the file containing the state reward of the model. This file is optional.
* @param transitionRewardFilename The path and name of the file containing the transition rewards of the model. This file is optional.
* @param choiceLabelingFilename The path and name of the file containing the choice labeling of the model. This file is optional.
* @return The parsed model encapsulated in a Result structure.
*/
static Result parseNondeterministicModel(std::string const& transitionsFilename, std::string const& labelingFilename, std::string const& stateRewardFilename = "", std::string const& transitionRewardFilename = "", std::string const& choiceLabelingFilename = "");
};
} /* namespace parser */
} /* namespace storm */
#endif /* STORM_PARSER_NONDETERMINISTICMODELPARSER_H_ */

643
src/parser/NondeterministicSparseTransitionParser.cpp

@ -1,10 +1,3 @@
/*!
* NondeterministicSparseTransitionParser.cpp
*
* Created on: 20.11.2012
* Author: Gereon Kremer
*/
#include "src/parser/NondeterministicSparseTransitionParser.h"
#include <string>
@ -25,318 +18,324 @@
extern log4cplus::Logger logger;
namespace storm {
namespace parser {
using namespace storm::utility::cstring;
storm::storage::SparseMatrix<double> NondeterministicSparseTransitionParser::parseNondeterministicTransitions(std::string const& filename) {
storm::storage::SparseMatrix<double> emptyMatrix;
return NondeterministicSparseTransitionParser::parse(filename, false, emptyMatrix);
}
storm::storage::SparseMatrix<double> NondeterministicSparseTransitionParser::parseNondeterministicTransitionRewards(std::string const& filename, storm::storage::SparseMatrix<double> const & modelInformation) {
return NondeterministicSparseTransitionParser::parse(filename, true, modelInformation);
}
storm::storage::SparseMatrix<double> NondeterministicSparseTransitionParser::parse(std::string const &filename, bool isRewardFile, storm::storage::SparseMatrix<double> const & modelInformation) {
// Enforce locale where decimal point is '.'.
setlocale(LC_NUMERIC, "C");
if (!MappedFile::fileExistsAndIsReadable(filename.c_str())) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": File does not exist or is not readable.");
throw storm::exceptions::FileIoException() << "Error while parsing " << filename << ": File does not exist or is not readable.";
}
// Open file.
MappedFile file(filename.c_str());
char const* buf = file.getData();
// Perform first pass, i.e. obtain number of columns, rows and non-zero elements.
NondeterministicSparseTransitionParser::FirstPassResult firstPass = NondeterministicSparseTransitionParser::firstPass(file.getData(), isRewardFile, modelInformation);
// If first pass returned zero, the file format was wrong.
if (firstPass.numberOfNonzeroEntries == 0) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": erroneous file format.");
throw storm::exceptions::WrongFormatException() << "Error while parsing " << filename << ": erroneous file format.";
}
// Perform second pass.
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if(buf[0] < '0' || buf[0] > '9') {
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
if (isRewardFile) {
// The reward matrix should match the size of the transition matrix.
if (firstPass.choices > modelInformation.getRowCount() || (uint_fast64_t)(firstPass.highestStateIndex + 1) > modelInformation.getColumnCount()) {
LOG4CPLUS_ERROR(logger, "Reward matrix size exceeds transition matrix size.");
throw storm::exceptions::OutOfRangeException() << "Reward matrix size exceeds transition matrix size.";
} else if (firstPass.choices != modelInformation.getRowCount()) {
LOG4CPLUS_ERROR(logger, "Reward matrix row count does not match transition matrix row count.");
throw storm::exceptions::OutOfRangeException() << "Reward matrix row count does not match transition matrix row count.";
} else if(firstPass.numberOfNonzeroEntries > modelInformation.getEntryCount()) {
LOG4CPLUS_ERROR(logger, "The reward matrix has more entries than the transition matrix. There must be a reward for a non existent transition");
throw storm::exceptions::OutOfRangeException() << "The reward matrix has more entries than the transition matrix.";
} else {
firstPass.highestStateIndex = modelInformation.getColumnCount() - 1;
}
}
// Create the matrix builder.
// The matrix to be build should have as many columns as we have nodes and as many rows as we have choices.
// Those two values, as well as the number of nonzero elements, was been calculated in the first run.
LOG4CPLUS_INFO(logger, "Attempting to create matrix of size " << firstPass.choices << " x " << (firstPass.highestStateIndex+1) << " with " << firstPass.numberOfNonzeroEntries << " entries.");
storm::storage::SparseMatrixBuilder<double> matrixBuilder;
if(!isRewardFile) {
matrixBuilder = storm::storage::SparseMatrixBuilder<double>(firstPass.choices, firstPass.highestStateIndex + 1, firstPass.numberOfNonzeroEntries, true, true, firstPass.highestStateIndex + 1);
} else {
matrixBuilder = storm::storage::SparseMatrixBuilder<double>(firstPass.choices, firstPass.highestStateIndex + 1, firstPass.numberOfNonzeroEntries, true, true, modelInformation.getRowGroupCount());
}
// Initialize variables for the parsing run.
uint_fast64_t source = 0, target = 0, lastSource = 0, choice = 0, lastChoice = 0, curRow = 0;
double val = 0.0;
bool dontFixDeadlocks = storm::settings::generalSettings().isDontFixDeadlocksSet();
bool hadDeadlocks = false;
// The first state already starts a new row group of the matrix.
matrixBuilder.newRowGroup(0);
// Read all transitions from file.
while (buf[0] != '\0') {
// Read source state and choice.
source = checked_strtol(buf, &buf);
choice = checked_strtol(buf, &buf);
if (isRewardFile) {
// If we have switched the source state, we possibly need to insert the rows of the last
// source state.
if (source != lastSource) {
curRow += ((modelInformation.getRowGroupIndices())[lastSource + 1] - (modelInformation.getRowGroupIndices())[lastSource]) -(lastChoice + 1);
}
// If we skipped some states, we need to reserve empty rows for all their nondeterministic
// choices.
for (uint_fast64_t i = lastSource + 1; i < source; ++i) {
curRow += ((modelInformation.getRowGroupIndices())[i + 1] - (modelInformation.getRowGroupIndices())[i]);
}
// If we advanced to the next state, but skipped some choices, we have to reserve rows
// for them
if (source != lastSource) {
curRow += choice + 1;
} else if (choice != lastChoice) {
curRow += choice - lastChoice;
}
} else {
// Increase line count if we have either finished reading the transitions of a certain state
// or we have finished reading one nondeterministic choice of a state.
if ((source != lastSource || choice != lastChoice)) {
++curRow;
}
// Check if we have skipped any source node, i.e. if any node has no
// outgoing transitions. If so, insert a self-loop.
// Also begin a new rowGroup for the skipped state.
for (uint_fast64_t node = lastSource + 1; node < source; node++) {
hadDeadlocks = true;
if (!dontFixDeadlocks) {
matrixBuilder.newRowGroup(curRow);
matrixBuilder.addNextValue(curRow, node, 1);
++curRow;
LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": node " << node << " has no outgoing transitions. A self-loop was inserted.");
} else {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": node " << node << " has no outgoing transitions.");
}
}
if (source != lastSource) {
// Add create a new rowGroup for the source, if this is the first choice we encounter for this state.
matrixBuilder.newRowGroup(curRow);
}
}
// Read target and value and write it to the matrix.
target = checked_strtol(buf, &buf);
val = checked_strtod(buf, &buf);
matrixBuilder.addNextValue(curRow, target, val);
lastSource = source;
lastChoice = choice;
// Proceed to beginning of next line in file and next row in matrix.
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
if (dontFixDeadlocks && hadDeadlocks && !isRewardFile) throw storm::exceptions::WrongFormatException() << "Some of the states do not have outgoing transitions.";
// Since we assume the transition rewards are for the transitions of the model, we copy the rowGroupIndices.
if(isRewardFile) {
// We already have rowGroup 0.
for(uint_fast64_t index = 1; index < modelInformation.getRowGroupIndices().size() - 1; index++) {
matrixBuilder.newRowGroup(modelInformation.getRowGroupIndices()[index]);
}
} else {
for (uint_fast64_t node = lastSource + 1; node <= firstPass.highestStateIndex; node++) {
matrixBuilder.newRowGroup(curRow + 1);
}
}
// Finally, build the actual matrix, test and return it.
storm::storage::SparseMatrix<double> resultMatrix = matrixBuilder.build();
// Since we cannot do the testing if each transition for which there is a reward in the reward file also exists in the transition matrix during parsing, we have to do it afterwards.
if(isRewardFile && !resultMatrix.isSubmatrixOf(modelInformation)) {
LOG4CPLUS_ERROR(logger, "There are rewards for non existent transitions given in the reward file.");
throw storm::exceptions::WrongFormatException() << "There are rewards for non existent transitions given in the reward file.";
}
return resultMatrix;
}
NondeterministicSparseTransitionParser::FirstPassResult NondeterministicSparseTransitionParser::firstPass(char const* buf, bool isRewardFile, storm::storage::SparseMatrix<double> const & modelInformation) {
// Check file header and extract number of transitions.
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if(buf[0] < '0' || buf[0] > '9') {
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
// Read all transitions.
uint_fast64_t source = 0, target = 0, choice = 0, lastChoice = 0, lastSource = 0, lastTarget = -1;
double val = 0.0;
NondeterministicSparseTransitionParser::FirstPassResult result;
// Since the first line is already a new choice but is not covered below, that has to be covered here.
result.choices = 1;
while (buf[0] != '\0') {
// Read source state and choice.
source = checked_strtol(buf, &buf);
// Read the name of the nondeterministic choice.
choice = checked_strtol(buf, &buf);
if (source < lastSource) {
LOG4CPLUS_ERROR(logger, "The current source state " << source << " is smaller than the last one " << lastSource << ".");
throw storm::exceptions::InvalidArgumentException() << "The current source state " << source << " is smaller than the last one " << lastSource << ".";
}
// Check if we encountered a state index that is bigger than all previously seen.
if (source > result.highestStateIndex) {
result.highestStateIndex = source;
}
if (isRewardFile) {
// Make sure that the highest state index of the reward file is not higher than the highest state index of the corresponding model.
if(result.highestStateIndex > modelInformation.getColumnCount() - 1) {
LOG4CPLUS_ERROR(logger, "State index " << result.highestStateIndex << " found. This exceeds the highest state index of the model, which is " << modelInformation.getColumnCount() - 1 << " .");
throw storm::exceptions::OutOfRangeException() << "State index " << result.highestStateIndex << " found. This exceeds the highest state index of the model, which is " << modelInformation.getColumnCount() - 1 << " .";
}
// If we have switched the source state, we possibly need to insert rows for skipped choices of the last
// source state.
if (source != lastSource) {
// number of choices skipped = number of choices of last state - number of choices read
result.choices += ((modelInformation.getRowGroupIndices())[lastSource + 1] - (modelInformation.getRowGroupIndices())[lastSource]) - (lastChoice + 1);
}
// If we skipped some states, we need to reserve empty rows for all their nondeterministic
// choices.
for (uint_fast64_t i = lastSource + 1; i < source; ++i) {
result.choices += ((modelInformation.getRowGroupIndices())[i + 1] - (modelInformation.getRowGroupIndices())[i]);
}
// If we advanced to the next state, but skipped some choices, we have to reserve rows
// for them.
if (source != lastSource) {
result.choices += choice + 1;
} else if (choice != lastChoice) {
result.choices += choice - lastChoice;
}
} else {
// If we have skipped some states, we need to reserve the space for the self-loop insertion
// in the second pass.
if (source > lastSource + 1) {
result.numberOfNonzeroEntries += source - lastSource - 1;
result.choices += source - lastSource - 1;
}
if (source != lastSource || choice != lastChoice) {
// If we have switched the source state or the nondeterministic choice, we need to
// reserve one row more.
++result.choices;
}
}
// Read target and check if we encountered a state index that is bigger than all previously seen.
target = checked_strtol(buf, &buf);
if (target > result.highestStateIndex) {
result.highestStateIndex = target;
}
// Also, have we already seen this transition?
if (target == lastTarget && choice == lastChoice && source == lastSource) {
LOG4CPLUS_ERROR(logger, "The same transition (" << source << ", " << choice << ", " << target << ") is given twice.");
throw storm::exceptions::InvalidArgumentException() << "The same transition (" << source << ", " << choice << ", " << target << ") is given twice.";
}
// Read value and check whether it's positive.
val = checked_strtod(buf, &buf);
if (!isRewardFile && (val < 0.0 || val > 1.0 )) {
LOG4CPLUS_ERROR(logger, "Expected a positive probability but got \"" << std::string(buf, 0, 16) << "\".");
NondeterministicSparseTransitionParser::FirstPassResult nullResult;
return nullResult;
}
else if (val < 0.0) {
LOG4CPLUS_ERROR(logger, "Expected a positive reward value but got \"" << std::string(buf, 0, 16) << "\".");
NondeterministicSparseTransitionParser::FirstPassResult nullResult;
return nullResult;
}
lastChoice = choice;
lastSource = source;
lastTarget = target;
// Increase number of non-zero values.
result.numberOfNonzeroEntries++;
// The PRISM output format lists the name of the transition in the fourth column,
// but omits the fourth column if it is an internal action. In either case we can skip to the end of the line.
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
if (isRewardFile) {
// If not all rows were filled for the last state, we need to insert them.
result.choices += ((modelInformation.getRowGroupIndices())[lastSource + 1] - (modelInformation.getRowGroupIndices())[lastSource] ) - (lastChoice + 1);
// If we skipped some states, we need to reserve empty rows for all their nondeterministic
// choices.
for (uint_fast64_t i = lastSource + 1; i < modelInformation.getRowGroupIndices().size() - 1; ++i) {
result.choices += ((modelInformation.getRowGroupIndices())[i + 1] - (modelInformation.getRowGroupIndices())[i]);
}
}
return result;
}
} // namespace parser
} // namespace storm
namespace parser {
using namespace storm::utility::cstring;
template<typename ValueType>
storm::storage::SparseMatrix<ValueType> NondeterministicSparseTransitionParser<ValueType>::parseNondeterministicTransitions(std::string const& filename) {
storm::storage::SparseMatrix<ValueType> emptyMatrix;
return NondeterministicSparseTransitionParser::parse(filename, false, emptyMatrix);
}
template<typename ValueType>
template<typename MatrixValueType>
storm::storage::SparseMatrix<ValueType> NondeterministicSparseTransitionParser<ValueType>::parseNondeterministicTransitionRewards(std::string const& filename, storm::storage::SparseMatrix<MatrixValueType> const& modelInformation) {
return NondeterministicSparseTransitionParser::parse(filename, true, modelInformation);
}
template<typename ValueType>
template<typename MatrixValueType>
storm::storage::SparseMatrix<ValueType> NondeterministicSparseTransitionParser<ValueType>::parse(std::string const& filename, bool isRewardFile, storm::storage::SparseMatrix<MatrixValueType> const& modelInformation) {
// Enforce locale where decimal point is '.'.
setlocale(LC_NUMERIC, "C");
if (!MappedFile::fileExistsAndIsReadable(filename.c_str())) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": File does not exist or is not readable.");
throw storm::exceptions::FileIoException() << "Error while parsing " << filename << ": File does not exist or is not readable.";
}
// Open file.
MappedFile file(filename.c_str());
char const* buf = file.getData();
// Perform first pass, i.e. obtain number of columns, rows and non-zero elements.
NondeterministicSparseTransitionParser::FirstPassResult firstPass = NondeterministicSparseTransitionParser::firstPass(file.getData(), isRewardFile, modelInformation);
// If first pass returned zero, the file format was wrong.
if (firstPass.numberOfNonzeroEntries == 0) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": erroneous file format.");
throw storm::exceptions::WrongFormatException() << "Error while parsing " << filename << ": erroneous file format.";
}
// Perform second pass.
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if (buf[0] < '0' || buf[0] > '9') {
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
if (isRewardFile) {
// The reward matrix should match the size of the transition matrix.
if (firstPass.choices > modelInformation.getRowCount() || (uint_fast64_t) (firstPass.highestStateIndex + 1) > modelInformation.getColumnCount()) {
LOG4CPLUS_ERROR(logger, "Reward matrix size exceeds transition matrix size.");
throw storm::exceptions::OutOfRangeException() << "Reward matrix size exceeds transition matrix size.";
} else if (firstPass.choices != modelInformation.getRowCount()) {
LOG4CPLUS_ERROR(logger, "Reward matrix row count does not match transition matrix row count.");
throw storm::exceptions::OutOfRangeException() << "Reward matrix row count does not match transition matrix row count.";
} else if (firstPass.numberOfNonzeroEntries > modelInformation.getEntryCount()) {
LOG4CPLUS_ERROR(logger, "The reward matrix has more entries than the transition matrix. There must be a reward for a non existent transition");
throw storm::exceptions::OutOfRangeException() << "The reward matrix has more entries than the transition matrix.";
} else {
firstPass.highestStateIndex = modelInformation.getColumnCount() - 1;
}
}
// Create the matrix builder.
// The matrix to be build should have as many columns as we have nodes and as many rows as we have choices.
// Those two values, as well as the number of nonzero elements, was been calculated in the first run.
LOG4CPLUS_INFO(logger, "Attempting to create matrix of size " << firstPass.choices << " x " << (firstPass.highestStateIndex + 1) << " with " << firstPass.numberOfNonzeroEntries << " entries.");
storm::storage::SparseMatrixBuilder<ValueType> matrixBuilder;
if (!isRewardFile) {
matrixBuilder = storm::storage::SparseMatrixBuilder<ValueType>(firstPass.choices, firstPass.highestStateIndex + 1, firstPass.numberOfNonzeroEntries, true, true, firstPass.highestStateIndex + 1);
} else {
matrixBuilder = storm::storage::SparseMatrixBuilder<ValueType>(firstPass.choices, firstPass.highestStateIndex + 1, firstPass.numberOfNonzeroEntries, true, true, modelInformation.getRowGroupCount());
}
// Initialize variables for the parsing run.
uint_fast64_t source = 0, target = 0, lastSource = 0, choice = 0, lastChoice = 0, curRow = 0;
double val = 0.0;
bool dontFixDeadlocks = storm::settings::generalSettings().isDontFixDeadlocksSet();
bool hadDeadlocks = false;
// The first state already starts a new row group of the matrix.
matrixBuilder.newRowGroup(0);
// Read all transitions from file.
while (buf[0] != '\0') {
// Read source state and choice.
source = checked_strtol(buf, &buf);
choice = checked_strtol(buf, &buf);
if (isRewardFile) {
// If we have switched the source state, we possibly need to insert the rows of the last
// source state.
if (source != lastSource) {
curRow += ((modelInformation.getRowGroupIndices())[lastSource + 1] - (modelInformation.getRowGroupIndices())[lastSource]) -(lastChoice + 1);
}
// If we skipped some states, we need to reserve empty rows for all their nondeterministic
// choices.
for (uint_fast64_t i = lastSource + 1; i < source; ++i) {
curRow += ((modelInformation.getRowGroupIndices())[i + 1] - (modelInformation.getRowGroupIndices())[i]);
}
// If we advanced to the next state, but skipped some choices, we have to reserve rows
// for them
if (source != lastSource) {
curRow += choice + 1;
} else if (choice != lastChoice) {
curRow += choice - lastChoice;
}
} else {
// Increase line count if we have either finished reading the transitions of a certain state
// or we have finished reading one nondeterministic choice of a state.
if ((source != lastSource || choice != lastChoice)) {
++curRow;
}
// Check if we have skipped any source node, i.e. if any node has no
// outgoing transitions. If so, insert a self-loop.
// Also begin a new rowGroup for the skipped state.
for (uint_fast64_t node = lastSource + 1; node < source; node++) {
hadDeadlocks = true;
if (!dontFixDeadlocks) {
matrixBuilder.newRowGroup(curRow);
matrixBuilder.addNextValue(curRow, node, 1);
++curRow;
LOG4CPLUS_WARN(logger, "Warning while parsing " << filename << ": node " << node << " has no outgoing transitions. A self-loop was inserted.");
} else {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": node " << node << " has no outgoing transitions.");
}
}
if (source != lastSource) {
// Add create a new rowGroup for the source, if this is the first choice we encounter for this state.
matrixBuilder.newRowGroup(curRow);
}
}
// Read target and value and write it to the matrix.
target = checked_strtol(buf, &buf);
val = checked_strtod(buf, &buf);
matrixBuilder.addNextValue(curRow, target, val);
lastSource = source;
lastChoice = choice;
// Proceed to beginning of next line in file and next row in matrix.
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
if (dontFixDeadlocks && hadDeadlocks && !isRewardFile) throw storm::exceptions::WrongFormatException() << "Some of the states do not have outgoing transitions.";
// Since we assume the transition rewards are for the transitions of the model, we copy the rowGroupIndices.
if (isRewardFile) {
// We already have rowGroup 0.
for (uint_fast64_t index = 1; index < modelInformation.getRowGroupIndices().size() - 1; index++) {
matrixBuilder.newRowGroup(modelInformation.getRowGroupIndices()[index]);
}
} else {
for (uint_fast64_t node = lastSource + 1; node <= firstPass.highestStateIndex; node++) {
matrixBuilder.newRowGroup(curRow + 1);
}
}
// Finally, build the actual matrix, test and return it.
storm::storage::SparseMatrix<ValueType> resultMatrix = matrixBuilder.build();
// Since we cannot do the testing if each transition for which there is a reward in the reward file also exists in the transition matrix during parsing, we have to do it afterwards.
if (isRewardFile && !resultMatrix.isSubmatrixOf(modelInformation)) {
LOG4CPLUS_ERROR(logger, "There are rewards for non existent transitions given in the reward file.");
throw storm::exceptions::WrongFormatException() << "There are rewards for non existent transitions given in the reward file.";
}
return resultMatrix;
}
template<typename ValueType>
template<typename MatrixValueType>
typename NondeterministicSparseTransitionParser<ValueType>::FirstPassResult NondeterministicSparseTransitionParser<ValueType>::firstPass(char const* buf, bool isRewardFile, storm::storage::SparseMatrix<MatrixValueType> const& modelInformation) {
// Check file header and extract number of transitions.
// Skip the format hint if it is there.
buf = trimWhitespaces(buf);
if (buf[0] < '0' || buf[0] > '9') {
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
// Read all transitions.
uint_fast64_t source = 0, target = 0, choice = 0, lastChoice = 0, lastSource = 0, lastTarget = -1;
double val = 0.0;
typename NondeterministicSparseTransitionParser<ValueType>::FirstPassResult result;
// Since the first line is already a new choice but is not covered below, that has to be covered here.
result.choices = 1;
while (buf[0] != '\0') {
// Read source state and choice.
source = checked_strtol(buf, &buf);
// Read the name of the nondeterministic choice.
choice = checked_strtol(buf, &buf);
if (source < lastSource) {
LOG4CPLUS_ERROR(logger, "The current source state " << source << " is smaller than the last one " << lastSource << ".");
throw storm::exceptions::InvalidArgumentException() << "The current source state " << source << " is smaller than the last one " << lastSource << ".";
}
// Check if we encountered a state index that is bigger than all previously seen.
if (source > result.highestStateIndex) {
result.highestStateIndex = source;
}
if (isRewardFile) {
// Make sure that the highest state index of the reward file is not higher than the highest state index of the corresponding model.
if (result.highestStateIndex > modelInformation.getColumnCount() - 1) {
LOG4CPLUS_ERROR(logger, "State index " << result.highestStateIndex << " found. This exceeds the highest state index of the model, which is " << modelInformation.getColumnCount() - 1 << " .");
throw storm::exceptions::OutOfRangeException() << "State index " << result.highestStateIndex << " found. This exceeds the highest state index of the model, which is " << modelInformation.getColumnCount() - 1 << " .";
}
// If we have switched the source state, we possibly need to insert rows for skipped choices of the last
// source state.
if (source != lastSource) {
// number of choices skipped = number of choices of last state - number of choices read
result.choices += ((modelInformation.getRowGroupIndices())[lastSource + 1] - (modelInformation.getRowGroupIndices())[lastSource]) - (lastChoice + 1);
}
// If we skipped some states, we need to reserve empty rows for all their nondeterministic
// choices.
for (uint_fast64_t i = lastSource + 1; i < source; ++i) {
result.choices += ((modelInformation.getRowGroupIndices())[i + 1] - (modelInformation.getRowGroupIndices())[i]);
}
// If we advanced to the next state, but skipped some choices, we have to reserve rows
// for them.
if (source != lastSource) {
result.choices += choice + 1;
} else if (choice != lastChoice) {
result.choices += choice - lastChoice;
}
} else {
// If we have skipped some states, we need to reserve the space for the self-loop insertion
// in the second pass.
if (source > lastSource + 1) {
result.numberOfNonzeroEntries += source - lastSource - 1;
result.choices += source - lastSource - 1;
}
if (source != lastSource || choice != lastChoice) {
// If we have switched the source state or the nondeterministic choice, we need to
// reserve one row more.
++result.choices;
}
}
// Read target and check if we encountered a state index that is bigger than all previously seen.
target = checked_strtol(buf, &buf);
if (target > result.highestStateIndex) {
result.highestStateIndex = target;
}
// Also, have we already seen this transition?
if (target == lastTarget && choice == lastChoice && source == lastSource) {
LOG4CPLUS_ERROR(logger, "The same transition (" << source << ", " << choice << ", " << target << ") is given twice.");
throw storm::exceptions::InvalidArgumentException() << "The same transition (" << source << ", " << choice << ", " << target << ") is given twice.";
}
// Read value and check whether it's positive.
val = checked_strtod(buf, &buf);
if (!isRewardFile && (val < 0.0 || val > 1.0)) {
LOG4CPLUS_ERROR(logger, "Expected a positive probability but got \"" << std::string(buf, 0, 16) << "\".");
NondeterministicSparseTransitionParser::FirstPassResult nullResult;
return nullResult;
} else if (val < 0.0) {
LOG4CPLUS_ERROR(logger, "Expected a positive reward value but got \"" << std::string(buf, 0, 16) << "\".");
NondeterministicSparseTransitionParser::FirstPassResult nullResult;
return nullResult;
}
lastChoice = choice;
lastSource = source;
lastTarget = target;
// Increase number of non-zero values.
result.numberOfNonzeroEntries++;
// The PRISM output format lists the name of the transition in the fourth column,
// but omits the fourth column if it is an internal action. In either case we can skip to the end of the line.
buf = forwardToLineEnd(buf);
buf = trimWhitespaces(buf);
}
if (isRewardFile) {
// If not all rows were filled for the last state, we need to insert them.
result.choices += ((modelInformation.getRowGroupIndices())[lastSource + 1] - (modelInformation.getRowGroupIndices())[lastSource]) - (lastChoice + 1);
// If we skipped some states, we need to reserve empty rows for all their nondeterministic
// choices.
for (uint_fast64_t i = lastSource + 1; i < modelInformation.getRowGroupIndices().size() - 1; ++i) {
result.choices += ((modelInformation.getRowGroupIndices())[i + 1] - (modelInformation.getRowGroupIndices())[i]);
}
}
return result;
}
template class NondeterministicSparseTransitionParser<double>;
template storm::storage::SparseMatrix<double> NondeterministicSparseTransitionParser<double>::parseNondeterministicTransitionRewards(std::string const& filename, storm::storage::SparseMatrix<double> const& modelInformation);
template storm::storage::SparseMatrix<double> NondeterministicSparseTransitionParser<double>::parse(std::string const& filename, bool isRewardFile, storm::storage::SparseMatrix<double> const& modelInformation);
} // namespace parser
} // namespace storm

173
src/parser/NondeterministicSparseTransitionParser.h

@ -6,91 +6,94 @@
#include <vector>
namespace storm {
namespace parser {
/*!
* A class providing the functionality to parse the transitions of a nondeterministic model.
*
* The file is parsed in two passes.
* The first pass tests the file format and collects statistical data needed for the second pass.
* The second pass then collects the actual file data and compiles it into a Result.
*/
class NondeterministicSparseTransitionParser {
public:
/*!
* A structure representing the result of the first pass of this parser.
* It contains the number of non-zero entries in the model, the highest state index and the total number if nondeterministic choices.
*/
struct FirstPassResult {
/*!
* The default constructor.
* Constructs an empty FirstPassResult.
*/
FirstPassResult() : numberOfNonzeroEntries(0), highestStateIndex(0), choices(0) {
// Intentionally left empty.
}
//! The total number of non-zero entries of the model.
uint_fast64_t numberOfNonzeroEntries;
//! The highest state index that appears in the model.
uint_fast64_t highestStateIndex;
//! The total number of nondeterministic choices within the transition system.
uint_fast64_t choices;
};
/*!
* Load a nondeterministic transition system from file and create a sparse adjacency matrix whose entries represent the weights of the edges
*
* @param filename The path and name of file to be parsed.
*/
static storm::storage::SparseMatrix<double> parseNondeterministicTransitions(std::string const & filename);
/*!
* Load a nondeterministic transition system from file and create a sparse adjacency matrix whose entries represent the weights of the edges
*
* @param filename The path and name of file to be parsed.
* @param modelInformation The information about the transition structure of nondeterministic model in which the transition rewards shall be used.
* @return A struct containing the parsed file contents, i.e. the transition reward matrix and the mapping between its rows and the states of the model.
*/
static storm::storage::SparseMatrix<double> parseNondeterministicTransitionRewards(std::string const & filename, storm::storage::SparseMatrix<double> const & modelInformation);
private:
/*!
* This method does the first pass through the buffer containing the content of some transition file.
*
* It computes the overall number of nondeterministic choices, i.e. the
* number of rows in the matrix that should be created.
* It also calculates the overall number of non-zero cells, i.e. the number
* of elements the matrix has to hold, and the maximum node id, i.e. the
* number of columns of the matrix.
*
* @param buffer Buffer containing the data to scan. This is expected to be some char array.
* @param insertDiagonalEntriesIfMissing A flag set iff entries on the primary diagonal of the matrix should be added in case they are missing in the parsed file.
* @return A structure representing the result of the first pass.
*/
static FirstPassResult firstPass(char const* buffer, bool isRewardFile, storm::storage::SparseMatrix<double> const & modelInformation);
/*!
* The main parsing routine.
* Opens the given file, calls the first pass and performs the second pass, parsing the content of the file into a SparseMatrix.
*
* @param filename The path and name of file to be parsed.
* @param rewardFile A flag set iff the file to be parsed contains transition rewards.
* @param insertDiagonalEntriesIfMissing A flag set iff entries on the primary diagonal of the matrix should be added in case they are missing in the parsed file.
* @param modelInformation A struct containing information that is used to check if the transition reward matrix fits to the rest of the model.
* @return A SparseMatrix containing the parsed file contents.
*/
static storm::storage::SparseMatrix<double> parse(std::string const& filename, bool isRewardFile, storm::storage::SparseMatrix<double> const & modelInformation);
};
} // namespace parser
namespace parser {
/*!
* A class providing the functionality to parse the transitions of a nondeterministic model.
*
* The file is parsed in two passes.
* The first pass tests the file format and collects statistical data needed for the second pass.
* The second pass then collects the actual file data and compiles it into a Result.
*/
template<typename ValueType = double>
class NondeterministicSparseTransitionParser {
public:
/*!
* A structure representing the result of the first pass of this parser.
* It contains the number of non-zero entries in the model, the highest state index and the total number if nondeterministic choices.
*/
struct FirstPassResult {
/*!
* The default constructor.
* Constructs an empty FirstPassResult.
*/
FirstPassResult() : numberOfNonzeroEntries(0), highestStateIndex(0), choices(0) {
// Intentionally left empty.
}
//! The total number of non-zero entries of the model.
uint_fast64_t numberOfNonzeroEntries;
//! The highest state index that appears in the model.
uint_fast64_t highestStateIndex;
//! The total number of nondeterministic choices within the transition system.
uint_fast64_t choices;
};
/*!
* Load a nondeterministic transition system from file and create a sparse adjacency matrix whose entries represent the weights of the edges
*
* @param filename The path and name of file to be parsed.
*/
static storm::storage::SparseMatrix<ValueType> parseNondeterministicTransitions(std::string const& filename);
/*!
* Load a nondeterministic transition system from file and create a sparse adjacency matrix whose entries represent the weights of the edges
*
* @param filename The path and name of file to be parsed.
* @param modelInformation The information about the transition structure of nondeterministic model in which the transition rewards shall be used.
* @return A struct containing the parsed file contents, i.e. the transition reward matrix and the mapping between its rows and the states of the model.
*/
template<typename MatrixValueType>
static storm::storage::SparseMatrix<ValueType> parseNondeterministicTransitionRewards(std::string const& filename, storm::storage::SparseMatrix<MatrixValueType> const& modelInformation);
private:
/*!
* This method does the first pass through the buffer containing the content of some transition file.
*
* It computes the overall number of nondeterministic choices, i.e. the
* number of rows in the matrix that should be created.
* It also calculates the overall number of non-zero cells, i.e. the number
* of elements the matrix has to hold, and the maximum node id, i.e. the
* number of columns of the matrix.
*
* @param buffer Buffer containing the data to scan. This is expected to be some char array.
* @param insertDiagonalEntriesIfMissing A flag set iff entries on the primary diagonal of the matrix should be added in case they are missing in the parsed file.
* @return A structure representing the result of the first pass.
*/
template<typename MatrixValueType>
static FirstPassResult firstPass(char const* buffer, bool isRewardFile, storm::storage::SparseMatrix<MatrixValueType> const& modelInformation);
/*!
* The main parsing routine.
* Opens the given file, calls the first pass and performs the second pass, parsing the content of the file into a SparseMatrix.
*
* @param filename The path and name of file to be parsed.
* @param rewardFile A flag set iff the file to be parsed contains transition rewards.
* @param insertDiagonalEntriesIfMissing A flag set iff entries on the primary diagonal of the matrix should be added in case they are missing in the parsed file.
* @param modelInformation A struct containing information that is used to check if the transition reward matrix fits to the rest of the model.
* @return A SparseMatrix containing the parsed file contents.
*/
template<typename MatrixValueType>
static storm::storage::SparseMatrix<ValueType> parse(std::string const& filename, bool isRewardFile, storm::storage::SparseMatrix<MatrixValueType> const& modelInformation);
};
} // namespace parser
} // namespace storm
#endif /* STORM_PARSER_NONDETERMINISTICSPARSETRANSITIONPARSER_H__H_ */

73
src/parser/SparseChoiceLabelingParser.cpp

@ -0,0 +1,73 @@
#include "src/parser/SparseChoiceLabelingParser.h"
#include "src/exceptions/WrongFormatException.h"
#include "src/exceptions/OutOfRangeException.h"
#include "src/exceptions/FileIoException.h"
#include "src/parser/MappedFile.h"
#include "src/utility/cstring.h"
namespace storm {
namespace parser {
using namespace storm::utility::cstring;
std::vector<storm::models::sparse::LabelSet> SparseChoiceLabelingParser::parseChoiceLabeling(std::vector<uint_fast64_t> const& nondeterministicChoiceIndices, std::string const& filename) {
// Open file.
if (!MappedFile::fileExistsAndIsReadable(filename.c_str())) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": File does not exist or is not readable.");
throw storm::exceptions::FileIoException() << "Error while parsing " << filename << ": File does not exist or is not readable.";
}
MappedFile file(filename.c_str());
char const* buf = file.getData();
uint_fast64_t totalNumberOfChoices = nondeterministicChoiceIndices.back();
// Create choice labeling vector with given choice count.
std::vector<storm::models::sparse::LabelSet> result(totalNumberOfChoices);
// Now parse state reward assignments.
uint_fast64_t state = 0;
uint_fast64_t lastState = (uint_fast64_t) - 1;
uint_fast64_t lastChoice = (uint_fast64_t) - 1;
uint_fast64_t const startIndexComparison = lastState;
uint_fast64_t const startChoiceIndexComparison = lastChoice;
uint_fast64_t choice = 0;
uint_fast64_t label = 0;
// Iterate over states.
while (buf[0] != '\0') {
// Parse state number and choice.
state = checked_strtol(buf, &buf);
choice = checked_strtol(buf, &buf);
// If the state has already been read or skipped once there might be a problem with the file (doubled lines, or blocks).
// Note: The value -1 shows that lastState has not yet been set, i.e. this is the first run of the loop (state index (2^64)-1 is a really bad starting index).
if (state < lastState && lastState != startIndexComparison) {
STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Error while parsing " << filename << ": State " << state << " was found but has already been read or skipped previously.");
}
if (state == lastState && choice < lastChoice && lastChoice != startChoiceIndexComparison) {
STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Error while parsing " << filename << ": Choice " << choice << " was found but has already been read or skipped previously.");
}
if (state >= nondeterministicChoiceIndices.size()) {
STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Error while parsing " << filename << ": Illegal state " << state << ".");
}
uint_fast64_t numberOfChoicesForState = nondeterministicChoiceIndices[state + 1] - nondeterministicChoiceIndices[state];
if (choice >= numberOfChoicesForState) {
STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Error while parsing " << filename << ": Choice " << choice << " is illegal for state " << state << ", because this state has fewer choices.");
}
label = checked_strtol(buf, &buf);
result[nondeterministicChoiceIndices[state] + choice].insert(label);
buf = trimWhitespaces(buf);
lastState = state;
lastChoice = choice;
}
return result;
}
}
}

27
src/parser/SparseChoiceLabelingParser.h

@ -0,0 +1,27 @@
#ifndef STORM_PARSER_SPARSECHOICELABELINGPARSER_H_
#define STORM_PARSER_SPARSECHOICELABELINGPARSER_H_
#include "src/models/sparse/Model.h"
namespace storm {
namespace parser {
/*!
* A class providing the functionality to parse a choice labeling.
*/
class SparseChoiceLabelingParser {
public:
/*!
* Parses the given file and returns the resulting choice labeling.
*
* @param nondeterministicChoiceIndices The indices at which the choices
* of the states begin.
* @param filename The name of the file to parse.
* @return The resulting choice labeling.
*/
static std::vector<storm::models::sparse::LabelSet> parseChoiceLabeling(std::vector<uint_fast64_t> const& nondeterministicChoiceIndices, std::string const& filename);
};
}
}
#endif /* STORM_PARSER_SPARSECHOICELABELINGPARSER_H_ */

126
src/parser/SparseStateRewardParser.cpp

@ -1,9 +1,3 @@
/*!
* SparseStateRewardParser.cpp
*
* Created on: 23.12.2012
* Author: Christian Dehnert
*/
#include <iostream>
#include "src/parser/SparseStateRewardParser.h"
@ -17,61 +11,65 @@
extern log4cplus::Logger logger;
namespace storm {
namespace parser {
using namespace storm::utility::cstring;
std::vector<double> SparseStateRewardParser::parseSparseStateReward(uint_fast64_t stateCount, std::string const & filename) {
// Open file.
if (!MappedFile::fileExistsAndIsReadable(filename.c_str())) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": File does not exist or is not readable.");
throw storm::exceptions::FileIoException() << "Error while parsing " << filename << ": File does not exist or is not readable.";
}
MappedFile file(filename.c_str());
char const* buf = file.getData();
// Create state reward vector with given state count.
std::vector<double> stateRewards(stateCount);
// Now parse state reward assignments.
uint_fast64_t state = 0;
uint_fast64_t lastState = (uint_fast64_t)-1;
uint_fast64_t const startIndexComparison = lastState;
double reward;
// Iterate over states.
while (buf[0] != '\0') {
// Parse state number and reward value.
state = checked_strtol(buf, &buf);
// If the state has already been read or skipped once there might be a problem with the file (doubled lines, or blocks).
// Note: The value -1 shows that lastState has not yet been set, i.e. this is the first run of the loop (state index (2^64)-1 is a really bad starting index).
if (state <= lastState && lastState != startIndexComparison) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": State " << state << " was found but has already been read or skipped previously.");
throw storm::exceptions::WrongFormatException() << "Error while parsing " << filename << ": State " << state << " was found but has already been read or skipped previously.";
}
if(stateCount <= state) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": Found reward for a state of an invalid index \"" << state << "\". The model has only " << stateCount << " states.");
throw storm::exceptions::OutOfRangeException() << "Error while parsing " << filename << ": Found reward for a state of an invalid index \"" << state << "\"";
}
reward = checked_strtod(buf, &buf);
if (reward < 0.0) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": Expected positive reward value but got \"" << reward << "\".");
throw storm::exceptions::WrongFormatException() << "Error while parsing " << filename << ": State reward file specifies illegal reward value.";
}
stateRewards[state] = reward;
buf = trimWhitespaces(buf);
lastState = state;
}
return stateRewards;
}
} // namespace parser
} // namespace storm
namespace parser {
using namespace storm::utility::cstring;
template<typename ValueType>
std::vector<ValueType> SparseStateRewardParser<ValueType>::parseSparseStateReward(uint_fast64_t stateCount, std::string const& filename) {
// Open file.
if (!MappedFile::fileExistsAndIsReadable(filename.c_str())) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": File does not exist or is not readable.");
throw storm::exceptions::FileIoException() << "Error while parsing " << filename << ": File does not exist or is not readable.";
}
MappedFile file(filename.c_str());
char const* buf = file.getData();
// Create state reward vector with given state count.
std::vector<double> stateRewards(stateCount);
// Now parse state reward assignments.
uint_fast64_t state = 0;
uint_fast64_t lastState = (uint_fast64_t) - 1;
uint_fast64_t const startIndexComparison = lastState;
double reward;
// Iterate over states.
while (buf[0] != '\0') {
// Parse state.
state = checked_strtol(buf, &buf);
// If the state has already been read or skipped once there might be a problem with the file (doubled lines, or blocks).
// Note: The value -1 shows that lastState has not yet been set, i.e. this is the first run of the loop (state index (2^64)-1 is a really bad starting index).
if (state <= lastState && lastState != startIndexComparison) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": State " << state << " was found but has already been read or skipped previously.");
throw storm::exceptions::WrongFormatException() << "Error while parsing " << filename << ": State " << state << " was found but has already been read or skipped previously.";
}
if (stateCount <= state) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": Found reward for a state of an invalid index \"" << state << "\". The model has only " << stateCount << " states.");
throw storm::exceptions::OutOfRangeException() << "Error while parsing " << filename << ": Found reward for a state of an invalid index \"" << state << "\"";
}
// Parse reward value.
reward = checked_strtod(buf, &buf);
if (reward < 0.0) {
LOG4CPLUS_ERROR(logger, "Error while parsing " << filename << ": Expected positive reward value but got \"" << reward << "\".");
throw storm::exceptions::WrongFormatException() << "Error while parsing " << filename << ": State reward file specifies illegal reward value.";
}
stateRewards[state] = reward;
buf = trimWhitespaces(buf);
lastState = state;
}
return stateRewards;
}
template class SparseStateRewardParser<double>;
} // namespace parser
} // namespace storm

33
src/parser/SparseStateRewardParser.h

@ -6,26 +6,27 @@
#include <string>
namespace storm {
namespace parser {
namespace parser {
/*!
* A class providing the functionality to parse a the state rewards of a model.
*/
class SparseStateRewardParser {
public:
/*!
* A class providing the functionality to parse a the state rewards of a model.
*/
template<typename ValueType = double>
class SparseStateRewardParser {
public:
/*!
* Reads a state reward file and puts the result in a state reward vector.
*
* @param stateCount The number of states.
* @param filename The path and name of the state reward file.
* @return The created state reward vector.
*/
static std::vector<double> parseSparseStateReward(uint_fast64_t stateCount, std::string const &filename);
/*!
* Reads a state reward file and puts the result in a state reward vector.
*
* @param stateCount The number of states.
* @param filename The path and name of the state reward file.
* @return The created state reward vector.
*/
static std::vector<ValueType> parseSparseStateReward(uint_fast64_t stateCount, std::string const& filename);
};
};
} // namespace parser
} // namespace parser
} // namespace storm
#endif /* STORM_PARSER_SPARSESTATEREWARDPARSER_H_ */

11
src/settings/modules/GeneralSettings.cpp

@ -33,6 +33,7 @@ namespace storm {
const std::string GeneralSettings::propertyOptionShortName = "prop";
const std::string GeneralSettings::transitionRewardsOptionName = "transrew";
const std::string GeneralSettings::stateRewardsOptionName = "staterew";
const std::string GeneralSettings::choiceLabelingOptionName = "choicelab";
const std::string GeneralSettings::counterexampleOptionName = "counterexample";
const std::string GeneralSettings::counterexampleOptionShortName = "cex";
const std::string GeneralSettings::dontFixDeadlockOptionName = "nofixdl";
@ -84,6 +85,8 @@ namespace storm {
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The file from which to read the transition rewards.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName, stateRewardsOptionName, false, "If given, the state rewards are read from this file and added to the explicit model. Note that this requires the model to be given as an explicit model (i.e., via --" + explicitOptionName + ").")
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The file from which to read the state rewards.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName, choiceLabelingOptionName, false, "If given, the choice labels are read from this file and added to the explicit model. Note that this requires the model to be given as an explicit model (i.e., via --" + explicitOptionName + ").")
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("filename", "The file from which to read the choice labels.").addValidationFunctionString(storm::settings::ArgumentValidators::existingReadableFileValidator()).build()).build());
this->addOption(storm::settings::OptionBuilder(moduleName, dontFixDeadlockOptionName, false, "If the model contains deadlock states, they need to be fixed by setting this option.").setShortName(dontFixDeadlockOptionShortName).build());
std::vector<std::string> engines = {"sparse", "hybrid", "dd"};
@ -193,6 +196,14 @@ namespace storm {
return this->getOption(stateRewardsOptionName).getArgumentByName("filename").getValueAsString();
}
bool GeneralSettings::isChoiceLabelingSet() const {
return this->getOption(choiceLabelingOptionName).getHasOptionBeenSet();
}
std::string GeneralSettings::getChoiceLabelingFilename() const {
return this->getOption(choiceLabelingOptionName).getArgumentByName("filename").getValueAsString();
}
bool GeneralSettings::isCounterexampleSet() const {
return this->getOption(counterexampleOptionName).getHasOptionBeenSet();
}

129
src/settings/modules/GeneralSettings.h

@ -10,39 +10,42 @@ namespace storm {
enum class LpSolverType;
enum class MinMaxTechnique;
}
namespace settings {
namespace modules {
/*!
* This class represents the general settings.
*/
class GeneralSettings : public ModuleSettings {
public:
public:
// An enumeration of all engines.
enum class Engine { Sparse, Hybrid, Dd };
enum class Engine {
Sparse, Hybrid, Dd
};
/*!
* Creates a new set of general settings that is managed by the given manager.
*
* @param settingsManager The responsible manager.
*/
GeneralSettings(storm::settings::SettingsManager& settingsManager);
/*!
* Retrieves whether the help option was set.
*
* @return True if the help option was set.
*/
bool isHelpSet() const;
/*!
/*!
* Retrieves whether the version option was set.
*
* @return True if the version option was set.
*/
bool isVersionSet() const;
/*!
* Retrieves the name of the module for which to show the help or "all" to indicate that the full help
* needs to be shown.
@ -50,56 +53,56 @@ namespace storm {
* @return The name of the module for which to show the help or "all".
*/
std::string getHelpModuleName() const;
/*!
* Retrieves whether the verbose option was set.
*
* @return True if the verbose option was set.
*/
bool isVerboseSet() const;
/*!
* Retrieves the precision to use for numerical operations.
*
* @return The precision to use for numerical operations.
*/
double getPrecision() const;
/*!
* Retrieves whether the export-to-dot option was set.
*
* @return True if the export-to-dot option was set.
*/
bool isExportDotSet() const;
/*!
* Retrieves the name in which to write the model in dot format, if the export-to-dot option was set.
*
* @return The name of the file in which to write the exported model.
*/
std::string getExportDotFilename() const;
/*!
* Retrieves whether the config option was set.
*
* @return True if the config option was set.
*/
bool isConfigSet() const;
/*!
* Retrieves the name of the file that is to be scanned for settings.
*
* @return The name of the file that is to be scanned for settings.
*/
std::string getConfigFilename() const;
/*!
* Retrieves whether the explicit option was set.
*
* @return True if the explicit option was set.
*/
bool isExplicitSet() const;
/*!
* Retrieves the name of the file that contains the transitions if the model was given using the explicit
* option.
@ -115,14 +118,14 @@ namespace storm {
* @return The name of the file that contains the state labeling.
*/
std::string getLabelingFilename() const;
/*!
* Retrieves whether the symbolic option was set.
*
* @return True if the symbolic option was set.
*/
bool isSymbolicSet() const;
/*!
* Retrieves the name of the file that contains the symbolic model specification if the model was given
* using the symbolic option.
@ -130,14 +133,14 @@ namespace storm {
* @return The name of the file that contains the symbolic model specification.
*/
std::string getSymbolicModelFilename() const;
/*!
* Retrieves whether the property option was set.
*
* @return True if the property option was set.
*/
bool isPropertySet() const;
/*!
* Retrieves the property specified with the property option.
*
@ -159,14 +162,14 @@ namespace storm {
* @return The name of the file that contains the transition rewards.
*/
std::string getTransitionRewardsFilename() const;
/*!
* Retrieves whether the state reward option was set.
*
* @return True if the state reward option was set.
*/
bool isStateRewardsSet() const;
/*!
* Retrieves the name of the file that contains the state rewards if the model was given using the
* explicit option.
@ -174,7 +177,22 @@ namespace storm {
* @return The name of the file that contains the state rewards.
*/
std::string getStateRewardsFilename() const;
/*!
* Retrieves whether the choice labeling option was set.
*
* @return True iff the choice labeling option was set.
*/
bool isChoiceLabelingSet() const;
/*!
* Retrieves the name of the file that contains the choice labeling
* if the model was given using the explicit option.
*
* @return The name of the file that contains the choice labeling.
*/
std::string getChoiceLabelingFilename() const;
/*!
* Retrieves whether the counterexample option was set.
*
@ -189,7 +207,7 @@ namespace storm {
* @return The name of the file to which the counterexample is to be written.
*/
std::string getCounterexampleFilename() const;
/*!
* Retrieves whether the dont-fix-deadlocks option was set.
*
@ -205,7 +223,7 @@ namespace storm {
* @return The memento that will eventually restore the original value.
*/
std::unique_ptr<storm::settings::SettingMemento> overrideDontFixDeadlocksSet(bool stateToSet);
/*!
* Overrides the option to enable the PRISM compatibility mode by setting it to the specified value. As
* soon as the returned memento goes out of scope, the original value is restored.
@ -214,14 +232,14 @@ namespace storm {
* @return The memento that will eventually restore the original value.
*/
std::unique_ptr<storm::settings::SettingMemento> overridePrismCompatibilityMode(bool stateToSet);
/*!
* Retrieves whether the timeout option was set.
*
* @return True if the timeout option was set.
*/
bool isTimeoutSet() const;
/*!
* Retrieves the time after which the computation has to be aborted in case the timeout option was set.
*
@ -235,42 +253,42 @@ namespace storm {
* @return The selected convergence criterion.
*/
storm::solver::EquationSolverType getEquationSolver() const;
/*!
* Retrieves whether a equation solver has been set.
*
* @return True iff an equation solver has been set.
*/
bool isEquationSolverSet() const;
/*!
* Retrieves the selected LP solver.
*
* @return The selected LP solver.
*/
storm::solver::LpSolverType getLpSolver() const;
/*!
* Retrieves whether the export-to-dot option was set.
*
* @return True if the export-to-dot option was set.
*/
bool isConstantsSet() const;
/*!
* Retrieves the string that defines the constants of a symbolic model (given via the symbolic option).
*
* @return The string that defines the constants of a symbolic model.
*/
std::string getConstantDefinitionString() const;
/*!
* Retrieves whether statistics are to be shown for counterexample generation.
*
* @return True iff statistics are to be shown for counterexample generation.
*/
bool isShowStatisticsSet() const;
/*!
* Retrieves whether the option to perform bisimulation minimization is set.
*
@ -284,21 +302,21 @@ namespace storm {
* @return True iff the option was set.
*/
bool isCudaSet() const;
/*!
* Retrieves the selected engine.
*
* @return The selected engine.
*/
Engine getEngine() const;
/*!
* Retrieves whether the PRISM compatibility mode was enabled.
*
* @return True iff the PRISM compatibility mode was enabled.
*/
bool isPrismCompatibilityEnabled() const;
#ifdef STORM_HAVE_CARL
/*!
* Retrieves whether the option enabling parametric model checking is set.
@ -307,21 +325,21 @@ namespace storm {
*/
bool isParametricSet() const;
#endif
/*!
* Retrieves whether a min/max equation solving technique has been set.
*
* @return True iff an equation solving technique has been set.
*/
bool isMinMaxEquationSolvingTechniqueSet() const;
/*!
* Retrieves the selected min/max equation solving technique.
*
* @return The selected min/max equation solving technique.
*/
storm::solver::MinMaxTechnique getMinMaxEquationSolvingTechnique() const;
/*!
* Retrieves whether a min/max equation solving technique has been set.
*
* @return True iff an equation solving technique has been set.
*/
bool isMinMaxEquationSolvingTechniqueSet() const;
/*!
* Retrieves the selected min/max equation solving technique.
*
* @return The selected min/max equation solving technique.
*/
storm::solver::MinMaxTechnique getMinMaxEquationSolvingTechnique() const;
bool check() const override;
// The name of the module.
@ -331,7 +349,7 @@ namespace storm {
// Define the string names of the options as constants.
static const std::string helpOptionName;
static const std::string helpOptionShortName;
static const std::string versionOptionName;
static const std::string versionOptionName;
static const std::string verboseOptionName;
static const std::string verboseOptionShortName;
static const std::string precisionOptionName;
@ -347,6 +365,7 @@ namespace storm {
static const std::string propertyOptionShortName;
static const std::string transitionRewardsOptionName;
static const std::string stateRewardsOptionName;
static const std::string choiceLabelingOptionName;
static const std::string counterexampleOptionName;
static const std::string counterexampleOptionShortName;
static const std::string dontFixDeadlockOptionName;
@ -366,13 +385,13 @@ namespace storm {
static const std::string cudaOptionName;
static const std::string prismCompatibilityOptionName;
static const std::string prismCompatibilityOptionShortName;
static const std::string minMaxEquationSolvingTechniqueOptionName;
static const std::string minMaxEquationSolvingTechniqueOptionName;
#ifdef STORM_HAVE_CARL
static const std::string parametricOptionName;
#endif
};
} // namespace modules
} // namespace settings
} // namespace storm

257
src/storage/BitVector.cpp

@ -12,20 +12,20 @@
namespace storm {
namespace storage {
BitVector::const_iterator::const_iterator(uint64_t const* dataPtr, uint_fast64_t startIndex, uint_fast64_t endIndex, bool setOnFirstBit) : dataPtr(dataPtr), endIndex(endIndex) {
BitVector::const_iterator::const_iterator(uint64_t const* dataPtr, uint_fast64_t startIndex, uint_fast64_t endIndex, bool setOnFirstBit) : dataPtr(dataPtr), endIndex(endIndex) {
if (setOnFirstBit) {
// Set the index of the first set bit in the vector.
currentIndex = getNextSetIndex(dataPtr, startIndex, endIndex);
} else {
currentIndex = startIndex;
}
}
}
BitVector::const_iterator::const_iterator(const_iterator const& other) : dataPtr(other.dataPtr), currentIndex(other.currentIndex), endIndex(other.endIndex) {
// Intentionally left empty.
}
BitVector::const_iterator& BitVector::const_iterator::operator=(const_iterator const& other) {
// Only assign contents if the source and target are not the same.
if (this != &other) {
@ -35,20 +35,20 @@ namespace storm {
}
return *this;
}
BitVector::const_iterator& BitVector::const_iterator::operator++() {
currentIndex = getNextSetIndex(dataPtr, ++currentIndex, endIndex);
return *this;
}
uint_fast64_t BitVector::const_iterator::operator*() const {
return currentIndex;
}
bool BitVector::const_iterator::operator!=(const_iterator const& other) const {
return currentIndex != other.currentIndex;
}
BitVector::const_iterator& BitVector::const_iterator::operator++() {
currentIndex = getNextSetIndex(dataPtr, ++currentIndex, endIndex);
return *this;
}
uint_fast64_t BitVector::const_iterator::operator*() const {
return currentIndex;
}
bool BitVector::const_iterator::operator!=(const_iterator const& other) const {
return currentIndex != other.currentIndex;
}
bool BitVector::const_iterator::operator==(const_iterator const& other) const {
return currentIndex == other.currentIndex;
}
@ -56,7 +56,7 @@ namespace storm {
BitVector::BitVector() : bitCount(0), bucketVector() {
// Intentionally left empty.
}
BitVector::BitVector(uint_fast64_t length, bool init) : bitCount(length) {
// Compute the correct number of buckets needed to store the given number of bits.
uint_fast64_t bucketCount = length >> 6;
@ -72,29 +72,28 @@ namespace storm {
bucketVector = std::vector<uint64_t>(bucketCount, 0);
}
}
template<typename InputIterator>
BitVector::BitVector(uint_fast64_t length, InputIterator begin, InputIterator end) : BitVector(length) {
set(begin, end);
}
BitVector::BitVector(uint_fast64_t length, std::vector<uint_fast64_t> setEntries) : BitVector(length, setEntries.begin(), setEntries.end())
{
BitVector::BitVector(uint_fast64_t length, std::vector<uint_fast64_t> setEntries) : BitVector(length, setEntries.begin(), setEntries.end()) {
// Intentionally left empty.
}
BitVector::BitVector(uint_fast64_t bucketCount, uint_fast64_t bitCount) : bitCount(bitCount), bucketVector(bucketCount) {
STORM_LOG_ASSERT((bucketCount << 6) == bitCount, "Bit count does not match number of buckets.");
}
BitVector::BitVector(BitVector const& other) : bitCount(other.bitCount), bucketVector(other.bucketVector) {
// Intentionally left empty.
}
//BitVector::BitVector(BitVector&& other) : bitCount(other.bitCount), bucketVector(std::move(other.bucketVector)) {
// Intentionally left empty.
// Intentionally left empty.
//}
BitVector& BitVector::operator=(BitVector const& other) {
// Only perform the assignment if the source and target are not identical.
if (this != &other) {
@ -103,18 +102,18 @@ namespace storm {
}
return *this;
}
bool BitVector::operator<(BitVector const& other) const {
if (this->size() < other.size()) {
return true;
} else if (this->size() > other.size()) {
return false;
}
std::vector<uint64_t>::const_iterator first1 = this->bucketVector.begin();
std::vector<uint64_t>::const_iterator last1 = this->bucketVector.end();
std::vector<uint64_t>::const_iterator first2 = other.bucketVector.begin();
for (; first1 != last1; ++first1, ++first2) {
if (*first1 < *first2) {
return true;
@ -124,40 +123,40 @@ namespace storm {
}
return false;
}
BitVector& BitVector::operator=(BitVector&& other) {
// Only perform the assignment if the source and target are not identical.
if (this != &other) {
bitCount = other.bitCount;
bucketVector = std::move(other.bucketVector);
}
return *this;
}
bool BitVector::operator==(BitVector const& other) const {
// If the lengths of the vectors do not match, they are considered unequal.
if (this->bitCount != other.bitCount) return false;
// If the lengths match, we compare the buckets one by one.
for (std::vector<uint64_t>::const_iterator it1 = bucketVector.begin(), it2 = other.bucketVector.begin(); it1 != bucketVector.end(); ++it1, ++it2) {
if (*it1 != *it2) {
return false;
}
}
// All buckets were equal, so the bit vectors are equal.
return true;
}
bool BitVector::operator!=(BitVector const& other) const {
return !(*this == other);
}
void BitVector::set(uint_fast64_t index, bool value) {
STORM_LOG_ASSERT(index < bitCount, "Invalid call to BitVector::set: written index " << index << " out of bounds.");
uint64_t bucket = index >> 6;
uint64_t mask = 1ull << (63 - (index & mod64mask));
if (value) {
bucketVector[bucket] |= mask;
@ -165,32 +164,32 @@ namespace storm {
bucketVector[bucket] &= ~mask;
}
}
template<typename InputIterator>
void BitVector::set(InputIterator begin, InputIterator end) {
for (InputIterator it = begin; it != end; ++it) {
this->set(*it);
}
}
bool BitVector::operator[](uint_fast64_t index) const {
uint64_t bucket = index >> 6;
uint64_t mask = 1ull << (63 - (index & mod64mask));
return (this->bucketVector[bucket] & mask) == mask;
}
bool BitVector::get(uint_fast64_t index) const {
STORM_LOG_ASSERT(index < bitCount, "Invalid call to BitVector::get: read index " << index << " out of bounds.");
return (*this)[index];
}
void BitVector::resize(uint_fast64_t newLength, bool init) {
if (newLength > bitCount) {
uint_fast64_t newBucketCount = newLength >> 6;
if ((newLength & mod64mask) != 0) {
++newBucketCount;
}
if (newBucketCount > bucketVector.size()) {
if (init) {
bucketVector.back() |= ((1ull << (64 - (bitCount & mod64mask))) - 1ull);
@ -218,19 +217,19 @@ namespace storm {
truncateLastBucket();
}
}
BitVector BitVector::operator&(BitVector const& other) const {
STORM_LOG_ASSERT(bitCount == other.bitCount, "Length of the bit vectors does not match.");
BitVector result(bitCount);
std::vector<uint64_t>::iterator it = result.bucketVector.begin();
for (std::vector<uint64_t>::const_iterator it1 = bucketVector.begin(), it2 = other.bucketVector.begin(); it != result.bucketVector.end(); ++it1, ++it2, ++it) {
*it = *it1 & *it2;
}
return result;
}
BitVector& BitVector::operator&=(BitVector const& other) {
STORM_LOG_ASSERT(bitCount == other.bitCount, "Length of the bit vectors does not match.");
@ -238,22 +237,22 @@ namespace storm {
for (std::vector<uint64_t>::const_iterator otherIt = other.bucketVector.begin(); it != bucketVector.end() && otherIt != other.bucketVector.end(); ++it, ++otherIt) {
*it &= *otherIt;
}
return *this;
}
BitVector BitVector::operator|(BitVector const& other) const {
STORM_LOG_ASSERT(bitCount == other.bitCount, "Length of the bit vectors does not match.");
BitVector result(bitCount);
std::vector<uint64_t>::iterator it = result.bucketVector.begin();
for (std::vector<uint64_t>::const_iterator it1 = bucketVector.begin(), it2 = other.bucketVector.begin(); it != result.bucketVector.end(); ++it1, ++it2, ++it) {
*it = *it1 | *it2;
}
return result;
}
BitVector& BitVector::operator|=(BitVector const& other) {
STORM_LOG_ASSERT(bitCount == other.bitCount, "Length of the bit vectors does not match.");
@ -261,28 +260,28 @@ namespace storm {
for (std::vector<uint64_t>::const_iterator otherIt = other.bucketVector.begin(); it != bucketVector.end() && otherIt != other.bucketVector.end(); ++it, ++otherIt) {
*it |= *otherIt;
}
return *this;
}
BitVector BitVector::operator^(BitVector const& other) const {
STORM_LOG_ASSERT(bitCount == other.bitCount, "Length of the bit vectors does not match.");
BitVector result(bitCount);
std::vector<uint64_t>::iterator it = result.bucketVector.begin();
for (std::vector<uint64_t>::const_iterator it1 = bucketVector.begin(), it2 = other.bucketVector.begin(); it != result.bucketVector.end(); ++it1, ++it2, ++it) {
*it = *it1 ^ *it2 ;
*it = *it1 ^ *it2;
}
result.truncateLastBucket();
return result;
}
BitVector BitVector::operator%(BitVector const& filter) const {
STORM_LOG_ASSERT(bitCount == filter.bitCount, "Length of the bit vectors does not match.");
BitVector result(filter.getNumberOfSetBits());
// If the current bit vector has not too many elements compared to the given bit vector we prefer iterating
// over its elements.
if (filter.getNumberOfSetBits() / 10 < this->getNumberOfSetBits()) {
@ -302,44 +301,44 @@ namespace storm {
}
}
}
return result;
}
BitVector BitVector::operator~() const {
BitVector result(this->bitCount);
std::vector<uint64_t>::iterator it = result.bucketVector.begin();
for (std::vector<uint64_t>::const_iterator it1 = bucketVector.begin(); it != result.bucketVector.end(); ++it1, ++it) {
*it = ~(*it1);
}
result.truncateLastBucket();
return result;
}
void BitVector::complement() {
for (auto& element : bucketVector) {
element = ~element;
}
truncateLastBucket();
}
BitVector BitVector::implies(BitVector const& other) const {
STORM_LOG_ASSERT(bitCount == other.bitCount, "Length of the bit vectors does not match.");
BitVector result(bitCount);
std::vector<uint64_t>::iterator it = result.bucketVector.begin();
for (std::vector<uint64_t>::const_iterator it1 = bucketVector.begin(), it2 = other.bucketVector.begin(); it != result.bucketVector.end(); ++it1, ++it2, ++it) {
*it = ~(*it1) | *it2;
}
result.truncateLastBucket();
return result;
}
bool BitVector::isSubsetOf(BitVector const& other) const {
STORM_LOG_ASSERT(bitCount == other.bitCount, "Length of the bit vectors does not match.");
for (std::vector<uint64_t>::const_iterator it1 = bucketVector.begin(), it2 = other.bucketVector.begin(); it1 != bucketVector.end(); ++it1, ++it2) {
if ((*it1 & *it2) != *it1) {
return false;
@ -347,10 +346,10 @@ namespace storm {
}
return true;
}
bool BitVector::isDisjointFrom(BitVector const& other) const {
STORM_LOG_ASSERT(bitCount == other.bitCount, "Length of the bit vectors does not match.");
for (std::vector<uint64_t>::const_iterator it1 = bucketVector.begin(), it2 = other.bucketVector.begin(); it1 != bucketVector.end(); ++it1, ++it2) {
if ((*it1 & *it2) != 0) {
return false;
@ -358,18 +357,18 @@ namespace storm {
}
return true;
}
bool BitVector::matches(uint_fast64_t bitIndex, BitVector const& other) const {
STORM_LOG_ASSERT((bitIndex & mod64mask) == 0, "Bit index must be a multiple of 64.");
STORM_LOG_ASSERT(other.size() <= this->size() - bitIndex, "Bit vector argument is too long.");
// Compute the first bucket that needs to be checked and the number of buckets.
uint64_t index = bitIndex >> 6;
std::vector<uint64_t>::const_iterator first1 = bucketVector.begin() + index;
std::vector<uint64_t>::const_iterator first2 = other.bucketVector.begin();
std::vector<uint64_t>::const_iterator last2 = other.bucketVector.end();
for (; first2 != last2; ++first1, ++first2) {
if (*first1 != *first2) {
return false;
@ -377,45 +376,45 @@ namespace storm {
}
return true;
}
void BitVector::set(uint_fast64_t bitIndex, BitVector const& other) {
STORM_LOG_ASSERT((bitIndex & mod64mask) == 0, "Bit index must be a multiple of 64.");
STORM_LOG_ASSERT(other.size() <= this->size() - bitIndex, "Bit vector argument is too long.");
// Compute the first bucket that needs to be checked and the number of buckets.
uint64_t index = bitIndex >> 6;
std::vector<uint64_t>::iterator first1 = bucketVector.begin() + index;
std::vector<uint64_t>::const_iterator first2 = other.bucketVector.begin();
std::vector<uint64_t>::const_iterator last2 = other.bucketVector.end();
for (; first2 != last2; ++first1, ++first2) {
*first1 = *first2;
}
}
storm::storage::BitVector BitVector::get(uint_fast64_t bitIndex, uint_fast64_t numberOfBits) const {
uint64_t numberOfBuckets = numberOfBits >> 6;
uint64_t index = bitIndex >> 6;
STORM_LOG_ASSERT(index + numberOfBuckets <= this->bucketCount(), "Argument is out-of-range.");
storm::storage::BitVector result(numberOfBuckets, numberOfBits);
std::copy(this->bucketVector.begin() + index, this->bucketVector.begin() + index + numberOfBuckets, result.bucketVector.begin());
return result;
}
uint_fast64_t BitVector::getAsInt(uint_fast64_t bitIndex, uint_fast64_t numberOfBits) const {
uint64_t bucket = bitIndex >> 6;
uint64_t bitIndexInBucket = bitIndex & mod64mask;
uint64_t mask;
if (bitIndexInBucket == 0) {
mask = -1ull;
} else {
mask = (1ull << (64 - bitIndexInBucket)) - 1ull;
}
if (bitIndexInBucket + numberOfBits < 64) {
// If the value stops before the end of the bucket, we need to erase some lower bits.
mask &= ~((1ull << (64 - (bitIndexInBucket + numberOfBits))) - 1ull);
@ -424,39 +423,39 @@ namespace storm {
// In this case, the integer "crosses" the bucket line.
uint64_t result = (bucketVector[bucket] & mask);
++bucket;
// Compute the remaining number of bits.
numberOfBits -= (64 - bitIndexInBucket);
// Shift the intermediate result to the right location.
result <<= numberOfBits;
// Strip away everything from the second bucket that is beyond the final index and add it to the
// intermediate result.
mask = ~((1ull << (64 - numberOfBits)) - 1ull);
uint64_t lowerBits = bucketVector[bucket] & mask;
result |= (lowerBits >> (64 - numberOfBits));
return result;
} else {
// In this case, it suffices to take the current mask.
return bucketVector[bucket] & mask;
}
}
void BitVector::setFromInt(uint_fast64_t bitIndex, uint_fast64_t numberOfBits, uint64_t value) {
STORM_LOG_ASSERT((value >> numberOfBits) == 0, "Integer value too large to fit in the given number of bits.");
uint64_t bucket = bitIndex >> 6;
uint64_t bitIndexInBucket = bitIndex & mod64mask;
uint64_t mask;
if (bitIndexInBucket == 0) {
mask = -1ull;
} else {
mask = (1ull << (64 - bitIndexInBucket)) - 1ull;
}
if (bitIndexInBucket + numberOfBits < 64) {
// If the value stops before the end of the bucket, we need to erase some lower bits.
mask &= ~((1ull << (64 - (bitIndexInBucket + numberOfBits))) - 1ull);
@ -465,13 +464,13 @@ namespace storm {
// Write the part of the value that falls into the first bucket.
bucketVector[bucket] = (bucketVector[bucket] & ~mask) | (value >> (numberOfBits + (bitIndexInBucket - 64)));
++bucket;
// Compute the remaining number of bits.
numberOfBits -= (64 - bitIndexInBucket);
// Shift the bits of the value such that the already set bits disappear.
value <<= (64 - numberOfBits);
// Put the remaining bits in their place.
mask = ((1ull << (64 - numberOfBits)) - 1ull);
bucketVector[bucket] = (bucketVector[bucket] & mask) | value;
@ -479,7 +478,7 @@ namespace storm {
bucketVector[bucket] = (bucketVector[bucket] & ~mask) | value;
}
}
bool BitVector::empty() const {
for (auto& element : bucketVector) {
if (element != 0) {
@ -488,7 +487,7 @@ namespace storm {
}
return true;
}
bool BitVector::full() const {
// Check that all buckets except the last one have all bits set.
for (uint_fast64_t index = 0; index < bucketVector.size() - 1; ++index) {
@ -496,7 +495,7 @@ namespace storm {
return false;
}
}
// Now check whether the relevant bits are set in the last bucket.
uint64_t mask = ~((1ull << (64 - (bitCount & mod64mask))) - 1ull);
if ((bucketVector.back() & mask) != mask) {
@ -504,20 +503,20 @@ namespace storm {
}
return true;
}
void BitVector::clear() {
for (auto& element : bucketVector) {
element = 0;
}
}
uint_fast64_t BitVector::getNumberOfSetBits() const {
return getNumberOfSetBitsBeforeIndex(bucketVector.size() << 6);
}
uint_fast64_t BitVector::getNumberOfSetBitsBeforeIndex(uint_fast64_t index) const {
uint_fast64_t result = 0;
// First, count all full buckets.
uint_fast64_t bucket = index >> 6;
for (uint_fast64_t i = 0; i < bucket; ++i) {
@ -537,7 +536,7 @@ namespace storm {
result += cnt;
#endif
}
// Now check if we have to count part of a bucket.
uint64_t tmp = index & mod64mask;
if (tmp != 0) {
@ -555,35 +554,35 @@ namespace storm {
result += cnt;
#endif
}
return result;
}
size_t BitVector::size() const {
return static_cast<size_t>(bitCount);
return static_cast<size_t> (bitCount);
}
std::size_t BitVector::getSizeInBytes() const {
return sizeof(*this) + sizeof(uint64_t) * bucketVector.size();
return sizeof (*this) + sizeof (uint64_t) * bucketVector.size();
}
BitVector::const_iterator BitVector::begin() const {
return const_iterator(bucketVector.data(), 0, bitCount);
}
BitVector::const_iterator BitVector::end() const {
return const_iterator(bucketVector.data(), bitCount, bitCount, false);
}
uint_fast64_t BitVector::getNextSetIndex(uint_fast64_t startingIndex) const {
return getNextSetIndex(bucketVector.data(), startingIndex, bitCount);
}
uint_fast64_t BitVector::getNextSetIndex(uint64_t const* dataPtr, uint_fast64_t startingIndex, uint_fast64_t endIndex) {
uint_fast8_t currentBitInByte = startingIndex & mod64mask;
uint64_t const* bucketIt = dataPtr + (startingIndex >> 6);
startingIndex = (startingIndex >> 6 << 6);
uint64_t mask;
if (currentBitInByte == 0) {
mask = -1ull;
@ -593,14 +592,14 @@ namespace storm {
while (startingIndex < endIndex) {
// Compute the remaining bucket content.
uint64_t remainingInBucket = *bucketIt & mask;
// Check if there is at least one bit in the remainder of the bucket that is set to true.
if (remainingInBucket != 0) {
// As long as the current bit is not set, move the current bit.
while ((remainingInBucket & (1ull << (63 - currentBitInByte))) == 0) {
++currentBitInByte;
}
// Only return the index of the set bit if we are still in the valid range.
if (startingIndex + currentBitInByte < endIndex) {
return startingIndex + currentBitInByte;
@ -608,49 +607,52 @@ namespace storm {
return endIndex;
}
}
// Advance to the next bucket.
startingIndex += 64; ++bucketIt; mask = -1ull; currentBitInByte = 0;
startingIndex += 64;
++bucketIt;
mask = -1ull;
currentBitInByte = 0;
}
return endIndex;
}
void BitVector::truncateLastBucket() {
if ((bitCount & mod64mask) != 0) {
bucketVector.back() &= ~((1ll << (64 - (bitCount & mod64mask))) - 1ll);
}
}
size_t BitVector::bucketCount() const {
return bucketVector.size();
}
std::ostream& operator<<(std::ostream& out, BitVector const& bitVector) {
out << "bit vector(" << bitVector.getNumberOfSetBits() << "/" << bitVector.bitCount << ") [";
for (auto index : bitVector) {
out << index << " ";
}
out << "]";
return out;
}
std::size_t NonZeroBitVectorHash::operator()(storm::storage::BitVector const& bv) const {
STORM_LOG_ASSERT(bv.size() > 0, "Cannot hash bit vector of zero size.");
std::size_t result = 0;
for (uint_fast64_t index = 0; index < bv.bucketVector.size(); ++index) {
result ^= result << 3;
result ^= result >> bv.getAsInt(index << 6, 5);
}
// Erase the last bit and add one to definitely make this hash value non-zero.
result &= ~1ull;
result += 1;
return result;
}
// All necessary explicit template instantiations.
template BitVector::BitVector(uint_fast64_t length, std::vector<uint_fast64_t>::iterator begin, std::vector<uint_fast64_t>::iterator end);
template BitVector::BitVector(uint_fast64_t length, std::vector<uint_fast64_t>::const_iterator begin, std::vector<uint_fast64_t>::const_iterator end);
@ -664,6 +666,7 @@ namespace storm {
}
namespace std {
std::size_t hash<storm::storage::BitVector>::operator()(storm::storage::BitVector const& bv) const {
return boost::hash_range(bv.bucketVector.begin(), bv.bucketVector.end());
}

12
src/utility/storm.h

@ -70,12 +70,11 @@
#include "src/exceptions/NotImplementedException.h"
namespace storm {
template<typename ValueType>
std::shared_ptr<storm::models::sparse::Model<ValueType>> buildExplicitModel(std::string const& transitionsFile, std::string const& labelingFile, boost::optional<std::string> const& stateRewardsFile = boost::optional<std::string>(), boost::optional<std::string> const& transitionRewardsFile = boost::optional<std::string>()) {
return storm::parser::AutoParser::parseModel(transitionsFile, labelingFile, stateRewardsFile ? stateRewardsFile.get() : "", transitionRewardsFile ? transitionRewardsFile.get() : "");
}
template<typename ValueType>
std::shared_ptr<storm::models::sparse::Model<ValueType>> buildExplicitModel(std::string const& transitionsFile, std::string const& labelingFile, boost::optional<std::string> const& stateRewardsFile = boost::optional<std::string>(), boost::optional<std::string> const& transitionRewardsFile = boost::optional<std::string>(), boost::optional<std::string> const& choiceLabelingFile = boost::optional<std::string>()) {
return storm::parser::AutoParser<>::parseModel(transitionsFile, labelingFile, stateRewardsFile ? stateRewardsFile.get() : "", transitionRewardsFile ? transitionRewardsFile.get() : "", choiceLabelingFile ? choiceLabelingFile.get() : "" );
}
storm::prism::Program parseProgram(std::string const& path);
std::vector<std::shared_ptr<storm::logic::Formula>> parseFormulasForExplicit(std::string const& inputString);
@ -382,8 +381,7 @@ namespace storm {
storm::settings::modules::GeneralSettings const& settings = storm::settings::generalSettings();
STORM_LOG_THROW(settings.isExplicitSet(), storm::exceptions::InvalidStateException, "Unable to build explicit model without model files.");
std::shared_ptr<storm::models::ModelBase> model = buildExplicitModel<ValueType>(settings.getTransitionFilename(), settings.getLabelingFilename(), settings.isStateRewardsSet() ? settings.getStateRewardsFilename() : boost::optional<std::string>(), settings.isTransitionRewardsSet() ? settings.getTransitionRewardsFilename() : boost::optional<std::string>());
std::shared_ptr<storm::models::ModelBase> model = buildExplicitModel<ValueType>(settings.getTransitionFilename(), settings.getLabelingFilename(), settings.isStateRewardsSet() ? settings.getStateRewardsFilename() : boost::optional<std::string>(), settings.isTransitionRewardsSet() ? settings.getTransitionRewardsFilename() : boost::optional<std::string>(), settings.isChoiceLabelingSet() ? settings.getChoiceLabelingFilename() : boost::optional<std::string>());
// Preprocess the model if needed.
model = preprocessModel<ValueType>(model, formulas);

166
test/functional/modelchecker/GmmxxDtmcPrctlModelCheckerTest.cpp

@ -15,149 +15,149 @@
#include "src/parser/AutoParser.h"
TEST(GmmxxDtmcPrctlModelCheckerTest, Die) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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");
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Dtmc);
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>();
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>();
ASSERT_EQ(dtmc->getNumberOfStates(), 13ull);
ASSERT_EQ(dtmc->getNumberOfTransitions(), 20ull);
ASSERT_EQ(dtmc->getNumberOfStates(), 13ull);
ASSERT_EQ(dtmc->getNumberOfTransitions(), 20ull);
storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<double>> checker(*dtmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::GmmxxLinearEquationSolverFactory<double>()));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("P=? [F \"one\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1.0/6.0, quantitativeResult1[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
EXPECT_NEAR(1.0 / 6.0, quantitativeResult1[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("P=? [F \"two\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1.0/6.0, quantitativeResult2[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
EXPECT_NEAR(1.0 / 6.0, quantitativeResult2[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("P=? [F \"three\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1.0/6.0, quantitativeResult3[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
EXPECT_NEAR(1.0 / 6.0, quantitativeResult3[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("R=? [F \"done\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(11.0/3.0, quantitativeResult4[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
EXPECT_NEAR(11.0 / 3.0, quantitativeResult4[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
}
TEST(GmmxxDtmcPrctlModelCheckerTest, Crowds) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.tra", STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.lab", "", "");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.tra", STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.lab", "", "");
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Dtmc);
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>();
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>();
ASSERT_EQ(8607ull, dtmc->getNumberOfStates());
ASSERT_EQ(15113ull, dtmc->getNumberOfTransitions());
ASSERT_EQ(8607ull, dtmc->getNumberOfStates());
ASSERT_EQ(15113ull, dtmc->getNumberOfTransitions());
storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<double>> checker(*dtmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::GmmxxLinearEquationSolverFactory<double>()));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("P=? [F \"observe0Greater1\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.3328800375801578281, quantitativeResult1[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.3328800375801578281, quantitativeResult1[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("P=? [F \"observeIGreater1\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.1522194965, quantitativeResult2[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.1522194965, quantitativeResult2[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("P=? [F \"observeOnlyTrueSender\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.32153724292835045, quantitativeResult3[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.32153724292835045, quantitativeResult3[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
}
TEST(GmmxxDtmcPrctlModelCheckerTest, SynchronousLeader) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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(abstractModel->getType(), storm::models::ModelType::Dtmc);
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>();
ASSERT_EQ(12400ull, dtmc->getNumberOfStates());
ASSERT_EQ(16495ull, dtmc->getNumberOfTransitions());
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>();
ASSERT_EQ(12400ull, dtmc->getNumberOfStates());
ASSERT_EQ(16495ull, dtmc->getNumberOfTransitions());
storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<double>> checker(*dtmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::GmmxxLinearEquationSolverFactory<double>()));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("P=? [F \"elected\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1.0, quantitativeResult1[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
EXPECT_NEAR(1.0, quantitativeResult1[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("P=? [F<=20 \"elected\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.9999965911265462636, quantitativeResult2[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.9999965911265462636, quantitativeResult2[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("R=? [F \"elected\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1.044879046, quantitativeResult3[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
EXPECT_NEAR(1.044879046, quantitativeResult3[0], storm::settings::gmmxxEquationSolverSettings().getPrecision());
}
TEST(GmmxxDtmcPrctlModelCheckerTest, LRASingleBscc) {
storm::storage::SparseMatrixBuilder<double> matrixBuilder;
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc;
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
{
matrixBuilder = storm::storage::SparseMatrixBuilder<double>(2, 2, 2);
matrixBuilder.addNextValue(0, 1, 1.);
matrixBuilder.addNextValue(1, 0, 1.);
storm::storage::SparseMatrix<double> transitionMatrix = matrixBuilder.build();
storm::models::sparse::StateLabeling ap(2);
ap.addLabel("a");
ap.addLabelToState("a", 1);
dtmc.reset(new storm::models::sparse::Dtmc<double>(transitionMatrix, ap));
storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<double>> checker(*dtmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::NativeLinearEquationSolverFactory<double>()));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("LRA=? [\"a\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(.5, quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(.5, quantitativeResult1[1], storm::settings::nativeEquationSolverSettings().getPrecision());
}
@ -168,44 +168,44 @@ TEST(GmmxxDtmcPrctlModelCheckerTest, LRASingleBscc) {
matrixBuilder.addNextValue(1, 0, .5);
matrixBuilder.addNextValue(1, 1, .5);
storm::storage::SparseMatrix<double> transitionMatrix = matrixBuilder.build();
storm::models::sparse::StateLabeling ap(2);
ap.addLabel("a");
ap.addLabelToState("a", 1);
dtmc.reset(new storm::models::sparse::Dtmc<double>(transitionMatrix, ap));
storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<double>> checker(*dtmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::NativeLinearEquationSolverFactory<double>()));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("LRA=? [\"a\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(.5, quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(.5, quantitativeResult1[1], storm::settings::nativeEquationSolverSettings().getPrecision());
}
{
matrixBuilder = storm::storage::SparseMatrixBuilder<double>(3, 3, 3);
matrixBuilder.addNextValue(0, 1, 1);
matrixBuilder.addNextValue(1, 2, 1);
matrixBuilder.addNextValue(2, 0, 1);
storm::storage::SparseMatrix<double> transitionMatrix = matrixBuilder.build();
storm::models::sparse::StateLabeling ap(3);
ap.addLabel("a");
ap.addLabelToState("a", 2);
dtmc.reset(new storm::models::sparse::Dtmc<double>(transitionMatrix, ap));
storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<double>> checker(*dtmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::GmmxxLinearEquationSolverFactory<double>()));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("LRA=? [\"a\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1. / 3., quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1. / 3., quantitativeResult1[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1. / 3., quantitativeResult1[2], storm::settings::nativeEquationSolverSettings().getPrecision());
@ -215,41 +215,41 @@ TEST(GmmxxDtmcPrctlModelCheckerTest, LRASingleBscc) {
TEST(GmmxxDtmcPrctlModelCheckerTest, LRA) {
storm::storage::SparseMatrixBuilder<double> matrixBuilder;
std::shared_ptr<storm::models::sparse::Dtmc<double>> mdp;
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
{
matrixBuilder = storm::storage::SparseMatrixBuilder<double>(15, 15, 20, true);
matrixBuilder.addNextValue(0, 1, 1);
matrixBuilder.addNextValue(1, 4, 0.7);
matrixBuilder.addNextValue(1, 6, 0.3);
matrixBuilder.addNextValue(2, 0, 1);
matrixBuilder.addNextValue(3, 5, 0.8);
matrixBuilder.addNextValue(3, 9, 0.2);
matrixBuilder.addNextValue(4, 3, 1);
matrixBuilder.addNextValue(5, 3, 1);
matrixBuilder.addNextValue(6, 7, 1);
matrixBuilder.addNextValue(7, 8, 1);
matrixBuilder.addNextValue(8, 6, 1);
matrixBuilder.addNextValue(9, 10, 1);
matrixBuilder.addNextValue(10, 9, 1);
matrixBuilder.addNextValue(11, 9, 1);
matrixBuilder.addNextValue(12, 5, 0.4);
matrixBuilder.addNextValue(12, 8, 0.3);
matrixBuilder.addNextValue(12, 11, 0.3);
matrixBuilder.addNextValue(13, 7, 0.7);
matrixBuilder.addNextValue(13, 12, 0.3);
matrixBuilder.addNextValue(14, 12, 1);
storm::storage::SparseMatrix<double> transitionMatrix = matrixBuilder.build();
storm::models::sparse::StateLabeling ap(15);
ap.addLabel("a");
ap.addLabelToState("a", 1);
@ -259,21 +259,21 @@ TEST(GmmxxDtmcPrctlModelCheckerTest, LRA) {
ap.addLabelToState("a", 11);
ap.addLabelToState("a", 13);
ap.addLabelToState("a", 14);
mdp.reset(new storm::models::sparse::Dtmc<double>(transitionMatrix, ap));
storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<double>> checker(*mdp, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::GmmxxLinearEquationSolverFactory<double>()));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("LRA=? [\"a\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.3 / 3., quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult1[3], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1. / 3., quantitativeResult1[6], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult1[9], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.3/3., quantitativeResult1[12], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.3 / 3., quantitativeResult1[12], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(.79 / 3., quantitativeResult1[13], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.3 / 3., quantitativeResult1[14], storm::settings::nativeEquationSolverSettings().getPrecision());
}

152
test/functional/modelchecker/GmmxxMdpPrctlModelCheckerTest.cpp

@ -16,175 +16,175 @@
#include "src/parser/AutoParser.h"
TEST(GmmxxMdpPrctlModelCheckerTest, Dice) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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");
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Mdp);
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
ASSERT_EQ(mdp->getNumberOfStates(), 169ull);
ASSERT_EQ(mdp->getNumberOfTransitions(), 436ull);
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Gmmxx)));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"two\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0277777612209320068, quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"two\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0277777612209320068, quantitativeResult2[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"three\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0555555224418640136, quantitativeResult3[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"three\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0555555224418640136, quantitativeResult4[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"four\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult5 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.083333283662796020508, quantitativeResult5[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"four\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult6 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.083333283662796020508, quantitativeResult6[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"done\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult7 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(7.333329499, quantitativeResult7[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"done\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult8 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(7.333329499, quantitativeResult8[0], storm::settings::nativeEquationSolverSettings().getPrecision());
abstractModel = storm::parser::AutoParser::parseModel(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", "");
abstractModel = storm::parser::AutoParser<>::parseModel(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(abstractModel->getType(), storm::models::ModelType::Mdp);
std::shared_ptr<storm::models::sparse::Mdp<double>> stateRewardMdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> stateRewardModelChecker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Gmmxx)));
formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"done\"]");
result = stateRewardModelChecker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult9 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(7.333329499, quantitativeResult9[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"done\"]");
result = stateRewardModelChecker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult10 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(7.333329499, quantitativeResult10[0], storm::settings::nativeEquationSolverSettings().getPrecision());
abstractModel = storm::parser::AutoParser::parseModel(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");
abstractModel = storm::parser::AutoParser<>::parseModel(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(abstractModel->getType(), storm::models::ModelType::Mdp);
std::shared_ptr<storm::models::sparse::Mdp<double>> stateAndTransitionRewardMdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> stateAndTransitionRewardModelChecker(*stateAndTransitionRewardMdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Gmmxx)));
formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"done\"]");
result = stateAndTransitionRewardModelChecker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult11 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(14.666658998, quantitativeResult11[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"done\"]");
result = stateAndTransitionRewardModelChecker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult12 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(14.666658998, quantitativeResult12[0], storm::settings::nativeEquationSolverSettings().getPrecision());
}
TEST(GmmxxMdpPrctlModelCheckerTest, AsynchronousLeader) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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");
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
ASSERT_EQ(storm::models::ModelType::Mdp, abstractModel->getType());
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
ASSERT_EQ(3172ull, mdp->getNumberOfStates());
ASSERT_EQ(7144ull, mdp->getNumberOfTransitions());
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Gmmxx)));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"elected\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1, quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"elected\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1, quantitativeResult2[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F<=25 \"elected\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0625, quantitativeResult3[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F<=25 \"elected\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0625, quantitativeResult4[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"elected\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult5 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(4.285689611, quantitativeResult5[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"elected\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult6 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(4.285689611, quantitativeResult6[0], storm::settings::nativeEquationSolverSettings().getPrecision());
}

6
test/functional/modelchecker/NativeDtmcPrctlModelCheckerTest.cpp

@ -17,7 +17,7 @@
#include "src/parser/AutoParser.h"
TEST(SparseDtmcPrctlModelCheckerTest, Die) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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");
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
@ -61,7 +61,7 @@ TEST(SparseDtmcPrctlModelCheckerTest, Die) {
}
TEST(SparseDtmcPrctlModelCheckerTest, Crowds) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.tra", STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.lab", "", "");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.tra", STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.lab", "", "");
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Dtmc);
@ -98,7 +98,7 @@ TEST(SparseDtmcPrctlModelCheckerTest, Crowds) {
}
TEST(SparseDtmcPrctlModelCheckerTest, SynchronousLeader) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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(abstractModel->getType(), storm::models::ModelType::Dtmc);

656
test/functional/modelchecker/NativeMdpPrctlModelCheckerTest.cpp

@ -15,505 +15,505 @@
#include "src/parser/AutoParser.h"
TEST(SparseMdpPrctlModelCheckerTest, Dice) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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");
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Mdp);
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
ASSERT_EQ(mdp->getNumberOfStates(), 169ull);
ASSERT_EQ(mdp->getNumberOfTransitions(), 436ull);
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
ASSERT_EQ(mdp->getNumberOfStates(), 169ull);
ASSERT_EQ(mdp->getNumberOfTransitions(), 436ull);
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Native)));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"two\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0277777612209320068, quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0277777612209320068, quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"two\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0277777612209320068, quantitativeResult2[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0277777612209320068, quantitativeResult2[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"three\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0555555224418640136, quantitativeResult3[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0555555224418640136, quantitativeResult3[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"three\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0555555224418640136, quantitativeResult4[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0555555224418640136, quantitativeResult4[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"four\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult5 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.083333283662796020508, quantitativeResult5[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.083333283662796020508, quantitativeResult5[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"four\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult6 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.083333283662796020508, quantitativeResult6[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.083333283662796020508, quantitativeResult6[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"done\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult7 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(7.333329499, quantitativeResult7[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(7.333329499, quantitativeResult7[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"done\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult8 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(7.333329499, quantitativeResult8[0], storm::settings::nativeEquationSolverSettings().getPrecision());
abstractModel = storm::parser::AutoParser::parseModel(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", "");
EXPECT_NEAR(7.333329499, quantitativeResult8[0], storm::settings::nativeEquationSolverSettings().getPrecision());
abstractModel = storm::parser::AutoParser<>::parseModel(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(abstractModel->getType(), storm::models::ModelType::Mdp);
std::shared_ptr<storm::models::sparse::Mdp<double>> stateRewardMdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
std::shared_ptr<storm::models::sparse::Mdp<double>> stateRewardMdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> stateRewardModelChecker(*stateRewardMdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Native)));
formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"done\"]");
result = stateRewardModelChecker.check(*formula);
result = stateRewardModelChecker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult9 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(7.333329499, quantitativeResult9[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(7.333329499, quantitativeResult9[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"done\"]");
result = stateRewardModelChecker.check(*formula);
result = stateRewardModelChecker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult10 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(7.333329499, quantitativeResult10[0], storm::settings::nativeEquationSolverSettings().getPrecision());
abstractModel = storm::parser::AutoParser::parseModel(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");
EXPECT_NEAR(7.333329499, quantitativeResult10[0], storm::settings::nativeEquationSolverSettings().getPrecision());
abstractModel = storm::parser::AutoParser<>::parseModel(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(abstractModel->getType(), storm::models::ModelType::Mdp);
std::shared_ptr<storm::models::sparse::Mdp<double>> stateAndTransitionRewardMdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> stateAndTransitionRewardModelChecker(*stateAndTransitionRewardMdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Native)));
std::shared_ptr<storm::models::sparse::Mdp<double>> stateAndTransitionRewardMdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> stateAndTransitionRewardModelChecker(*stateAndTransitionRewardMdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Native)));
formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"done\"]");
result = stateAndTransitionRewardModelChecker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult11 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(14.666658998, quantitativeResult11[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(14.666658998, quantitativeResult11[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"done\"]");
result = stateAndTransitionRewardModelChecker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult12 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(14.666658998, quantitativeResult12[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(14.666658998, quantitativeResult12[0], storm::settings::nativeEquationSolverSettings().getPrecision());
}
TEST(SparseMdpPrctlModelCheckerTest, AsynchronousLeader) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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");
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
ASSERT_EQ(storm::models::ModelType::Mdp, abstractModel->getType());
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
ASSERT_EQ(3172ull, mdp->getNumberOfStates());
ASSERT_EQ(7144ull, mdp->getNumberOfTransitions());
ASSERT_EQ(3172ull, mdp->getNumberOfStates());
ASSERT_EQ(7144ull, mdp->getNumberOfTransitions());
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Native)));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"elected\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1, quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1, quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"elected\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1, quantitativeResult2[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1, quantitativeResult2[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F<=25 \"elected\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0625, quantitativeResult3[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0625, quantitativeResult3[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F<=25 \"elected\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>();
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0625, quantitativeResult4[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0625, quantitativeResult4[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"elected\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult5 = result->asExplicitQuantitativeCheckResult<double>();
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult5 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(4.285689611, quantitativeResult5[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(4.285689611, quantitativeResult5[0], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"elected\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult6 = result->asExplicitQuantitativeCheckResult<double>();
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult6 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(4.285689611, quantitativeResult6[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(4.285689611, quantitativeResult6[0], storm::settings::nativeEquationSolverSettings().getPrecision());
}
TEST(SparseMdpPrctlModelCheckerTest, LRA_SingleMec) {
storm::storage::SparseMatrixBuilder<double> matrixBuilder;
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp;
storm::storage::SparseMatrixBuilder<double> matrixBuilder;
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp;
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
{
matrixBuilder = storm::storage::SparseMatrixBuilder<double>(2, 2, 2);
matrixBuilder.addNextValue(0, 1, 1.);
matrixBuilder.addNextValue(1, 0, 1.);
storm::storage::SparseMatrix<double> transitionMatrix = matrixBuilder.build();
storm::models::sparse::StateLabeling ap(2);
ap.addLabel("a");
ap.addLabelToState("a", 1);
{
matrixBuilder = storm::storage::SparseMatrixBuilder<double>(2, 2, 2);
matrixBuilder.addNextValue(0, 1, 1.);
matrixBuilder.addNextValue(1, 0, 1.);
storm::storage::SparseMatrix<double> transitionMatrix = matrixBuilder.build();
mdp.reset(new storm::models::sparse::Mdp<double>(transitionMatrix, ap));
storm::models::sparse::StateLabeling ap(2);
ap.addLabel("a");
ap.addLabelToState("a", 1);
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Native)));
mdp.reset(new storm::models::sparse::Mdp<double>(transitionMatrix, ap));
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Native)));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"a\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
std::unique_ptr<storm::modelchecker::CheckResult> result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(.5, quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(.5, quantitativeResult1[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(.5, quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(.5, quantitativeResult1[1], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"a\"]");
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(.5, quantitativeResult2[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(.5, quantitativeResult2[1], storm::settings::nativeEquationSolverSettings().getPrecision());
}
{
matrixBuilder = storm::storage::SparseMatrixBuilder<double>(2, 2, 4);
matrixBuilder.addNextValue(0, 0, .5);
matrixBuilder.addNextValue(0, 1, .5);
matrixBuilder.addNextValue(1, 0, .5);
matrixBuilder.addNextValue(1, 1, .5);
storm::storage::SparseMatrix<double> transitionMatrix = matrixBuilder.build();
EXPECT_NEAR(.5, quantitativeResult2[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(.5, quantitativeResult2[1], storm::settings::nativeEquationSolverSettings().getPrecision());
}
{
matrixBuilder = storm::storage::SparseMatrixBuilder<double>(2, 2, 4);
matrixBuilder.addNextValue(0, 0, .5);
matrixBuilder.addNextValue(0, 1, .5);
matrixBuilder.addNextValue(1, 0, .5);
matrixBuilder.addNextValue(1, 1, .5);
storm::storage::SparseMatrix<double> transitionMatrix = matrixBuilder.build();
storm::models::sparse::StateLabeling ap(2);
ap.addLabel("a");
ap.addLabelToState("a", 1);
storm::models::sparse::StateLabeling ap(2);
ap.addLabel("a");
ap.addLabelToState("a", 1);
mdp.reset(new storm::models::sparse::Mdp<double>(transitionMatrix, ap));
mdp.reset(new storm::models::sparse::Mdp<double>(transitionMatrix, ap));
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Native)));
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Native)));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"a\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
std::unique_ptr<storm::modelchecker::CheckResult> result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(.5, quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(.5, quantitativeResult1[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(.5, quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(.5, quantitativeResult1[1], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"a\"]");
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(.5, quantitativeResult2[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(.5, quantitativeResult2[1], storm::settings::nativeEquationSolverSettings().getPrecision());
}
{
matrixBuilder = storm::storage::SparseMatrixBuilder<double>(4, 3, 4, true, true, 3);
matrixBuilder.newRowGroup(0);
matrixBuilder.addNextValue(0, 1, 1);
matrixBuilder.newRowGroup(1);
matrixBuilder.addNextValue(1, 0, 1);
matrixBuilder.addNextValue(2, 2, 1);
matrixBuilder.newRowGroup(3);
matrixBuilder.addNextValue(3, 0, 1);
storm::storage::SparseMatrix<double> transitionMatrix = matrixBuilder.build();
storm::models::sparse::StateLabeling ap(3);
ap.addLabel("a");
ap.addLabelToState("a", 2);
ap.addLabel("b");
ap.addLabelToState("b", 0);
ap.addLabel("c");
ap.addLabelToState("c", 0);
ap.addLabelToState("c", 2);
mdp.reset(new storm::models::sparse::Mdp<double>(transitionMatrix, ap));
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Native)));
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(.5, quantitativeResult2[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(.5, quantitativeResult2[1], storm::settings::nativeEquationSolverSettings().getPrecision());
}
{
matrixBuilder = storm::storage::SparseMatrixBuilder<double>(4, 3, 4, true, true, 3);
matrixBuilder.newRowGroup(0);
matrixBuilder.addNextValue(0, 1, 1);
matrixBuilder.newRowGroup(1);
matrixBuilder.addNextValue(1, 0, 1);
matrixBuilder.addNextValue(2, 2, 1);
matrixBuilder.newRowGroup(3);
matrixBuilder.addNextValue(3, 0, 1);
storm::storage::SparseMatrix<double> transitionMatrix = matrixBuilder.build();
storm::models::sparse::StateLabeling ap(3);
ap.addLabel("a");
ap.addLabelToState("a", 2);
ap.addLabel("b");
ap.addLabelToState("b", 0);
ap.addLabel("c");
ap.addLabelToState("c", 0);
ap.addLabelToState("c", 2);
mdp.reset(new storm::models::sparse::Mdp<double>(transitionMatrix, ap));
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Native)));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"a\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
std::unique_ptr<storm::modelchecker::CheckResult> result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1. / 3., quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1. / 3., quantitativeResult1[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1. / 3., quantitativeResult1[2], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1. / 3., quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1. / 3., quantitativeResult1[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1. / 3., quantitativeResult1[2], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"a\"]");
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0, quantitativeResult2[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult2[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult2[2], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult2[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult2[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult2[2], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"b\"]");
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.5, quantitativeResult3[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.5, quantitativeResult3[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.5, quantitativeResult3[2], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.5, quantitativeResult3[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.5, quantitativeResult3[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.5, quantitativeResult3[2], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"b\"]");
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>();
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1. / 3., quantitativeResult4[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1. / 3., quantitativeResult4[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1. / 3., quantitativeResult4[2], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1. / 3., quantitativeResult4[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1. / 3., quantitativeResult4[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1. / 3., quantitativeResult4[2], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"c\"]");
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult5 = result->asExplicitQuantitativeCheckResult<double>();
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult5 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(2. / 3., quantitativeResult5[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(2. / 3., quantitativeResult5[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(2. / 3., quantitativeResult5[2], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(2. / 3., quantitativeResult5[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(2. / 3., quantitativeResult5[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(2. / 3., quantitativeResult5[2], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"c\"]");
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult6 = result->asExplicitQuantitativeCheckResult<double>();
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult6 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.5, quantitativeResult6[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.5, quantitativeResult6[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.5, quantitativeResult6[2], storm::settings::nativeEquationSolverSettings().getPrecision());
}
EXPECT_NEAR(0.5, quantitativeResult6[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.5, quantitativeResult6[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.5, quantitativeResult6[2], storm::settings::nativeEquationSolverSettings().getPrecision());
}
}
TEST(SparseMdpPrctlModelCheckerTest, LRA) {
storm::storage::SparseMatrixBuilder<double> matrixBuilder;
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp;
storm::storage::SparseMatrixBuilder<double> matrixBuilder;
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp;
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
{
matrixBuilder = storm::storage::SparseMatrixBuilder<double>(4, 3, 4, true, true, 3);
matrixBuilder.newRowGroup(0);
matrixBuilder.addNextValue(0, 1, 1);
matrixBuilder.newRowGroup(1);
matrixBuilder.addNextValue(1, 1, 1);
matrixBuilder.addNextValue(2, 2, 1);
matrixBuilder.newRowGroup(3);
matrixBuilder.addNextValue(3, 2, 1);
storm::storage::SparseMatrix<double> transitionMatrix = matrixBuilder.build();
storm::models::sparse::StateLabeling ap(3);
ap.addLabel("a");
ap.addLabelToState("a", 0);
ap.addLabel("b");
ap.addLabelToState("b", 1);
ap.addLabel("c");
ap.addLabelToState("c", 2);
mdp.reset(new storm::models::sparse::Mdp<double>(transitionMatrix, ap));
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Native)));
{
matrixBuilder = storm::storage::SparseMatrixBuilder<double>(4, 3, 4, true, true, 3);
matrixBuilder.newRowGroup(0);
matrixBuilder.addNextValue(0, 1, 1);
matrixBuilder.newRowGroup(1);
matrixBuilder.addNextValue(1, 1, 1);
matrixBuilder.addNextValue(2, 2, 1);
matrixBuilder.newRowGroup(3);
matrixBuilder.addNextValue(3, 2, 1);
storm::storage::SparseMatrix<double> transitionMatrix = matrixBuilder.build();
storm::models::sparse::StateLabeling ap(3);
ap.addLabel("a");
ap.addLabelToState("a", 0);
ap.addLabel("b");
ap.addLabelToState("b", 1);
ap.addLabel("c");
ap.addLabelToState("c", 2);
mdp.reset(new storm::models::sparse::Mdp<double>(transitionMatrix, ap));
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Native)));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"a\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0, quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult1[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult1[2], storm::settings::nativeEquationSolverSettings().getPrecision());
std::unique_ptr<storm::modelchecker::CheckResult> result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0, quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult1[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult1[2], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"a\"]");
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0, quantitativeResult2[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult2[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult2[2], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult2[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult2[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult2[2], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"b\"]");
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1.0, quantitativeResult3[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1.0, quantitativeResult3[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult3[2], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1.0, quantitativeResult3[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1.0, quantitativeResult3[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult3[2], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"b\"]");
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>();
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0, quantitativeResult4[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult4[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult4[2], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult4[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult4[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult4[2], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"c\"]");
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult5 = result->asExplicitQuantitativeCheckResult<double>();
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult5 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1.0, quantitativeResult5[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1.0, quantitativeResult5[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1.0, quantitativeResult5[2], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1.0, quantitativeResult5[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1.0, quantitativeResult5[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1.0, quantitativeResult5[2], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"c\"]");
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult6 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0, quantitativeResult6[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult6[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1.0, quantitativeResult6[2], storm::settings::nativeEquationSolverSettings().getPrecision());
}
{
matrixBuilder = storm::storage::SparseMatrixBuilder<double>(22, 15, 28, true, true, 15);
matrixBuilder.newRowGroup(0);
matrixBuilder.addNextValue(0, 1, 1);
matrixBuilder.newRowGroup(1);
matrixBuilder.addNextValue(1, 0, 1);
matrixBuilder.addNextValue(2, 2, 1);
matrixBuilder.addNextValue(3, 4, 0.7);
matrixBuilder.addNextValue(3, 6, 0.3);
matrixBuilder.newRowGroup(4);
matrixBuilder.addNextValue(4, 0, 1);
matrixBuilder.newRowGroup(5);
matrixBuilder.addNextValue(5, 4, 1);
matrixBuilder.addNextValue(6, 5, 0.8);
matrixBuilder.addNextValue(6, 9, 0.2);
matrixBuilder.newRowGroup(7);
matrixBuilder.addNextValue(7, 3, 1);
matrixBuilder.addNextValue(8, 5, 1);
matrixBuilder.newRowGroup(9);
matrixBuilder.addNextValue(9, 3, 1);
matrixBuilder.newRowGroup(10);
matrixBuilder.addNextValue(10, 7, 1);
matrixBuilder.newRowGroup(11);
matrixBuilder.addNextValue(11, 6, 1);
matrixBuilder.addNextValue(12, 8, 1);
matrixBuilder.newRowGroup(13);
matrixBuilder.addNextValue(13, 6, 1);
matrixBuilder.newRowGroup(14);
matrixBuilder.addNextValue(14, 10, 1);
matrixBuilder.newRowGroup(15);
matrixBuilder.addNextValue(15, 9, 1);
matrixBuilder.addNextValue(16, 11, 1);
matrixBuilder.newRowGroup(17);
matrixBuilder.addNextValue(17, 9, 1);
matrixBuilder.newRowGroup(18);
matrixBuilder.addNextValue(18, 5, 0.4);
matrixBuilder.addNextValue(18, 8, 0.3);
matrixBuilder.addNextValue(18, 11, 0.3);
matrixBuilder.newRowGroup(19);
matrixBuilder.addNextValue(19, 7, 0.7);
matrixBuilder.addNextValue(19, 12, 0.3);
matrixBuilder.newRowGroup(20);
matrixBuilder.addNextValue(20, 12, 0.1);
matrixBuilder.addNextValue(20, 13, 0.9);
matrixBuilder.addNextValue(21, 12, 1);
storm::storage::SparseMatrix<double> transitionMatrix = matrixBuilder.build();
storm::models::sparse::StateLabeling ap(15);
ap.addLabel("a");
ap.addLabelToState("a", 1);
ap.addLabelToState("a", 4);
ap.addLabelToState("a", 5);
ap.addLabelToState("a", 7);
ap.addLabelToState("a", 11);
ap.addLabelToState("a", 13);
ap.addLabelToState("a", 14);
mdp.reset(new storm::models::sparse::Mdp<double>(transitionMatrix, ap));
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Native)));
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult6 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.0, quantitativeResult6[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult6[1], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1.0, quantitativeResult6[2], storm::settings::nativeEquationSolverSettings().getPrecision());
}
{
matrixBuilder = storm::storage::SparseMatrixBuilder<double>(22, 15, 28, true, true, 15);
matrixBuilder.newRowGroup(0);
matrixBuilder.addNextValue(0, 1, 1);
matrixBuilder.newRowGroup(1);
matrixBuilder.addNextValue(1, 0, 1);
matrixBuilder.addNextValue(2, 2, 1);
matrixBuilder.addNextValue(3, 4, 0.7);
matrixBuilder.addNextValue(3, 6, 0.3);
matrixBuilder.newRowGroup(4);
matrixBuilder.addNextValue(4, 0, 1);
matrixBuilder.newRowGroup(5);
matrixBuilder.addNextValue(5, 4, 1);
matrixBuilder.addNextValue(6, 5, 0.8);
matrixBuilder.addNextValue(6, 9, 0.2);
matrixBuilder.newRowGroup(7);
matrixBuilder.addNextValue(7, 3, 1);
matrixBuilder.addNextValue(8, 5, 1);
matrixBuilder.newRowGroup(9);
matrixBuilder.addNextValue(9, 3, 1);
matrixBuilder.newRowGroup(10);
matrixBuilder.addNextValue(10, 7, 1);
matrixBuilder.newRowGroup(11);
matrixBuilder.addNextValue(11, 6, 1);
matrixBuilder.addNextValue(12, 8, 1);
matrixBuilder.newRowGroup(13);
matrixBuilder.addNextValue(13, 6, 1);
matrixBuilder.newRowGroup(14);
matrixBuilder.addNextValue(14, 10, 1);
matrixBuilder.newRowGroup(15);
matrixBuilder.addNextValue(15, 9, 1);
matrixBuilder.addNextValue(16, 11, 1);
matrixBuilder.newRowGroup(17);
matrixBuilder.addNextValue(17, 9, 1);
matrixBuilder.newRowGroup(18);
matrixBuilder.addNextValue(18, 5, 0.4);
matrixBuilder.addNextValue(18, 8, 0.3);
matrixBuilder.addNextValue(18, 11, 0.3);
matrixBuilder.newRowGroup(19);
matrixBuilder.addNextValue(19, 7, 0.7);
matrixBuilder.addNextValue(19, 12, 0.3);
matrixBuilder.newRowGroup(20);
matrixBuilder.addNextValue(20, 12, 0.1);
matrixBuilder.addNextValue(20, 13, 0.9);
matrixBuilder.addNextValue(21, 12, 1);
storm::storage::SparseMatrix<double> transitionMatrix = matrixBuilder.build();
storm::models::sparse::StateLabeling ap(15);
ap.addLabel("a");
ap.addLabelToState("a", 1);
ap.addLabelToState("a", 4);
ap.addLabelToState("a", 5);
ap.addLabelToState("a", 7);
ap.addLabelToState("a", 11);
ap.addLabelToState("a", 13);
ap.addLabelToState("a", 14);
mdp.reset(new storm::models::sparse::Mdp<double>(transitionMatrix, ap));
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Native)));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("LRAmax=? [\"a\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
std::unique_ptr<storm::modelchecker::CheckResult> result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(37./60., quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(2./3., quantitativeResult1[3], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.5, quantitativeResult1[6], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1./3., quantitativeResult1[9], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(31./60., quantitativeResult1[12], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(101./200., quantitativeResult1[13], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(31./60., quantitativeResult1[14], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(37. / 60., quantitativeResult1[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(2. / 3., quantitativeResult1[3], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.5, quantitativeResult1[6], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1. / 3., quantitativeResult1[9], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(31. / 60., quantitativeResult1[12], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(101. / 200., quantitativeResult1[13], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(31. / 60., quantitativeResult1[14], storm::settings::nativeEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("LRAmin=? [\"a\"]");
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.3 / 3., quantitativeResult2[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult2[3], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1./3., quantitativeResult2[6], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult2[9], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.3 / 3., quantitativeResult2[12], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(.79 / 3., quantitativeResult2[13], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.3 / 3., quantitativeResult2[14], storm::settings::nativeEquationSolverSettings().getPrecision());
}
result = std::move(checker.check(*formula));
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.3 / 3., quantitativeResult2[0], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult2[3], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(1. / 3., quantitativeResult2[6], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.0, quantitativeResult2[9], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.3 / 3., quantitativeResult2[12], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(.79 / 3., quantitativeResult2[13], storm::settings::nativeEquationSolverSettings().getPrecision());
EXPECT_NEAR(0.3 / 3., quantitativeResult2[14], storm::settings::nativeEquationSolverSettings().getPrecision());
}
}

104
test/functional/modelchecker/SparseDtmcEliminationModelCheckerTest.cpp

@ -13,125 +13,125 @@
#include "src/parser/AutoParser.h"
TEST(SparseDtmcEliminationModelCheckerTest, Die) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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");
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Dtmc);
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>();
ASSERT_EQ(dtmc->getNumberOfStates(), 13ull);
ASSERT_EQ(dtmc->getNumberOfTransitions(), 20ull);
storm::modelchecker::SparseDtmcEliminationModelChecker<storm::models::sparse::Dtmc<double>> checker(*dtmc);
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("P=? [F \"one\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1.0/6.0, quantitativeResult1[0], storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(1.0 / 6.0, quantitativeResult1[0], storm::settings::generalSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("P=? [F \"two\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1.0/6.0, quantitativeResult2[0], storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(1.0 / 6.0, quantitativeResult2[0], storm::settings::generalSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("P=? [F \"three\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1.0/6.0, quantitativeResult3[0], storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(1.0 / 6.0, quantitativeResult3[0], storm::settings::generalSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("R=? [F \"done\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(11.0/3.0, quantitativeResult4[0], storm::settings::generalSettings().getPrecision());
EXPECT_NEAR(11.0 / 3.0, quantitativeResult4[0], storm::settings::generalSettings().getPrecision());
}
TEST(SparseDtmcEliminationModelCheckerTest, Crowds) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.tra", STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.lab", "", "");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.tra", STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.lab", "", "");
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Dtmc);
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>();
ASSERT_EQ(8607ull, dtmc->getNumberOfStates());
ASSERT_EQ(15113ull, dtmc->getNumberOfTransitions());
storm::modelchecker::SparseDtmcEliminationModelChecker<storm::models::sparse::Dtmc<double>> checker(*dtmc);
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("P=? [F \"observe0Greater1\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.3328800375801578281, quantitativeResult1[0], storm::settings::generalSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("P=? [F \"observeIGreater1\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.1522194965, quantitativeResult2[0], storm::settings::generalSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("P=? [F \"observeOnlyTrueSender\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.32153724292835045, quantitativeResult3[0], storm::settings::generalSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("P=? [F \"observe0Greater1\" || F \"observeIGreater1\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.15330064292476167, quantitativeResult4[0], storm::settings::generalSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("P=? [F \"observeOnlyTrueSender\" || F \"observe0Greater1\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult5 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(0.96592521978041668, quantitativeResult5[0], storm::settings::generalSettings().getPrecision());
}
TEST(SparseDtmcEliminationModelCheckerTest, SynchronousLeader) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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");
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Dtmc);
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>();
ASSERT_EQ(12400ull, dtmc->getNumberOfStates());
ASSERT_EQ(16495ull, dtmc->getNumberOfTransitions());
storm::modelchecker::SparseDtmcEliminationModelChecker<storm::models::sparse::Dtmc<double>> checker(*dtmc);
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("P=? [F \"elected\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1.0, quantitativeResult1[0], storm::settings::generalSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("R=? [F \"elected\"]");
result = checker.check(*formula);
storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
EXPECT_NEAR(1.0448979, quantitativeResult3[0], storm::settings::generalSettings().getPrecision());
}

160
test/functional/modelchecker/TopologicalValueIterationMdpPrctlModelCheckerTest.cpp

@ -17,176 +17,176 @@
#include "storm-config.h"
TEST(TopologicalValueIterationMdpPrctlModelCheckerTest, Dice) {
//storm::settings::Settings* s = storm::settings::Settings::getInstance();
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = storm::parser::AutoParser::parseModel(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")->as<storm::models::sparse::Mdp<double>>();
//storm::settings::Settings* s = storm::settings::Settings::getInstance();
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = storm::parser::AutoParser<>::parseModel(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")->as<storm::models::sparse::Mdp<double>>();
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
ASSERT_EQ(mdp->getNumberOfStates(), 169ull);
ASSERT_EQ(mdp->getNumberOfTransitions(), 436ull);
ASSERT_EQ(mdp->getNumberOfStates(), 169ull);
ASSERT_EQ(mdp->getNumberOfTransitions(), 436ull);
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> mc(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Topological)));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"two\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = mc.check(*formula);
ASSERT_NEAR(0.0277777612209320068, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
std::unique_ptr<storm::modelchecker::CheckResult> result = mc.check(*formula);
ASSERT_NEAR(0.0277777612209320068, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"two\"]");
result = mc.check(*formula);
ASSERT_NEAR(0.0277777612209320068, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
result = mc.check(*formula);
ASSERT_NEAR(0.0277777612209320068, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"three\"]");
result = mc.check(*formula);
ASSERT_NEAR(0.0555555224418640136, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
result = mc.check(*formula);
ASSERT_NEAR(0.0555555224418640136, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"three\"]");
result = mc.check(*formula);
ASSERT_NEAR(0.0555555224418640136, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
result = mc.check(*formula);
ASSERT_NEAR(0.0555555224418640136, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"four\"]");
result = mc.check(*formula);
ASSERT_NEAR(0.083333283662796020508, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
result = mc.check(*formula);
ASSERT_NEAR(0.083333283662796020508, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"four\"]");
result = mc.check(*formula);
ASSERT_NEAR(0.083333283662796020508, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(0.083333283662796020508, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"done\"]");
result = mc.check(*formula);
result = mc.check(*formula);
#ifdef STORM_HAVE_CUDA
ASSERT_NEAR(7.333329499, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(7.333329499, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
#else
ASSERT_NEAR(7.33332904, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(7.33332904, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
#endif
formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"done\"]");
result = mc.check(*formula);
result = mc.check(*formula);
#ifdef STORM_HAVE_CUDA
ASSERT_NEAR(7.333329499, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(7.333329499, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
#else
ASSERT_NEAR(7.33333151, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(7.33333151, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
#endif
// ------------- state rewards --------------
std::shared_ptr<storm::models::sparse::Mdp<double>> stateRewardMdp = storm::parser::AutoParser::parseModel(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", "")->as<storm::models::sparse::Mdp<double>>();
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> stateRewardModelChecker(*stateRewardMdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Topological)));
// ------------- state rewards --------------
std::shared_ptr<storm::models::sparse::Mdp<double>> stateRewardMdp = storm::parser::AutoParser<>::parseModel(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", "")->as<storm::models::sparse::Mdp<double>>();
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> stateRewardModelChecker(*stateRewardMdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Topological)));
formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"done\"]");
result = stateRewardModelChecker.check(*formula);
result = stateRewardModelChecker.check(*formula);
#ifdef STORM_HAVE_CUDA
ASSERT_NEAR(7.333329499, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(7.333329499, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
#else
ASSERT_NEAR(7.33332904, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(7.33332904, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
#endif
formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"done\"]");
result = stateRewardModelChecker.check(*formula);
result = stateRewardModelChecker.check(*formula);
#ifdef STORM_HAVE_CUDA
ASSERT_NEAR(7.333329499, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(7.333329499, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
#else
ASSERT_NEAR(7.33333151, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(7.33333151, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
#endif
// -------------------------------- state and transition reward ------------------------
std::shared_ptr<storm::models::sparse::Mdp<double>> stateAndTransitionRewardMdp = storm::parser::AutoParser::parseModel(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")->as<storm::models::sparse::Mdp<double>>();
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> stateAndTransitionRewardModelChecker(*stateAndTransitionRewardMdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Topological)));
// -------------------------------- state and transition reward ------------------------
std::shared_ptr<storm::models::sparse::Mdp<double>> stateAndTransitionRewardMdp = storm::parser::AutoParser<>::parseModel(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")->as<storm::models::sparse::Mdp<double>>();
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> stateAndTransitionRewardModelChecker(*stateAndTransitionRewardMdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Topological)));
formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"done\"]");
result = stateAndTransitionRewardModelChecker.check(*formula);
result = stateAndTransitionRewardModelChecker.check(*formula);
#ifdef STORM_HAVE_CUDA
ASSERT_NEAR(14.666658998, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(14.666658998, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
#else
ASSERT_NEAR(14.6666581, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(14.6666581, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
#endif
formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"done\"]");
result = stateAndTransitionRewardModelChecker.check(*formula);
result = stateAndTransitionRewardModelChecker.check(*formula);
#ifdef STORM_HAVE_CUDA
ASSERT_NEAR(14.666658998, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(14.666658998, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
#else
ASSERT_NEAR(14.666663, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(14.666663, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
#endif
}
TEST(TopologicalValueIterationMdpPrctlModelCheckerTest, AsynchronousLeader) {
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = storm::parser::AutoParser::parseModel(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")->as<storm::models::sparse::Mdp<double>>();
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = storm::parser::AutoParser<>::parseModel(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")->as<storm::models::sparse::Mdp<double>>();
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
ASSERT_EQ(mdp->getNumberOfStates(), 3172ull);
ASSERT_EQ(mdp->getNumberOfTransitions(), 7144ull);
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> mc(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Topological)));
ASSERT_EQ(mdp->getNumberOfStates(), 3172ull);
ASSERT_EQ(mdp->getNumberOfTransitions(), 7144ull);
storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> mc(*mdp, std::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Topological)));
std::shared_ptr<storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"elected\"]");
std::unique_ptr<storm::modelchecker::CheckResult> result = mc.check(*formula);
ASSERT_LT(std::abs(result->asExplicitQuantitativeCheckResult<double>()[0] - 1),
storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
std::unique_ptr<storm::modelchecker::CheckResult> result = mc.check(*formula);
ASSERT_LT(std::abs(result->asExplicitQuantitativeCheckResult<double>()[0] - 1),
storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"elected\"]");
result = mc.check(*formula);
result = mc.check(*formula);
ASSERT_NEAR(1, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(1, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F<=25 \"elected\"]");
result = mc.check(*formula);
result = mc.check(*formula);
ASSERT_NEAR(0.0625, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(0.0625, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F<=25 \"elected\"]");
result = mc.check(*formula);
result = mc.check(*formula);
ASSERT_NEAR(0.0625, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(0.0625, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"elected\"]");
result = mc.check(*formula);
result = mc.check(*formula);
#ifdef STORM_HAVE_CUDA
ASSERT_NEAR(4.285689611, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(4.285689611, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
#else
ASSERT_NEAR(4.285701547, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(4.285701547, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
#endif
formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"elected\"]");
result = mc.check(*formula);
result = mc.check(*formula);
#ifdef STORM_HAVE_CUDA
ASSERT_NEAR(4.285689611, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(4.285689611, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
#else
ASSERT_NEAR(4.285703591, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
ASSERT_NEAR(4.285703591, result->asExplicitQuantitativeCheckResult<double>()[0], storm::settings::topologicalValueIterationEquationSolverSettings().getPrecision());
#endif
}

76
test/functional/parser/AutoParserTest.cpp

@ -7,60 +7,60 @@
#include "src/exceptions/WrongFormatException.h"
TEST(AutoParserTest, NonExistingFile) {
// No matter what happens, please do NOT create a file with the name "nonExistingFile.not"!
ASSERT_THROW(storm::parser::AutoParser::parseModel(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
// No matter what happens, please do NOT create a file with the name "nonExistingFile.not"!
ASSERT_THROW(storm::parser::AutoParser<>::parseModel(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
}
TEST(AutoParserTest, BasicParsing) {
// Parse model, which is a Dtmc.
std::shared_ptr<storm::models::sparse::Model<double>> modelPtr = storm::parser::AutoParser::parseModel(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/autoParser/dtmc.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/autoParser.lab");
// Parse model, which is a Dtmc.
std::shared_ptr<storm::models::sparse::Model<double>> modelPtr = storm::parser::AutoParser<>::parseModel(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/autoParser/dtmc.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/autoParser.lab");
// Test if parsed correctly.
// Test if parsed correctly.
ASSERT_EQ(storm::models::ModelType::Dtmc, modelPtr->getType());
ASSERT_EQ(12ul, modelPtr->getNumberOfStates());
ASSERT_EQ(26ul, modelPtr->getNumberOfTransitions());
ASSERT_EQ(1ul, modelPtr->getInitialStates().getNumberOfSetBits());
ASSERT_TRUE(modelPtr->hasLabel("three"));
ASSERT_FALSE(modelPtr->hasRewardModel());
ASSERT_EQ(12ul, modelPtr->getNumberOfStates());
ASSERT_EQ(26ul, modelPtr->getNumberOfTransitions());
ASSERT_EQ(1ul, modelPtr->getInitialStates().getNumberOfSetBits());
ASSERT_TRUE(modelPtr->hasLabel("three"));
ASSERT_FALSE(modelPtr->hasRewardModel());
}
TEST(AutoParserTest, WrongHint) {
// The hint given describes the content but does not conform to the format.
ASSERT_THROW(storm::parser::AutoParser::parseModel(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/autoParser/wrongHint.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/autoParser.lab"), storm::exceptions::WrongFormatException);
// The hint given describes the content but does not conform to the format.
ASSERT_THROW(storm::parser::AutoParser<>::parseModel(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/autoParser/wrongHint.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/autoParser.lab"), storm::exceptions::WrongFormatException);
}
TEST(AutoParserTest, NoHint) {
// There is no hint contained in the given file, so the parser cannot decide which kind of model it is.
ASSERT_THROW(storm::parser::AutoParser::parseModel(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/autoParser/noHint.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/autoParser.lab"), storm::exceptions::WrongFormatException);
// There is no hint contained in the given file, so the parser cannot decide which kind of model it is.
ASSERT_THROW(storm::parser::AutoParser<>::parseModel(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/autoParser/noHint.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/autoParser.lab"), storm::exceptions::WrongFormatException);
}
TEST(AutoParserTest, Decision) {
// Test if the AutoParser recognizes each model kind and correctly parses it.
// Test if the AutoParser recognizes each model kind and correctly parses it.
// Dtmc
std::shared_ptr<storm::models::sparse::Model<double>> modelPtr = storm::parser::AutoParser::parseModel(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/autoParser/dtmc.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/autoParser.lab");
ASSERT_EQ(storm::models::ModelType::Dtmc, modelPtr->getType());
ASSERT_EQ(12ul, modelPtr->getNumberOfStates());
ASSERT_EQ(26ul, modelPtr->getNumberOfTransitions());
// Dtmc
std::shared_ptr<storm::models::sparse::Model<double>> modelPtr = storm::parser::AutoParser<>::parseModel(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/autoParser/dtmc.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/autoParser.lab");
ASSERT_EQ(storm::models::ModelType::Dtmc, modelPtr->getType());
ASSERT_EQ(12ul, modelPtr->getNumberOfStates());
ASSERT_EQ(26ul, modelPtr->getNumberOfTransitions());
// Ctmc
modelPtr.reset();
modelPtr = storm::parser::AutoParser::parseModel(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/autoParser/ctmc.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/autoParser.lab");
ASSERT_EQ(storm::models::ModelType::Ctmc, modelPtr->getType());
ASSERT_EQ(12ul, modelPtr->getNumberOfStates());
ASSERT_EQ(26ul, modelPtr->getNumberOfTransitions());
// Ctmc
modelPtr.reset();
modelPtr = storm::parser::AutoParser<>::parseModel(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/autoParser/ctmc.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/autoParser.lab");
ASSERT_EQ(storm::models::ModelType::Ctmc, modelPtr->getType());
ASSERT_EQ(12ul, modelPtr->getNumberOfStates());
ASSERT_EQ(26ul, modelPtr->getNumberOfTransitions());
// Mdp
modelPtr.reset();
modelPtr = storm::parser::AutoParser::parseModel(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/autoParser/mdp.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/autoParser.lab");
ASSERT_EQ(storm::models::ModelType::Mdp, modelPtr->getType());
ASSERT_EQ(12ul, modelPtr->getNumberOfStates());
ASSERT_EQ(28ul, modelPtr->getNumberOfTransitions());
// Mdp
modelPtr.reset();
modelPtr = storm::parser::AutoParser<>::parseModel(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/autoParser/mdp.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/autoParser.lab");
ASSERT_EQ(storm::models::ModelType::Mdp, modelPtr->getType());
ASSERT_EQ(12ul, modelPtr->getNumberOfStates());
ASSERT_EQ(28ul, modelPtr->getNumberOfTransitions());
// MA
modelPtr.reset();
modelPtr = storm::parser::AutoParser::parseModel(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/autoParser/ma.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/autoParser.lab");
ASSERT_EQ(storm::models::ModelType::MarkovAutomaton, modelPtr->getType());
ASSERT_EQ(12ul, modelPtr->getNumberOfStates());
ASSERT_EQ(27ul, modelPtr->getNumberOfTransitions());
// MA
modelPtr.reset();
modelPtr = storm::parser::AutoParser<>::parseModel(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/autoParser/ma.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/autoParser.lab");
ASSERT_EQ(storm::models::ModelType::MarkovAutomaton, modelPtr->getType());
ASSERT_EQ(12ul, modelPtr->getNumberOfStates());
ASSERT_EQ(27ul, modelPtr->getNumberOfTransitions());
}

117
test/functional/parser/DeterministicModelParserTest.cpp

@ -12,88 +12,87 @@
#include "src/exceptions/OutOfRangeException.h"
TEST(DeterministicModelParserTest, NonExistingFile) {
// No matter what happens, please do NOT create a file with the name "nonExistingFile.not"!
ASSERT_THROW(storm::parser::DeterministicModelParser::parseDtmc(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
// No matter what happens, please do NOT create a file with the name "nonExistingFile.not"!
ASSERT_THROW(storm::parser::DeterministicModelParser<>::parseDtmc(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
ASSERT_THROW(storm::parser::DeterministicModelParser::parseCtmc(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
ASSERT_THROW(storm::parser::DeterministicModelParser<>::parseCtmc(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
}
TEST(DeterministicModelParserTest, BasicDtmcParsing) {
// Parse a Dtmc and check the result.
storm::models::sparse::Dtmc<double> dtmc(storm::parser::DeterministicModelParser::parseDtmc(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_general.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/dtmc_general.lab", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_general.state.rew", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_general.trans.rew"));
// Parse a Dtmc and check the result.
storm::models::sparse::Dtmc<double> dtmc(storm::parser::DeterministicModelParser<>::parseDtmc(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_general.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/dtmc_general.lab", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_general.state.rew", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_general.trans.rew"));
ASSERT_EQ(8ul, dtmc.getNumberOfStates());
ASSERT_EQ(16ul, dtmc.getNumberOfTransitions());
ASSERT_EQ(8ul, dtmc.getNumberOfStates());
ASSERT_EQ(16ul, dtmc.getNumberOfTransitions());
ASSERT_EQ(2ul, dtmc.getInitialStates().getNumberOfSetBits());
ASSERT_TRUE(dtmc.getInitialStates().get(0));
ASSERT_TRUE(dtmc.getInitialStates().get(7));
ASSERT_EQ(5ul, dtmc.getStateLabeling().getNumberOfLabels());
ASSERT_EQ(2ul, dtmc.getLabelsOfState(6).size());
ASSERT_EQ(2ul, dtmc.getInitialStates().getNumberOfSetBits());
ASSERT_TRUE(dtmc.getInitialStates().get(0));
ASSERT_TRUE(dtmc.getInitialStates().get(7));
ASSERT_EQ(5ul, dtmc.getStateLabeling().getNumberOfLabels());
ASSERT_EQ(2ul, dtmc.getLabelsOfState(6).size());
ASSERT_TRUE(dtmc.hasRewardModel());
ASSERT_EQ(42, dtmc.getRewardModel("").getStateRewardVector()[7]);
double rewardSum = 0;
for(uint_fast64_t i = 0; i < dtmc.getRewardModel("").getStateRewardVector().size(); i++) {
rewardSum += dtmc.getRewardModel("").getStateRewardVector()[i];
}
ASSERT_EQ(263.32, rewardSum);
ASSERT_TRUE(dtmc.getRewardModel("").hasTransitionRewards());
ASSERT_EQ(17ul, dtmc.getRewardModel("").getTransitionRewardMatrix().getEntryCount());
rewardSum = 0;
for(uint_fast64_t i = 0; i < dtmc.getRewardModel("").getTransitionRewardMatrix().getRowCount(); i++) {
rewardSum += dtmc.getRewardModel("").getTransitionRewardMatrix().getRowSum(i);
}
ASSERT_EQ(125.4, rewardSum);
ASSERT_EQ(42, dtmc.getRewardModel("").getStateRewardVector()[7]);
double rewardSum = 0;
for (uint_fast64_t i = 0; i < dtmc.getRewardModel("").getStateRewardVector().size(); i++) {
rewardSum += dtmc.getRewardModel("").getStateRewardVector()[i];
}
ASSERT_EQ(263.32, rewardSum);
ASSERT_TRUE(dtmc.getRewardModel("").hasTransitionRewards());
ASSERT_EQ(17ul, dtmc.getRewardModel("").getTransitionRewardMatrix().getEntryCount());
rewardSum = 0;
for (uint_fast64_t i = 0; i < dtmc.getRewardModel("").getTransitionRewardMatrix().getRowCount(); i++) {
rewardSum += dtmc.getRewardModel("").getTransitionRewardMatrix().getRowSum(i);
}
ASSERT_EQ(125.4, rewardSum);
}
TEST(DeterministicModelParserTest, BasicCtmcParsing) {
// Parse a Ctmc and check the result.
storm::models::sparse::Ctmc<double> ctmc(storm::parser::DeterministicModelParser::parseCtmc(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_general.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/dtmc_general.lab", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_general.state.rew", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_general.trans.rew"));
// Parse a Ctmc and check the result.
storm::models::sparse::Ctmc<double> ctmc(storm::parser::DeterministicModelParser<>::parseCtmc(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_general.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/dtmc_general.lab", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_general.state.rew", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_general.trans.rew"));
ASSERT_EQ(8ul, ctmc.getNumberOfStates());
ASSERT_EQ(16ul, ctmc.getNumberOfTransitions());
ASSERT_EQ(8ul, ctmc.getNumberOfStates());
ASSERT_EQ(16ul, ctmc.getNumberOfTransitions());
ASSERT_EQ(2ul, ctmc.getInitialStates().getNumberOfSetBits());
ASSERT_TRUE(ctmc.getInitialStates().get(0));
ASSERT_TRUE(ctmc.getInitialStates().get(7));
ASSERT_EQ(5ul, ctmc.getStateLabeling().getNumberOfLabels());
ASSERT_EQ(2ul, ctmc.getLabelsOfState(6).size());
ASSERT_EQ(2ul, ctmc.getInitialStates().getNumberOfSetBits());
ASSERT_TRUE(ctmc.getInitialStates().get(0));
ASSERT_TRUE(ctmc.getInitialStates().get(7));
ASSERT_EQ(5ul, ctmc.getStateLabeling().getNumberOfLabels());
ASSERT_EQ(2ul, ctmc.getLabelsOfState(6).size());
ASSERT_TRUE(ctmc.hasRewardModel());
ASSERT_EQ(42, ctmc.getRewardModel("").getStateRewardVector()[7]);
double rewardSum = 0;
for(uint_fast64_t i = 0; i < ctmc.getRewardModel("").getStateRewardVector().size(); i++) {
rewardSum += ctmc.getRewardModel("").getStateRewardVector()[i];
}
ASSERT_EQ(263.32, rewardSum);
ASSERT_TRUE(ctmc.getRewardModel("").hasTransitionRewards());
ASSERT_EQ(17ul, ctmc.getRewardModel("").getTransitionRewardMatrix().getEntryCount());
rewardSum = 0;
for(uint_fast64_t i = 0; i < ctmc.getRewardModel("").getTransitionRewardMatrix().getRowCount(); i++) {
rewardSum += ctmc.getRewardModel("").getTransitionRewardMatrix().getRowSum(i);
}
ASSERT_EQ(125.4, rewardSum);
ASSERT_EQ(42, ctmc.getRewardModel("").getStateRewardVector()[7]);
double rewardSum = 0;
for (uint_fast64_t i = 0; i < ctmc.getRewardModel("").getStateRewardVector().size(); i++) {
rewardSum += ctmc.getRewardModel("").getStateRewardVector()[i];
}
ASSERT_EQ(263.32, rewardSum);
ASSERT_TRUE(ctmc.getRewardModel("").hasTransitionRewards());
ASSERT_EQ(17ul, ctmc.getRewardModel("").getTransitionRewardMatrix().getEntryCount());
rewardSum = 0;
for (uint_fast64_t i = 0; i < ctmc.getRewardModel("").getTransitionRewardMatrix().getRowCount(); i++) {
rewardSum += ctmc.getRewardModel("").getTransitionRewardMatrix().getRowSum(i);
}
ASSERT_EQ(125.4, rewardSum);
}
TEST(DeterministicModelParserTest, MismatchedFiles) {
// Test file combinations that do not match, i.e. differing number of states, transitions, etc.
// Test file combinations that do not match, i.e. differing number of states, transitions, etc.
// The labeling file contains a label for a non existent state.
ASSERT_THROW(storm::parser::DeterministicModelParser::parseDtmc(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_mismatched.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/dtmc_general.lab"), storm::exceptions::OutOfRangeException);
// The labeling file contains a label for a non existent state.
ASSERT_THROW(storm::parser::DeterministicModelParser<>::parseDtmc(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_mismatched.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/dtmc_general.lab"), storm::exceptions::OutOfRangeException);
// The state reward file contains a reward for a non existent state.
ASSERT_THROW(storm::parser::DeterministicModelParser::parseDtmc(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_mismatched.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/dtmc_mismatched.lab", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_general.state.rew"), storm::exceptions::OutOfRangeException);
// The state reward file contains a reward for a non existent state.
ASSERT_THROW(storm::parser::DeterministicModelParser<>::parseDtmc(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_mismatched.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/dtmc_mismatched.lab", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_general.state.rew"), storm::exceptions::OutOfRangeException);
// The transition reward file contains rewards for a non existent state.
ASSERT_THROW(storm::parser::DeterministicModelParser::parseDtmc(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_mismatched.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/dtmc_mismatched.lab", "", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_general.trans.rew"), storm::exceptions::OutOfRangeException);
// The transition reward file contains rewards for a non existent state.
ASSERT_THROW(storm::parser::DeterministicModelParser<>::parseDtmc(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_mismatched.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/dtmc_mismatched.lab", "", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_general.trans.rew"), storm::exceptions::OutOfRangeException);
// The transition reward file contains rewards for a non existent transition
ASSERT_THROW(storm::parser::DeterministicModelParser::parseDtmc(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_mismatched.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/dtmc_mismatched.lab", "", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_mismatched.trans.rew"), storm::exceptions::OutOfRangeException);
// The transition reward file contains rewards for a non existent transition
ASSERT_THROW(storm::parser::DeterministicModelParser<>::parseDtmc(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_mismatched.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/dtmc_mismatched.lab", "", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_mismatched.trans.rew"), storm::exceptions::OutOfRangeException);
}

361
test/functional/parser/DeterministicSparseTransitionParserTest.cpp

@ -20,223 +20,218 @@
TEST(DeterministicSparseTransitionParserTest, NonExistingFile) {
// No matter what happens, please do NOT create a file with the name "nonExistingFile.not"!
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
// No matter what happens, please do NOT create a file with the name "nonExistingFile.not"!
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
storm::storage::SparseMatrix<double> nullMatrix;
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", nullMatrix), storm::exceptions::FileIoException);
storm::storage::SparseMatrix<double> nullMatrix;
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", nullMatrix), storm::exceptions::FileIoException);
}
TEST(DeterministicSparseTransitionParserTest, BasicTransitionsParsing) {
// Parse a deterministic transitions file and test the resulting matrix.
storm::storage::SparseMatrix<double> transitionMatrix = storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_general.tra");
ASSERT_EQ(8ul, transitionMatrix.getColumnCount());
ASSERT_EQ(21ul, transitionMatrix.getEntryCount());
// Test every entry of the matrix.
storm::storage::SparseMatrix<double>::const_iterator cIter = transitionMatrix.begin(0);
ASSERT_EQ(0ul, cIter->getColumn());
ASSERT_EQ(0, cIter->getValue());
cIter++;
ASSERT_EQ(1ul, cIter->getColumn());
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(1ul, cIter->getColumn());
ASSERT_EQ(0, cIter->getValue());
cIter++;
ASSERT_EQ(2ul, cIter->getColumn());
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(2ul, cIter->getColumn());
ASSERT_EQ(0, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(0.4, cIter->getValue());
cIter++;
ASSERT_EQ(4ul, cIter->getColumn());
ASSERT_EQ(0.4, cIter->getValue());
cIter++;
ASSERT_EQ(5ul, cIter->getColumn());
ASSERT_EQ(0.2, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(4ul, cIter->getColumn());
ASSERT_EQ(0, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(0.1, cIter->getValue());
cIter++;
ASSERT_EQ(4ul, cIter->getColumn());
ASSERT_EQ(0.1, cIter->getValue());
cIter++;
ASSERT_EQ(5ul, cIter->getColumn());
ASSERT_EQ(0.1, cIter->getValue());
cIter++;
ASSERT_EQ(6ul, cIter->getColumn());
ASSERT_EQ(0.7, cIter->getValue());
cIter++;
ASSERT_EQ(0ul, cIter->getColumn());
ASSERT_EQ(0.9, cIter->getValue());
cIter++;
ASSERT_EQ(5ul, cIter->getColumn());
ASSERT_EQ(0, cIter->getValue());
cIter++;
ASSERT_EQ(6ul, cIter->getColumn());
ASSERT_EQ(0.1, cIter->getValue());
cIter++;
ASSERT_EQ(6ul, cIter->getColumn());
ASSERT_EQ(0.224653, cIter->getValue());
cIter++;
ASSERT_EQ(7ul, cIter->getColumn());
ASSERT_EQ(0.775347, cIter->getValue());
// Parse a deterministic transitions file and test the resulting matrix.
storm::storage::SparseMatrix<double> transitionMatrix = storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_general.tra");
ASSERT_EQ(8ul, transitionMatrix.getColumnCount());
ASSERT_EQ(21ul, transitionMatrix.getEntryCount());
// Test every entry of the matrix.
storm::storage::SparseMatrix<double>::const_iterator cIter = transitionMatrix.begin(0);
ASSERT_EQ(0ul, cIter->getColumn());
ASSERT_EQ(0, cIter->getValue());
cIter++;
ASSERT_EQ(1ul, cIter->getColumn());
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(1ul, cIter->getColumn());
ASSERT_EQ(0, cIter->getValue());
cIter++;
ASSERT_EQ(2ul, cIter->getColumn());
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(2ul, cIter->getColumn());
ASSERT_EQ(0, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(0.4, cIter->getValue());
cIter++;
ASSERT_EQ(4ul, cIter->getColumn());
ASSERT_EQ(0.4, cIter->getValue());
cIter++;
ASSERT_EQ(5ul, cIter->getColumn());
ASSERT_EQ(0.2, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(4ul, cIter->getColumn());
ASSERT_EQ(0, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(0.1, cIter->getValue());
cIter++;
ASSERT_EQ(4ul, cIter->getColumn());
ASSERT_EQ(0.1, cIter->getValue());
cIter++;
ASSERT_EQ(5ul, cIter->getColumn());
ASSERT_EQ(0.1, cIter->getValue());
cIter++;
ASSERT_EQ(6ul, cIter->getColumn());
ASSERT_EQ(0.7, cIter->getValue());
cIter++;
ASSERT_EQ(0ul, cIter->getColumn());
ASSERT_EQ(0.9, cIter->getValue());
cIter++;
ASSERT_EQ(5ul, cIter->getColumn());
ASSERT_EQ(0, cIter->getValue());
cIter++;
ASSERT_EQ(6ul, cIter->getColumn());
ASSERT_EQ(0.1, cIter->getValue());
cIter++;
ASSERT_EQ(6ul, cIter->getColumn());
ASSERT_EQ(0.224653, cIter->getValue());
cIter++;
ASSERT_EQ(7ul, cIter->getColumn());
ASSERT_EQ(0.775347, cIter->getValue());
}
TEST(DeterministicSparseTransitionParserTest, BasicTransitionsRewardsParsing) {
// First parse a transition file. Then parse a transition reward file for the resulting transition matrix.
storm::storage::SparseMatrix<double> transitionMatrix = storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_general.tra");
storm::storage::SparseMatrix<double> rewardMatrix = storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_general.trans.rew", transitionMatrix);
ASSERT_EQ(8ul, rewardMatrix.getColumnCount());
ASSERT_EQ(17ul, rewardMatrix.getEntryCount());
// Test every entry of the matrix.
storm::storage::SparseMatrix<double>::const_iterator cIter = rewardMatrix.begin(0);
ASSERT_EQ(1ul, cIter->getColumn());
ASSERT_EQ(10, cIter->getValue());
cIter++;
ASSERT_EQ(2ul, cIter->getColumn());
ASSERT_EQ(5, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(5.5, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(21.4, cIter->getValue());
cIter++;
ASSERT_EQ(4ul, cIter->getColumn());
ASSERT_EQ(4, cIter->getValue());
cIter++;
ASSERT_EQ(5ul, cIter->getColumn());
ASSERT_EQ(2, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(0.1, cIter->getValue());
cIter++;
ASSERT_EQ(4ul, cIter->getColumn());
ASSERT_EQ(1.1, cIter->getValue());
cIter++;
ASSERT_EQ(5ul, cIter->getColumn());
ASSERT_EQ(9.5, cIter->getValue());
cIter++;
ASSERT_EQ(6ul, cIter->getColumn());
ASSERT_EQ(6.7, cIter->getValue());
cIter++;
ASSERT_EQ(0ul, cIter->getColumn());
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(5ul, cIter->getColumn());
ASSERT_EQ(0, cIter->getValue());
cIter++;
ASSERT_EQ(6ul, cIter->getColumn());
ASSERT_EQ(12, cIter->getValue());
cIter++;
ASSERT_EQ(6ul, cIter->getColumn());
ASSERT_EQ(35.224653, cIter->getValue());
cIter++;
ASSERT_EQ(7ul, cIter->getColumn());
ASSERT_EQ(9.875347, cIter->getValue());
// First parse a transition file. Then parse a transition reward file for the resulting transition matrix.
storm::storage::SparseMatrix<double> transitionMatrix = storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_general.tra");
storm::storage::SparseMatrix<double> rewardMatrix = storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_general.trans.rew", transitionMatrix);
ASSERT_EQ(8ul, rewardMatrix.getColumnCount());
ASSERT_EQ(17ul, rewardMatrix.getEntryCount());
// Test every entry of the matrix.
storm::storage::SparseMatrix<double>::const_iterator cIter = rewardMatrix.begin(0);
ASSERT_EQ(1ul, cIter->getColumn());
ASSERT_EQ(10, cIter->getValue());
cIter++;
ASSERT_EQ(2ul, cIter->getColumn());
ASSERT_EQ(5, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(5.5, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(21.4, cIter->getValue());
cIter++;
ASSERT_EQ(4ul, cIter->getColumn());
ASSERT_EQ(4, cIter->getValue());
cIter++;
ASSERT_EQ(5ul, cIter->getColumn());
ASSERT_EQ(2, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(3ul, cIter->getColumn());
ASSERT_EQ(0.1, cIter->getValue());
cIter++;
ASSERT_EQ(4ul, cIter->getColumn());
ASSERT_EQ(1.1, cIter->getValue());
cIter++;
ASSERT_EQ(5ul, cIter->getColumn());
ASSERT_EQ(9.5, cIter->getValue());
cIter++;
ASSERT_EQ(6ul, cIter->getColumn());
ASSERT_EQ(6.7, cIter->getValue());
cIter++;
ASSERT_EQ(0ul, cIter->getColumn());
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(5ul, cIter->getColumn());
ASSERT_EQ(0, cIter->getValue());
cIter++;
ASSERT_EQ(6ul, cIter->getColumn());
ASSERT_EQ(12, cIter->getValue());
cIter++;
ASSERT_EQ(6ul, cIter->getColumn());
ASSERT_EQ(35.224653, cIter->getValue());
cIter++;
ASSERT_EQ(7ul, cIter->getColumn());
ASSERT_EQ(9.875347, cIter->getValue());
}
TEST(DeterministicSparseTransitionParserTest, Whitespaces) {
// Test the resilience of the parser against whitespaces.
// Do so by comparing the hash of the matrix resulting from the file without whitespaces with the hash of the matrix resulting from the file with whitespaces.
uint_fast64_t correctHash = storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_general.tra").hash();
storm::storage::SparseMatrix<double> transitionMatrix = storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_whitespaces.tra");
ASSERT_EQ(correctHash, transitionMatrix.hash());
// Test the resilience of the parser against whitespaces.
// Do so by comparing the hash of the matrix resulting from the file without whitespaces with the hash of the matrix resulting from the file with whitespaces.
uint_fast64_t correctHash = storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_general.tra").hash();
storm::storage::SparseMatrix<double> transitionMatrix = storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_whitespaces.tra");
ASSERT_EQ(correctHash, transitionMatrix.hash());
// Do the same for the corresponding transition rewards file (with and without whitespaces)
correctHash = storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_general.trans.rew", transitionMatrix).hash();
ASSERT_EQ(correctHash, storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_whitespaces.trans.rew", transitionMatrix).hash());
// Do the same for the corresponding transition rewards file (with and without whitespaces)
correctHash = storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_general.trans.rew", transitionMatrix).hash();
ASSERT_EQ(correctHash, storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_whitespaces.trans.rew", transitionMatrix).hash());
}
TEST(DeterministicSparseTransitionParserTest, MixedTransitionOrder) {
// Since the MatrixBuilder needs sequential input of new elements reordering of transitions or states should throw an exception.
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_mixedTransitionOrder.tra"), storm::exceptions::InvalidArgumentException);
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_mixedStateOrder.tra"), storm::exceptions::InvalidArgumentException);
// Since the MatrixBuilder needs sequential input of new elements reordering of transitions or states should throw an exception.
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_mixedTransitionOrder.tra"), storm::exceptions::InvalidArgumentException);
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_mixedStateOrder.tra"), storm::exceptions::InvalidArgumentException);
storm::storage::SparseMatrix<double> transitionMatrix = storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_general.tra");
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_mixedTransitionOrder.trans.rew", transitionMatrix), storm::exceptions::InvalidArgumentException);
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_mixedStateOrder.trans.rew", transitionMatrix), storm::exceptions::InvalidArgumentException);
storm::storage::SparseMatrix<double> transitionMatrix = storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_general.tra");
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_mixedTransitionOrder.trans.rew", transitionMatrix), storm::exceptions::InvalidArgumentException);
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_mixedStateOrder.trans.rew", transitionMatrix), storm::exceptions::InvalidArgumentException);
}
TEST(DeterministicSparseTransitionParserTest, FixDeadlocks) {
// Set the fixDeadlocks flag temporarily. It is set to its old value once the deadlockOption object is destructed.
// Set the fixDeadlocks flag temporarily. It is set to its old value once the deadlockOption object is destructed.
std::unique_ptr<storm::settings::SettingMemento> fixDeadlocks = storm::settings::mutableGeneralSettings().overrideDontFixDeadlocksSet(false);
// Parse a transitions file with the fixDeadlocks Flag set and test if it works.
storm::storage::SparseMatrix<double> transitionMatrix = storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_deadlock.tra");
ASSERT_EQ(9ul, transitionMatrix.getColumnCount());
ASSERT_EQ(23ul, transitionMatrix.getEntryCount());
storm::storage::SparseMatrix<double>::const_iterator cIter = transitionMatrix.begin(7);
ASSERT_EQ(7ul, cIter->getColumn());
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(6ul, cIter->getColumn());
ASSERT_EQ(0.224653, cIter->getValue());
cIter++;
ASSERT_EQ(7ul, cIter->getColumn());
ASSERT_EQ(0.775347, cIter->getValue());
cIter++;
ASSERT_EQ(8ul, cIter->getColumn());
ASSERT_EQ(0, cIter->getValue());
// Parse a transitions file with the fixDeadlocks Flag set and test if it works.
storm::storage::SparseMatrix<double> transitionMatrix = storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_deadlock.tra");
ASSERT_EQ(9ul, transitionMatrix.getColumnCount());
ASSERT_EQ(23ul, transitionMatrix.getEntryCount());
storm::storage::SparseMatrix<double>::const_iterator cIter = transitionMatrix.begin(7);
ASSERT_EQ(7ul, cIter->getColumn());
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(6ul, cIter->getColumn());
ASSERT_EQ(0.224653, cIter->getValue());
cIter++;
ASSERT_EQ(7ul, cIter->getColumn());
ASSERT_EQ(0.775347, cIter->getValue());
cIter++;
ASSERT_EQ(8ul, cIter->getColumn());
ASSERT_EQ(0, cIter->getValue());
}
TEST(DeterministicSparseTransitionParserTest, DontFixDeadlocks) {
// Try to parse a transitions file containing a deadlock state with the fixDeadlocksFlag unset. This should throw an exception.
// Try to parse a transitions file containing a deadlock state with the fixDeadlocksFlag unset. This should throw an exception.
std::unique_ptr<storm::settings::SettingMemento> dontFixDeadlocks = storm::settings::mutableGeneralSettings().overrideDontFixDeadlocksSet(true);
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_deadlock.tra"), storm::exceptions::WrongFormatException);
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_deadlock.tra"), storm::exceptions::WrongFormatException);
}
TEST(DeterministicSparseTransitionParserTest, DoubledLines) {
// There is a redundant line in the transition file. As the transition already exists this should throw an exception.
// Note: If two consecutive lines are doubled no exception is thrown.
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_doubledLines.tra"), storm::exceptions::InvalidArgumentException);
// There is a redundant line in the transition file. As the transition already exists this should throw an exception.
// Note: If two consecutive lines are doubled no exception is thrown.
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_doubledLines.tra"), storm::exceptions::InvalidArgumentException);
}
TEST(DeterministicSparseTransitionParserTest, RewardForNonExistentTransition) {
// First parse a transition file. Then parse a transition reward file for the resulting transition matrix.
storm::storage::SparseMatrix<double> transitionMatrix = storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_general.tra");
// First parse a transition file. Then parse a transition reward file for the resulting transition matrix.
storm::storage::SparseMatrix<double> transitionMatrix = storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/dtmc_general.tra");
// There is a reward for a transition that does not exist in the transition matrix.
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser::parseDeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_rewardForNonExTrans.trans.rew", transitionMatrix), storm::exceptions::WrongFormatException);
// There is a reward for a transition that does not exist in the transition matrix.
ASSERT_THROW(storm::parser::DeterministicSparseTransitionParser<>::parseDeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/dtmc_rewardForNonExTrans.trans.rew", transitionMatrix), storm::exceptions::WrongFormatException);
}

82
test/functional/parser/MarkovAutomatonParserTest.cpp

@ -7,60 +7,58 @@
#include "src/exceptions/OutOfRangeException.h"
TEST(MarkovAutomatonParserTest, NonExistingFile) {
// No matter what happens, please do NOT create a file with the name "nonExistingFile.not"!
ASSERT_THROW(storm::parser::MarkovAutomatonParser::parseMarkovAutomaton(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
// No matter what happens, please do NOT create a file with the name "nonExistingFile.not"!
ASSERT_THROW(storm::parser::MarkovAutomatonParser<>::parseMarkovAutomaton(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
}
TEST(MarkovAutomatonParserTest, BasicParsing) {
// Get the parsing result.
storm::models::sparse::MarkovAutomaton<double> result = storm::parser::MarkovAutomatonParser<>::parseMarkovAutomaton(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/ma_general.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/ma_general.lab", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/ma_general.state.rew");
// Get the parsing result.
storm::models::sparse::MarkovAutomaton<double> result = storm::parser::MarkovAutomatonParser::parseMarkovAutomaton(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/ma_general.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/ma_general.lab", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/ma_general.state.rew");
// Test sizes and counts.
ASSERT_EQ(6ul, result.getNumberOfStates());
ASSERT_EQ(7ul, result.getNumberOfChoices());
ASSERT_EQ(12ul, result.getNumberOfTransitions());
// Test sizes and counts.
ASSERT_EQ(6ul, result.getNumberOfStates());
ASSERT_EQ(7ul, result.getNumberOfChoices());
ASSERT_EQ(12ul, result.getNumberOfTransitions());
// Test the exit rates. These have to be 0 for all non-Markovian states.
std::vector<double> rates = result.getExitRates();
ASSERT_EQ(2, result.getExitRate(0));
ASSERT_FALSE(result.isMarkovianState(1));
ASSERT_EQ(0, result.getExitRate(1));
ASSERT_EQ(15, result.getExitRate(2));
ASSERT_FALSE(result.isMarkovianState(3));
ASSERT_EQ(0, result.getExitRate(3));
ASSERT_FALSE(result.isMarkovianState(4));
ASSERT_EQ(0, result.getExitRate(4));
ASSERT_FALSE(result.isMarkovianState(5));
ASSERT_EQ(0, result.getExitRate(5));
// Test the exit rates. These have to be 0 for all non-Markovian states.
std::vector<double> rates = result.getExitRates();
ASSERT_EQ(2, result.getExitRate(0));
ASSERT_FALSE(result.isMarkovianState(1));
ASSERT_EQ(0, result.getExitRate(1));
ASSERT_EQ(15, result.getExitRate(2));
ASSERT_FALSE(result.isMarkovianState(3));
ASSERT_EQ(0, result.getExitRate(3));
ASSERT_FALSE(result.isMarkovianState(4));
ASSERT_EQ(0, result.getExitRate(4));
ASSERT_FALSE(result.isMarkovianState(5));
ASSERT_EQ(0, result.getExitRate(5));
// Test the labeling.
ASSERT_EQ(3ul, result.getStateLabeling().getNumberOfLabels());
ASSERT_EQ(1ul, result.getInitialStates().getNumberOfSetBits());
ASSERT_EQ(0ul, result.getLabelsOfState(4).size());
ASSERT_EQ(1ul, result.getStateLabeling().getStates("goal").getNumberOfSetBits());
// Test the labeling.
ASSERT_EQ(3ul, result.getStateLabeling().getNumberOfLabels());
ASSERT_EQ(1ul, result.getInitialStates().getNumberOfSetBits());
ASSERT_EQ(0ul, result.getLabelsOfState(4).size());
ASSERT_EQ(1ul, result.getStateLabeling().getStates("goal").getNumberOfSetBits());
// Test the state rewards.
ASSERT_TRUE(result.hasRewardModel());
double rewardSum = 0;
for (uint_fast64_t i = 0; i < result.getRewardModel("").getStateRewardVector().size(); i++) {
rewardSum += result.getRewardModel("").getStateRewardVector()[i];
}
ASSERT_EQ(1015.765099984, rewardSum);
ASSERT_EQ(0, result.getRewardModel("").getStateRewardVector()[0]);
// Test the state rewards.
ASSERT_TRUE(result.hasRewardModel());
double rewardSum = 0;
for (uint_fast64_t i = 0; i < result.getRewardModel("").getStateRewardVector().size(); i++) {
rewardSum += result.getRewardModel("").getStateRewardVector()[i];
}
ASSERT_EQ(1015.765099984, rewardSum);
ASSERT_EQ(0, result.getRewardModel("").getStateRewardVector()[0]);
// Test the transition rewards.
ASSERT_FALSE(result.getRewardModel("").hasTransitionRewards());
// Test the transition rewards.
ASSERT_FALSE(result.getRewardModel("").hasTransitionRewards());
}
TEST(MarkovAutomatonParserTest, MismatchedFiles) {
// Test file combinations that do not match, i.e. differing number of states, transitions, etc.
// Test file combinations that do not match, i.e. differing number of states, transitions, etc.
// The labeling file contains a label for a non existent state.
ASSERT_THROW(storm::parser::MarkovAutomatonParser::parseMarkovAutomaton(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/ma_general.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/ma_mismatched.lab"), storm::exceptions::OutOfRangeException);
// The labeling file contains a label for a non existent state.
ASSERT_THROW(storm::parser::MarkovAutomatonParser<>::parseMarkovAutomaton(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/ma_general.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/ma_mismatched.lab"), storm::exceptions::OutOfRangeException);
// The state reward file contains a reward for a non existent state.
ASSERT_THROW(storm::parser::MarkovAutomatonParser::parseMarkovAutomaton(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/ma_general.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/ma_general.lab", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/ma_mismatched.state.rew"), storm::exceptions::OutOfRangeException);
// The state reward file contains a reward for a non existent state.
ASSERT_THROW(storm::parser::MarkovAutomatonParser<>::parseMarkovAutomaton(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/ma_general.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/ma_general.lab", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/ma_mismatched.state.rew"), storm::exceptions::OutOfRangeException);
}

336
test/functional/parser/MarkovAutomatonSparseTransitionParserTest.cpp

@ -24,189 +24,189 @@
TEST(MarkovAutomatonSparseTransitionParserTest, NonExistingFile) {
// No matter what happens, please do NOT create a file with the name "nonExistingFile.not"!
ASSERT_THROW(storm::parser::MarkovAutomatonSparseTransitionParser::parseMarkovAutomatonTransitions(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
// No matter what happens, please do NOT create a file with the name "nonExistingFile.not"!
ASSERT_THROW(storm::parser::MarkovAutomatonSparseTransitionParser<>::parseMarkovAutomatonTransitions(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
}
TEST(MarkovAutomatonSparseTransitionParserTest, BasicParsing) {
// The file that will be used for the test.
std::string filename = STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/ma_general.tra";
// Execute the parser.
storm::parser::MarkovAutomatonSparseTransitionParser::Result result = storm::parser::MarkovAutomatonSparseTransitionParser::parseMarkovAutomatonTransitions(filename);
// Build the actual transition matrix.
storm::storage::SparseMatrix<double> transitionMatrix(result.transitionMatrixBuilder.build(0,0));
// Test all sizes and counts.
ASSERT_EQ(STATE_COUNT, transitionMatrix.getColumnCount());
ASSERT_EQ(CHOICE_COUNT, transitionMatrix.getRowCount());
ASSERT_EQ(12ul, transitionMatrix.getEntryCount());
ASSERT_EQ(6ul, transitionMatrix.getRowGroupCount());
ASSERT_EQ(7ul, transitionMatrix.getRowGroupIndices().size());
ASSERT_EQ(CHOICE_COUNT, result.markovianChoices.size());
ASSERT_EQ(STATE_COUNT, result.markovianStates.size());
ASSERT_EQ(2ul, result.markovianStates.getNumberOfSetBits());
ASSERT_EQ(STATE_COUNT, result.exitRates.size());
// Test the general structure of the transition system (that will be an Markov automaton).
// Test the mapping between states and transition matrix rows.
ASSERT_EQ(0ul, transitionMatrix.getRowGroupIndices()[0]);
ASSERT_EQ(1ul, transitionMatrix.getRowGroupIndices()[1]);
ASSERT_EQ(2ul, transitionMatrix.getRowGroupIndices()[2]);
ASSERT_EQ(3ul, transitionMatrix.getRowGroupIndices()[3]);
ASSERT_EQ(4ul, transitionMatrix.getRowGroupIndices()[4]);
ASSERT_EQ(6ul, transitionMatrix.getRowGroupIndices()[5]);
ASSERT_EQ(7ul, transitionMatrix.getRowGroupIndices()[6]);
// Test the Markovian states.
ASSERT_TRUE(result.markovianStates.get(0));
ASSERT_FALSE(result.markovianStates.get(1));
ASSERT_TRUE(result.markovianStates.get(2));
ASSERT_FALSE(result.markovianStates.get(3));
ASSERT_FALSE(result.markovianStates.get(4));
ASSERT_FALSE(result.markovianStates.get(5));
// Test the exit rates. These have to be 0 for all non-Markovian states.
ASSERT_EQ(2, result.exitRates[0]);
ASSERT_EQ(0, result.exitRates[1]);
ASSERT_EQ(15, result.exitRates[2]);
ASSERT_EQ(0, result.exitRates[3]);
ASSERT_EQ(0, result.exitRates[4]);
ASSERT_EQ(0, result.exitRates[5]);
// Finally, test the transition matrix itself.
storm::storage::SparseMatrix<double>::const_iterator cIter = transitionMatrix.begin(0);
ASSERT_EQ(2, cIter->getValue());
cIter++;
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(2, cIter->getValue());
cIter++;
ASSERT_EQ(4, cIter->getValue());
cIter++;
ASSERT_EQ(8, cIter->getValue());
cIter++;
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(transitionMatrix.end(), cIter);
// The file that will be used for the test.
std::string filename = STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/ma_general.tra";
// Execute the parser.
typename storm::parser::MarkovAutomatonSparseTransitionParser<>::Result result = storm::parser::MarkovAutomatonSparseTransitionParser<>::parseMarkovAutomatonTransitions(filename);
// Build the actual transition matrix.
storm::storage::SparseMatrix<double> transitionMatrix(result.transitionMatrixBuilder.build(0, 0));
// Test all sizes and counts.
ASSERT_EQ(STATE_COUNT, transitionMatrix.getColumnCount());
ASSERT_EQ(CHOICE_COUNT, transitionMatrix.getRowCount());
ASSERT_EQ(12ul, transitionMatrix.getEntryCount());
ASSERT_EQ(6ul, transitionMatrix.getRowGroupCount());
ASSERT_EQ(7ul, transitionMatrix.getRowGroupIndices().size());
ASSERT_EQ(CHOICE_COUNT, result.markovianChoices.size());
ASSERT_EQ(STATE_COUNT, result.markovianStates.size());
ASSERT_EQ(2ul, result.markovianStates.getNumberOfSetBits());
ASSERT_EQ(STATE_COUNT, result.exitRates.size());
// Test the general structure of the transition system (that will be an Markov automaton).
// Test the mapping between states and transition matrix rows.
ASSERT_EQ(0ul, transitionMatrix.getRowGroupIndices()[0]);
ASSERT_EQ(1ul, transitionMatrix.getRowGroupIndices()[1]);
ASSERT_EQ(2ul, transitionMatrix.getRowGroupIndices()[2]);
ASSERT_EQ(3ul, transitionMatrix.getRowGroupIndices()[3]);
ASSERT_EQ(4ul, transitionMatrix.getRowGroupIndices()[4]);
ASSERT_EQ(6ul, transitionMatrix.getRowGroupIndices()[5]);
ASSERT_EQ(7ul, transitionMatrix.getRowGroupIndices()[6]);
// Test the Markovian states.
ASSERT_TRUE(result.markovianStates.get(0));
ASSERT_FALSE(result.markovianStates.get(1));
ASSERT_TRUE(result.markovianStates.get(2));
ASSERT_FALSE(result.markovianStates.get(3));
ASSERT_FALSE(result.markovianStates.get(4));
ASSERT_FALSE(result.markovianStates.get(5));
// Test the exit rates. These have to be 0 for all non-Markovian states.
ASSERT_EQ(2, result.exitRates[0]);
ASSERT_EQ(0, result.exitRates[1]);
ASSERT_EQ(15, result.exitRates[2]);
ASSERT_EQ(0, result.exitRates[3]);
ASSERT_EQ(0, result.exitRates[4]);
ASSERT_EQ(0, result.exitRates[5]);
// Finally, test the transition matrix itself.
storm::storage::SparseMatrix<double>::const_iterator cIter = transitionMatrix.begin(0);
ASSERT_EQ(2, cIter->getValue());
cIter++;
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(2, cIter->getValue());
cIter++;
ASSERT_EQ(4, cIter->getValue());
cIter++;
ASSERT_EQ(8, cIter->getValue());
cIter++;
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(transitionMatrix.end(), cIter);
}
TEST(MarkovAutomatonSparseTransitionParserTest, Whitespaces) {
// The file that will be used for the test.
std::string filename = STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/ma_whitespaces.tra";
// Execute the parser.
storm::parser::MarkovAutomatonSparseTransitionParser::Result result = storm::parser::MarkovAutomatonSparseTransitionParser::parseMarkovAutomatonTransitions(filename);
// Build the actual transition matrix.
storm::storage::SparseMatrix<double> transitionMatrix(result.transitionMatrixBuilder.build());
// Test all sizes and counts.
ASSERT_EQ(STATE_COUNT, transitionMatrix.getColumnCount());
ASSERT_EQ(CHOICE_COUNT, transitionMatrix.getRowCount());
ASSERT_EQ(12ul, transitionMatrix.getEntryCount());
ASSERT_EQ(6ul, transitionMatrix.getRowGroupCount());
ASSERT_EQ(7ul, transitionMatrix.getRowGroupIndices().size());
ASSERT_EQ(CHOICE_COUNT, result.markovianChoices.size());
ASSERT_EQ(STATE_COUNT, result.markovianStates.size());
ASSERT_EQ(2ul, result.markovianStates.getNumberOfSetBits());
ASSERT_EQ(STATE_COUNT, result.exitRates.size());
// Test the general structure of the transition system (that will be an Markov automaton).
// Test the mapping between states and transition matrix rows.
ASSERT_EQ(0ul, transitionMatrix.getRowGroupIndices()[0]);
ASSERT_EQ(1ul, transitionMatrix.getRowGroupIndices()[1]);
ASSERT_EQ(2ul, transitionMatrix.getRowGroupIndices()[2]);
ASSERT_EQ(3ul, transitionMatrix.getRowGroupIndices()[3]);
ASSERT_EQ(4ul, transitionMatrix.getRowGroupIndices()[4]);
ASSERT_EQ(6ul, transitionMatrix.getRowGroupIndices()[5]);
ASSERT_EQ(7ul, transitionMatrix.getRowGroupIndices()[6]);
// Test the Markovian states.
ASSERT_TRUE(result.markovianStates.get(0));
ASSERT_FALSE(result.markovianStates.get(1));
ASSERT_TRUE(result.markovianStates.get(2));
ASSERT_FALSE(result.markovianStates.get(3));
ASSERT_FALSE(result.markovianStates.get(4));
ASSERT_FALSE(result.markovianStates.get(5));
// Test the exit rates. These have to be 0 for all non-Markovian states.
ASSERT_EQ(2, result.exitRates[0]);
ASSERT_EQ(0, result.exitRates[1]);
ASSERT_EQ(15, result.exitRates[2]);
ASSERT_EQ(0, result.exitRates[3]);
ASSERT_EQ(0, result.exitRates[4]);
ASSERT_EQ(0, result.exitRates[5]);
// Finally, test the transition matrix itself.
storm::storage::SparseMatrix<double>::const_iterator cIter = transitionMatrix.begin(0);
ASSERT_EQ(2, cIter->getValue());
cIter++;
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(2, cIter->getValue());
cIter++;
ASSERT_EQ(4, cIter->getValue());
cIter++;
ASSERT_EQ(8, cIter->getValue());
cIter++;
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(transitionMatrix.end(), cIter);
// The file that will be used for the test.
std::string filename = STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/ma_whitespaces.tra";
// Execute the parser.
typename storm::parser::MarkovAutomatonSparseTransitionParser<>::Result result = storm::parser::MarkovAutomatonSparseTransitionParser<>::parseMarkovAutomatonTransitions(filename);
// Build the actual transition matrix.
storm::storage::SparseMatrix<double> transitionMatrix(result.transitionMatrixBuilder.build());
// Test all sizes and counts.
ASSERT_EQ(STATE_COUNT, transitionMatrix.getColumnCount());
ASSERT_EQ(CHOICE_COUNT, transitionMatrix.getRowCount());
ASSERT_EQ(12ul, transitionMatrix.getEntryCount());
ASSERT_EQ(6ul, transitionMatrix.getRowGroupCount());
ASSERT_EQ(7ul, transitionMatrix.getRowGroupIndices().size());
ASSERT_EQ(CHOICE_COUNT, result.markovianChoices.size());
ASSERT_EQ(STATE_COUNT, result.markovianStates.size());
ASSERT_EQ(2ul, result.markovianStates.getNumberOfSetBits());
ASSERT_EQ(STATE_COUNT, result.exitRates.size());
// Test the general structure of the transition system (that will be an Markov automaton).
// Test the mapping between states and transition matrix rows.
ASSERT_EQ(0ul, transitionMatrix.getRowGroupIndices()[0]);
ASSERT_EQ(1ul, transitionMatrix.getRowGroupIndices()[1]);
ASSERT_EQ(2ul, transitionMatrix.getRowGroupIndices()[2]);
ASSERT_EQ(3ul, transitionMatrix.getRowGroupIndices()[3]);
ASSERT_EQ(4ul, transitionMatrix.getRowGroupIndices()[4]);
ASSERT_EQ(6ul, transitionMatrix.getRowGroupIndices()[5]);
ASSERT_EQ(7ul, transitionMatrix.getRowGroupIndices()[6]);
// Test the Markovian states.
ASSERT_TRUE(result.markovianStates.get(0));
ASSERT_FALSE(result.markovianStates.get(1));
ASSERT_TRUE(result.markovianStates.get(2));
ASSERT_FALSE(result.markovianStates.get(3));
ASSERT_FALSE(result.markovianStates.get(4));
ASSERT_FALSE(result.markovianStates.get(5));
// Test the exit rates. These have to be 0 for all non-Markovian states.
ASSERT_EQ(2, result.exitRates[0]);
ASSERT_EQ(0, result.exitRates[1]);
ASSERT_EQ(15, result.exitRates[2]);
ASSERT_EQ(0, result.exitRates[3]);
ASSERT_EQ(0, result.exitRates[4]);
ASSERT_EQ(0, result.exitRates[5]);
// Finally, test the transition matrix itself.
storm::storage::SparseMatrix<double>::const_iterator cIter = transitionMatrix.begin(0);
ASSERT_EQ(2, cIter->getValue());
cIter++;
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(2, cIter->getValue());
cIter++;
ASSERT_EQ(4, cIter->getValue());
cIter++;
ASSERT_EQ(8, cIter->getValue());
cIter++;
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(0.5, cIter->getValue());
cIter++;
ASSERT_EQ(1, cIter->getValue());
cIter++;
ASSERT_EQ(transitionMatrix.end(), cIter);
}
TEST(MarkovAutomatonSparseTransitionParserTest, FixDeadlocks) {
// Set the fixDeadlocks flag temporarily. It is set to its old value once the deadlockOption object is destructed.
// Set the fixDeadlocks flag temporarily. It is set to its old value once the deadlockOption object is destructed.
std::unique_ptr<storm::settings::SettingMemento> fixDeadlocks = storm::settings::mutableGeneralSettings().overrideDontFixDeadlocksSet(false);
// Parse a Markov Automaton transition file with the fixDeadlocks Flag set and test if it works.
storm::parser::MarkovAutomatonSparseTransitionParser::Result result = storm::parser::MarkovAutomatonSparseTransitionParser::parseMarkovAutomatonTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/ma_deadlock.tra");
// Test if the result is consistent with the parsed Markov Automaton.
storm::storage::SparseMatrix<double> resultMatrix(result.transitionMatrixBuilder.build());
ASSERT_EQ(STATE_COUNT + 1, resultMatrix.getColumnCount());
ASSERT_EQ(13ul, resultMatrix.getEntryCount());
ASSERT_EQ(7ul, resultMatrix.getRowGroupCount());
ASSERT_EQ(8ul, resultMatrix.getRowGroupIndices().size());
ASSERT_EQ(CHOICE_COUNT +1, result.markovianChoices.size());
ASSERT_EQ(STATE_COUNT +1, result.markovianStates.size());
ASSERT_EQ(2ul, result.markovianStates.getNumberOfSetBits());
ASSERT_EQ(STATE_COUNT + 1, result.exitRates.size());
// Parse a Markov Automaton transition file with the fixDeadlocks Flag set and test if it works.
typename storm::parser::MarkovAutomatonSparseTransitionParser<>::Result result = storm::parser::MarkovAutomatonSparseTransitionParser<>::parseMarkovAutomatonTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/ma_deadlock.tra");
// Test if the result is consistent with the parsed Markov Automaton.
storm::storage::SparseMatrix<double> resultMatrix(result.transitionMatrixBuilder.build());
ASSERT_EQ(STATE_COUNT + 1, resultMatrix.getColumnCount());
ASSERT_EQ(13ul, resultMatrix.getEntryCount());
ASSERT_EQ(7ul, resultMatrix.getRowGroupCount());
ASSERT_EQ(8ul, resultMatrix.getRowGroupIndices().size());
ASSERT_EQ(CHOICE_COUNT + 1, result.markovianChoices.size());
ASSERT_EQ(STATE_COUNT + 1, result.markovianStates.size());
ASSERT_EQ(2ul, result.markovianStates.getNumberOfSetBits());
ASSERT_EQ(STATE_COUNT + 1, result.exitRates.size());
}
TEST(MarkovAutomatonSparseTransitionParserTest, DontFixDeadlocks) {
// Try to parse a Markov Automaton transition file containing a deadlock state with the fixDeadlocksFlag unset. This should throw an exception.
// Try to parse a Markov Automaton transition file containing a deadlock state with the fixDeadlocksFlag unset. This should throw an exception.
std::unique_ptr<storm::settings::SettingMemento> dontFixDeadlocks = storm::settings::mutableGeneralSettings().overrideDontFixDeadlocksSet(true);
ASSERT_THROW(storm::parser::MarkovAutomatonSparseTransitionParser::parseMarkovAutomatonTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/ma_deadlock.tra"), storm::exceptions::WrongFormatException);
ASSERT_THROW(storm::parser::MarkovAutomatonSparseTransitionParser<>::parseMarkovAutomatonTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/ma_deadlock.tra"), storm::exceptions::WrongFormatException);
}

81
test/functional/parser/NondeterministicModelParserTest.cpp

@ -10,55 +10,54 @@
#include "src/exceptions/InvalidArgumentException.h"
TEST(NondeterministicModelParserTest, NonExistingFile) {
// No matter what happens, please do NOT create a file with the name "nonExistingFile.not"!
ASSERT_THROW(storm::parser::NondeterministicModelParser::parseMdp(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
// No matter what happens, please do NOT create a file with the name "nonExistingFile.not"!
ASSERT_THROW(storm::parser::NondeterministicModelParser<>::parseMdp(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
}
TEST(NondeterministicModelParserTest, BasicMdpParsing) {
// Parse a Mdp and check the result.
storm::models::sparse::Mdp<double> mdp(storm::parser::NondeterministicModelParser::parseMdp(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/mdp_general.lab", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_general.state.rew", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_general.trans.rew"));
ASSERT_EQ(6ul, mdp.getNumberOfStates());
ASSERT_EQ(22ul, mdp.getNumberOfTransitions());
ASSERT_EQ(11ul, mdp.getNumberOfChoices());
ASSERT_EQ(2ul, mdp.getInitialStates().getNumberOfSetBits());
ASSERT_TRUE(mdp.getInitialStates().get(0));
ASSERT_TRUE(mdp.getInitialStates().get(4));
ASSERT_EQ(4ul, mdp.getStateLabeling().getNumberOfLabels());
ASSERT_EQ(3ul, mdp.getLabelsOfState(0).size());
ASSERT_TRUE(mdp.hasRewardModel());
ASSERT_EQ(0, mdp.getRewardModel("").getStateRewardVector()[0]);
ASSERT_EQ(42, mdp.getRewardModel("").getStateRewardVector()[4]);
double rewardSum = 0;
for(uint_fast64_t i = 0; i < mdp.getRewardModel("").getStateRewardVector().size(); i++) {
rewardSum += mdp.getRewardModel("").getStateRewardVector()[i];
}
ASSERT_EQ(158.32, rewardSum);
ASSERT_TRUE(mdp.getRewardModel("").hasTransitionRewards());
ASSERT_EQ(17ul, mdp.getRewardModel("").getTransitionRewardMatrix().getEntryCount());
rewardSum = 0;
for(uint_fast64_t i = 0; i < mdp.getRewardModel("").getTransitionRewardMatrix().getRowCount(); i++) {
rewardSum += mdp.getRewardModel("").getTransitionRewardMatrix().getRowSum(i);
}
ASSERT_EQ(1376.864, rewardSum);
// Parse a Mdp and check the result.
storm::models::sparse::Mdp<double> mdp(storm::parser::NondeterministicModelParser<>::parseMdp(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/mdp_general.lab", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_general.state.rew", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_general.trans.rew"));
ASSERT_EQ(6ul, mdp.getNumberOfStates());
ASSERT_EQ(22ul, mdp.getNumberOfTransitions());
ASSERT_EQ(11ul, mdp.getNumberOfChoices());
ASSERT_EQ(2ul, mdp.getInitialStates().getNumberOfSetBits());
ASSERT_TRUE(mdp.getInitialStates().get(0));
ASSERT_TRUE(mdp.getInitialStates().get(4));
ASSERT_EQ(4ul, mdp.getStateLabeling().getNumberOfLabels());
ASSERT_EQ(3ul, mdp.getLabelsOfState(0).size());
ASSERT_TRUE(mdp.hasRewardModel());
ASSERT_EQ(0, mdp.getRewardModel("").getStateRewardVector()[0]);
ASSERT_EQ(42, mdp.getRewardModel("").getStateRewardVector()[4]);
double rewardSum = 0;
for (uint_fast64_t i = 0; i < mdp.getRewardModel("").getStateRewardVector().size(); i++) {
rewardSum += mdp.getRewardModel("").getStateRewardVector()[i];
}
ASSERT_EQ(158.32, rewardSum);
ASSERT_TRUE(mdp.getRewardModel("").hasTransitionRewards());
ASSERT_EQ(17ul, mdp.getRewardModel("").getTransitionRewardMatrix().getEntryCount());
rewardSum = 0;
for (uint_fast64_t i = 0; i < mdp.getRewardModel("").getTransitionRewardMatrix().getRowCount(); i++) {
rewardSum += mdp.getRewardModel("").getTransitionRewardMatrix().getRowSum(i);
}
ASSERT_EQ(1376.864, rewardSum);
}
TEST(NondeterministicModelParserTest, MismatchedFiles) {
// Test file combinations that do not match, i.e. differing number of states, transitions, etc.
// Test file combinations that do not match, i.e. differing number of states, transitions, etc.
// The labeling file contains a label for a non existent state.
ASSERT_THROW(storm::parser::NondeterministicModelParser::parseMdp(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_mismatched.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/mdp_general.lab"), storm::exceptions::OutOfRangeException);
// The labeling file contains a label for a non existent state.
ASSERT_THROW(storm::parser::NondeterministicModelParser<>::parseMdp(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_mismatched.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/mdp_general.lab"), storm::exceptions::OutOfRangeException);
// The state reward file contains a reward for a non existent state.
ASSERT_THROW(storm::parser::NondeterministicModelParser::parseMdp(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_mismatched.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/mdp_mismatched.lab", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_general.state.rew"), storm::exceptions::OutOfRangeException);
// The state reward file contains a reward for a non existent state.
ASSERT_THROW(storm::parser::NondeterministicModelParser<>::parseMdp(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_mismatched.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/mdp_mismatched.lab", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_general.state.rew"), storm::exceptions::OutOfRangeException);
// The transition reward file contains rewards for a non existent state.
ASSERT_THROW(storm::parser::NondeterministicModelParser::parseMdp(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_mismatched.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/mdp_mismatched.lab", "", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_general.trans.rew"), storm::exceptions::OutOfRangeException);
// The transition reward file contains rewards for a non existent state.
ASSERT_THROW(storm::parser::NondeterministicModelParser<>::parseMdp(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_mismatched.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/mdp_mismatched.lab", "", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_general.trans.rew"), storm::exceptions::OutOfRangeException);
// The transition reward file contains rewards for a non existent transition
ASSERT_THROW(storm::parser::NondeterministicModelParser::parseMdp(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_mismatched.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/mdp_mismatched.lab", "", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_mismatched.trans.rew"), storm::exceptions::OutOfRangeException);
// The transition reward file contains rewards for a non existent transition
ASSERT_THROW(storm::parser::NondeterministicModelParser<>::parseMdp(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_mismatched.tra", STORM_CPP_TESTS_BASE_PATH "/functional/parser/lab_files/mdp_mismatched.lab", "", STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_mismatched.trans.rew"), storm::exceptions::OutOfRangeException);
}

39
test/functional/parser/NondeterministicSparseTransitionParserTest.cpp

@ -20,19 +20,18 @@
#include "src/exceptions/InvalidArgumentException.h"
TEST(NondeterministicSparseTransitionParserTest, NonExistingFile) {
// No matter what happens, please do NOT create a file with the name "nonExistingFile.not"!
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
storm::storage::SparseMatrix<double> nullInformation;
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", nullInformation), storm::exceptions::FileIoException);
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", nullInformation), storm::exceptions::FileIoException);
}
TEST(NondeterministicSparseTransitionParserTest, BasicTransitionsParsing) {
// Parse a nondeterministic transitions file and test the result.
storm::storage::SparseMatrix<double> result(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra"));
storm::storage::SparseMatrix<double> result(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra"));
// Test the row mapping, i.e. at which row which state starts.
ASSERT_EQ(6ul, result.getRowGroupCount());
@ -122,8 +121,8 @@ TEST(NondeterministicSparseTransitionParserTest, BasicTransitionsParsing) {
TEST(NondeterministicSparseTransitionParserTest, BasicTransitionsRewardsParsing) {
// Parse a nondeterministic transitions file and test the result.
storm::storage::SparseMatrix<double> modelInformation(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra"));
storm::storage::SparseMatrix<double> result(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_general.trans.rew", modelInformation));
storm::storage::SparseMatrix<double> modelInformation(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra"));
storm::storage::SparseMatrix<double> result(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_general.trans.rew", modelInformation));
// Test the transition matrix.
ASSERT_EQ(6ul, result.getColumnCount());
@ -188,8 +187,8 @@ TEST(NondeterministicSparseTransitionParserTest, BasicTransitionsRewardsParsing)
TEST(NondeterministicSparseTransitionParserTest, Whitespaces) {
// Test the resilience of the parser against whitespaces.
// Do so by comparing the hashes of the transition matices and the rowMapping vectors element by element.
storm::storage::SparseMatrix<double> correctResult(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra"));
storm::storage::SparseMatrix<double> whitespaceResult = storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_whitespaces.tra");
storm::storage::SparseMatrix<double> correctResult(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra"));
storm::storage::SparseMatrix<double> whitespaceResult = storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_whitespaces.tra");
ASSERT_EQ(correctResult.hash(), whitespaceResult.hash());
ASSERT_EQ(correctResult.getRowGroupIndices().size(), whitespaceResult.getRowGroupIndices().size());
for(uint_fast64_t i = 0; i < correctResult.getRowGroupIndices().size(); i++) {
@ -197,18 +196,18 @@ TEST(NondeterministicSparseTransitionParserTest, Whitespaces) {
}
// Do the same (minus the unused rowMapping) for the corresponding transition rewards file (with and without whitespaces)
uint_fast64_t correctHash = storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_general.trans.rew", correctResult).hash();
ASSERT_EQ(correctHash, storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_whitespaces.trans.rew", whitespaceResult).hash());
uint_fast64_t correctHash = storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_general.trans.rew", correctResult).hash();
ASSERT_EQ(correctHash, storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_whitespaces.trans.rew", whitespaceResult).hash());
}
TEST(NondeterministicSparseTransitionParserTest, MixedTransitionOrder) {
// Since the MatrixBuilder needs sequential input of new elements reordering of transitions or states should throw an exception.
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_mixedTransitionOrder.tra"), storm::exceptions::InvalidArgumentException);
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_mixedStateOrder.tra"), storm::exceptions::InvalidArgumentException);
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_mixedTransitionOrder.tra"), storm::exceptions::InvalidArgumentException);
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_mixedStateOrder.tra"), storm::exceptions::InvalidArgumentException);
storm::storage::SparseMatrix<double> modelInformation = storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra");
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_mixedTransitionOrder.trans.rew", modelInformation), storm::exceptions::InvalidArgumentException);
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_mixedStateOrder.trans.rew", modelInformation), storm::exceptions::InvalidArgumentException);
storm::storage::SparseMatrix<double> modelInformation = storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra");
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_mixedTransitionOrder.trans.rew", modelInformation), storm::exceptions::InvalidArgumentException);
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_mixedStateOrder.trans.rew", modelInformation), storm::exceptions::InvalidArgumentException);
}
TEST(NondeterministicSparseTransitionParserTest, FixDeadlocks) {
@ -216,7 +215,7 @@ TEST(NondeterministicSparseTransitionParserTest, FixDeadlocks) {
std::unique_ptr<storm::settings::SettingMemento> fixDeadlocks = storm::settings::mutableGeneralSettings().overrideDontFixDeadlocksSet(false);
// Parse a transitions file with the fixDeadlocks Flag set and test if it works.
storm::storage::SparseMatrix<double> result(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_deadlock.tra"));
storm::storage::SparseMatrix<double> result(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_deadlock.tra"));
ASSERT_EQ(8ul, result.getRowGroupIndices().size());
ASSERT_EQ(9ul, result.getRowGroupIndices()[5]);
@ -256,19 +255,19 @@ TEST(NondeterministicSparseTransitionParserTest, DontFixDeadlocks) {
// Try to parse a transitions file containing a deadlock state with the fixDeadlocksFlag unset. This should throw an exception.
std::unique_ptr<storm::settings::SettingMemento> dontFixDeadlocks = storm::settings::mutableGeneralSettings().overrideDontFixDeadlocksSet(true);
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_deadlock.tra"), storm::exceptions::WrongFormatException);
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_deadlock.tra"), storm::exceptions::WrongFormatException);
}
TEST(NondeterministicSparseTransitionParserTest, DoubledLines) {
// There is a redundant line in the transition file. As the transition already exists this should throw an exception.
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_doubledLines.tra"), storm::exceptions::InvalidArgumentException);
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_doubledLines.tra"), storm::exceptions::InvalidArgumentException);
}
TEST(NondeterministicSparseTransitionParserTest, RewardForNonExistentTransition) {
// First parse a transition file. Then parse a transition reward file for the resulting transition matrix.
storm::storage::SparseMatrix<double> transitionResult = storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra");
storm::storage::SparseMatrix<double> transitionResult = storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra");
// There is a reward for a transition that does not exist in the transition matrix.
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_rewardForNonExTrans.trans.rew", transitionResult), storm::exceptions::WrongFormatException);
ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_rewardForNonExTrans.trans.rew", transitionResult), storm::exceptions::WrongFormatException);
}

44
test/functional/parser/SparseStateRewardParserTest.cpp

@ -16,13 +16,11 @@
#include "src/exceptions/OutOfRangeException.h"
TEST(SparseStateRewardParserTest, NonExistingFile) {
// No matter what happens, please do NOT create a file with the name "nonExistingFile.not"!
ASSERT_THROW(storm::parser::SparseStateRewardParser::parseSparseStateReward(42, STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
// No matter what happens, please do NOT create a file with the name "nonExistingFile.not"!
ASSERT_THROW(storm::parser::SparseStateRewardParser<>::parseSparseStateReward(42, STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
}
double round(double val, int precision)
{
double round(double val, int precision) {
std::stringstream s;
s << std::setprecision(precision) << std::setiosflags(std::ios_base::fixed) << val;
s >> val;
@ -31,35 +29,35 @@ double round(double val, int precision)
TEST(SparseStateRewardParserTest, BasicParsing) {
// Get the parsing result.
std::vector<double> result = storm::parser::SparseStateRewardParser::parseSparseStateReward(100, STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/state_reward_parser_basic.state.rew");
// Get the parsing result.
std::vector<double> result = storm::parser::SparseStateRewardParser<>::parseSparseStateReward(100, STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/state_reward_parser_basic.state.rew");
// Now test if the correct value were parsed.
for(int i = 0; i < 100; i++) {
ASSERT_EQ(std::round(2*i + 15/13*i*i - 1.5/(i+0.1) + 15.7), std::round(result[i]));
}
// Now test if the correct value were parsed.
for (int i = 0; i < 100; i++) {
ASSERT_EQ(std::round(2 * i + 15 / 13 * i * i - 1.5 / (i + 0.1) + 15.7), std::round(result[i]));
}
}
TEST(SparseStateRewardParserTest, Whitespaces) {
// Get the parsing result.
std::vector<double> result = storm::parser::SparseStateRewardParser::parseSparseStateReward(100, STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/state_reward_parser_whitespaces.state.rew");
// Get the parsing result.
std::vector<double> result = storm::parser::SparseStateRewardParser<>::parseSparseStateReward(100, STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/state_reward_parser_whitespaces.state.rew");
// Now test if the correct value were parsed.
for(int i = 0; i < 100; i++) {
ASSERT_EQ(std::round(2*i + 15/13*i*i - 1.5/(i+0.1) + 15.7), std::round(result[i]));
}
// Now test if the correct value were parsed.
for (int i = 0; i < 100; i++) {
ASSERT_EQ(std::round(2 * i + 15 / 13 * i * i - 1.5 / (i + 0.1) + 15.7), std::round(result[i]));
}
}
TEST(SparseStateRewardParserTest, DoubledLines) {
// There are multiple lines attributing a reward to the same state.
ASSERT_THROW(storm::parser::SparseStateRewardParser::parseSparseStateReward(11, STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/state_reward_parser_doubledLines.state.rew"), storm::exceptions::WrongFormatException);
// There are multiple lines attributing a reward to the same state.
ASSERT_THROW(storm::parser::SparseStateRewardParser<>::parseSparseStateReward(11, STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/state_reward_parser_doubledLines.state.rew"), storm::exceptions::WrongFormatException);
// There is a line for a state that has been skipped.
ASSERT_THROW(storm::parser::SparseStateRewardParser::parseSparseStateReward(11, STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/state_reward_parser_doubledLinesSkipped.state.rew"), storm::exceptions::WrongFormatException);
// There is a line for a state that has been skipped.
ASSERT_THROW(storm::parser::SparseStateRewardParser<>::parseSparseStateReward(11, STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/state_reward_parser_doubledLinesSkipped.state.rew"), storm::exceptions::WrongFormatException);
}
TEST(SparseStateRewardParserTest, RewardForNonExistentState) {
// The index of one of the state that are to be given rewards is higher than the number of states in the model.
ASSERT_THROW(storm::parser::SparseStateRewardParser::parseSparseStateReward(99, STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/state_reward_parser_basic.state.rew"), storm::exceptions::OutOfRangeException);
// The index of one of the state that are to be given rewards is higher than the number of states in the model.
ASSERT_THROW(storm::parser::SparseStateRewardParser<>::parseSparseStateReward(99, STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/state_reward_parser_basic.state.rew"), storm::exceptions::OutOfRangeException);
}

68
test/functional/storage/DeterministicModelBisimulationDecompositionTest.cpp

@ -5,10 +5,10 @@
#include "src/models/sparse/StandardRewardModel.h"
TEST(DeterministicModelBisimulationDecomposition, Die) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(STORM_CPP_BASE_PATH "/examples/dtmc/die/die.tra", STORM_CPP_BASE_PATH "/examples/dtmc/die/die.lab", "", "");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/dtmc/die/die.tra", STORM_CPP_BASE_PATH "/examples/dtmc/die/die.lab", "", "");
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Dtmc);
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>();
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>();
storm::storage::DeterministicModelBisimulationDecomposition<double> bisim(*dtmc);
std::shared_ptr<storm::models::sparse::Model<double>> result;
@ -19,38 +19,38 @@ TEST(DeterministicModelBisimulationDecomposition, Die) {
EXPECT_EQ(20ul, result->getNumberOfTransitions());
#ifdef WINDOWS
storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options;
storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options;
#else
typename storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options;
typename storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options;
#endif
options.respectedAtomicPropositions = std::set<std::string>({"one"});
storm::storage::DeterministicModelBisimulationDecomposition<double> bisim2(*dtmc, options);
ASSERT_NO_THROW(result = bisim2.getQuotient());
EXPECT_EQ(storm::models::ModelType::Dtmc, result->getType());
EXPECT_EQ(5ul, result->getNumberOfStates());
EXPECT_EQ(8ul, result->getNumberOfTransitions());
options.bounded = false;
options.weak = true;
storm::storage::DeterministicModelBisimulationDecomposition<double> bisim3(*dtmc, options);
ASSERT_NO_THROW(result = bisim3.getQuotient());
EXPECT_EQ(storm::models::ModelType::Dtmc, result->getType());
EXPECT_EQ(5ul, result->getNumberOfStates());
EXPECT_EQ(8ul, result->getNumberOfTransitions());
auto labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("one");
auto eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula);
#ifdef WINDOWS
storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options2(*dtmc, *eventuallyFormula);
storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options2(*dtmc, *eventuallyFormula);
#else
typename storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options2(*dtmc, *eventuallyFormula);
typename storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options2(*dtmc, *eventuallyFormula);
#endif
storm::storage::DeterministicModelBisimulationDecomposition<double> bisim4(*dtmc, options2);
ASSERT_NO_THROW(result = bisim4.getQuotient());
EXPECT_EQ(storm::models::ModelType::Dtmc, result->getType());
@ -59,50 +59,50 @@ TEST(DeterministicModelBisimulationDecomposition, Die) {
}
TEST(DeterministicModelBisimulationDecomposition, Crowds) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.tra", STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.lab", "", "");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.tra", STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds5_5.lab", "", "");
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Dtmc);
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>();
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>();
storm::storage::DeterministicModelBisimulationDecomposition<double> bisim(*dtmc);
std::shared_ptr<storm::models::sparse::Model<double>> result;
ASSERT_NO_THROW(result = bisim.getQuotient());
EXPECT_EQ(storm::models::ModelType::Dtmc, result->getType());
EXPECT_EQ(334ul, result->getNumberOfStates());
EXPECT_EQ(546ul, result->getNumberOfTransitions());
#ifdef WINDOWS
storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options;
#else
typename storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options;
typename storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options;
#endif
options.respectedAtomicPropositions = std::set<std::string>({"observe0Greater1"});
storm::storage::DeterministicModelBisimulationDecomposition<double> bisim2(*dtmc, options);
ASSERT_NO_THROW(result = bisim2.getQuotient());
EXPECT_EQ(storm::models::ModelType::Dtmc, result->getType());
EXPECT_EQ(65ul, result->getNumberOfStates());
EXPECT_EQ(105ul, result->getNumberOfTransitions());
options.bounded = false;
options.weak = true;
storm::storage::DeterministicModelBisimulationDecomposition<double> bisim3(*dtmc, options);
ASSERT_NO_THROW(result = bisim3.getQuotient());
EXPECT_EQ(storm::models::ModelType::Dtmc, result->getType());
EXPECT_EQ(43ul, result->getNumberOfStates());
EXPECT_EQ(83ul, result->getNumberOfTransitions());
auto labelFormula = std::make_shared<storm::logic::AtomicLabelFormula>("observe0Greater1");
auto eventuallyFormula = std::make_shared<storm::logic::EventuallyFormula>(labelFormula);
#ifdef WINDOWS
storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options2(*dtmc, *eventuallyFormula);
storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options2(*dtmc, *eventuallyFormula);
#else
typename storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options2(*dtmc, *eventuallyFormula);
typename storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options2(*dtmc, *eventuallyFormula);
#endif
storm::storage::DeterministicModelBisimulationDecomposition<double> bisim4(*dtmc, options2);
ASSERT_NO_THROW(result = bisim4.getQuotient());
@ -110,11 +110,11 @@ TEST(DeterministicModelBisimulationDecomposition, Crowds) {
EXPECT_EQ(storm::models::ModelType::Dtmc, result->getType());
EXPECT_EQ(64ul, result->getNumberOfStates());
EXPECT_EQ(104ul, result->getNumberOfTransitions());
auto probabilityOperatorFormula = std::make_shared<storm::logic::ProbabilityOperatorFormula>(eventuallyFormula);
#ifdef WINDOWS
storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options3(*dtmc, *probabilityOperatorFormula);
storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options3(*dtmc, *probabilityOperatorFormula);
#else
typename storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options3(*dtmc, *probabilityOperatorFormula);
#endif
@ -124,17 +124,17 @@ TEST(DeterministicModelBisimulationDecomposition, Crowds) {
EXPECT_EQ(storm::models::ModelType::Dtmc, result->getType());
EXPECT_EQ(64ul, result->getNumberOfStates());
EXPECT_EQ(104ul, result->getNumberOfTransitions());
auto boundedUntilFormula = std::make_shared<storm::logic::BoundedUntilFormula>(std::make_shared<storm::logic::BooleanLiteralFormula>(true), labelFormula, 50);
#ifdef WINDOWS
storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options4(*dtmc, *boundedUntilFormula);
storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options4(*dtmc, *boundedUntilFormula);
#else
typename storm::storage::DeterministicModelBisimulationDecomposition<double>::Options options4(*dtmc, *boundedUntilFormula);
#endif
storm::storage::DeterministicModelBisimulationDecomposition<double> bisim6(*dtmc, options4);
ASSERT_NO_THROW(result = bisim6.getQuotient());
EXPECT_EQ(storm::models::ModelType::Dtmc, result->getType());
EXPECT_EQ(65ul, result->getNumberOfStates());
EXPECT_EQ(105ul, result->getNumberOfTransitions());

6
test/functional/storage/MaximalEndComponentDecompositionTest.cpp

@ -6,7 +6,7 @@
#include "src/models/sparse/StandardRewardModel.h"
TEST(MaximalEndComponentDecomposition, FullSystem1) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny1.tra", STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny1.lab", "", "");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny1.tra", STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny1.lab", "", "");
std::shared_ptr<storm::models::sparse::MarkovAutomaton<double>> markovAutomaton = abstractModel->as<storm::models::sparse::MarkovAutomaton<double>>();
@ -74,7 +74,7 @@ TEST(MaximalEndComponentDecomposition, FullSystem1) {
}
TEST(MaximalEndComponentDecomposition, FullSystem2) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny2.tra", STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny2.lab", "", "");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny2.tra", STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny2.lab", "", "");
std::shared_ptr<storm::models::sparse::MarkovAutomaton<double>> markovAutomaton = abstractModel->as<storm::models::sparse::MarkovAutomaton<double>>();
@ -103,7 +103,7 @@ TEST(MaximalEndComponentDecomposition, FullSystem2) {
}
TEST(MaximalEndComponentDecomposition, Subsystem) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny1.tra", STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny1.lab", "", "");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny1.tra", STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny1.lab", "", "");
std::shared_ptr<storm::models::sparse::MarkovAutomaton<double>> markovAutomaton = abstractModel->as<storm::models::sparse::MarkovAutomaton<double>>();

4
test/functional/storage/StronglyConnectedComponentDecompositionTest.cpp

@ -36,7 +36,7 @@ TEST(StronglyConnectedComponentDecomposition, SmallSystemFromMatrix) {
}
TEST(StronglyConnectedComponentDecomposition, FullSystem1) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny1.tra", STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny1.lab", "", "");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny1.tra", STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny1.lab", "", "");
std::shared_ptr<storm::models::sparse::MarkovAutomaton<double>> markovAutomaton = abstractModel->as<storm::models::sparse::MarkovAutomaton<double>>();
@ -55,7 +55,7 @@ TEST(StronglyConnectedComponentDecomposition, FullSystem1) {
}
TEST(StronglyConnectedComponentDecomposition, FullSystem2) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny2.tra", STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny2.lab", "", "");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny2.tra", STORM_CPP_BASE_PATH "/examples/ma/tiny/tiny2.lab", "", "");
std::shared_ptr<storm::models::sparse::MarkovAutomaton<double>> markovAutomaton = abstractModel->as<storm::models::sparse::MarkovAutomaton<double>>();

8
test/performance/graph/GraphTest.cpp

@ -9,7 +9,7 @@
#include "src/models/sparse/StandardRewardModel.h"
TEST(GraphTest, ExplicitProb01) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>();
storm::storage::BitVector trueStates(dtmc->getNumberOfStates(), true);
@ -31,7 +31,7 @@ TEST(GraphTest, ExplicitProb01) {
dtmc = nullptr;
abstractModel = storm::parser::AutoParser::parseModel(STORM_CPP_BASE_PATH "/examples/dtmc/synchronous_leader/leader6_8.tra", STORM_CPP_BASE_PATH "/examples/dtmc/synchronous_leader/leader6_8.lab", "", "");
abstractModel = storm::parser::AutoParser<>::parseModel(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::sparse::Dtmc<double>> dtmc2 = abstractModel->as<storm::models::sparse::Dtmc<double>>();
trueStates = storm::storage::BitVector(dtmc2->getNumberOfStates(), true);
@ -45,7 +45,7 @@ TEST(GraphTest, ExplicitProb01) {
}
TEST(GraphTest, PerformProb01MinMax) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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::sparse::Mdp<double>> mdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
storm::storage::BitVector trueStates(mdp->getNumberOfStates(), true);
@ -61,7 +61,7 @@ TEST(GraphTest, PerformProb01MinMax) {
mdp = nullptr;
abstractModel = storm::parser::AutoParser::parseModel(STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin4_6.tra", STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin4_6.lab", "", "");
abstractModel = storm::parser::AutoParser<>::parseModel(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::sparse::Mdp<double>> mdp2 = abstractModel->as<storm::models::sparse::Mdp<double>>();
trueStates = storm::storage::BitVector(mdp2->getNumberOfStates(), true);

4
test/performance/modelchecker/GmmxxDtmcPrctModelCheckerTest.cpp

@ -11,7 +11,7 @@
#include "src/models/sparse/StandardRewardModel.h"
TEST(GmmxxDtmcPrctlModelCheckerTest, Crowds) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds20_5.tra", STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds20_5.lab", "", "");
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Dtmc);
@ -49,7 +49,7 @@ TEST(GmmxxDtmcPrctlModelCheckerTest, Crowds) {
TEST(GmmxxDtmcPrctlModelCheckerTest, SynchronousLeader) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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(abstractModel->getType(), storm::models::ModelType::Dtmc);

4
test/performance/modelchecker/GmmxxMdpPrctlModelCheckerTest.cpp

@ -12,7 +12,7 @@
#include "src/parser/FormulaParser.h"
TEST(GmxxMdpPrctlModelCheckerTest, AsynchronousLeader) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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(abstractModel->getType(), storm::models::ModelType::Mdp);
@ -70,7 +70,7 @@ TEST(GmxxMdpPrctlModelCheckerTest, AsynchronousLeader) {
}
TEST(GmxxMdpPrctlModelCheckerTest, Consensus) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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", "");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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(abstractModel->getType(), storm::models::ModelType::Mdp);

4
test/performance/modelchecker/NativeDtmcPrctlModelCheckerTest.cpp

@ -12,7 +12,7 @@
#include "src/models/sparse/StandardRewardModel.h"
TEST(NativeDtmcPrctlModelCheckerTest, Crowds) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds20_5.tra", STORM_CPP_BASE_PATH "/examples/dtmc/crowds/crowds20_5.lab", "", "");
ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Dtmc);
@ -50,7 +50,7 @@ TEST(NativeDtmcPrctlModelCheckerTest, Crowds) {
TEST(NativeDtmcPrctlModelCheckerTest, SynchronousLeader) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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(abstractModel->getType(), storm::models::ModelType::Dtmc);

4
test/performance/modelchecker/NativeMdpPrctlModelCheckerTest.cpp

@ -13,7 +13,7 @@
#include "src/parser/FormulaParser.h"
TEST(SparseMdpPrctlModelCheckerTest, AsynchronousLeader) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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(abstractModel->getType(), storm::models::ModelType::Mdp);
@ -71,7 +71,7 @@ TEST(SparseMdpPrctlModelCheckerTest, AsynchronousLeader) {
}
TEST(SparseMdpPrctlModelCheckerTest, Consensus) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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", "");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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(abstractModel->getType(), storm::models::ModelType::Mdp);

4
test/performance/modelchecker/TopologicalValueIterationMdpPrctlModelCheckerTest.cpp

@ -12,7 +12,7 @@
#include "src/parser/FormulaParser.h"
TEST(DISABLED_TopologicalValueIterationMdpPrctlModelCheckerTest, AsynchronousLeader) {
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = storm::parser::AutoParser::parseModel(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")->as<storm::models::sparse::Mdp<double>>();
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = storm::parser::AutoParser<>::parseModel(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")->as<storm::models::sparse::Mdp<double>>();
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;
@ -59,7 +59,7 @@ TEST(DISABLED_TopologicalValueIterationMdpPrctlModelCheckerTest, Consensus) {
// Increase the maximal number of iterations, because the solver does not converge otherwise.
// This is done in the main cpp unit
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = storm::parser::AutoParser::parseModel(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", "")->as<storm::models::sparse::Mdp<double>>();
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = storm::parser::AutoParser<>::parseModel(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", "")->as<storm::models::sparse::Mdp<double>>();
// A parser that we use for conveniently constructing the formulas.
storm::parser::FormulaParser formulaParser;

4
test/performance/storage/MaximalEndComponentDecompositionTest.cpp

@ -6,7 +6,7 @@
#include "src/models/sparse/StandardRewardModel.h"
TEST(MaximalEndComponentDecomposition, AsynchronousLeader) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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::sparse::Mdp<double>> mdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
storm::storage::MaximalEndComponentDecomposition<double> mecDecomposition;
@ -17,7 +17,7 @@ TEST(MaximalEndComponentDecomposition, AsynchronousLeader) {
}
TEST(MaximalEndComponentDecomposition, Consensus) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin6_4.tra", STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin6_4.lab", "", "");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin6_4.tra", STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin6_4.lab", "", "");
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
storm::storage::MaximalEndComponentDecomposition<double> mecDecomposition;

8
test/performance/storage/StronglyConnectedComponentDecompositionTest.cpp

@ -7,7 +7,7 @@
#include "src/models/sparse/StandardRewardModel.h"
TEST(StronglyConnectedComponentDecomposition, Crowds) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>();
storm::storage::StronglyConnectedComponentDecomposition<double> sccDecomposition;
@ -25,7 +25,7 @@ TEST(StronglyConnectedComponentDecomposition, Crowds) {
}
TEST(StronglyConnectedComponentDecomposition, SynchronousLeader) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(STORM_CPP_BASE_PATH "/examples/dtmc/synchronous_leader/leader6_9.tra", STORM_CPP_BASE_PATH "/examples/dtmc/synchronous_leader/leader6_9.lab", "", "");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/dtmc/synchronous_leader/leader6_9.tra", STORM_CPP_BASE_PATH "/examples/dtmc/synchronous_leader/leader6_9.lab", "", "");
std::shared_ptr<storm::models::sparse::Dtmc<double>> dtmc = abstractModel->as<storm::models::sparse::Dtmc<double>>();
storm::storage::StronglyConnectedComponentDecomposition<double> sccDecomposition;
@ -43,7 +43,7 @@ TEST(StronglyConnectedComponentDecomposition, SynchronousLeader) {
}
TEST(StronglyConnectedComponentDecomposition, AsynchronousLeader) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(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::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(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::sparse::Mdp<double>> mdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
storm::storage::StronglyConnectedComponentDecomposition<double> sccDecomposition;
@ -61,7 +61,7 @@ TEST(StronglyConnectedComponentDecomposition, AsynchronousLeader) {
}
TEST(StronglyConnectedComponentDecomposition, Consensus) {
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser::parseModel(STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin6_4.tra", STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin6_4.lab", "", "");
std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin6_4.tra", STORM_CPP_BASE_PATH "/examples/mdp/consensus/coin6_4.lab", "", "");
std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
storm::storage::StronglyConnectedComponentDecomposition<double> sccDecomposition;

|||||||
100:0
Loading…
Cancel
Save