mCRL2
Loading...
Searching...
No Matches
shared_subset.h
Go to the documentation of this file.
1// Author(s): Ruud Koolen
2// Copyright: see the accompanying file COPYING or copy at
3// https://github.com/mCRL2org/mCRL2/blob/master/COPYING
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
11
12#ifndef MCRL2_ATERMPP_SHARED_SUBSET_H
13#define MCRL2_ATERMPP_SHARED_SUBSET_H
14
15#include <boost/iterator/iterator_facade.hpp>
18
19static inline int highest_bit(std::size_t x)
20{
21 int i = -1;
22 while (x)
23 {
24 x = x >> 1;
25 i++;
26 }
27 return i;
28}
29
30namespace atermpp
31{
32namespace detail
33{
34
38template <typename T>
40{
41 protected:
43 {
44 static atermpp::aterm_string true_ = atermpp::aterm_string("true");
45 return true_;
46 }
47
49 {
50 static atermpp::aterm_string false_ = atermpp::aterm_string("false");
51 return false_;
52 }
53
55 {
56 static atermpp::function_symbol node_ = atermpp::function_symbol("node", 3);
57 return node_;
58 }
59
60 class bdd_node : public atermpp::aterm
61 {
62 public:
64 {}
65
67 : atermpp::aterm(t)
68 {}
69
70 bdd_node(bool value)
71 : atermpp::aterm(value ? get_true() : get_false())
72 {}
73
74 bdd_node(std::size_t bit, const bdd_node& true_node, const bdd_node& false_node)
76 {}
77
78 bool is_true()
79 {
80 return *this == get_true();
81 }
82
83 bool is_false()
84 {
85 return *this == get_false();
86 }
87
88 bool is_node()
89 {
90 return function() == get_node();
91 }
92
93 std::size_t bit()
94 {
95 return down_cast<aterm_int>((*this)[0]).value();
96 }
97
99 {
100 return bdd_node(down_cast<aterm>((*this)[1]));
101 }
102
104 {
105 return bdd_node(down_cast<aterm>((*this)[2]));
106 }
107 };
108
109 protected:
110 std::vector<T> *m_set;
111 std::size_t m_bits;
113
114 public:
115 // Iterates over elements in the subset *in order*. The predicate-constructor of shared_subset depends on this property.
116 class iterator: public boost::iterator_facade<iterator, T, boost::forward_traversal_tag>
117 {
118 protected:
120 std::size_t m_index;
121
122 public:
123
125 : m_subset(nullptr),
126 m_index(-1)
127 {
128 }
129
130 iterator(const shared_subset& subset)
131 : m_subset(&subset),
132 m_index(0)
133 {
135 }
136
137 std::size_t index() const
138 {
139 return m_index;
140 }
141
142 operator bool() const
143 {
144 return m_index != (std::size_t)(-1);
145 }
146
147 private:
149
150 bool equal(iterator const& other) const
151 {
152 return m_index == other.m_index;
153 }
154
155 T& dereference() const
156 {
157 return (*m_subset->m_set)[m_index];
158 }
159
161 {
162 m_index++;
164 }
165
167 {
168 std::vector<bdd_node> path_stack;
169 bdd_node node = m_subset->m_bdd_root;
170
171 while (true)
172 {
173 assert(m_subset->m_set != nullptr);
174 if (m_index >= m_subset->m_set->size())
175 {
176 m_index = -1;
177 return;
178 }
179
180 while (node.is_node())
181 {
182 path_stack.push_back(node);
183 node = (m_index & ((std::size_t)1 << node.bit())) ? node.true_node() : node.false_node();
184 }
185
186 if (node.is_true())
187 {
188 return;
189 }
190
191 while (true)
192 {
193 bdd_node start;
194 std::size_t bit;
195
196 if (path_stack.empty())
197 {
198 start = m_subset->m_bdd_root;
199 bit = m_subset->m_bits;
200 }
201 else
202 {
203 start = node;
204 bit = path_stack.back().bit();
205 }
206
207 if (!start.is_false())
208 {
209 assert(start.is_node());
210 bool found = false;
211 for (std::size_t i = start.bit() + 1; i < bit; i++)
212 {
213 if (!(m_index & ((std::size_t)1 << i)))
214 {
215 m_index |= ((std::size_t)1 << i);
216 m_index &= ~(((std::size_t)1 << i) - 1);
217 found = true;
218 break;
219 }
220 }
221 if (found)
222 {
223 break;
224 }
225 }
226
227 if (path_stack.empty())
228 {
229 m_index = -1;
230 return;
231 }
232 else
233 {
234 node = path_stack.back();
235 path_stack.pop_back();
236 if (!(m_index & ((std::size_t)1 << bit)) && !node.true_node().is_false())
237 {
238 m_index |= ((std::size_t)1 << bit);
239 m_index &= ~(((std::size_t)1 << bit) - 1);
240 break;
241 }
242 }
243 }
244 }
245 }
246 };
247
249 : m_set(nullptr),
250 m_bits(0),
251 m_bdd_root(false)
252 {}
253
255 shared_subset(std::vector<T>& set)
256 : m_set(&set),
257 m_bdd_root(true)
258 {
259 m_bits = 0;
260 while (m_set->size() > ((std::size_t)1 << m_bits))
261 {
262 m_bits++;
263 }
264
265#ifndef NDEBUG
266 std::size_t index = 0;
267 for (iterator i = begin(); i != end(); i++)
268 {
269 assert(i.index() == index++);
270 }
271 assert(index == m_set->size());
272#endif
273 }
274
275 template <class Predicate>
276 shared_subset(const shared_subset<T>& set, Predicate p)
277 : m_set(set.m_set),
278 m_bits(set.m_bits)
279 {
280 std::vector<bdd_node> trees;
281 std::fill_n(std::back_inserter(trees), m_bits + 1, bdd_node());
282 std::size_t completed = 0;
283 for (iterator i = set.begin(); i != set.end(); i++)
284 {
285 if (p(*i))
286 {
287 std::size_t target = i.index();
288
289 for (int bit = highest_bit(target); bit >= 0; bit--)
290 {
291 if ((target & ((std::size_t)1 << bit)) && !(completed & ((std::size_t)1 << bit)))
292 {
293 bdd_node tree(false);
294 for (int j = 0; j < bit; j++)
295 {
296 bdd_node true_node;
297 bdd_node false_node;
298 if (completed & ((std::size_t)1 << j))
299 {
300 true_node = tree;
301 false_node = trees[j];
302 }
303 else
304 {
305 true_node = false;
306 false_node = tree;
307 }
308 if (true_node == false_node)
309 {
310 tree = true_node;
311 }
312 else
313 {
314 tree = bdd_node(j, true_node, false_node);
315 }
316 }
317 trees[bit] = tree;
318 completed |= ((std::size_t)1 << bit);
319 completed &= ~(((std::size_t)1 << bit) - 1);
320 }
321 }
322
323 bdd_node tree(true);
324 std::size_t bit;
325 for (bit = 0; target & ((std::size_t)1 << bit); bit++)
326 {
327 if (tree != trees[bit])
328 {
329 tree = bdd_node(bit, tree, trees[bit]);
330 }
331 }
332 trees[bit] = tree;
333 completed = target + 1;
334 }
335 }
336
337 if (completed != ((std::size_t)1 << m_bits))
338 {
339 bdd_node tree(false);
340 for (std::size_t j = 0; j < m_bits; j++)
341 {
342 bdd_node true_node;
343 bdd_node false_node;
344 if (completed & ((std::size_t)1 << j))
345 {
346 true_node = tree;
347 false_node = trees[j];
348 }
349 else
350 {
351 true_node = false;
352 false_node = tree;
353 }
354 if (true_node == false_node)
355 {
356 tree = true_node;
357 }
358 else
359 {
360 tree = bdd_node(j, true_node, false_node);
361 }
362 }
363 trees[m_bits] = tree;
364 }
365
366 m_bdd_root = trees[m_bits];
367
368#ifndef NDEBUG
369 iterator i = set.begin();
370 iterator j = begin();
371 while (i != set.end() && !p(*i))
372 {
373 i++;
374 }
375 while (i != set.end() && j != end())
376 {
377 assert (&*i == &*j);
378 i++;
379 j++;
380 while (i != set.end() && !p(*i))
381 {
382 i++;
383 }
384 }
385 assert (i == set.end() && j == end());
386#endif
387 }
388
390 {
391 return iterator(*this);
392 }
393
394 iterator end() const
395 {
396 return iterator();
397 }
398};
399
400} // namespace detail
401} // namespace atermpp
402
403#endif
Term containing an integer.
An integer term stores a single std::size_t value. It carries no arguments.
Definition aterm_int.h:26
Term containing a string.
const function_symbol & function() const
Returns the function symbol belonging to an aterm.
Definition aterm.h:144
bdd_node(std::size_t bit, const bdd_node &true_node, const bdd_node &false_node)
bool equal(iterator const &other) const
iterator(const shared_subset &subset)
const shared_subset< T > * m_subset
Stores a subset of a given base set using maximum sharing.
shared_subset(std::vector< T > &set)
Constructor.
shared_subset(const shared_subset< T > &set, Predicate p)
static atermpp::function_symbol & get_node()
static atermpp::aterm_string & get_true()
static atermpp::aterm_string & get_false()
The main namespace for the aterm++ library.
Definition algorithm.h:21
static int highest_bit(std::size_t x)