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
7.6 KiB

  1. #include "storm/storage/Distribution.h"
  2. #include <algorithm>
  3. #include <iostream>
  4. #include "storm/utility/macros.h"
  5. #include "storm/utility/constants.h"
  6. #include "storm/utility/ConstantsComparator.h"
  7. #include "storm/settings/SettingsManager.h"
  8. #include "storm/adapters/CarlAdapter.h"
  9. namespace storm {
  10. namespace storage {
  11. template<typename ValueType, typename StateType>
  12. Distribution<ValueType, StateType>::Distribution() {
  13. // Intentionally left empty.
  14. }
  15. template<typename ValueType, typename StateType>
  16. void Distribution<ValueType, StateType>::add(Distribution const& other) {
  17. container_type newDistribution;
  18. std::set_union(this->distribution.begin(), this->distribution.end(), other.distribution.begin(), other.distribution.end(), std::inserter(newDistribution, newDistribution.begin()));
  19. this->distribution = std::move(newDistribution);
  20. }
  21. template<typename ValueType, typename StateType>
  22. bool Distribution<ValueType, StateType>::equals(Distribution<ValueType, StateType> const& other, storm::utility::ConstantsComparator<ValueType> const& comparator) const {
  23. // We need to check equality by ourselves, because we need to account for epsilon differences.
  24. if (this->distribution.size() != other.distribution.size()) {
  25. return false;
  26. }
  27. auto first1 = this->distribution.begin();
  28. auto last1 = this->distribution.end();
  29. auto first2 = other.distribution.begin();
  30. for (; first1 != last1; ++first1, ++first2) {
  31. if (first1->first != first2->first) {
  32. return false;
  33. }
  34. if (!comparator.isEqual(first1->second, first2->second)) {
  35. return false;
  36. }
  37. }
  38. return true;
  39. }
  40. template<typename ValueType, typename StateType>
  41. void Distribution<ValueType, StateType>::addProbability(StateType const& state, ValueType const& probability) {
  42. auto it = this->distribution.find(state);
  43. if (it == this->distribution.end()) {
  44. this->distribution.emplace_hint(it, state, probability);
  45. } else {
  46. it->second += probability;
  47. }
  48. }
  49. template<typename ValueType, typename StateType>
  50. void Distribution<ValueType, StateType>::removeProbability(StateType const& state, ValueType const& probability, storm::utility::ConstantsComparator<ValueType> const& comparator) {
  51. auto it = this->distribution.find(state);
  52. STORM_LOG_ASSERT(it != this->distribution.end(), "Cannot remove probability, because the state is not in the support of the distribution.");
  53. it->second -= probability;
  54. if (comparator.isZero(it->second)) {
  55. this->distribution.erase(it);
  56. }
  57. }
  58. template<typename ValueType, typename StateType>
  59. void Distribution<ValueType, StateType>::shiftProbability(StateType const& fromState, StateType const& toState, ValueType const& probability, storm::utility::ConstantsComparator<ValueType> const& comparator) {
  60. removeProbability(fromState, probability, comparator);
  61. addProbability(toState, probability);
  62. }
  63. template<typename ValueType, typename StateType>
  64. typename Distribution<ValueType, StateType>::iterator Distribution<ValueType, StateType>::begin() {
  65. return this->distribution.begin();
  66. }
  67. template<typename ValueType, typename StateType>
  68. typename Distribution<ValueType, StateType>::const_iterator Distribution<ValueType, StateType>::begin() const {
  69. return this->distribution.begin();
  70. }
  71. template<typename ValueType, typename StateType>
  72. typename Distribution<ValueType, StateType>::const_iterator Distribution<ValueType, StateType>::cbegin() const {
  73. return this->begin();
  74. }
  75. template<typename ValueType, typename StateType>
  76. typename Distribution<ValueType, StateType>::iterator Distribution<ValueType, StateType>::end() {
  77. return this->distribution.end();
  78. }
  79. template<typename ValueType, typename StateType>
  80. typename Distribution<ValueType, StateType>::const_iterator Distribution<ValueType, StateType>::end() const {
  81. return this->distribution.end();
  82. }
  83. template<typename ValueType, typename StateType>
  84. typename Distribution<ValueType, StateType>::const_iterator Distribution<ValueType, StateType>::cend() const {
  85. return this->end();
  86. }
  87. template<typename ValueType, typename StateType>
  88. void Distribution<ValueType, StateType>::scale(StateType const& state) {
  89. auto probabilityIterator = this->distribution.find(state);
  90. if (probabilityIterator != this->distribution.end()) {
  91. ValueType scaleValue = storm::utility::one<ValueType>() / probabilityIterator->second;
  92. this->distribution.erase(probabilityIterator);
  93. for (auto& entry : this->distribution) {
  94. entry.second *= scaleValue;
  95. }
  96. }
  97. }
  98. template<typename ValueType, typename StateType>
  99. std::size_t Distribution<ValueType, StateType>::size() const {
  100. return this->distribution.size();
  101. }
  102. template<typename ValueType, typename StateType>
  103. std::ostream& operator<<(std::ostream& out, Distribution<ValueType, StateType> const& distribution) {
  104. out << "{";
  105. for (auto const& entry : distribution) {
  106. out << "[" << entry.second << ": " << entry.first << "], ";
  107. }
  108. out << "}";
  109. return out;
  110. }
  111. template<typename ValueType, typename StateType>
  112. bool Distribution<ValueType, StateType>::less(Distribution<ValueType, StateType> const& other, storm::utility::ConstantsComparator<ValueType> const& comparator) const {
  113. if (this->size() != other.size()) {
  114. return this->size() < other.size();
  115. }
  116. auto firstIt = this->begin();
  117. auto firstIte = this->end();
  118. auto secondIt = other.begin();
  119. for (; firstIt != firstIte; ++firstIt, ++secondIt) {
  120. // If the two blocks already differ, we can decide which distribution is smaller.
  121. if (firstIt->first != secondIt->first) {
  122. return firstIt->first < secondIt->first;
  123. }
  124. // If the blocks are the same, but the probability differs, we can also decide which distribution is smaller.
  125. if (!comparator.isEqual(firstIt->second, secondIt->second)) {
  126. return comparator.isLess(firstIt->second, secondIt->second);
  127. }
  128. }
  129. return false;
  130. }
  131. template class Distribution<double>;
  132. template std::ostream& operator<<(std::ostream& out, Distribution<double> const& distribution);
  133. #ifdef STORM_HAVE_CARL
  134. template class Distribution<storm::RationalNumber>;
  135. template std::ostream& operator<<(std::ostream& out, Distribution<storm::RationalNumber> const& distribution);
  136. template class Distribution<storm::RationalFunction>;
  137. template std::ostream& operator<<(std::ostream& out, Distribution<storm::RationalFunction> const& distribution);
  138. #endif
  139. }
  140. }