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.

189 lines
5.0 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 EDGECONTAINEREXPLICITAPELEMENT_H
  19. #define EDGECONTAINEREXPLICITAPELEMENT_H
  20. /** @file
  21. * Provides an implementation of an EdgeContainer with APElements as labels,
  22. * which stores the edges in a vector, which is complete, ie there are
  23. * always 2^AP edges.
  24. */
  25. #include "common/Exceptions.hpp"
  26. #include "APSet.hpp"
  27. #include "APElement.hpp"
  28. #include <boost/iterator/iterator_facade.hpp>
  29. #include <utility>
  30. /**
  31. * An EdgeContainer, which stores
  32. * the edges (labeled by APElements) in a vector, which is complete, ie there are
  33. * always 2^AP edges.
  34. * The template parameter To signifies the type of target for the edges,
  35. * it can e.g. be an int to store a state index or a BitSet to
  36. * store multiple targets for a single edge.
  37. */
  38. template <typename To>
  39. class EdgeContainerExplicit_APElement {
  40. public:
  41. /** The type of this container class */
  42. typedef EdgeContainerExplicit_APElement<To> container_type;
  43. /** The type of the edges */
  44. typedef std::pair<APElement, To* > edge_type;
  45. /**
  46. * Constructor.
  47. * @param sizeAP the number of atomic propositions in the APSet
  48. */
  49. EdgeContainerExplicit_APElement(unsigned int sizeAP=1) : _sizeAP(sizeAP) {
  50. _arraySize=1<<sizeAP;
  51. _storage=new To*[_arraySize];
  52. for (unsigned int i=0;i<_arraySize;i++) {
  53. _storage[i]=0;
  54. }
  55. };
  56. /** Destructor */
  57. ~EdgeContainerExplicit_APElement() {delete[] _storage;};
  58. /** Add an edge that doesn't already exist */
  59. void addEdge(APElement label, To &to) {addEdge(label, &to);}
  60. /** Add an edge that doesn't already exist */
  61. void addEdge(APElement label, To *to) {
  62. if (get(label)) {
  63. THROW_EXCEPTION(IllegalArgumentException, "Trying to add edge which already exists!");
  64. }
  65. set(label, to);
  66. }
  67. /** Remove an edge */
  68. void removeEdge(APElement label) {
  69. if (!get(label)) {
  70. THROW_EXCEPTION(IllegalArgumentException, "Trying to remove non-existing edge!");
  71. }
  72. set(label, 0);
  73. }
  74. /** Get the target of the edge labeled with label*/
  75. To* get(APElement label) {
  76. if (label.getBitSet()>=_arraySize) {
  77. THROW_EXCEPTION(IndexOutOfBoundsException, "");
  78. }
  79. return _storage[label.getBitSet()];
  80. };
  81. /** Set the target of an edge labeled with <i>label</i> to <i>to</i> */
  82. void set(APElement label, To& to) {
  83. set(label, &to);
  84. }
  85. /** Set the target of an edge labeled with <i>label</i> to <i>to</i> */
  86. void set(APElement label, To *to) {
  87. if (label.getBitSet()>=_arraySize) {
  88. THROW_EXCEPTION(IndexOutOfBoundsException, "");
  89. }
  90. _storage[label.getBitSet()]=to;
  91. };
  92. /** An iterator over all the edges. */
  93. class EdgeIterator
  94. : public boost::iterator_facade< EdgeIterator,
  95. edge_type,
  96. boost::forward_traversal_tag,
  97. edge_type>
  98. {
  99. public:
  100. EdgeIterator(container_type& container)
  101. : _container(container), _i(0)
  102. {
  103. if (!_container.get(_i)) {
  104. // edge with index 0 doesn't exist, increment until we find the first edge
  105. increment();
  106. }
  107. };
  108. explicit EdgeIterator(container_type& container,
  109. unsigned int i)
  110. : _container(container), _i(i)
  111. {
  112. };
  113. private:
  114. friend class boost::iterator_core_access;
  115. void increment() {
  116. while (++_i < _container._arraySize &&
  117. _container.get(_i) == 0)
  118. {
  119. ; //nop
  120. }
  121. }
  122. bool equal(EdgeIterator const& other) const {
  123. return
  124. (&this->_container == &other._container)
  125. && (this->_i == other._i);
  126. }
  127. edge_type dereference() const {
  128. To* to=_container.get(_i);
  129. return edge_type(APElement(_i), to);
  130. }
  131. container_type& _container;
  132. unsigned int _i;
  133. };
  134. /**
  135. * Returns an iterator pointing to the first edge.
  136. * This iterator iterates over all the 2^AP edges,
  137. * irrespective that some may not have a target
  138. * (dereferencing will return NULL for these).
  139. */
  140. EdgeIterator begin() {return EdgeIterator(*this);}
  141. /** Returns an iterator pointing after the last edge. */
  142. EdgeIterator end() {return EdgeIterator(*this,_arraySize);}
  143. /** Type of the iterator over all the edges */
  144. typedef EdgeIterator iterator;
  145. private:
  146. /** The size of the APSet */
  147. unsigned int _sizeAP;
  148. /** The number of edges */
  149. unsigned long _arraySize;
  150. /** The storage area for the edges */
  151. To** _storage;
  152. };
  153. #endif