spot  1.0.2
tgbaexplicit.hh
Go to the documentation of this file.
1 // -*- coding: utf-8 -*-
2 // Copyright (C) 2009, 2010, 2011, 2012 Laboratoire de Recherche et
3 // Développement de l'Epita.
4 // Copyright (C) 2003, 2004, 2006 Laboratoire d'Informatique de Paris
5 // 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
6 // Université Pierre et Marie Curie.
7 //
8 // This file is part of Spot, a model checking library.
9 //
10 // Spot is free software; you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Spot is distributed in the hope that it will be useful, but WITHOUT
16 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 // License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 
23 #ifndef SPOT_TGBA_TGBAEXPLICIT_HH
24 # define SPOT_TGBA_TGBAEXPLICIT_HH
25 
26 #include <sstream>
27 #include <list>
28 
29 #include "tgba.hh"
30 #include "sba.hh"
31 #include "tgba/formula2bdd.hh"
32 #include "misc/hash.hh"
33 #include "misc/bddop.hh"
34 #include "ltlast/formula.hh"
35 #include "ltlvisit/tostring.hh"
36 
37 namespace spot
38 {
39  // How to destroy the label of a state.
40  template<typename T>
41  struct destroy_key
42  {
43  void destroy(T t)
44  {
45  (void) t;
46  }
47  };
48 
49  template<>
50  struct destroy_key<const ltl::formula*>
51  {
52  void destroy(const ltl::formula* t)
53  {
54  t->destroy();
55  }
56  };
57 
60  template<typename Label, typename label_hash>
62  {
63  public:
65  {
66  }
67 
68  state_explicit(const Label& l):
69  label_(l)
70  {
71  }
72 
73  virtual ~state_explicit()
74  {
75  }
76 
77  virtual void destroy() const
78  {
79  }
80 
81  typedef Label label_t;
82  typedef label_hash label_hash_t;
83 
84  struct transition
85  {
86  bdd condition;
89  };
90 
91  typedef std::list<transition> transitions_t;
93 
94  const Label& label() const
95  {
96  return label_;
97  }
98 
99  bool empty() const
100  {
101  return successors.empty();
102  }
103 
104  virtual int compare(const state* other) const
105  {
108  assert (s);
109 
110  // Do not simply return "o - this", it might not fit in an int.
111  if (s < this)
112  return -1;
113  if (s > this)
114  return 1;
115  return 0;
116  }
117 
118  virtual size_t hash() const
119  {
120  return
121  reinterpret_cast<const char*>(this) - static_cast<const char*>(0);
122  }
123 
125  clone() const
126  {
127  return const_cast<state_explicit<Label, label_hash>*>(this);
128  }
129 
130  protected:
131  Label label_;
132  };
133 
137  public state_explicit<int, identity_hash<int> >
138  {
139  public:
141  : state_explicit<int, identity_hash<int> >()
142  {
143  }
144 
146  : state_explicit<int, identity_hash<int> >(label)
147  {
148  }
149 
150  static const int default_val;
151  };
152 
156  public state_explicit<std::string, string_hash>
157  {
158  public:
160  state_explicit<std::string, string_hash>()
161  {
162  }
163 
164  state_explicit_string(const std::string& label)
165  : state_explicit<std::string, string_hash>(label)
166  {
167  }
168 
169  static const std::string default_val;
170  };
171 
175  public state_explicit<const ltl::formula*, ltl::formula_ptr_hash>
176  {
177  public:
179  state_explicit<const ltl::formula*, ltl::formula_ptr_hash>()
180  {
181  }
182 
184  : state_explicit<const ltl::formula*, ltl::formula_ptr_hash>(label)
185  {
186  }
187 
188  static const ltl::formula* default_val;
189  };
190 
193  template<typename State>
195  {
196  public:
197  tgba_explicit_succ_iterator(const State* start,
198  bdd all_acc)
199  : start_(start),
201  {
202  }
203 
204  virtual void first()
205  {
206  it_ = start_->successors.begin();
207  }
208 
209  virtual void next()
210  {
211  ++it_;
212  }
213 
214  virtual bool done() const
215  {
216  return it_ == start_->successors.end();
217  }
218 
219  virtual State* current_state() const
220  {
221  assert(!done());
222  const State* res = down_cast<const State*>(it_->dest);
223  assert(res);
224  return const_cast<State*>(res);
225  }
226 
227  virtual bdd current_condition() const
228  {
229  assert(!done());
230  return it_->condition;
231  }
232 
233  virtual bdd current_acceptance_conditions() const
234  {
235  assert(!done());
236  return it_->acceptance_conditions;
237  }
238 
239  typename State::transitions_t::const_iterator
240  get_iterator() const
241  {
242  return it_;
243  }
244 
245  private:
246  const State* start_;
247  typename State::transitions_t::const_iterator it_;
249  };
250 
253  template<typename State, typename Type>
254  class explicit_graph: public Type
255  {
256  public:
257  typedef typename State::label_t label_t;
258  typedef typename State::label_hash_t label_hash_t;
259  typedef typename State::transitions_t transitions_t;
260  typedef typename State::transition transition;
261  typedef State state;
262  protected:
263  typedef Sgi::hash_map<label_t, State, label_hash_t> ls_map;
264  typedef Sgi::hash_map<label_t, State*, label_hash_t> alias_map;
265  typedef Sgi::hash_map<const State*, label_t, ptr_hash<State> > sl_map;
266 
267  public:
268 
270  : ls_(),
271  sl_(),
272  init_(0),
273  dict_(dict),
274  all_acceptance_conditions_(bddfalse),
277  {
278  }
279 
281  {
282  return add_state(State::default_val);
283  }
284 
285  size_t num_states() const
286  {
287  return sl_.size();
288  }
289 
290  transition*
291  create_transition(State* source, const State* dest)
292  {
293  transition t;
294 
295  t.dest = dest;
296  t.condition = bddtrue;
297  t.acceptance_conditions = bddfalse;
298 
299  typename transitions_t::iterator i =
300  source->successors.insert(source->successors.end(), t);
301 
302  return &*i;
303  }
304 
305  transition*
306  create_transition(const label_t& source, const label_t& dest)
307  {
308  // It's important that the source be created before the
309  // destination, so the first source encountered becomes the
310  // default initial state.
311  State* s = add_state(source);
312  return create_transition(s, add_state(dest));
313  }
314 
315  transition*
317  {
318  return const_cast<transition*>(&(*(si->get_iterator())));
319  }
320 
322  {
323  t->condition &= formula_to_bdd(f, dict_, this);
324  f->destroy();
325  }
326 
328  void add_conditions(transition* t, bdd f)
329  {
330  dict_->register_propositions(f, this);
331  t->condition &= f;
332  }
333 
335  {
336  return dict_->is_registered_acceptance_variable(f, this);
337  }
338 
339  //old tgba explicit labelled interface
340  bool has_state(const label_t& name)
341  {
342  return ls_.find(name) != ls_.end();
343  }
344 
345  const label_t& get_label(const State* s) const
346  {
347  typename sl_map::const_iterator i = sl_.find(s);
348  assert(i != sl_.end());
349  return i->second;
350  }
351 
352  const label_t& get_label(const spot::state* s) const
353  {
354  const State* se = down_cast<const State*>(s);
355  assert(se);
356  return get_label(se);
357  }
358 
359  void
361  {
362  bdd all = this->all_acceptance_conditions();
363  typename ls_map::iterator i;
364  for (i = ls_.begin(); i != ls_.end(); ++i)
365  {
366  typename transitions_t::iterator i2;
367  for (i2 = i->second.successors.begin();
368  i2 != i->second.successors.end(); ++i2)
369  i2->acceptance_conditions = all - i2->acceptance_conditions;
370  }
371  }
372 
373  void
375  {
376  typedef typename transitions_t::iterator trans_t;
377  typedef std::map<int, trans_t> acc_map;
378  typedef Sgi::hash_map<const spot::state*, acc_map,
379  ptr_hash<spot::state> > dest_map;
380 
381  typename ls_map::iterator i;
382  for (i = ls_.begin(); i != ls_.end(); ++i)
383  {
384  const spot::state* last_dest = 0;
385  dest_map dm;
386  typename dest_map::iterator dmi = dm.end();
387  typename transitions_t::iterator t1 = i->second.successors.begin();
388 
389  // Loop over all outgoing transitions (cond,acc,dest), and
390  // store them into dest_map[dest][acc] so that we can merge
391  // conditions.
392  while (t1 != i->second.successors.end())
393  {
394  const spot::state* dest = t1->dest;
395  if (dest != last_dest)
396  {
397  last_dest = dest;
398  dmi = dm.find(dest);
399  if (dmi == dm.end())
400  dmi = dm.insert(std::make_pair(dest, acc_map())).first;
401  }
402  int acc = t1->acceptance_conditions.id();
403  typename acc_map::iterator it = dmi->second.find(acc);
404  if (it == dmi->second.end())
405  {
406  dmi->second[acc] = t1;
407  ++t1;
408  }
409  else
410  {
411  it->second->condition |= t1->condition;
412  t1 = i->second.successors.erase(t1);
413  }
414  }
415  }
416  }
417 
420  State* add_state(const label_t& name)
421  {
422  typename ls_map::iterator i = ls_.find(name);
423  if (i == ls_.end())
424  {
425  typename alias_map::iterator j = alias_.find(name);
426  if (j != alias_.end())
427  return j->second;
428 
429  State* res =
430  &(ls_.insert(std::make_pair(name, State(name))).first->second);
431  sl_[res] = name;
432  // The first state we add is the initial state.
433  // It can also be overridden with set_init_state().
434  if (!init_)
435  init_ = res;
436  return res;
437  }
438  return &(i->second);
439  }
440 
441  State*
443  {
444  State* s = add_state(state);
445  init_ = s;
446  return s;
447  }
448 
449  // tgba interface
450  virtual ~explicit_graph()
451  {
452  typename ls_map::iterator i = ls_.begin();
453 
454  while (i != ls_.end())
455  {
456  label_t s = i->first;
457  i->second.destroy();
458  ++i;
460  dest.destroy(s);
461  }
462 
463  this->dict_->unregister_all_my_variables(this);
464  // These have already been destroyed by subclasses.
465  // Prevent destroying by tgba::~tgba.
466  this->last_support_conditions_input_ = 0;
467  this->last_support_variables_input_ = 0;
468  }
469 
470  virtual State* get_init_state() const
471  {
472  if (!init_)
473  const_cast<explicit_graph<State, Type>*>(this)->add_default_init();
474 
475  return init_;
476  }
477 
480  const spot::state* global_state = 0,
481  const tgba* global_automaton = 0) const
482  {
483  const State* s = down_cast<const State*>(state);
484  assert(s);
485 
486  (void) global_state;
487  (void) global_automaton;
488 
489  return
491  this
492  ->all_acceptance_conditions());
493  }
494 
495 
496  typedef std::string (*to_string_func_t)(const label_t& t);
497 
499  {
500  to_string_func_ = f;
501  }
502 
504  {
505  return to_string_func_;
506  }
507 
508  virtual std::string format_state(const spot::state* state) const
509  {
510  const State* se = down_cast<const State*>(state);
511  assert(se);
512  typename sl_map::const_iterator i = sl_.find(se);
513  assert(i != sl_.end());
514  assert(to_string_func_);
515  return to_string_func_(i->second);
516  }
517 
520  void add_state_alias(const label_t& alias, const label_t& real)
521  {
522  alias_[alias] = add_state(real);
523  }
524 
525 
531  {
532  assert(neg_acceptance_conditions_ == bddtrue);
533  assert(all_acceptance_conditions_computed_ == false);
534  bdd f = a->neg_acceptance_conditions();
535  this->dict_->register_acceptance_variables(f, this);
537  }
538 
539 
542  {
543  assert(neg_acceptance_conditions_ == bddtrue);
544  assert(all_acceptance_conditions_computed_ == false);
545 
546  this->dict_->register_acceptance_variables(bdd_support(acc), this);
550  }
551 
553  {
554  bdd c = get_acceptance_condition(f);
555  t->acceptance_conditions |= c;
556  }
557 
561  {
562  bdd sup = bdd_support(f);
563  this->dict_->register_acceptance_variables(sup, this);
564  while (sup != bddtrue)
565  {
566  neg_acceptance_conditions_ &= bdd_nithvar(bdd_var(sup));
567  sup = bdd_high(sup);
568  }
569  t->acceptance_conditions |= f;
570  }
571 
572  virtual bdd all_acceptance_conditions() const
573  {
575  {
579  }
581  }
582 
583  virtual bdd_dict* get_dict() const
584  {
585  return this->dict_;
586  }
587 
588  virtual bdd neg_acceptance_conditions() const
589  {
591  }
592 
593  void
595  {
596  int v = this->dict_->register_acceptance_variable(f, this);
597  f->destroy();
598  bdd neg = bdd_nithvar(v);
600 
601  // Append neg to all acceptance conditions.
602 
603  // FIXME: Declaring acceptance conditions after the automaton
604  // has been constructed is very slow because we traverse the
605  // entire automaton for each new acceptance condition. It would
606  // be better to fix the automaton in a single pass after all
607  // acceptance conditions have been declared.
608  typename ls_map::iterator i;
609  for (i = this->ls_.begin(); i != this->ls_.end(); ++i)
610  {
611  typename transitions_t::iterator i2;
612  for (i2 = i->second.successors.begin();
613  i2 != i->second.successors.end(); ++i2)
614  i2->acceptance_conditions &= neg;
615  }
616 
618  }
619 
621  {
622  bdd_dict::fv_map::iterator i = this->dict_->acc_map.find(f);
623  assert(this->has_acceptance_condition(f));
624  f->destroy();
625  bdd v = bdd_ithvar(i->second);
626  v &= bdd_exist(neg_acceptance_conditions_, v);
627  return v;
628  }
629 
630  protected:
631 
632  virtual bdd compute_support_conditions(const spot::state* in) const
633  {
634  const State* s = down_cast<const State*>(in);
635  assert(s);
636  const transitions_t& st = s->successors;
637 
638  bdd res = bddfalse;
639 
640  typename transitions_t::const_iterator i;
641  for (i = st.begin(); i != st.end(); ++i)
642  res |= i->condition;
643 
644  return res;
645  }
646 
647  virtual bdd compute_support_variables(const spot::state* in) const
648  {
649  const State* s = down_cast<const State*>(in);
650  assert(s);
651  const transitions_t& st = s->successors;
652 
653  bdd res = bddtrue;
654 
655  typename transitions_t::const_iterator i;
656  for (i = st.begin(); i != st.end(); ++i)
657  res &= bdd_support(i->condition);
658 
659  return res;
660  }
661 
665  State* init_;
666 
668 
673  };
674 
675  template <typename State>
676  class tgba_explicit: public explicit_graph<State, tgba>
677  {
678  public:
680  {
681  }
682 
683  virtual ~tgba_explicit()
684  {
685  }
686 
687  private:
688  // Disallow copy.
689  tgba_explicit(const tgba_explicit<State>& other);
690  tgba_explicit& operator=(const tgba_explicit& other);
691  };
692 
693  template <typename State>
694  class sba_explicit: public explicit_graph<State, sba>
695  {
696  public:
697  sba_explicit(bdd_dict* dict): explicit_graph<State, sba>(dict)
698  {
699  }
700 
701  virtual ~sba_explicit()
702  {
703  }
704 
705  virtual bool state_is_accepting(const spot::state* s) const
706  {
707  const State* st = down_cast<const State*>(s);
708  // Assume that an accepting state has only accepting output transitions
709  // So we need only to check one to decide
710  if (st->successors.empty())
711  return false;
712  return (st->successors.front().acceptance_conditions
713  == this->all_acceptance_conditions());
714  }
715 
716  private:
717  // Disallow copy.
718  sba_explicit(const sba_explicit<State>& other);
719  sba_explicit& operator=(const sba_explicit& other);
720  };
721 
722 
723  // It is tempting to write
724  //
725  // template<template<typename T>class graph, typename Type>
726  // class explicit_conf: public graph<T>
727  //
728  // to simplify the typedefs at the end of the file, however swig
729  // cannot parse this syntax.
730 
733  template<class graph, typename Type>
734  class explicit_conf: public graph
735  {
736  public:
737  explicit_conf(bdd_dict* d): graph(d)
738  {
739  this->set_to_string_func(to_string);
740  };
741 
742  static std::string to_string(const typename Type::label_t& l)
743  {
744  std::stringstream ss;
745  ss << l;
746  return ss.str();
747  }
748  };
749 
750  template<class graph>
751  class explicit_conf<graph, state_explicit_string>: public graph
752  {
753  public:
754  explicit_conf(bdd_dict* d): graph(d)
755  {
756  this->set_to_string_func(to_string);
757  };
758 
759  static std::string to_string(const std::string& l)
760  {
761  return l;
762  }
763  };
764 
765  template<class graph>
766  class explicit_conf<graph, state_explicit_formula>: public graph
767  {
768  public:
769  explicit_conf(bdd_dict* d): graph(d)
770  {
771  this->set_to_string_func(to_string);
772  };
773 
774  // Enable UTF8 output for the formulae that label states.
775  void enable_utf8()
776  {
777  this->set_to_string_func(to_utf8_string);
778  }
779 
780  static std::string to_string(const ltl::formula* const& l)
781  {
782  return ltl::to_string(l);
783  }
784 
785  static std::string to_utf8_string(const ltl::formula* const& l)
786  {
787  return ltl::to_utf8_string(l);
788  }
789  };
790 
791 
792  // Typedefs for tgba
793  typedef explicit_conf<tgba_explicit<state_explicit_string>,
799 
800  // Typedefs for sba
807 }
808 
809 #endif // SPOT_TGBA_TGBAEXPLICIT_HH

Please comment this page and report errors about it on the RefDocComments page.
Generated on Wed Mar 6 2013 09:25:14 for spot by doxygen 1.8.1.2