spot  1.1.4
tgbaexplicit.hh
Go to the documentation of this file.
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 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 
321  transition*
323  {
326  assert(tmp);
327  return get_transition(tmp);
328  }
329 
331  {
332  t->condition &= formula_to_bdd(f, dict_, this);
333  f->destroy();
334  }
335 
337  void add_conditions(transition* t, bdd f)
338  {
339  dict_->register_propositions(f, this);
340  t->condition &= f;
341  }
342 
344  {
345  return dict_->is_registered_acceptance_variable(f, this);
346  }
347 
348  //old tgba explicit labeled interface
349  bool has_state(const label_t& name)
350  {
351  return ls_.find(name) != ls_.end();
352  }
353 
358  const State* get_state(const label_t& name)
359  {
360  typename ls_map::const_iterator i = ls_.find(name);
361  if (i == ls_.end())
362  return 0;
363  return &i->second;
364  }
365 
366  const label_t& get_label(const State* s) const
367  {
368  typename sl_map::const_iterator i = sl_.find(s);
369  assert(i != sl_.end());
370  return i->second;
371  }
372 
373  const label_t& get_label(const spot::state* s) const
374  {
375  const State* se = down_cast<const State*>(s);
376  assert(se);
377  return get_label(se);
378  }
379 
380  void
382  {
383  bdd all = this->all_acceptance_conditions();
384  typename ls_map::iterator i;
385  for (i = ls_.begin(); i != ls_.end(); ++i)
386  {
387  typename transitions_t::iterator i2;
388  for (i2 = i->second.successors.begin();
389  i2 != i->second.successors.end(); ++i2)
390  i2->acceptance_conditions = all - i2->acceptance_conditions;
391  }
392  }
393 
394  void
396  {
397  typedef typename transitions_t::iterator trans_t;
398  typedef std::map<int, trans_t> acc_map;
399  typedef Sgi::hash_map<const spot::state*, acc_map,
400  ptr_hash<spot::state> > dest_map;
401 
402  typename ls_map::iterator i;
403  for (i = ls_.begin(); i != ls_.end(); ++i)
404  {
405  const spot::state* last_dest = 0;
406  dest_map dm;
407  typename dest_map::iterator dmi = dm.end();
408  typename transitions_t::iterator t1 = i->second.successors.begin();
409 
410  // Loop over all outgoing transitions (cond,acc,dest), and
411  // store them into dest_map[dest][acc] so that we can merge
412  // conditions.
413  while (t1 != i->second.successors.end())
414  {
415  const spot::state* dest = t1->dest;
416  if (dest != last_dest)
417  {
418  last_dest = dest;
419  dmi = dm.find(dest);
420  if (dmi == dm.end())
421  dmi = dm.insert(std::make_pair(dest, acc_map())).first;
422  }
423  int acc = t1->acceptance_conditions.id();
424  typename acc_map::iterator it = dmi->second.find(acc);
425  if (it == dmi->second.end())
426  {
427  dmi->second[acc] = t1;
428  ++t1;
429  }
430  else
431  {
432  it->second->condition |= t1->condition;
433  t1 = i->second.successors.erase(t1);
434  }
435  }
436  }
437  }
438 
441  State* add_state(const label_t& name)
442  {
443  typename ls_map::iterator i = ls_.find(name);
444  if (i == ls_.end())
445  {
446  typename alias_map::iterator j = alias_.find(name);
447  if (j != alias_.end())
448  return j->second;
449 
450  State* res =
451  &(ls_.insert(std::make_pair(name, State(name))).first->second);
452  sl_[res] = name;
453  // The first state we add is the initial state.
454  // It can also be overridden with set_init_state().
455  if (!init_)
456  init_ = res;
457  return res;
458  }
459  return &(i->second);
460  }
461 
462  State*
464  {
465  State* s = add_state(state);
466  init_ = s;
467  return s;
468  }
469 
470  // tgba interface
471  virtual ~explicit_graph()
472  {
473  typename ls_map::iterator i = ls_.begin();
474 
475  while (i != ls_.end())
476  {
477  label_t s = i->first;
478  i->second.destroy();
479  ++i;
481  dest.destroy(s);
482  }
483 
484  this->dict_->unregister_all_my_variables(this);
485  // These have already been destroyed by subclasses.
486  // Prevent destroying by tgba::~tgba.
487  this->last_support_conditions_input_ = 0;
488  this->last_support_variables_input_ = 0;
489  }
490 
491  virtual State* get_init_state() const
492  {
493  if (!init_)
494  const_cast<explicit_graph<State, Type>*>(this)->add_default_init();
495 
496  return init_;
497  }
498 
501  const spot::state* global_state = 0,
502  const tgba* global_automaton = 0) const
503  {
504  const State* s = down_cast<const State*>(state);
505  assert(s);
506 
507  (void) global_state;
508  (void) global_automaton;
509 
510  return
512  this
513  ->all_acceptance_conditions());
514  }
515 
516 
517  typedef std::string (*to_string_func_t)(const label_t& t);
518 
520  {
521  to_string_func_ = f;
522  }
523 
525  {
526  return to_string_func_;
527  }
528 
529  virtual std::string format_state(const spot::state* state) const
530  {
531  const State* se = down_cast<const State*>(state);
532  assert(se);
533  typename sl_map::const_iterator i = sl_.find(se);
534  assert(i != sl_.end());
535  assert(to_string_func_);
536  return to_string_func_(i->second);
537  }
538 
541  void add_state_alias(const label_t& alias, const label_t& real)
542  {
543  alias_[alias] = add_state(real);
544  }
545 
546 
552  {
553  assert(neg_acceptance_conditions_ == bddtrue);
554  assert(all_acceptance_conditions_computed_ == false);
555  bdd f = a->neg_acceptance_conditions();
556  this->dict_->register_acceptance_variables(f, this);
558  }
559 
560 
563  {
564  assert(neg_acceptance_conditions_ == bddtrue);
565  assert(all_acceptance_conditions_computed_ == false);
566 
567  this->dict_->register_acceptance_variables(bdd_support(acc), this);
571  }
572 
574  {
575  bdd c = get_acceptance_condition(f);
576  t->acceptance_conditions |= c;
577  }
578 
582  {
583  bdd sup = bdd_support(f);
584  this->dict_->register_acceptance_variables(sup, this);
585  while (sup != bddtrue)
586  {
587  neg_acceptance_conditions_ &= bdd_nithvar(bdd_var(sup));
588  sup = bdd_high(sup);
589  }
590  t->acceptance_conditions |= f;
591  }
592 
593  virtual bdd all_acceptance_conditions() const
594  {
596  {
600  }
602  }
603 
604  virtual bdd_dict* get_dict() const
605  {
606  return this->dict_;
607  }
608 
609  virtual bdd neg_acceptance_conditions() const
610  {
612  }
613 
614  void
616  {
617  int v = this->dict_->register_acceptance_variable(f, this);
618  f->destroy();
619  bdd neg = bdd_nithvar(v);
621 
622  // Append neg to all acceptance conditions.
623 
624  // FIXME: Declaring acceptance conditions after the automaton
625  // has been constructed is very slow because we traverse the
626  // entire automaton for each new acceptance condition. It would
627  // be better to fix the automaton in a single pass after all
628  // acceptance conditions have been declared.
629  typename ls_map::iterator i;
630  for (i = this->ls_.begin(); i != this->ls_.end(); ++i)
631  {
632  typename transitions_t::iterator i2;
633  for (i2 = i->second.successors.begin();
634  i2 != i->second.successors.end(); ++i2)
635  i2->acceptance_conditions &= neg;
636  }
637 
639  }
640 
642  {
643  bdd_dict::fv_map::iterator i = this->dict_->acc_map.find(f);
644  assert(this->has_acceptance_condition(f));
645  f->destroy();
646  bdd v = bdd_ithvar(i->second);
647  v &= bdd_exist(neg_acceptance_conditions_, v);
648  return v;
649  }
650 
651  protected:
652 
653  virtual bdd compute_support_conditions(const spot::state* in) const
654  {
655  const State* s = down_cast<const State*>(in);
656  assert(s);
657  const transitions_t& st = s->successors;
658 
659  bdd res = bddfalse;
660 
661  typename transitions_t::const_iterator i;
662  for (i = st.begin(); i != st.end(); ++i)
663  res |= i->condition;
664 
665  return res;
666  }
667 
668  virtual bdd compute_support_variables(const spot::state* in) const
669  {
670  const State* s = down_cast<const State*>(in);
671  assert(s);
672  const transitions_t& st = s->successors;
673 
674  bdd res = bddtrue;
675 
676  typename transitions_t::const_iterator i;
677  for (i = st.begin(); i != st.end(); ++i)
678  res &= bdd_support(i->condition);
679 
680  return res;
681  }
682 
686  State* init_;
687 
689 
694  };
695 
696  template <typename State>
697  class tgba_explicit: public explicit_graph<State, tgba>
698  {
699  public:
701  {
702  }
703 
704  virtual ~tgba_explicit()
705  {
706  }
707 
708  private:
709  // Disallow copy.
710  tgba_explicit(const tgba_explicit<State>& other);
711  tgba_explicit& operator=(const tgba_explicit& other);
712  };
713 
714  template <typename State>
715  class sba_explicit: public explicit_graph<State, sba>
716  {
717  public:
718  sba_explicit(bdd_dict* dict): explicit_graph<State, sba>(dict)
719  {
720  }
721 
722  virtual ~sba_explicit()
723  {
724  }
725 
726  virtual bool state_is_accepting(const spot::state* s) const
727  {
728  const State* st = down_cast<const State*>(s);
729  // Assume that an accepting state has only accepting output transitions
730  // So we need only to check one to decide
731  if (st->successors.empty())
732  return false;
733  return (st->successors.front().acceptance_conditions
734  == this->all_acceptance_conditions());
735  }
736 
737  private:
738  // Disallow copy.
739  sba_explicit(const sba_explicit<State>& other);
740  sba_explicit& operator=(const sba_explicit& other);
741  };
742 
743 
744  // It is tempting to write
745  //
746  // template<template<typename T>class graph, typename Type>
747  // class explicit_conf: public graph<T>
748  //
749  // to simplify the typedefs at the end of the file, however swig
750  // cannot parse this syntax.
751 
754  template<class graph, typename Type>
755  class explicit_conf: public graph
756  {
757  public:
758  explicit_conf(bdd_dict* d): graph(d)
759  {
760  this->set_to_string_func(to_string);
761  };
762 
763  static std::string to_string(const typename Type::label_t& l)
764  {
765  std::stringstream ss;
766  ss << l;
767  return ss.str();
768  }
769  };
770 
771  template<class graph>
772  class explicit_conf<graph, state_explicit_string>: public graph
773  {
774  public:
775  explicit_conf(bdd_dict* d): graph(d)
776  {
777  this->set_to_string_func(to_string);
778  };
779 
780  static std::string to_string(const std::string& l)
781  {
782  return l;
783  }
784  };
785 
786  template<class graph>
787  class explicit_conf<graph, state_explicit_formula>: public graph
788  {
789  public:
790  explicit_conf(bdd_dict* d): graph(d)
791  {
792  this->set_to_string_func(to_string);
793  };
794 
795  // Enable UTF8 output for the formulae that label states.
796  void enable_utf8()
797  {
798  this->set_to_string_func(to_utf8_string);
799  }
800 
801  static std::string to_string(const ltl::formula* const& l)
802  {
803  return ltl::to_string(l);
804  }
805 
806  static std::string to_utf8_string(const ltl::formula* const& l)
807  {
808  return ltl::to_utf8_string(l);
809  }
810  };
811 
812 
813  // Typedefs for tgba
814  typedef explicit_conf<tgba_explicit<state_explicit_string>,
820 
821  // Typedefs for sba
828 }
829 
830 #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 Mon Jul 29 2013 00:27:24 for spot by doxygen 1.8.4