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.

305 lines
8.5 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 DRA_H
  19. #define DRA_H
  20. /** @file
  21. * Provide class DRA<> which can store a deterministic Rabin or Streett automaton.
  22. */
  23. #include "DA.hpp"
  24. #include "DA_State.hpp"
  25. #include "RabinAcceptance.hpp"
  26. #include "APSet.hpp"
  27. #include "APElement.hpp"
  28. #include "DAUnionAlgorithm.hpp"
  29. #include "common/Index.hpp"
  30. #include "common/Exceptions.hpp"
  31. #include <iterator>
  32. #include <iostream>
  33. #include <map>
  34. #include <string>
  35. #include <memory>
  36. /**
  37. * A class representing a deterministic Rabin automaton.
  38. * <p>
  39. * For details on the template parameters, see class DA.
  40. * </p>
  41. * The DRA can be considered as a Streett automaton, if
  42. * a flag is set.
  43. */
  44. template <typename Label, template <typename N> class EdgeContainer >
  45. class DRA : public DA<Label, EdgeContainer, RabinAcceptance> {
  46. public:
  47. DRA(APSet_cp ap_set);
  48. virtual ~DRA();
  49. /** The type of the states of the DRA. */
  50. typedef typename DA<Label,EdgeContainer,RabinAcceptance>::state_type state_type;
  51. /** The type of the label on the edges. */
  52. typedef typename DA<Label,EdgeContainer,RabinAcceptance>::label_type label_type;
  53. /** The type of an iterator over the states. */
  54. typedef typename DA<Label,EdgeContainer,RabinAcceptance>::iterator iterator;
  55. /** The type of an iterator over the edges of a state. */
  56. typedef typename DA<Label,EdgeContainer,RabinAcceptance>::edge_iterator edge_iterator;
  57. /** Type of an iterator over the index of acceptance pairs. */
  58. typedef typename RabinAcceptance::acceptance_pair_iterator acceptance_pair_iterator;
  59. typedef RabinAcceptance acceptance_condition_type;
  60. /** Type of a reference counted pointer to the DRA (std::shared_ptr) */
  61. typedef std::shared_ptr< DRA<Label,EdgeContainer> > shared_ptr;
  62. /** Create a new instance of the automaton. */
  63. virtual DA<Label,EdgeContainer,RabinAcceptance> *createInstance(APSet_cp ap_set) {
  64. return new DRA<Label,EdgeContainer>(ap_set);
  65. }
  66. /** Make this automaton into an never accepting automaton */
  67. void constructEmpty() {
  68. state_type* n=DA<Label,EdgeContainer,RabinAcceptance>::newState();
  69. this->setStartState(n);
  70. for (APSet::element_iterator it_elem=
  71. DA<Label,EdgeContainer,RabinAcceptance>::getAPSet().all_elements_begin();
  72. it_elem!=DA<Label,EdgeContainer,RabinAcceptance>::getAPSet().all_elements_end();
  73. ++it_elem) {
  74. APElement label=(*it_elem);
  75. n->edges().addEdge(label, n);
  76. }
  77. }
  78. /**
  79. * Print the DRA/DSA in v2 format to the output stream.
  80. * This function can compact the automaton, which may invalidate iterators!
  81. */
  82. void print_explicit_v2(std::ostream& out) {
  83. if (!this->isCompact()) {
  84. this->makeCompact();
  85. }
  86. this->print_da_explicit_v2(typeID(),
  87. out);
  88. }
  89. /**
  90. * Print the DRA/DSA in DOT format to the output stream.
  91. * This function can compact the automaton, which may invalidate iterators!
  92. */
  93. void print_dot(std::ostream& out) {
  94. if (!this->isCompact()) {
  95. this->makeCompact();
  96. }
  97. this->print_da_dot(typeID(),
  98. out);
  99. }
  100. /**
  101. * Output operator for the DRA/DSA.
  102. */
  103. friend std::ostream& operator<<(std::ostream& out, DRA& dra) {
  104. dra.print_explicit_v2(out);
  105. return out;
  106. }
  107. /** Output state label for DOT printing.
  108. * @param out the output stream
  109. * @param state_index the state index
  110. */
  111. virtual void formatStateForDOT(std::ostream& out, unsigned int state_index) {
  112. state_type* cur_state=this->get(state_index);
  113. bool is_html=false;
  114. bool has_pos=false, has_neg=false;
  115. std::ostringstream acc_sig;
  116. for (unsigned int pair_index=0;pair_index<this->acceptance().size();pair_index++) {
  117. if (this->acceptance().isStateInAcceptance_L(pair_index, state_index)) {
  118. acc_sig << " +" << pair_index;
  119. has_pos=true;
  120. }
  121. if (this->acceptance().isStateInAcceptance_U(pair_index, state_index)) {
  122. acc_sig << " -" << pair_index;
  123. has_neg=true;
  124. }
  125. }
  126. std::string label;
  127. if (cur_state->hasDescription()) {
  128. std::string description=cur_state->getDescription();
  129. is_html=true;
  130. std::string acc_color;
  131. if (has_pos) {
  132. if (has_neg) {
  133. acc_color="BGCOLOR=\"lightblue\"";
  134. } else {
  135. acc_color="BGCOLOR=\"green\"";
  136. }
  137. } else {
  138. if (has_neg) {
  139. acc_color="BGCOLOR=\"red\"";
  140. }
  141. }
  142. StringAlgorithms::replace_all(description,
  143. "<TABLE>", "<TABLE BORDER=\"0\" CELLBORDER=\"1\">");
  144. out << "label= < ";
  145. out << "<TABLE BORDER=\"0\"><TR><TD BORDER=\"1\">";
  146. out << state_index;
  147. out << "</TD><TD " << acc_color << ">";
  148. out << acc_sig.str();
  149. out << "</TD></TR><TR><TD COLSPAN=\"2\">";
  150. out << description;
  151. out << "</TD></TR></TABLE>";
  152. out << " >, shape=box";
  153. } else {
  154. out << "label= \"" << state_index;
  155. if (acc_sig.str().length()!=0) {
  156. out << "\\n" << acc_sig.str();
  157. }
  158. out << "\"";
  159. if (!has_pos && !has_neg) {
  160. out << ", shape=circle";
  161. } else {
  162. out << ", shape=box";
  163. }
  164. }
  165. if (this->getStartState() == cur_state) {
  166. out << ", style=filled, color=black, fillcolor=grey";
  167. }
  168. }
  169. /**
  170. * Optimizes the acceptance condition.
  171. * This function may delete acceptance pairs,
  172. * which can invalidate iterators.
  173. */
  174. void optimizeAcceptanceCondition() {
  175. RabinAcceptance::acceptance_pair_iterator it=this->acceptance().acceptance_pair_begin();
  176. while (it!=this->acceptance().acceptance_pair_end()) {
  177. unsigned int id=*it;
  178. // increment iterator here so we can eventually delete
  179. // acceptance pair without side effects
  180. ++it;
  181. // L = L \ U
  182. if (this->acceptance().getAcceptance_L(id).intersects(this->acceptance().getAcceptance_U(id))) {
  183. BitSet L_minus_U=this->acceptance().getAcceptance_L(id);
  184. L_minus_U.Minus(this->acceptance().getAcceptance_U(id));
  185. this->acceptance().getAcceptance_L(id)=L_minus_U;
  186. }
  187. // remove if L is empty
  188. if (this->acceptance().getAcceptance_L(id).isEmpty()) {
  189. // no state is in L(id) -> remove
  190. this->acceptance().removeAcceptancePair(id);
  191. }
  192. }
  193. }
  194. /** Is this DRA considered as a Streett automaton? */
  195. bool isStreett() const {return _isStreett;}
  196. /** Consider this DRA as a Streett automaton. */
  197. void considerAsStreett(bool flag=true) {_isStreett=flag;}
  198. static
  199. shared_ptr calculateUnion(DRA& dra1, DRA& dra2,
  200. bool trueloop_check=true,
  201. bool detailed_states=false) {
  202. if (dra1.isStreett() ||
  203. dra2.isStreett()) {
  204. THROW_EXCEPTION(Exception, "Can not calculate union for Streett automata");
  205. }
  206. return DAUnionAlgorithm<DRA>::calculateUnion(dra1, dra2,
  207. trueloop_check,
  208. detailed_states);
  209. }
  210. static
  211. shared_ptr calculateUnionStuttered(DRA& dra1, DRA& dra2,
  212. StutterSensitivenessInformation::ptr stutter_information,
  213. bool trueloop_check=true,
  214. bool detailed_states=false) {
  215. if (dra1.isStreett() ||
  216. dra2.isStreett()) {
  217. THROW_EXCEPTION(Exception, "Can not calculate union for Streett automata");
  218. }
  219. return DAUnionAlgorithm<DRA>::calculateUnionStuttered(dra1, dra2,
  220. stutter_information,
  221. trueloop_check,
  222. detailed_states);
  223. }
  224. private:
  225. /** Return a string giving the type of the automaton. */
  226. std::string typeID() const {
  227. if (isStreett()) {
  228. return std::string("DSA");
  229. } else {
  230. return std::string("DRA");
  231. }
  232. }
  233. /** Marker, is this DRA considered as a Streett automaton? */
  234. bool _isStreett;
  235. };
  236. /**
  237. * Constructor.
  238. * @param ap_set the underlying APSet
  239. */
  240. template <typename Label, template <typename N> class EdgeContainer >
  241. DRA<Label, EdgeContainer>::DRA(APSet_cp ap_set)
  242. : DA<Label,EdgeContainer,RabinAcceptance>(ap_set), _isStreett(false) {
  243. }
  244. /**
  245. * Destructor.
  246. */
  247. template <typename Label, template <typename N> class EdgeContainer >
  248. DRA<Label, EdgeContainer>::~DRA() {
  249. }
  250. #endif