spot 2.14
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
29namespace 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.4