spot 2.2.2

- Main Page
- Related Pages
- Modules
- Classes
- Files

- File List

All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
twagraph.hh
1 // -*- coding: utf-8 -*-
2 // Copyright (C) 2014, 2015, 2016 Laboratoire de Recherche et Développement
3 // de l'Epita.
4 //
5 // This file is part of Spot, a model checking library.
6 //
7 // Spot is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // Spot is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20 #pragma once
21
22 #include <spot/twa/fwd.hh>
23 #include <spot/graph/graph.hh>
24 #include <spot/graph/ngraph.hh>
25 #include <spot/twa/bdddict.hh>
26 #include <spot/twa/twa.hh>
27 #include <spot/twaalgos/copy.hh>
28 #include <spot/tl/formula.hh>
29 #include <sstream>
30
31 namespace spot
32 {
33
34 struct SPOT_API twa_graph_state: public spot::state
35 {
36 public:
37 twa_graph_state() noexcept
38 {
39 }
40
41 virtual ~twa_graph_state() noexcept
42 {
43 }
44
45 virtual int compare(const spot::state* other) const override
46 {
47 auto o = down_cast<const twa_graph_state*>(other);
48 SPOT_ASSERT(o);
49
50 // Do not simply return "other - this", it might not fit in an int.
51 if (o < this)
52 return -1;
53 if (o > this)
54 return 1;
55 return 0;
56 }
57
58 virtual size_t hash() const override
59 {
60 return
61 reinterpret_cast<const char*>(this) - static_cast<const char*>(nullptr);
62 }
63
64 virtual twa_graph_state*
65 clone() const override
66 {
67 return const_cast<twa_graph_state*>(this);
68 }
69
70 virtual void destroy() const override
71 {
72 }
73 };
74
75 struct SPOT_API twa_graph_edge_data
76 {
77 bdd cond;
78 acc_cond::mark_t acc;
79
80 explicit twa_graph_edge_data() noexcept
81 : cond(bddfalse), acc(0)
82 {
83 }
84
85 twa_graph_edge_data(bdd cond, acc_cond::mark_t acc = 0U) noexcept
86 : cond(cond), acc(acc)
87 {
88 }
89
90 bool operator<(const twa_graph_edge_data& other) const
91 {
92 if (cond.id() < other.cond.id())
93 return true;
94 if (cond.id() > other.cond.id())
95 return false;
96 return acc < other.acc;
97 }
98
99 bool operator==(const twa_graph_edge_data& other) const
100 {
101 return cond.id() == other.cond.id() &&
102 acc == other.acc;
103 }
104 };
105
106
107 template<class Graph>
108 class SPOT_API twa_graph_succ_iterator final:
109 public twa_succ_iterator
110 {
111 private:
112 typedef typename Graph::edge edge;
113 typedef typename Graph::state_data_t state;
114 const Graph* g_;
115 edge t_;
116 edge p_;
117
118 public:
119 twa_graph_succ_iterator(const Graph* g, edge t)
120 : g_(g), t_(t)
121 {
122 }
123
124 void recycle(edge t)
125 {
126 t_ = t;
127 }
128
129 virtual bool first() override
130 {
131 p_ = t_;
132 return p_;
133 }
134
135 virtual bool next() override
136 {
137 p_ = g_->edge_storage(p_).next_succ;
138 return p_;
139 }
140
141 virtual bool done() const override
142 {
143 return !p_;
144 }
145
146 virtual const twa_graph_state* dst() const override
147 {
148 SPOT_ASSERT(!done());
149 return &g_->state_data(g_->edge_storage(p_).dst);
150 }
151
152 virtual bdd cond() const override
153 {
154 SPOT_ASSERT(!done());
155 return g_->edge_data(p_).cond;
156 }
157
158 virtual acc_cond::mark_t acc() const override
159 {
160 SPOT_ASSERT(!done());
161 return g_->edge_data(p_).acc;
162 }
163
164 edge pos() const
165 {
166 return p_;
167 }
168
169 };
170
171 class SPOT_API twa_graph final: public twa
172 {
173 public:
174 typedef digraph<twa_graph_state, twa_graph_edge_data> graph_t;
175 typedef graph_t::edge_storage_t edge_storage_t;
176 // We avoid using graph_t::state because graph_t is not
177 // instantiated in the SWIG bindings, and SWIG would therefore
178 // handle graph_t::state as an abstract type.
179 typedef unsigned state_num;
180 static_assert(std::is_same<typename graph_t::state, state_num>::value,
181 "type mismatch");
182
183 protected:
184 graph_t g_;
185 mutable unsigned init_number_;
186
187 public:
188 twa_graph(const bdd_dict_ptr& dict)
189 : twa(dict),
190 init_number_(0)
191 {
192 }
193
194 explicit twa_graph(const const_twa_graph_ptr& other, prop_set p)
195 : twa(other->get_dict()),
196 g_(other->g_), init_number_(other->init_number_)
197 {
198 copy_acceptance_of(other);
199 copy_ap_of(other);
200 prop_copy(other, p);
201 }
202
203 virtual ~twa_graph()
204 {
205 }
206
207 #ifndef SWIG
208 template <typename State_Name,
209 typename Name_Hash = std::hash<State_Name>,
210 typename Name_Equal = std::equal_to<State_Name>>
211 using namer = named_graph<graph_t, State_Name, Name_Hash, Name_Equal>;
212
213 template <typename State_Name,
214 typename Name_Hash = std::hash<State_Name>,
215 typename Name_Equal = std::equal_to<State_Name>>
216 namer<State_Name, Name_Hash, Name_Equal>*
217 create_namer()
218 {
219 return new named_graph<graph_t, State_Name, Name_Hash, Name_Equal>(g_);
220 }
221
222 namer<formula>*
223 create_formula_namer()
224 {
225 return create_namer<formula>();
226 }
227
228 void
229 release_formula_namer(namer<formula>* namer, bool keep_names);
230 #endif
231
232 graph_t& get_graph()
233 {
234 return g_;
235 }
236
237 const graph_t& get_graph() const
238 {
239 return g_;
240 }
241
242 unsigned num_states() const
243 {
244 return g_.num_states();
245 }
246
247 unsigned num_edges() const
248 {
249 return g_.num_edges();
250 }
251
252 void set_init_state(state_num s)
253 {
254 if (SPOT_UNLIKELY(s >= num_states()))
255 throw std::invalid_argument
256 ("set_init_state() called with nonexisiting state");
257 init_number_ = s;
258 }
259
260 void set_init_state(const state* s)
261 {
262 set_init_state(state_number(s));
263 }
264
265 state_num get_init_state_number() const
266 {
267 if (num_states() == 0)
268 const_cast<graph_t&>(g_).new_state();
269 return init_number_;
270 }
271
272 virtual const twa_graph_state* get_init_state() const override
273 {
274 if (num_states() == 0)
275 const_cast<graph_t&>(g_).new_state();
276 return state_from_number(init_number_);
277 }
278
279 virtual twa_succ_iterator*
280 succ_iter(const state* st) const override
281 {
282 auto s = down_cast<const typename graph_t::state_storage_t*>(st);
283 SPOT_ASSERT(s);
284 SPOT_ASSERT(!s->succ || g_.is_valid_edge(s->succ));
285
286 if (this->iter_cache_)
287 {
288 auto it =
289 down_cast<twa_graph_succ_iterator<graph_t>*>(this->iter_cache_);
290 it->recycle(s->succ);
291 this->iter_cache_ = nullptr;
292 return it;
293 }
294 return new twa_graph_succ_iterator<graph_t>(&g_, s->succ);
295 }
296
297 state_num
298 state_number(const state* st) const
299 {
300 auto s = down_cast<const typename graph_t::state_storage_t*>(st);
301 SPOT_ASSERT(s);
302 return s - &g_.state_storage(0);
303 }
304
305 const twa_graph_state*
306 state_from_number(state_num n) const
307 {
308 return &g_.state_data(n);
309 }
310
311 std::string format_state(unsigned n) const
312 {
313 std::stringstream ss;
314 ss << n;
315 return ss.str();
316 }
317
318 virtual std::string format_state(const state* st) const override
319 {
320 return format_state(state_number(st));
321 }
322
323 unsigned edge_number(const twa_succ_iterator* it) const
324 {
325 auto* i = down_cast<const twa_graph_succ_iterator<graph_t>*>(it);
326 return i->pos();
327 }
328
329 twa_graph_edge_data& edge_data(const twa_succ_iterator* it)
330 {
331 return g_.edge_data(edge_number(it));
332 }
333
334 twa_graph_edge_data& edge_data(unsigned t)
335 {
336 return g_.edge_data(t);
337 }
338
339 const twa_graph_edge_data& edge_data(const twa_succ_iterator* it) const
340 {
341 return g_.edge_data(edge_number(it));
342 }
343
344 const twa_graph_edge_data& edge_data(unsigned t) const
345 {
346 return g_.edge_data(t);
347 }
348
349 edge_storage_t& edge_storage(const twa_succ_iterator* it)
350 {
351 return g_.edge_storage(edge_number(it));
352 }
353
354 edge_storage_t& edge_storage(unsigned t)
355 {
356 return g_.edge_storage(t);
357 }
358
359 const edge_storage_t
360 edge_storage(const twa_succ_iterator* it) const
361 {
362 return g_.edge_storage(edge_number(it));
363 }
364
365 const edge_storage_t edge_storage(unsigned t) const
366 {
367 return g_.edge_storage(t);
368 }
369
370 unsigned new_state()
371 {
372 return g_.new_state();
373 }
374
375 unsigned new_states(unsigned n)
376 {
377 return g_.new_states(n);
378 }
379
380 unsigned new_edge(unsigned src, unsigned dst,
381 bdd cond, acc_cond::mark_t acc = 0U)
382 {
383 return g_.new_edge(src, dst, cond, acc);
384 }
385
386 unsigned new_acc_edge(unsigned src, unsigned dst,
387 bdd cond, bool acc = true)
388 {
389 if (acc)
390 return g_.new_edge(src, dst, cond, this->acc().all_sets());
391 else
392 return g_.new_edge(src, dst, cond);
393 }
394
395 #ifndef SWIG
396 internal::state_out<const graph_t>
397 out(unsigned src) const
398 {
399 return g_.out(src);
400 }
401 #endif
402
403 internal::state_out<graph_t>
404 out(unsigned src)
405 {
406 return g_.out(src);
407 }
408
409 #ifndef SWIG
410 auto states() const
411 SPOT_RETURN(g_.states());
412 auto states()
413 SPOT_RETURN(g_.states());
414
415 internal::all_trans<const graph_t>
416 edges() const
417 {
418 return g_.edges();
419 }
420 #endif
421
422 internal::all_trans<graph_t>
423 edges()
424 {
425 return g_.edges();
426 }
427
428 #ifndef SWIG
429 auto edge_vector() const
430 SPOT_RETURN(g_.edge_vector());
431 auto edge_vector()
432 SPOT_RETURN(g_.edge_vector());
433
434 auto is_dead_edge(const graph_t::edge_storage_t& t) const
435 SPOT_RETURN(g_.is_dead_edge(t));
436 #endif
437
440 void merge_edges();
441
450 void purge_dead_states();
451
463 void purge_unreachable_states();
464
469 void remove_unused_ap();
470
471 acc_cond::mark_t state_acc_sets(unsigned s) const
472 {
473 if (SPOT_UNLIKELY(!((bool)prop_state_acc() || num_sets() == 0)))
474 throw std::runtime_error
475 ("state_acc_sets() should only be called on "
476 "automata with state-based acceptance");
477
478 for (auto& t: g_.out(s))
479 // Stop at the first edge, since the remaining should be
480 // labeled identically.
481 return t.acc;
482 return 0U;
483 }
484
485 bool state_is_accepting(unsigned s) const
486 {
487 if (SPOT_UNLIKELY(!((bool)prop_state_acc() || num_sets() == 0)))
488 throw std::runtime_error
489 ("state_is_accepting() should only be called on "
490 "automata with state-based acceptance");
491 for (auto& t: g_.out(s))
492 // Stop at the first edge, since the remaining should be
493 // labeled identically.
494 return acc().accepting(t.acc);
495 return false;
496 }
497
498 bool state_is_accepting(const state* s) const
499 {
500 return state_is_accepting(state_number(s));
501 }
502
503 bool operator==(const twa_graph& aut) const
504 {
505 if (num_states() != aut.num_states() ||
506 num_edges() != aut.num_edges() ||
507 num_sets() != aut.num_sets())
508 return false;
509 auto& trans1 = edge_vector();
510 auto& trans2 = aut.edge_vector();
511 return std::equal(trans1.begin() + 1, trans1.end(),
512 trans2.begin() + 1);
513 }
514
515 void defrag_states(std::vector<unsigned>&& newst, unsigned used_states);
516 };
517
518 inline twa_graph_ptr make_twa_graph(const bdd_dict_ptr& dict)
519 {
520 return std::make_shared<twa_graph>(dict);
521 }
522
523 inline twa_graph_ptr make_twa_graph(const twa_graph_ptr& aut,
524 twa::prop_set p)
525 {
526 return std::make_shared<twa_graph>(aut, p);
527 }
528
529 inline twa_graph_ptr make_twa_graph(const const_twa_graph_ptr& aut,
530 twa::prop_set p)
531 {
532 return std::make_shared<twa_graph>(aut, p);
533 }
534
535 inline twa_graph_ptr make_twa_graph(const const_twa_ptr& aut,
536 twa::prop_set p)
537 {
538 auto a = std::dynamic_pointer_cast<const twa_graph>(aut);
539 if (a)
540 return std::make_shared<twa_graph>(a, p);
541 else
542 return copy(aut, p);
543 }
544 }
spot
Definition: graph.hh:32
spot::digraph::num_edges
unsigned num_edges() const
The number of edges in the automaton.
Definition: graph.hh:639
spot::digraph::edge_storage
edge_storage_t & edge_storage(edge s)
return a reference to the storage of an edge
Definition: graph.hh:715
spot::twa_graph_state::destroy
virtual void destroy() const override
Release a state.
Definition: twagraph.hh:70
spot::digraph::edge_data
edge_storage_t::data_t & edge_data(edge s)
return the Edgeg_Data of an edge.
Definition: graph.hh:733
spot::digraph::new_state
state new_state(Args &&...args)
Create a new states.
Definition: graph.hh:650
spot::digraph::num_states
unsigned num_states() const
The number of states in the automaton.
Definition: graph.hh:631
spot::twa
A Transition-based ω-Automaton.
Definition: twa.hh:621
formula.hh
LTL/PSL formula interface.
spot::digraph::out
internal::state_out< digraph > out(state src)
Return a fake container with all edges leaving src.
Definition: graph.hh:784
spot::state
Abstract class for states.
Definition: twa.hh:50
spot::twa_graph_state::hash
virtual size_t hash() const override
Hash a state.
Definition: twagraph.hh:58
spot::internal::edge_storage
Definition: graph.hh:183
spot::digraph::states
const state_vector & states() const
Return the vector of states.
Definition: graph.hh:828
spot::named_graph
Definition: ngraph.hh:32
spot::op::U
until
spot::digraph::is_dead_edge
bool is_dead_edge(unsigned t) const
Tests whether an edge has been erased.
Definition: graph.hh:891
spot::internal::distate_storage
Definition: graph.hh:158
spot::copy
twa_graph_ptr copy(const const_twa_ptr &aut, twa::prop_set p, bool preserve_names=false, unsigned max_states=-1U)
Build an explicit automaton from all states of aut,.
spot::twa_graph_succ_iterator::first
virtual bool first() override
Position the iterator on the first successor (if any).
Definition: twagraph.hh:129
spot::twa_succ_iterator
Iterate over the successors of a state.
Definition: twa.hh:397
spot::internal::all_trans
Definition: graph.hh:528
spot::twa_graph_succ_iterator::cond
virtual bdd cond() const override
Get the condition on the edge leading to this successor.
Definition: twagraph.hh:152
spot::digraph::edge_vector
const edge_vector_t & edge_vector() const
Return the vector of all edges.
Definition: graph.hh:862
spot::twa_graph_succ_iterator::done
virtual bool done() const override
Check whether the iteration is finished.
Definition: twagraph.hh:141
spot::twa_graph_state::compare
virtual int compare(const spot::state *other) const override
Compares two states (that come from the same automaton).
Definition: twagraph.hh:45
spot::twa_graph_succ_iterator::dst
virtual const twa_graph_state * dst() const override
Get the destination state of the current edge.
Definition: twagraph.hh:146
spot::twa::prop_set
A structure for selecting a set of automaton properties to copy.
Definition: twa.hh:1356
spot::twa::num_sets
unsigned num_sets() const
Number of acceptance sets used by the automaton.
Definition: twa.hh:905
spot::digraph::new_states
state new_states(unsigned n, Args &&...args)
Create n new states.
Definition: graph.hh:664
spot::twa_graph_succ_iterator::acc
virtual acc_cond::mark_t acc() const override
Get the acceptance mark of the edge leading to this successor.
Definition: twagraph.hh:158
spot::digraph::edges
internal::all_trans< const digraph > edges() const
Return a fake container with all edges (exluding erased edges)
Definition: graph.hh:843
spot::digraph::is_valid_edge
bool is_valid_edge(edge t) const
Test whether the given edge is valid.
Definition: graph.hh:879
spot::digraph::new_edge
edge new_edge(state src, out_state dst, Args &&...args)
Create a new edge.
Definition: graph.hh:752
spot::twa_graph_succ_iterator
Definition: twagraph.hh:108
spot::digraph
A directed graph.
Definition: graph.hh:35
spot::digraph::state_storage
state_storage_t & state_storage(state s)
return a reference to the storage of a state
Definition: graph.hh:679
spot::internal::state_out
Definition: graph.hh:401
spot::twa_graph
Definition: twagraph.hh:171
spot::twa_graph_state
Definition: twagraph.hh:34
spot::twa_graph_succ_iterator::next
virtual bool next() override
Jump to the next successor (if any).
Definition: twagraph.hh:135
spot::acc_cond::mark_t
Definition: acc.hh:34
spot::digraph::state_data
state_storage_t::data_t & state_data(state s)
return the State_Data associated to a state
Definition: graph.hh:697
spot::twa_graph_edge_data
Definition: twagraph.hh:75
spot::twa_graph_state::clone
virtual twa_graph_state * clone() const override
Duplicate a state.
Definition: twagraph.hh:65

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.