366 lines
16 KiB

  1. #include "DFTState.h"
  2. #include "DFTElements.h"
  3. #include "DFT.h"
  4. namespace storm {
  5. namespace storage {
  6. template<typename ValueType>
  7. DFTState<ValueType>::DFTState(DFT<ValueType> const& dft, DFTStateGenerationInfo const& stateGenerationInfo, size_t id) : mStatus(dft.stateVectorSize()), mId(id), mDft(dft), mStateGenerationInfo(stateGenerationInfo) {
  8. // Initialize uses
  9. for(size_t id : mDft.getSpareIndices()) {
  10. std::shared_ptr<DFTGate<ValueType> const> elem = mDft.getGate(id);
  11. assert(elem->isSpareGate());
  12. assert(elem->nrChildren() > 0);
  13. this->setUses(id, elem->children()[0]->id());
  14. }
  15. // Initialize activation
  16. propagateActivation(mDft.getTopLevelIndex());
  17. std::vector<size_t> alwaysActiveBEs = dft.nonColdBEs();
  18. mIsCurrentlyFailableBE.insert(mIsCurrentlyFailableBE.end(), alwaysActiveBEs.begin(), alwaysActiveBEs.end());
  19. }
  20. template<typename ValueType>
  21. DFTState<ValueType>::DFTState(storm::storage::BitVector const& status, DFT<ValueType> const& dft, DFTStateGenerationInfo const& stateGenerationInfo, size_t id) : mStatus(status), mId(id), mDft(dft), mStateGenerationInfo(stateGenerationInfo) {
  22. for(size_t index = 0; index < mDft.nrElements(); ++index) {
  23. // Initialize currently failable BE
  24. if (mDft.isBasicElement(index) && isOperational(index)) {
  25. std::shared_ptr<const DFTBE<ValueType>> be = mDft.getBasicElement(index);
  26. if ((!be->isColdBasicElement() && be->canFail()) || !mDft.hasRepresentant(index) || isActive(mDft.getRepresentant(index)->id())) {
  27. mIsCurrentlyFailableBE.push_back(index);
  28. STORM_LOG_TRACE("Currently failable: " << mDft.getBasicElement(index)->toString());
  29. }
  30. } else if (mDft.getElement(index)->isSpareGate()) {
  31. // Initialize used representants
  32. uint_fast64_t useId = uses(index);
  33. mUsedRepresentants.push_back(useId);
  34. STORM_LOG_TRACE("Spare " << index << " uses " << useId);
  35. }
  36. }
  37. // Initialize failable dependencies
  38. for (size_t dependencyId : mDft.getDependencies()) {
  39. std::shared_ptr<DFTDependency<ValueType> const> dependency = mDft.getDependency(dependencyId);
  40. assert(dependencyId == dependency->id());
  41. if (hasFailed(dependency->triggerEvent()->id()) && getElementState(dependency->dependentEvent()->id()) == DFTElementState::Operational) {
  42. mFailableDependencies.push_back(dependencyId);
  43. STORM_LOG_TRACE("New dependency failure: " << dependency->toString());
  44. }
  45. }
  46. }
  47. template<typename ValueType>
  48. DFTElementState DFTState<ValueType>::getElementState(size_t id) const {
  49. return static_cast<DFTElementState>(getElementStateInt(id));
  50. }
  51. template<typename ValueType>
  52. DFTDependencyState DFTState<ValueType>::getDependencyState(size_t id) const {
  53. return static_cast<DFTDependencyState>(getElementStateInt(id));
  54. }
  55. template<typename ValueType>
  56. int DFTState<ValueType>::getElementStateInt(size_t id) const {
  57. return mStatus.getAsInt(mStateGenerationInfo.getStateIndex(id), 2);
  58. }
  59. template<typename ValueType>
  60. int DFTState<ValueType>::getElementStateInt(storm::storage::BitVector const& state, size_t indexId) {
  61. return state.getAsInt(indexId, 2);
  62. }
  63. template<typename ValueType>
  64. size_t DFTState<ValueType>::getId() const {
  65. return mId;
  66. }
  67. template<typename ValueType>
  68. void DFTState<ValueType>::setId(size_t id) {
  69. mId = id;
  70. }
  71. template<typename ValueType>
  72. bool DFTState<ValueType>::isOperational(size_t id) const {
  73. return getElementState(id) == DFTElementState::Operational;
  74. }
  75. template<typename ValueType>
  76. bool DFTState<ValueType>::hasFailed(size_t id) const {
  77. return mStatus[mStateGenerationInfo.getStateIndex(id)];
  78. }
  79. template<typename ValueType>
  80. bool DFTState<ValueType>::hasFailed(storm::storage::BitVector const& state, size_t indexId) {
  81. return state[indexId];
  82. }
  83. template<typename ValueType>
  84. bool DFTState<ValueType>::isFailsafe(size_t id) const {
  85. return mStatus[mStateGenerationInfo.getStateIndex(id)+1];
  86. }
  87. template<typename ValueType>
  88. bool DFTState<ValueType>::isFailsafe(storm::storage::BitVector const& state, size_t indexId) {
  89. return state[indexId+1];
  90. }
  91. template<typename ValueType>
  92. bool DFTState<ValueType>::dontCare(size_t id) const {
  93. return getElementState(id) == DFTElementState::DontCare;
  94. }
  95. template<typename ValueType>
  96. bool DFTState<ValueType>::dependencyTriggered(size_t id) const {
  97. return getElementStateInt(id) > 0;
  98. }
  99. template<typename ValueType>
  100. bool DFTState<ValueType>::dependencySuccessful(size_t id) const {
  101. return mStatus[mStateGenerationInfo.getStateIndex(id)];
  102. }
  103. template<typename ValueType>
  104. bool DFTState<ValueType>::dependencyUnsuccessful(size_t id) const {
  105. return mStatus[mStateGenerationInfo.getStateIndex(id)+1];
  106. }
  107. template<typename ValueType>
  108. void DFTState<ValueType>::setFailed(size_t id) {
  109. mStatus.set(mStateGenerationInfo.getStateIndex(id));
  110. }
  111. template<typename ValueType>
  112. void DFTState<ValueType>::setFailsafe(size_t id) {
  113. mStatus.set(mStateGenerationInfo.getStateIndex(id)+1);
  114. }
  115. template<typename ValueType>
  116. void DFTState<ValueType>::setDontCare(size_t id) {
  117. if (mDft.isRepresentative(id)) {
  118. // Activate dont care element
  119. activate(id);
  120. }
  121. mStatus.setFromInt(mStateGenerationInfo.getStateIndex(id), 2, static_cast<uint_fast64_t>(DFTElementState::DontCare) );
  122. }
  123. template<typename ValueType>
  124. void DFTState<ValueType>::setDependencySuccessful(size_t id) {
  125. // Only distinguish between passive and dont care dependencies
  126. //mStatus.set(mStateGenerationInfo.getStateIndex(id));
  127. setDependencyDontCare(id);
  128. }
  129. template<typename ValueType>
  130. void DFTState<ValueType>::setDependencyUnsuccessful(size_t id) {
  131. // Only distinguish between passive and dont care dependencies
  132. //mStatus.set(mStateGenerationInfo.getStateIndex(id)+1);
  133. setDependencyDontCare(id);
  134. }
  135. template<typename ValueType>
  136. void DFTState<ValueType>::setDependencyDontCare(size_t id) {
  137. mStatus.setFromInt(mStateGenerationInfo.getStateIndex(id), 2, static_cast<uint_fast64_t>(DFTDependencyState::DontCare));
  138. }
  139. template<typename ValueType>
  140. void DFTState<ValueType>::beNoLongerFailable(size_t id) {
  141. auto it = std::find(mIsCurrentlyFailableBE.begin(), mIsCurrentlyFailableBE.end(), id);
  142. if(it != mIsCurrentlyFailableBE.end()) {
  143. mIsCurrentlyFailableBE.erase(it);
  144. }
  145. }
  146. template<typename ValueType>
  147. bool DFTState<ValueType>::updateFailableDependencies(size_t id) {
  148. if (!hasFailed(id)) {
  149. return false;
  150. }
  151. for (auto dependency : mDft.getElement(id)->outgoingDependencies()) {
  152. assert(dependency->triggerEvent()->id() == id);
  153. if (getElementState(dependency->dependentEvent()->id()) == DFTElementState::Operational) {
  154. assert(!isFailsafe(dependency->dependentEvent()->id()));
  155. mFailableDependencies.push_back(dependency->id());
  156. STORM_LOG_TRACE("New dependency failure: " << dependency->toString());
  157. }
  158. }
  159. return nrFailableDependencies() > 0;
  160. }
  161. template<typename ValueType>
  162. void DFTState<ValueType>::updateDontCareDependencies(size_t id) {
  163. assert(mDft.isBasicElement(id));
  164. assert(hasFailed(id));
  165. for (auto dependency : mDft.getBasicElement(id)->ingoingDependencies()) {
  166. assert(dependency->dependentEvent()->id() == id);
  167. setDependencyDontCare(dependency->id());
  168. }
  169. }
  170. template<typename ValueType>
  171. std::pair<std::shared_ptr<DFTBE<ValueType> const>, bool> DFTState<ValueType>::letNextBEFail(size_t index)
  172. {
  173. STORM_LOG_TRACE("currently failable: " << getCurrentlyFailableString());
  174. if (nrFailableDependencies() > 0) {
  175. // Consider failure due to dependency
  176. assert(index < nrFailableDependencies());
  177. std::shared_ptr<DFTDependency<ValueType> const> dependency = mDft.getDependency(getDependencyId(index));
  178. std::pair<std::shared_ptr<DFTBE<ValueType> const>,bool> res(mDft.getBasicElement(dependency->dependentEvent()->id()), true);
  179. mFailableDependencies.erase(mFailableDependencies.begin() + index);
  180. setFailed(res.first->id());
  181. setDependencySuccessful(dependency->id());
  182. return res;
  183. } else {
  184. // Consider "normal" failure
  185. assert(index < nrFailableBEs());
  186. std::pair<std::shared_ptr<DFTBE<ValueType> const>,bool> res(mDft.getBasicElement(mIsCurrentlyFailableBE[index]), false);
  187. assert(res.first->canFail());
  188. mIsCurrentlyFailableBE.erase(mIsCurrentlyFailableBE.begin() + index);
  189. setFailed(res.first->id());
  190. return res;
  191. }
  192. }
  193. template<typename ValueType>
  194. void DFTState<ValueType>::letDependencyBeUnsuccessful(size_t index) {
  195. assert(nrFailableDependencies() > 0 && index < nrFailableDependencies());
  196. std::shared_ptr<DFTDependency<ValueType> const> dependency = mDft.getDependency(getDependencyId(index));
  197. mFailableDependencies.erase(mFailableDependencies.begin() + index);
  198. setDependencyUnsuccessful(dependency->id());
  199. }
  200. template<typename ValueType>
  201. void DFTState<ValueType>::activate(size_t repr) {
  202. size_t activationIndex = mStateGenerationInfo.getSpareActivationIndex(repr);
  203. mStatus.set(activationIndex);
  204. }
  205. template<typename ValueType>
  206. bool DFTState<ValueType>::isActive(size_t id) const {
  207. assert(mDft.isRepresentative(id));
  208. return mStatus[mStateGenerationInfo.getSpareActivationIndex(id)];
  209. }
  210. template<typename ValueType>
  211. void DFTState<ValueType>::propagateActivation(size_t representativeId) {
  212. if (representativeId != mDft.getTopLevelIndex()) {
  213. activate(representativeId);
  214. }
  215. for(size_t elem : mDft.module(representativeId)) {
  216. if(mDft.isBasicElement(elem) && isOperational(elem)) {
  217. std::shared_ptr<const DFTBE<ValueType>> be = mDft.getBasicElement(elem);
  218. if (be->isColdBasicElement() && be->canFail()) {
  219. mIsCurrentlyFailableBE.push_back(elem);
  220. }
  221. } else if (mDft.getElement(elem)->isSpareGate() && !isActive(uses(elem))) {
  222. propagateActivation(uses(elem));
  223. }
  224. }
  225. }
  226. template<typename ValueType>
  227. uint_fast64_t DFTState<ValueType>::uses(size_t id) const {
  228. size_t nrUsedChild = extractUses(mStateGenerationInfo.getSpareUsageIndex(id));
  229. if (nrUsedChild == mDft.getMaxSpareChildCount()) {
  230. return id;
  231. } else {
  232. return mDft.getChild(id, nrUsedChild);
  233. }
  234. }
  235. template<typename ValueType>
  236. uint_fast64_t DFTState<ValueType>::extractUses(size_t from) const {
  237. assert(mStateGenerationInfo.usageInfoBits() < 64);
  238. return mStatus.getAsInt(from, mStateGenerationInfo.usageInfoBits());
  239. }
  240. template<typename ValueType>
  241. bool DFTState<ValueType>::isUsed(size_t child) const {
  242. return (std::find(mUsedRepresentants.begin(), mUsedRepresentants.end(), child) != mUsedRepresentants.end());
  243. }
  244. template<typename ValueType>
  245. void DFTState<ValueType>::setUses(size_t spareId, size_t child) {
  246. mStatus.setFromInt(mStateGenerationInfo.getSpareUsageIndex(spareId), mStateGenerationInfo.usageInfoBits(), mDft.getNrChild(spareId, child));
  247. mUsedRepresentants.push_back(child);
  248. }
  249. template<typename ValueType>
  250. void DFTState<ValueType>::finalizeUses(size_t spareId) {
  251. assert(hasFailed(spareId));
  252. mStatus.setFromInt(mStateGenerationInfo.getSpareUsageIndex(spareId), mStateGenerationInfo.usageInfoBits(), mDft.getMaxSpareChildCount());
  253. }
  254. template<typename ValueType>
  255. bool DFTState<ValueType>::hasOperationalPostSeqElements(size_t id) const {
  256. assert(!mDft.isDependency(id));
  257. assert(!mDft.isRestriction(id));
  258. auto const& postIds = mStateGenerationInfo.seqRestrictionPostElements(id);
  259. for(size_t id : postIds) {
  260. if(isOperational(id)) {
  261. return true;
  262. }
  263. }
  264. return false;
  265. }
  266. template<typename ValueType>
  267. bool DFTState<ValueType>::claimNew(size_t spareId, size_t currentlyUses, std::vector<std::shared_ptr<DFTElement<ValueType>>> const& children) {
  268. auto it = children.begin();
  269. while ((*it)->id() != currentlyUses) {
  270. assert(it != children.end());
  271. ++it;
  272. }
  273. ++it;
  274. while(it != children.end()) {
  275. size_t childId = (*it)->id();
  276. if(!hasFailed(childId) && !isUsed(childId)) {
  277. setUses(spareId, childId);
  278. if(isActive(currentlyUses)) {
  279. propagateActivation(childId);
  280. }
  281. return true;
  282. }
  283. ++it;
  284. }
  285. return false;
  286. }
  287. template<typename ValueType>
  288. bool DFTState<ValueType>::orderBySymmetry() {
  289. bool changed = false;
  290. for (size_t pos = 0; pos < mStateGenerationInfo.getSymmetrySize(); ++pos) {
  291. // Check each symmetry
  292. size_t length = mStateGenerationInfo.getSymmetryLength(pos);
  293. std::vector<size_t> symmetryIndices = mStateGenerationInfo.getSymmetryIndices(pos);
  294. // Sort symmetry group in decreasing order by bubble sort
  295. // TODO use better algorithm?
  296. size_t tmp;
  297. size_t n = symmetryIndices.size();
  298. do {
  299. tmp = 0;
  300. for (size_t i = 1; i < n; ++i) {
  301. if (mStatus.compareAndSwap(symmetryIndices[i-1], symmetryIndices[i], length)) {
  302. tmp = i;
  303. changed = true;
  304. }
  305. }
  306. n = tmp;
  307. } while (n > 0);
  308. }
  309. return changed;
  310. }
  311. // Explicitly instantiate the class.
  312. template class DFTState<double>;
  313. #ifdef STORM_HAVE_CARL
  314. template class DFTState<RationalFunction>;
  315. #endif
  316. }
  317. }