You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

170 lines
9.9 KiB

  1. #include "storm/builder/jit/ModelComponentsBuilder.h"
  2. #include "storm/models/sparse/StateLabeling.h"
  3. #include "storm/models/sparse/Dtmc.h"
  4. #include "storm/models/sparse/Ctmc.h"
  5. #include "storm/models/sparse/Mdp.h"
  6. #include "storm/models/sparse/MarkovAutomaton.h"
  7. #include "storm/models/sparse/StandardRewardModel.h"
  8. #include "storm/builder/RewardModelBuilder.h"
  9. #include "storm/settings/SettingsManager.h"
  10. #include "storm/settings/modules/CoreSettings.h"
  11. #include "storm/exceptions/WrongFormatException.h"
  12. #include "storm/utility/macros.h"
  13. #include "storm/utility/constants.h"
  14. namespace storm {
  15. namespace builder {
  16. namespace jit {
  17. template <typename IndexType, typename ValueType>
  18. ModelComponentsBuilder<IndexType, ValueType>::ModelComponentsBuilder(storm::jani::ModelType const& modelType) : modelType(modelType), isDeterministicModel(storm::jani::isDeterministicModel(modelType)), isDiscreteTimeModel(storm::jani::isDiscreteTimeModel(modelType)), currentRowGroup(0), currentRow(0), markovianStates(nullptr), transitionMatrixBuilder(std::make_unique<storm::storage::SparseMatrixBuilder<ValueType>>(0, 0, 0, true, !isDeterministicModel)) {
  19. if (modelType == storm::jani::ModelType::MA) {
  20. markovianStates = std::make_unique<storm::storage::BitVector>(10);
  21. }
  22. dontFixDeadlocks = storm::settings::getModule<storm::settings::modules::CoreSettings>().isDontFixDeadlocksSet();
  23. }
  24. template <typename IndexType, typename ValueType>
  25. ModelComponentsBuilder<IndexType, ValueType>::~ModelComponentsBuilder() {
  26. // Intentionally left empty.
  27. }
  28. template <typename IndexType, typename ValueType>
  29. void ModelComponentsBuilder<IndexType, ValueType>::addStateBehaviour(IndexType const& stateId, StateBehaviour<IndexType, ValueType>& behaviour) {
  30. // Compress the choices and reduce them depending on the model type.
  31. behaviour.reduce(modelType);
  32. STORM_LOG_ASSERT(stateId == currentRowGroup, "Expected states in different order.");
  33. if (!isDeterministicModel) {
  34. transitionMatrixBuilder->newRowGroup(currentRow);
  35. }
  36. if (!behaviour.empty()) {
  37. // Add state reward entries.
  38. auto stateRewardIt = behaviour.getStateRewards().begin();
  39. for (auto& rewardModelBuilder : rewardModelBuilders) {
  40. if (rewardModelBuilder.hasStateRewards()) {
  41. rewardModelBuilder.addStateReward(*stateRewardIt);
  42. ++stateRewardIt;
  43. }
  44. }
  45. for (auto const& choice : behaviour.getChoices()) {
  46. // Add the elements to the transition matrix.
  47. for (auto const& element : choice.getDistribution()) {
  48. transitionMatrixBuilder->addNextValue(currentRow, element.getIndex(), element.getValue());
  49. }
  50. // Add state-action reward entries.
  51. auto stateActionRewardIt = choice.getRewards().begin();
  52. for (auto& rewardModelBuilder : rewardModelBuilders) {
  53. if (rewardModelBuilder.hasStateActionRewards()) {
  54. rewardModelBuilder.addStateActionReward(*stateActionRewardIt);
  55. ++stateActionRewardIt;
  56. }
  57. }
  58. // Proceed to next row.
  59. ++currentRow;
  60. }
  61. // Mark the state as Markovian, if there is at least one Markovian choice.
  62. if (markovianStates) {
  63. markovianStates->grow(currentRowGroup + 1, false);
  64. markovianStates->set(currentRowGroup, behaviour.isMarkovianOrHybrid());
  65. }
  66. } else {
  67. if (behaviour.isExpanded() && dontFixDeadlocks) {
  68. STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Error while creating sparse matrix from JANI model: found deadlock state and fixing deadlocks was explicitly disabled.");
  69. } else {
  70. // Add the self-loop in the transition matrix.
  71. transitionMatrixBuilder->addNextValue(currentRow, currentRowGroup, storm::utility::one<ValueType>());
  72. ++currentRow;
  73. // Add the appropriate entries for the reward models.
  74. auto stateRewardIt = behaviour.getStateRewards().begin();
  75. for (auto& rewardModelBuilder : rewardModelBuilders) {
  76. if (rewardModelBuilder.hasStateRewards()) {
  77. rewardModelBuilder.addStateReward(*stateRewardIt);
  78. ++stateRewardIt;
  79. }
  80. if (rewardModelBuilder.hasStateActionRewards()) {
  81. rewardModelBuilder.addStateActionReward(storm::utility::zero<ValueType>());
  82. }
  83. }
  84. // Mark the state as Markovian.
  85. if (markovianStates) {
  86. markovianStates->grow(currentRowGroup + 1, false);
  87. markovianStates->set(currentRowGroup);
  88. }
  89. }
  90. }
  91. ++currentRowGroup;
  92. }
  93. template <typename IndexType, typename ValueType>
  94. storm::models::sparse::Model<ValueType, storm::models::sparse::StandardRewardModel<ValueType>>* ModelComponentsBuilder<IndexType, ValueType>::build(IndexType const& stateCount) {
  95. storm::storage::SparseMatrix<ValueType> transitionMatrix = this->transitionMatrixBuilder->build();
  96. // Start by building the labeling object.
  97. storm::models::sparse::StateLabeling stateLabeling(stateCount);
  98. for (auto& label : labels) {
  99. stateLabeling.addLabel(label.first, std::move(label.second));
  100. }
  101. // Then build all reward models.
  102. std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<ValueType>> rewardModels;
  103. for (auto& rewardModelBuilder : rewardModelBuilders) {
  104. rewardModels.emplace(rewardModelBuilder.getName(), rewardModelBuilder.build(transitionMatrix.getRowCount(), transitionMatrix.getColumnCount(), transitionMatrix.getRowGroupCount()));
  105. }
  106. if (modelType == storm::jani::ModelType::DTMC) {
  107. return new storm::models::sparse::Dtmc<ValueType, storm::models::sparse::StandardRewardModel<ValueType>>(std::move(transitionMatrix), std::move(stateLabeling), std::move(rewardModels));
  108. } else if (modelType == storm::jani::ModelType::CTMC) {
  109. return new storm::models::sparse::Ctmc<ValueType, storm::models::sparse::StandardRewardModel<ValueType>>(std::move(transitionMatrix), std::move(stateLabeling), std::move(rewardModels));
  110. } else if (modelType == storm::jani::ModelType::MDP) {
  111. return new storm::models::sparse::Mdp<ValueType, storm::models::sparse::StandardRewardModel<ValueType>>(std::move(transitionMatrix), std::move(stateLabeling), std::move(rewardModels));
  112. } else {
  113. std::vector<ValueType> exitRates(transitionMatrix.getRowGroupCount(), storm::utility::zero<ValueType>());
  114. for (auto state : *markovianStates) {
  115. for (auto const& element : transitionMatrix.getRow(transitionMatrix.getRowGroupIndices()[state])) {
  116. exitRates[state] += element.getValue();
  117. }
  118. for (auto& element : transitionMatrix.getRow(transitionMatrix.getRowGroupIndices()[state])) {
  119. element.setValue(element.getValue() / exitRates[state]);
  120. }
  121. }
  122. return new storm::models::sparse::MarkovAutomaton<ValueType, storm::models::sparse::StandardRewardModel<ValueType>>(std::move(transitionMatrix), std::move(stateLabeling), std::move(*markovianStates), std::move(exitRates), std::move(rewardModels));
  123. }
  124. }
  125. template <typename IndexType, typename ValueType>
  126. void ModelComponentsBuilder<IndexType, ValueType>::registerRewardModel(RewardModelInformation const& rewardModelInformation) {
  127. rewardModelBuilders.emplace_back(rewardModelInformation);
  128. }
  129. template <typename IndexType, typename ValueType>
  130. void ModelComponentsBuilder<IndexType, ValueType>::registerLabel(std::string const& name, IndexType const& stateCount) {
  131. labels.emplace_back(name, storm::storage::BitVector(stateCount));
  132. }
  133. template <typename IndexType, typename ValueType>
  134. void ModelComponentsBuilder<IndexType, ValueType>::addLabel(IndexType const& stateId, IndexType const& labelIndex) {
  135. labels[labelIndex].second.set(stateId);
  136. }
  137. template class ModelComponentsBuilder<uint32_t, double>;
  138. template class ModelComponentsBuilder<uint32_t, storm::RationalNumber>;
  139. template class ModelComponentsBuilder<uint32_t, storm::RationalFunction>;
  140. }
  141. }
  142. }