spot  1.2.6
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
tgbaexplicit.hh
1 // -*- coding: utf-8 -*-
2 // Copyright (C) 2009, 2010, 2011, 2012, 2013 Laboratoire de Recherche
3 // et 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 SPOT_API destroy_key
42  {
43  void destroy(T t)
44  {
45  (void) t;
46  }
47  };
48 
49  template<>
50  struct SPOT_API 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>
61  class SPOT_API state_explicit: public spot::state
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;
87  bdd acceptance_conditions;
89  };
90 
91  typedef std::list<transition> transitions_t;
92  transitions_t successors;
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  {
107  down_cast<const state_explicit<Label, label_hash>*>(other);
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 
136  class SPOT_API state_explicit_number:
137  public state_explicit<int, identity_hash<int> >
138  {
139  public:
142  {
143  }
144 
145  state_explicit_number(int label)
147  {
148  }
149 
150  static const int default_val;
151  };
152 
155  class SPOT_API state_explicit_string:
156  public state_explicit<std::string, string_hash>
157  {
158  public:
161  {
162  }
163 
164  state_explicit_string(const std::string& label)
166  {
167  }
168 
169  static const std::string default_val;
170  };
171 
174  class SPOT_API state_explicit_formula:
175  public state_explicit<const ltl::formula*, ltl::formula_ptr_hash>
176  {
177  public:
180  {
181  }
182 
185  {
186  }
187 
188  static const ltl::formula* default_val;
189  };
190 
193  template<typename State>
195  public tgba_succ_iterator
196  {
197  public:
198  tgba_explicit_succ_iterator(const State* start,
199  bdd all_acc)
200  : start_(start),
201  all_acceptance_conditions_(all_acc)
202  {
203  }
204 
205  virtual void first()
206  {
207  it_ = start_->successors.begin();
208  }
209 
210  virtual void next()
211  {
212  ++it_;
213  }
214 
215  virtual bool done() const
216  {
217  return it_ == start_->successors.end();
218  }
219 
220  virtual State* current_state() const
221  {
222  assert(!done());
223  const State* res = down_cast<const State*>(it_->dest);
224  assert(res);
225  return const_cast<State*>(res);
226  }
227 
228  virtual bdd current_condition() const
229  {
230  assert(!done());
231  return it_->condition;
232  }
233 
234  virtual bdd current_acceptance_conditions() const
235  {
236  assert(!done());
237  return it_->acceptance_conditions;
238  }
239 
240  typename State::transitions_t::const_iterator
241  get_iterator() const
242  {
243  return it_;
244  }
245 
246  private:
247  const State* start_;
248  typename State::transitions_t::const_iterator it_;
249  bdd all_acceptance_conditions_;
250  };
251 
254  template<typename State, typename Type>
255  class SPOT_API explicit_graph: public Type
256  {
257  public:
258  typedef typename State::label_t label_t;
259  typedef typename State::label_hash_t label_hash_t;
260  typedef typename State::transitions_t transitions_t;
261  typedef typename State::transition transition;
262  typedef State state;
263  protected:
264  typedef Sgi::hash_map<label_t, State, label_hash_t> ls_map;
265  typedef Sgi::hash_map<label_t, State*, label_hash_t> alias_map;
266  typedef Sgi::hash_map<const State*, label_t, ptr_hash<State> > sl_map;
267 
268  public:
269 
270  explicit_graph(bdd_dict* dict)
271  : ls_(),
272  sl_(),
273  init_(0),
274  dict_(dict),
275  all_acceptance_conditions_(bddfalse),
276  all_acceptance_conditions_computed_(false),
277  neg_acceptance_conditions_(bddtrue)
278  {
279  }
280 
281  State* add_default_init()
282  {
283  return add_state(State::default_val);
284  }
285 
286  size_t num_states() const
287  {
288  return sl_.size();
289  }
290 
291  transition*
292  create_transition(State* source, const State* dest)
293  {
294  transition t;
295 
296  t.dest = dest;
297  t.condition = bddtrue;
298  t.acceptance_conditions = bddfalse;
299 
300  typename transitions_t::iterator i =
301  source->successors.insert(source->successors.end(), t);
302 
303  return &*i;
304  }
305 
306  transition*
307  create_transition(const label_t& source, const label_t& dest)
308  {
309  // It's important that the source be created before the
310  // destination, so the first source encountered becomes the
311  // default initial state.
312  State* s = add_state(source);
313  return create_transition(s, add_state(dest));
314  }
315 
316  transition*
317  get_transition(const tgba_explicit_succ_iterator<State>* si)
318  {
319  return const_cast<transition*>(&(*(si->get_iterator())));
320  }
321 
322  transition*
323  get_transition(const tgba_succ_iterator* si)
324  {
326  = down_cast<const tgba_explicit_succ_iterator<State>*>(si);
327  assert(tmp);
328  return get_transition(tmp);
329  }
330 
331  void add_condition(transition* t, const ltl::formula* f)
332  {
333  t->condition &= formula_to_bdd(f, dict_, this);
334  f->destroy();
335  }
336 
338  void add_conditions(transition* t, bdd f)
339  {
340  dict_->register_propositions(f, this);
341  t->condition &= f;
342  }
343 
344  bool has_acceptance_condition(const ltl::formula* f) const
345  {
346  return dict_->is_registered_acceptance_variable(f, this);
347  }
348 
349  //old tgba explicit labeled interface
350  bool has_state(const label_t& name)
351  {
352  return ls_.find(name) != ls_.end();
353  }
354 
359  const State* get_state(const label_t& name)
360  {
361  typename ls_map::const_iterator i = ls_.find(name);
362  if (i == ls_.end())
363  return 0;
364  return &i->second;
365  }
366 
367  const label_t& get_label(const State* s) const
368  {
369  typename sl_map::const_iterator i = sl_.find(s);
370  assert(i != sl_.end());
371  return i->second;
372  }
373 
374  const label_t& get_label(const spot::state* s) const
375  {
376  const State* se = down_cast<const State*>(s);
377  assert(se);
378  return get_label(se);
379  }
380 
381  void
382  complement_all_acceptance_conditions()
383  {
384  bdd all = this->all_acceptance_conditions();
385  typename ls_map::iterator i;
386  for (i = ls_.begin(); i != ls_.end(); ++i)
387  {
388  typename transitions_t::iterator i2;
389  for (i2 = i->second.successors.begin();
390  i2 != i->second.successors.end(); ++i2)
391  i2->acceptance_conditions = all - i2->acceptance_conditions;
392  }
393  }
394 
395  void
396  merge_transitions()
397  {
398  typedef typename transitions_t::iterator trans_t;
399  typedef std::map<int, trans_t> acc_map;
400  typedef Sgi::hash_map<const spot::state*, acc_map,
401  ptr_hash<spot::state> > dest_map;
402 
403  typename ls_map::iterator i;
404  for (i = ls_.begin(); i != ls_.end(); ++i)
405  {
406  const spot::state* last_dest = 0;
407  dest_map dm;
408  typename dest_map::iterator dmi = dm.end();
409  typename transitions_t::iterator t1 = i->second.successors.begin();
410 
411  // Loop over all outgoing transitions (cond,acc,dest), and
412  // store them into dest_map[dest][acc] so that we can merge
413  // conditions.
414  while (t1 != i->second.successors.end())
415  {
416  const spot::state* dest = t1->dest;
417  if (dest != last_dest)
418  {
419  last_dest = dest;
420  dmi = dm.find(dest);
421  if (dmi == dm.end())
422  dmi = dm.insert(std::make_pair(dest, acc_map())).first;
423  }
424  int acc = t1->acceptance_conditions.id();
425  typename acc_map::iterator it = dmi->second.find(acc);
426  if (it == dmi->second.end())
427  {
428  dmi->second[acc] = t1;
429  ++t1;
430  }
431  else
432  {
433  it->second->condition |= t1->condition;
434  t1 = i->second.successors.erase(t1);
435  }
436  }
437  }
438  }
439 
442  State* add_state(const label_t& name)
443  {
444  typename ls_map::iterator i = ls_.find(name);
445  if (i == ls_.end())
446  {
447  typename alias_map::iterator j = alias_.find(name);
448  if (j != alias_.end())
449  return j->second;
450 
451  State* res =
452  &(ls_.insert(std::make_pair(name, State(name))).first->second);
453  sl_[res] = name;
454  // The first state we add is the initial state.
455  // It can also be overridden with set_init_state().
456  if (!init_)
457  init_ = res;
458  return res;
459  }
460  return &(i->second);
461  }
462 
463  State*
464  set_init_state(const label_t& state)
465  {
466  State* s = add_state(state);
467  init_ = s;
468  return s;
469  }
470 
471  // tgba interface
472  virtual ~explicit_graph()
473  {
474  typename ls_map::iterator i = ls_.begin();
475 
476  while (i != ls_.end())
477  {
478  label_t s = i->first;
479  i->second.destroy();
480  ++i;
481  destroy_key<label_t> dest;
482  dest.destroy(s);
483  }
484 
485  this->dict_->unregister_all_my_variables(this);
486  // These have already been destroyed by subclasses.
487  // Prevent destroying by tgba::~tgba.
488  this->last_support_conditions_input_ = 0;
489  this->last_support_variables_input_ = 0;
490  }
491 
492  virtual State* get_init_state() const
493  {
494  if (!init_)
495  const_cast<explicit_graph<State, Type>*>(this)->add_default_init();
496 
497  return init_;
498  }
499 
500  virtual tgba_explicit_succ_iterator<State>*
501  succ_iter(const spot::state* state,
502  const spot::state* global_state = 0,
503  const tgba* global_automaton = 0) const
504  {
505  const State* s = down_cast<const State*>(state);
506  assert(s);
507 
508  (void) global_state;
509  (void) global_automaton;
510 
511  return
512  new tgba_explicit_succ_iterator<State>(s,
513  this
514  ->all_acceptance_conditions());
515  }
516 
517 
518  typedef std::string (*to_string_func_t)(const label_t& t);
519 
520  void set_to_string_func(to_string_func_t f)
521  {
522  to_string_func_ = f;
523  }
524 
525  to_string_func_t get_to_string_func() const
526  {
527  return to_string_func_;
528  }
529 
530  virtual std::string format_state(const spot::state* state) const
531  {
532  const State* se = down_cast<const State*>(state);
533  assert(se);
534  typename sl_map::const_iterator i = sl_.find(se);
535  assert(i != sl_.end());
536  assert(to_string_func_);
537  return to_string_func_(i->second);
538  }
539 
542  void add_state_alias(const label_t& alias, const label_t& real)
543  {
544  alias_[alias] = add_state(real);
545  }
546 
547 
553  {
554  assert(neg_acceptance_conditions_ == bddtrue);
555  assert(all_acceptance_conditions_computed_ == false);
556  bdd f = a->neg_acceptance_conditions();
557  this->dict_->register_acceptance_variables(f, this);
558  neg_acceptance_conditions_ = f;
559  }
560 
561 
564  {
565  assert(neg_acceptance_conditions_ == bddtrue);
566  assert(all_acceptance_conditions_computed_ == false);
567 
568  this->dict_->register_acceptance_variables(bdd_support(acc), this);
569  neg_acceptance_conditions_ = compute_neg_acceptance_conditions(acc);
570  all_acceptance_conditions_computed_ = true;
571  all_acceptance_conditions_ = acc;
572  }
573 
574  void add_acceptance_condition(transition* t, const ltl::formula* f)
575  {
576  bdd c = get_acceptance_condition(f);
577  t->acceptance_conditions |= c;
578  }
579 
582  void add_acceptance_conditions(transition* t, bdd f)
583  {
584  bdd sup = bdd_support(f);
585  this->dict_->register_acceptance_variables(sup, this);
586  while (sup != bddtrue)
587  {
588  neg_acceptance_conditions_ &= bdd_nithvar(bdd_var(sup));
589  sup = bdd_high(sup);
590  }
591  t->acceptance_conditions |= f;
592  }
593 
594  virtual bdd all_acceptance_conditions() const
595  {
596  if (!all_acceptance_conditions_computed_)
597  {
598  all_acceptance_conditions_ =
599  compute_all_acceptance_conditions(neg_acceptance_conditions_);
600  all_acceptance_conditions_computed_ = true;
601  }
602  return all_acceptance_conditions_;
603  }
604 
605  virtual bdd_dict* get_dict() const
606  {
607  return this->dict_;
608  }
609 
610  virtual bdd neg_acceptance_conditions() const
611  {
612  return neg_acceptance_conditions_;
613  }
614 
615  void
616  declare_acceptance_condition(const ltl::formula* f)
617  {
618  int v = this->dict_->register_acceptance_variable(f, this);
619  f->destroy();
620  bdd neg = bdd_nithvar(v);
621  neg_acceptance_conditions_ &= neg;
622 
623  // Append neg to all acceptance conditions.
624 
625  // FIXME: Declaring acceptance conditions after the automaton
626  // has been constructed is very slow because we traverse the
627  // entire automaton for each new acceptance condition. It would
628  // be better to fix the automaton in a single pass after all
629  // acceptance conditions have been declared.
630  typename ls_map::iterator i;
631  for (i = this->ls_.begin(); i != this->ls_.end(); ++i)
632  {
633  typename transitions_t::iterator i2;
634  for (i2 = i->second.successors.begin();
635  i2 != i->second.successors.end(); ++i2)
636  i2->acceptance_conditions &= neg;
637  }
638 
639  all_acceptance_conditions_computed_ = false;
640  }
641 
642  bdd get_acceptance_condition(const ltl::formula* f)
643  {
644  bdd_dict::fv_map::iterator i = this->dict_->acc_map.find(f);
645  assert(this->has_acceptance_condition(f));
646  f->destroy();
647  bdd v = bdd_ithvar(i->second);
648  v &= bdd_exist(neg_acceptance_conditions_, v);
649  return v;
650  }
651 
652  protected:
653 
654  virtual bdd compute_support_conditions(const spot::state* in) const
655  {
656  const State* s = down_cast<const State*>(in);
657  assert(s);
658  const transitions_t& st = s->successors;
659 
660  bdd res = bddfalse;
661 
662  typename transitions_t::const_iterator i;
663  for (i = st.begin(); i != st.end(); ++i)
664  res |= i->condition;
665 
666  return res;
667  }
668 
669  virtual bdd compute_support_variables(const spot::state* in) const
670  {
671  const State* s = down_cast<const State*>(in);
672  assert(s);
673  const transitions_t& st = s->successors;
674 
675  bdd res = bddtrue;
676 
677  typename transitions_t::const_iterator i;
678  for (i = st.begin(); i != st.end(); ++i)
679  res &= bdd_support(i->condition);
680 
681  return res;
682  }
683 
684  ls_map ls_;
685  alias_map alias_;
686  sl_map sl_;
687  State* init_;
688 
689  bdd_dict* dict_;
690 
691  mutable bdd all_acceptance_conditions_;
692  mutable bool all_acceptance_conditions_computed_;
693  bdd neg_acceptance_conditions_;
694  to_string_func_t to_string_func_;
695  };
696 
697  template <typename State>
698  class SPOT_API tgba_explicit:
699  public explicit_graph<State, tgba>
700  {
701  public:
703  {
704  }
705 
706  virtual ~tgba_explicit()
707  {
708  }
709 
710  private:
711  // Disallow copy.
712  tgba_explicit(const tgba_explicit<State>& other);
713  tgba_explicit& operator=(const tgba_explicit& other);
714  };
715 
716  template <typename State>
717  class SPOT_API sba_explicit:
718  public explicit_graph<State, sba>
719  {
720  public:
722  {
723  }
724 
725  virtual ~sba_explicit()
726  {
727  }
728 
729  virtual bool state_is_accepting(const spot::state* s) const
730  {
731  const State* st = down_cast<const State*>(s);
732  // Assume that an accepting state has only accepting output transitions
733  // So we need only to check one to decide
734  if (st->successors.empty())
735  return false;
736  return (st->successors.front().acceptance_conditions
737  == this->all_acceptance_conditions());
738  }
739 
740  private:
741  // Disallow copy.
742  sba_explicit(const sba_explicit<State>& other);
743  sba_explicit& operator=(const sba_explicit& other);
744  };
745 
746 
747  // It is tempting to write
748  //
749  // template<template<typename T>class graph, typename Type>
750  // class explicit_conf: public graph<T>
751  //
752  // to simplify the typedefs at the end of the file, however swig
753  // cannot parse this syntax.
754 
757  template<class graph, typename Type>
758  class SPOT_API explicit_conf: public graph
759  {
760  public:
761  explicit_conf(bdd_dict* d): graph(d)
762  {
763  this->set_to_string_func(to_string);
764  };
765 
766  static std::string to_string(const typename Type::label_t& l)
767  {
768  std::stringstream ss;
769  ss << l;
770  return ss.str();
771  }
772  };
773 
774  template<class graph>
775  class SPOT_API explicit_conf<graph, state_explicit_string>: public graph
776  {
777  public:
778  explicit_conf(bdd_dict* d): graph(d)
779  {
780  this->set_to_string_func(to_string);
781  };
782 
783  static std::string to_string(const std::string& l)
784  {
785  return l;
786  }
787  };
788 
789  template<class graph>
790  class SPOT_API explicit_conf<graph, state_explicit_formula>: public graph
791  {
792  public:
793  explicit_conf(bdd_dict* d): graph(d)
794  {
795  this->set_to_string_func(to_string);
796  };
797 
798  // Enable UTF8 output for the formulae that label states.
799  void enable_utf8()
800  {
801  this->set_to_string_func(to_utf8_string);
802  }
803 
804  static std::string to_string(const ltl::formula* const& l)
805  {
806  return ltl::to_string(l);
807  }
808 
809  static std::string to_utf8_string(const ltl::formula* const& l)
810  {
811  return ltl::to_utf8_string(l);
812  }
813  };
814 
815 
816  // Typedefs for tgba
823 
824  // Typedefs for sba
831 }
832 
833 #endif // SPOT_TGBA_TGBAEXPLICIT_HH

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on Sat Dec 6 2014 12:28:44 for spot by doxygen 1.8.4