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.

256 lines
6.9 KiB

  1. /*
  2. * This file is part of the program ltl2dstar (http://www.ltl2dstar.de/).
  3. * Copyright (C) 2005-2007 Joachim Klein <j.klein@ltl2dstar.de>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. */
  18. #ifndef NBASTUTTERCLOSURE_HPP
  19. #define NBASTUTTERCLOSURE_HPP
  20. /** @file
  21. * Provides NBAStutterClosure.
  22. */
  23. #include "GraphAlgorithms.hpp"
  24. #include "NBAAnalysis.hpp"
  25. #include "APElement.hpp"
  26. #include <memory>
  27. /**
  28. * Calculate the stutter closure for an NBA.
  29. */
  30. class NBAStutterClosure {
  31. public:
  32. /** Calculate the stutter closure for the NBA, for all symbols.
  33. * @param nba the NBA
  34. */
  35. template<typename NBA_t>
  36. static std::shared_ptr<NBA_t> stutter_closure(NBA_t& nba) {
  37. APSet_cp apset=nba.getAPSet_cp();
  38. std::shared_ptr<NBA_t> nba_result_ptr(new NBA_t(apset));
  39. NBA_t& result=*nba_result_ptr;
  40. unsigned int element_count=apset->powersetSize();
  41. assert(nba.getStartState());
  42. unsigned int start_state=nba.getStartState()->getName();
  43. for (unsigned int i=0;i<nba.size();i++) {
  44. unsigned int st=result.nba_i_newState();
  45. assert(st==i);
  46. if (st==start_state) {
  47. result.setStartState(result[st]);
  48. }
  49. if (nba[st]->isFinal()) {
  50. result[st]->setFinal(true);
  51. }
  52. }
  53. for (unsigned int i=0;i<nba.size();i++) {
  54. for (unsigned int j=0;j<element_count;j++) {
  55. unsigned int st=result.nba_i_newState();
  56. assert( st == nba.size() + (i*element_count)+j);
  57. result[st]->addEdge(j, *(result[i]));
  58. result[st]->addEdge(j, *(result[st]));
  59. }
  60. }
  61. std::vector< std::vector<BitSet>* > reachable;
  62. reachable.resize(element_count);
  63. for (unsigned int j=0; j<element_count; j++) {
  64. NBAEdgeSuccessors<NBA_t> edge_successor(j);
  65. SCCs scc;
  66. GraphAlgorithms<NBA_t, NBAEdgeSuccessors<NBA_t> >::calculateSCCs(nba,
  67. scc,
  68. true,
  69. edge_successor);
  70. reachable[j]=scc.getReachabilityForAllStates();
  71. #ifdef VERBOSE
  72. std::cerr << "SCCs for " << APElement(j).toString(*apset) << std::endl;
  73. std::cerr << scc << std::endl;
  74. std::cerr << " Reachability: "<< std::endl;
  75. std::vector<BitSet>& reach=*reachable[j];
  76. for (unsigned int t=0; t < reach.size(); t++) {
  77. std::cerr << t << " -> " << reach[t] << std::endl;
  78. }
  79. std::cerr << " ---\n";
  80. #endif
  81. }
  82. for (unsigned int i=0;i<nba.size();i++) {
  83. typename NBA_t::state_type* from=result[i];
  84. for (unsigned int j=0;j<element_count;j++) {
  85. BitSet result_to;
  86. BitSet* to=nba[i]->getEdge(j);
  87. for (BitSetIterator it=BitSetIterator(*to);
  88. it!=BitSetIterator::end(*to);
  89. ++it) {
  90. unsigned int to_state=*it;
  91. // We can go directly to the original state
  92. result_to.set(to_state);
  93. // We can also go to the corresponding stutter state instead
  94. unsigned int stutter_state=nba.size() + (to_state*element_count)+j;
  95. result_to.set(stutter_state);
  96. // ... and then we can go directly to all the states that are j-reachable from to
  97. result_to.Union((*(reachable[j]))[to_state]);
  98. }
  99. *(from->getEdge(j)) = result_to;
  100. }
  101. }
  102. for (unsigned int i=0;
  103. i<reachable.size();
  104. ++i) {
  105. delete reachable[i];
  106. }
  107. return nba_result_ptr;
  108. }
  109. /** Calculate the stutter closure for the NBA, for a certain symbol.
  110. * @param nba the NBA
  111. * @param label the symbol for which to perform the stutter closure
  112. */
  113. template<typename NBA_t>
  114. static std::shared_ptr<NBA_t> stutter_closure(NBA_t& nba, APElement label) {
  115. APSet_cp apset=nba.getAPSet_cp();
  116. std::shared_ptr<NBA_t> nba_result_ptr(new NBA_t(apset));
  117. NBA_t& result=*nba_result_ptr;
  118. unsigned int element_count=apset->powersetSize();
  119. assert(nba.getStartState());
  120. unsigned int start_state=nba.getStartState()->getName();
  121. for (unsigned int i=0;i<nba.size();i++) {
  122. unsigned int st=result.nba_i_newState();
  123. assert(st==i);
  124. if (st==start_state) {
  125. result.setStartState(result[st]);
  126. }
  127. if (nba[st]->isFinal()) {
  128. result[st]->setFinal(true);
  129. }
  130. }
  131. for (unsigned int i=0;i<nba.size();i++) {
  132. unsigned int st=result.nba_i_newState();
  133. assert( st == nba.size() + i);
  134. result[st]->addEdge(label, *(result[i]));
  135. result[st]->addEdge(label, *(result[st]));
  136. }
  137. std::vector<BitSet>* reachable;
  138. NBAEdgeSuccessors<NBA_t> edge_successor(label);
  139. SCCs scc;
  140. GraphAlgorithms<NBA_t, NBAEdgeSuccessors<NBA_t> >::calculateSCCs(nba,
  141. scc,
  142. true,
  143. edge_successor);
  144. reachable=scc.getReachabilityForAllStates();
  145. // std::cerr << "SCCs for " << label.toString(*apset) << std::endl;
  146. // std::cerr << scc << std::endl;
  147. // std::cerr << " Reachability: "<< std::endl;
  148. // for (unsigned int t=0; t < reachable->size(); t++) {
  149. // std::cerr << t << " -> " << (*reachable)[t] << std::endl;
  150. // }
  151. // std::cerr << " ---\n";
  152. for (unsigned int i=0;i<nba.size();i++) {
  153. typename NBA_t::state_type* from=result[i];
  154. for (unsigned int j=0;j<element_count;j++) {
  155. BitSet result_to;
  156. BitSet* to=nba[i]->getEdge(j);
  157. if (j!=label) {
  158. result_to=*to;
  159. } else {
  160. for (BitSetIterator it=BitSetIterator(*to);
  161. it!=BitSetIterator::end(*to);
  162. ++it) {
  163. unsigned int to_state=*it;
  164. // We can go directly to the original state
  165. result_to.set(to_state);
  166. // We can also go to the corresponding stutter state instead
  167. unsigned int stutter_state=nba.size() + to_state;
  168. result_to.set(stutter_state);
  169. // ... and then we can go directly to all the states that are j-reachable from to
  170. result_to.Union((*reachable)[to_state]);
  171. }
  172. }
  173. *(from->getEdge(j)) = result_to;
  174. }
  175. }
  176. delete reachable;
  177. return nba_result_ptr;
  178. }
  179. private:
  180. /** The successors reachable via a certain label */
  181. template <typename NBA_t>
  182. class NBAEdgeSuccessors {
  183. public:
  184. typedef BitSetIterator successor_iterator;
  185. NBAEdgeSuccessors(APElement label) : _label(label) {};
  186. successor_iterator begin(NBA_t& graph, unsigned int v) {
  187. return BitSetIterator(*(graph[v]->getEdge(_label)));
  188. }
  189. successor_iterator end(NBA_t& graph, unsigned int v) {
  190. return BitSetIterator::end(*(graph[v]->getEdge(_label)));
  191. }
  192. private:
  193. APElement _label;
  194. };
  195. };
  196. #endif