spot  2.14.5
adjlist.hh
1 // -*- coding: utf-8 -*-
2 // Copyright (C) by the Spot authors, see the AUTHORS file for details.
3 //
4 // This file is part of Spot, a model checking library.
5 //
6 // Spot is free software; you can redistribute it and/or modify it
7 // under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // Spot is distributed in the hope that it will be useful, but WITHOUT
12 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 // License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 
19 #pragma once
20 
21 #include <spot/misc/common.hh>
22 #include <spot/misc/_config.h>
23 
24 #include <vector>
25 #include <iterator>
26 #include <cstddef>
27 #include <spot/graph/graph.hh>
28 
29 namespace spot
30 {
31  // This works almost like a digraph, but it does not support removal
32  // of edges, does not support data on edges, prepend edges instead
33  // of appending them, and only stores the destinations of edges, not
34  // their source. So this is a more compact memory representation.
35  template<class State_Data>
36  class SPOT_API adjlist
37  {
38  private:
39  // Edge structure in a linked list format
40  struct edge
41  {
42  unsigned dst;
43  // index of next edge, or 0.
44  unsigned next_index;
45  };
46 
47  struct state_storage: public internal::boxed_label<State_Data>
48  {
49  unsigned first_edge = 0;
50 
51 #ifndef SWIG
52  template <typename... Args,
53  typename = typename std::enable_if<
54  !internal::first_is_base_of<state_storage,
55  Args...>::value>::type>
56  state_storage(Args&&... args)
57  noexcept(std::is_nothrow_constructible
58  <internal::boxed_label<State_Data>, Args...>::value)
59  : internal::boxed_label<State_Data>{std::forward<Args>(args)...}
60  {
61  }
62 #endif
63  };
64 
65  std::vector<edge> edges_;
66  std::vector<state_storage> states_;
67 
68  public:
69  adjlist(unsigned max_states = 10, unsigned max_trans = 0)
70  {
71  states_.reserve(max_states);
72  if (max_trans == 0)
73  max_trans = max_states * 2;
74  edges_.reserve(max_trans + 1);
75  // Add a dummy edge at index 0 to simplify later comparisons.
76  // when next_index == 0, there is no successor.
77  edges_.push_back({-1U, 0U});
78  }
79 
80  template <typename... Args>
81  unsigned new_state(Args&&... args)
82  {
83  unsigned s = states_.size();
84  states_.emplace_back(std::forward<Args>(args)...);
85  return s;
86  }
87 
88  template <typename... Args>
89  unsigned new_states(unsigned n, Args&&... args)
90  {
91  unsigned s = states_.size();
92  states_.reserve(s + n);
93  while (n--)
94  states_.emplace_back(std::forward<Args>(args)...);
95  return s;
96  }
97 
98  typename internal::boxed_label<State_Data>::data_t&
99  state_data(unsigned s)
100  {
101  return states_[s].data();
102  }
103 
104  const typename internal::boxed_label<State_Data>::data_t&
105  state_data(unsigned s) const
106  {
107  return states_[s].data();
108  }
109 
110  void new_edge(unsigned src, unsigned dst)
111  {
112  unsigned pos = edges_.size();
113  state_storage& ss = states_[src];
114  edges_.emplace_back(edge{dst, ss.first_edge});
115  ss.first_edge = pos;
116  }
117 
118  // Iterator for range-based for loop support
120  {
121  private:
122  const adjlist* graph;
123  unsigned edge_index;
124 
125  public:
126  // Iterator traits
127  using iterator_category = std::input_iterator_tag;
128  using value_type = unsigned;
129  using difference_type = std::ptrdiff_t;
130  using pointer = const unsigned*;
131  using reference = const unsigned&;
132 
133  successor_iterator(const adjlist* g, unsigned idx)
134  : graph(g), edge_index(idx)
135  {
136  }
137 
138  int operator*() const
139  {
140  return graph->edges_[edge_index].dst;
141  }
142 
143  successor_iterator& operator++() {
144  edge_index = graph->edges_[edge_index].next_index;
145  return *this;
146  }
147 
148  successor_iterator operator++(int) {
149  successor_iterator tmp = *this;
150  ++(*this);
151  return tmp;
152  }
153 
154  friend bool operator==(const successor_iterator& iter, std::nullptr_t)
155  {
156  return iter.edge_index == 0;
157  }
158 
159  friend bool operator==(std::nullptr_t, const successor_iterator& iter)
160  {
161  return iter.edge_index == 0;
162  }
163 
164  friend bool operator!=(const successor_iterator& iter, std::nullptr_t)
165  {
166  return iter.edge_index != 0;
167  }
168 
169  friend bool operator!=(std::nullptr_t, const successor_iterator& iter)
170  {
171  return iter.edge_index != 0;
172  }
173  };
174 
176  {
177  private:
178  const adjlist* graph;
179  unsigned state;
180 
181  public:
182  successor_range(const adjlist* g, unsigned s)
183  : graph(g), state(s)
184  {
185  }
186 
187  successor_iterator begin() const
188  {
189  unsigned first_edge = (state < graph->states_.size()) ?
190  graph->states_[state].first_edge : 0;
191  return successor_iterator(graph, first_edge);
192  }
193 
194  std::nullptr_t end() const
195  {
196  return nullptr;
197  }
198  };
199 
200  successor_range out(unsigned state) const
201  {
202  return successor_range(this, state);
203  }
204 
205  unsigned num_states() const
206  {
207  return states_.size();
208  }
209 
210  unsigned num_edges() const
211  {
212  return edges_.size() - 1;
213  }
214  };
215 }
Definition: adjlist.hh:120
Definition: adjlist.hh:176
Definition: adjlist.hh:37
Abstract class for states.
Definition: twa.hh:47
@ U
until
Definition: automata.hh:26
Definition: graph.hh:66
Definition: graph.hh:46

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on Fri Feb 27 2015 10:00:07 for spot by doxygen 1.9.1