spot  0.9.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 2 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 Spot; see the file COPYING. If not, write to the Free
22 // Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23 // 02111-1307, USA.
24 
25 #ifndef SPOT_TGBA_TGBAEXPLICIT_HH
26 # define SPOT_TGBA_TGBAEXPLICIT_HH
27 
28 #include <sstream>
29 #include <list>
30 
31 #include "tgba.hh"
32 #include "sba.hh"
33 #include "tgba/formula2bdd.hh"
34 #include "misc/hash.hh"
35 #include "misc/bddop.hh"
36 #include "ltlast/formula.hh"
37 #include "ltlvisit/tostring.hh"
38 
39 namespace spot
40 {
41  // How to destroy the label of a state.
42  template<typename T>
43  struct destroy_key
44  {
45  void destroy(T t)
46  {
47  (void) t;
48  }
49  };
50 
51  template<>
52  struct destroy_key<const ltl::formula*>
53  {
54  void destroy(const ltl::formula* t)
55  {
56  t->destroy();
57  }
58  };
59 
62  template<typename Label, typename label_hash>
64  {
65  public:
67  {
68  }
69 
70  state_explicit(const Label& l):
71  label_(l)
72  {
73  }
74 
75  virtual ~state_explicit()
76  {
77  }
78 
79  virtual void destroy() const
80  {
81  }
82 
83  typedef Label label_t;
84  typedef label_hash label_hash_t;
85 
86  struct transition
87  {
88  bdd condition;
91  };
92 
93  typedef std::list<transition> transitions_t;
95 
96  const Label& label() const
97  {
98  return label_;
99  }
100 
101  bool empty() const
102  {
103  return successors.empty();
104  }
105 
106  virtual int compare(const state* other) const
107  {
110  assert (s);
111 
112  // Do not simply return "o - this", it might not fit in an int.
113  if (s < this)
114  return -1;
115  if (s > this)
116  return 1;
117  return 0;
118  }
119 
120  virtual size_t hash() const
121  {
122  return
123  reinterpret_cast<const char*>(this) - static_cast<const char*>(0);
124  }
125 
127  clone() const
128  {
129  return const_cast<state_explicit<Label, label_hash>*>(this);
130  }
131 
132  protected:
133  Label label_;
134  };
135 
139  public state_explicit<int, identity_hash<int> >
140  {
141  public:
143  : state_explicit<int, identity_hash<int> >()
144  {
145  }
146 
148  : state_explicit<int, identity_hash<int> >(label)
149  {
150  }
151 
152  static const int default_val;
153  };
154 
158  public state_explicit<std::string, string_hash>
159  {
160  public:
162  state_explicit<std::string, string_hash>()
163  {
164  }
165 
166  state_explicit_string(const std::string& label)
167  : state_explicit<std::string, string_hash>(label)
168  {
169  }
170 
171  static const std::string default_val;
172  };
173 
177  public state_explicit<const ltl::formula*, ltl::formula_ptr_hash>
178  {
179  public:
181  state_explicit<const ltl::formula*, ltl::formula_ptr_hash>()
182  {
183  }
184 
186  : state_explicit<const ltl::formula*, ltl::formula_ptr_hash>(label)
187  {
188  }
189 
190  static const ltl::formula* default_val;
191  };
192 
195  template<typename State>
197  {
198  public:
199  tgba_explicit_succ_iterator(const State* start,
200  bdd all_acc)
201  : start_(start),
203  {
204  }
205 
206  virtual void first()
207  {
208  it_ = start_->successors.begin();
209  }
210 
211  virtual void next()
212  {
213  ++it_;
214  }
215 
216  virtual bool done() const
217  {
218  return it_ == start_->successors.end();
219  }
220 
221  virtual State* current_state() const
222  {
223  assert(!done());
224  const State* res = down_cast<const State*>(it_->dest);
225  assert(res);
226  return const_cast<State*>(res);
227  }
228 
229  virtual bdd current_condition() const
230  {
231  assert(!done());
232  return it_->condition;
233  }
234 
235  virtual bdd current_acceptance_conditions() const
236  {
237  assert(!done());
238  return it_->acceptance_conditions;
239  }
240 
241  typename State::transitions_t::const_iterator
242  get_iterator() const
243  {
244  return it_;
245  }
246 
247  private:
248  const State* start_;
249  typename State::transitions_t::const_iterator it_;
251  };
252 
255  template<typename State, typename Type>
256  class explicit_graph: public Type
257  {
258  public:
259  typedef typename State::label_t label_t;
260  typedef typename State::label_hash_t label_hash_t;
261  typedef typename State::transitions_t transitions_t;
262  typedef typename State::transition transition;
263  typedef State state;
264  protected:
265  typedef Sgi::hash_map<label_t, State, label_hash_t> ls_map;
266  typedef Sgi::hash_map<const State*, label_t, ptr_hash<State> > sl_map;
267 
268  public:
269 
271  : ls_(),
272  sl_(),
273  init_(0),
274  dict_(dict),
275  all_acceptance_conditions_(bddfalse),
278  {
279  }
280 
282  {
283  return add_state(State::default_val);
284  }
285 
286  transition*
287  create_transition(State* source, const State* dest)
288  {
289  transition t;
290 
291  t.dest = dest;
292  t.condition = bddtrue;
293  t.acceptance_conditions = bddfalse;
294 
295  typename transitions_t::iterator i =
296  source->successors.insert(source->successors.end(), t);
297 
298  return &*i;
299  }
300 
301  transition*
302  create_transition(const label_t& source, const label_t& dest)
303  {
304  // It's important that the source be created before the
305  // destination, so the first source encountered becomes the
306  // default initial state.
307  State* s = add_state(source);
308  return create_transition(s, add_state(dest));
309  }
310 
311  transition*
313  {
314  return const_cast<transition*>(&(*(si->get_iterator())));
315  }
316 
318  {
319  t->condition &= formula_to_bdd(f, dict_, this);
320  f->destroy();
321  }
322 
324  void add_conditions(transition* t, bdd f)
325  {
326  dict_->register_propositions(f, this);
327  t->condition &= f;
328  }
329 
331  {
332  return dict_->is_registered_acceptance_variable(f, this);
333  }
334 
335  //old tgba explicit labelled interface
336  bool has_state(const label_t& name)
337  {
338  return ls_.find(name) != ls_.end();
339  }
340 
341  const label_t& get_label(const State* s) const
342  {
343  typename sl_map::const_iterator i = sl_.find(s);
344  assert(i != sl_.end());
345  return i->second;
346  }
347 
348  const label_t& get_label(const spot::state* s) const
349  {
350  const State* se = down_cast<const State*>(s);
351  assert(se);
352  return get_label(se);
353  }
354 
355  transition*
356  create_trainsition(const label_t& source, const label_t& dest)
357  {
358  // It's important that the source be created before the
359  // destination, so the first source encountered becomes the
360  // default initial state.
361  State* s = add_state(source);
362  return create_transition(s, add_state(dest));
363  }
364 
365  void
367  {
368  bdd all = this->all_acceptance_conditions();
369  typename ls_map::iterator i;
370  for (i = ls_.begin(); i != ls_.end(); ++i)
371  {
372  typename transitions_t::iterator i2;
373  for (i2 = i->second.successors.begin();
374  i2 != i->second.successors.end(); ++i2)
375  i2->acceptance_conditions = all - i2->acceptance_conditions;
376  }
377  }
378 
379  void
381  {
382  typename ls_map::iterator i;
383  for (i = ls_.begin(); i != ls_.end(); ++i)
384  {
385  typename transitions_t::iterator t1;
386  for (t1 = i->second.successors.begin();
387  t1 != i->second.successors.end(); ++t1)
388  {
389  bdd acc = t1->acceptance_conditions;
390  const state_explicit<label_t, label_hash_t>* dest = t1->dest;
391 
392  // Find another transition with the same destination and
393  // acceptance conditions.
394  typename transitions_t::iterator t2 = t1;
395  ++t2;
396  while (t2 != i->second.successors.end())
397  {
398  typename transitions_t::iterator t2copy = t2++;
399  if (t2copy->acceptance_conditions == acc && t2copy->dest == dest)
400  {
401  t1->condition |= t2copy->condition;
402  i->second.successors.erase(t2copy);
403  }
404  }
405  }
406  }
407  }
408 
411  State* add_state(const label_t& name)
412  {
413  typename ls_map::iterator i = ls_.find(name);
414  if (i == ls_.end())
415  {
416  State s(name);
417  ls_[name] = s;
418  sl_[&ls_[name]] = name;
419 
420  // The first state we add is the inititial state.
421  // It can also be overridden with set_init_state().
422  if (!init_)
423  init_ = &ls_[name];
424 
425  return &(ls_[name]);
426  }
427  return &(i->second);
428  }
429 
430  State*
432  {
433  State* s = add_state(state);
434  init_ = s;
435  return s;
436  }
437 
438  // tgba interface
439  virtual ~explicit_graph()
440  {
441  typename ls_map::iterator i = ls_.begin();
442 
443  while (i != ls_.end())
444  {
445  label_t s = i->first;
446 
447  // Do not erase the same state twice(Because of possible aliases).
448  if (sl_.erase(&(i->second)))
449  i->second.destroy();
450 
451  ++i;
453  dest.destroy(s);
454  }
455 
456  this->dict_->unregister_all_my_variables(this);
457  // These have already been destroyed by subclasses.
458  // Prevent destroying by tgba::~tgba.
459  this->last_support_conditions_input_ = 0;
460  this->last_support_variables_input_ = 0;
461  }
462 
463  virtual State* get_init_state() const
464  {
465  if (!init_)
466  const_cast<explicit_graph<State, Type>*>(this)->add_default_init();
467 
468  return init_;
469  }
470 
473  const spot::state* global_state = 0,
474  const tgba* global_automaton = 0) const
475  {
476  const State* s = down_cast<const State*>(state);
477  assert(s);
478 
479  (void) global_state;
480  (void) global_automaton;
481 
482  return
484  this
485  ->all_acceptance_conditions());
486  }
487 
488 
489  typedef std::string (*to_string_func_t)(const label_t& t);
490 
492  {
493  to_string_func_ = f;
494  }
495 
497  {
498  return to_string_func_;
499  }
500 
501  virtual std::string format_state(const spot::state* state) const
502  {
503  const State* se = down_cast<const State*>(state);
504  assert(se);
505  typename sl_map::const_iterator i = sl_.find(se);
506  assert(i != sl_.end());
507  assert(to_string_func_);
508  return to_string_func_(i->second);
509  }
510 
514  void add_state_alias(const label_t& alias, const label_t& real)
515  {
516  ls_[alias] = *(add_state(real));
517  }
518 
519 
525  {
526  assert(neg_acceptance_conditions_ == bddtrue);
527  assert(all_acceptance_conditions_computed_ == false);
528  bdd f = a->neg_acceptance_conditions();
529  this->dict_->register_acceptance_variables(f, this);
531  }
532 
533 
536  {
537  assert(neg_acceptance_conditions_ == bddtrue);
538  assert(all_acceptance_conditions_computed_ == false);
539 
540  this->dict_->register_acceptance_variables(bdd_support(acc), this);
544  }
545 
547  {
548  bdd c = get_acceptance_condition(f);
549  t->acceptance_conditions |= c;
550  }
551 
555  {
556  bdd sup = bdd_support(f);
557  this->dict_->register_acceptance_variables(sup, this);
558  while (sup != bddtrue)
559  {
560  neg_acceptance_conditions_ &= bdd_nithvar(bdd_var(sup));
561  sup = bdd_high(sup);
562  }
563  t->acceptance_conditions |= f;
564  }
565 
566  virtual bdd all_acceptance_conditions() const
567  {
569  {
573  }
575  }
576 
577  virtual bdd_dict* get_dict() const
578  {
579  return this->dict_;
580  }
581 
582  virtual bdd neg_acceptance_conditions() const
583  {
585  }
586 
587  void
589  {
590  int v = this->dict_->register_acceptance_variable(f, this);
591  f->destroy();
592  bdd neg = bdd_nithvar(v);
594 
595  // Append neg to all acceptance conditions.
597  for (i = this->ls_.begin(); i != this->ls_.end(); ++i)
598  {
599  typename transitions_t::iterator i2;
600  for (i2 = i->second.successors.begin();
601  i2 != i->second.successors.end(); ++i2)
602  i2->acceptance_conditions &= neg;
603  }
604 
606  }
607 
608  protected:
609 
611  {
612  bdd_dict::fv_map::iterator i = this->dict_->acc_map.find(f);
613  assert(this->has_acceptance_condition(f));
614  f->destroy();
615  bdd v = bdd_ithvar(i->second);
616  v &= bdd_exist(neg_acceptance_conditions_, v);
617  return v;
618  }
619 
620  virtual bdd compute_support_conditions(const spot::state* in) const
621  {
622  const State* s = down_cast<const State*>(in);
623  assert(s);
624  const transitions_t& st = s->successors;
625 
626  bdd res = bddfalse;
627 
628  typename transitions_t::const_iterator i;
629  for (i = st.begin(); i != st.end(); ++i)
630  res |= i->condition;
631 
632  return res;
633  }
634 
635  virtual bdd compute_support_variables(const spot::state* in) const
636  {
637  const State* s = down_cast<const State*>(in);
638  assert(s);
639  const transitions_t& st = s->successors;
640 
641  bdd res = bddtrue;
642 
643  typename transitions_t::const_iterator i;
644  for (i = st.begin(); i != st.end(); ++i)
645  res &= bdd_support(i->condition);
646 
647  return res;
648  }
649 
652  State* init_;
653 
655 
660  };
661 
662  template <typename State>
663  class tgba_explicit: public explicit_graph<State, tgba>
664  {
665  public:
667  {
668  }
669 
670  virtual ~tgba_explicit()
671  {
672  }
673 
674  private:
675  // Disallow copy.
676  tgba_explicit(const tgba_explicit<State>& other);
677  tgba_explicit& operator=(const tgba_explicit& other);
678  };
679 
680  template <typename State>
681  class sba_explicit: public explicit_graph<State, sba>
682  {
683  public:
684  sba_explicit(bdd_dict* dict): explicit_graph<State, sba>(dict)
685  {
686  }
687 
688  virtual ~sba_explicit()
689  {
690  }
691 
692  virtual bool state_is_accepting(const spot::state* s) const
693  {
694  const State* st = down_cast<const State*>(s);
695  // Assume that an accepting state has only accepting output transitions
696  // So we need only to check one to decide
697  if (st->successors.empty())
698  return false;
699  return st->successors.front().acceptance_conditions != bddfalse;
700  }
701 
702  private:
703  // Disallow copy.
704  sba_explicit(const sba_explicit<State>& other);
705  sba_explicit& operator=(const sba_explicit& other);
706  };
707 
708 
709  // It is tempting to write
710  //
711  // template<template<typename T>class graph, typename Type>
712  // class explicit_conf: public graph<T>
713  //
714  // to simplify the typedefs at the end of the file, however swig
715  // cannot parse this syntax.
716 
719  template<class graph, typename Type>
720  class explicit_conf: public graph
721  {
722  public:
723  explicit_conf(bdd_dict* d): graph(d)
724  {
725  this->set_to_string_func(to_string);
726  };
727 
728  static std::string to_string(const typename Type::label_t& l)
729  {
730  std::stringstream ss;
731  ss << l;
732  return ss.str();
733  }
734  };
735 
736  template<class graph>
737  class explicit_conf<graph, state_explicit_string>: public graph
738  {
739  public:
740  explicit_conf(bdd_dict* d): graph(d)
741  {
742  this->set_to_string_func(to_string);
743  };
744 
745  static std::string to_string(const std::string& l)
746  {
747  return l;
748  }
749  };
750 
751  template<class graph>
752  class explicit_conf<graph, state_explicit_formula>: public graph
753  {
754  public:
755  explicit_conf(bdd_dict* d): graph(d)
756  {
757  this->set_to_string_func(to_string);
758  };
759 
760  // Enable UTF8 output for the formulae that label states.
761  void enable_utf8()
762  {
763  this->set_to_string_func(to_utf8_string);
764  }
765 
766  static std::string to_string(const ltl::formula* const& l)
767  {
768  return ltl::to_string(l);
769  }
770 
771  static std::string to_utf8_string(const ltl::formula* const& l)
772  {
773  return ltl::to_utf8_string(l);
774  }
775  };
776 
777 
778  // Typedefs for tgba
779  typedef explicit_conf<tgba_explicit<state_explicit_string>,
785 
786  // Typedefs for sba
793 }
794 
795 #endif // SPOT_TGBA_TGBAEXPLICIT_HH

Please comment this page and report errors about it on the RefDocComments page.
Generated on Mon Jul 2 2012 17:35:47 for spot by doxygen 1.8.1.1