spot  1.99.3
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
twa.hh
1 // -*- coding: utf-8 -*-
2 // Copyright (C) 2009, 2011, 2013, 2014, 2015 Laboratoire de Recherche
3 // et Développement de l'Epita (LRDE).
4 // Copyright (C) 2003, 2004, 2005 Laboratoire d'Informatique de
5 // Paris 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 #pragma once
24 
25 #include "fwd.hh"
26 #include "acc.hh"
27 #include "bdddict.hh"
28 #include <cassert>
29 #include <memory>
30 #include <unordered_map>
31 #include <functional>
32 #include <array>
33 #include "misc/casts.hh"
34 #include "misc/hash.hh"
35 
36 namespace spot
37 {
40  class SPOT_API state
41  {
42  public:
53  virtual int compare(const state* other) const = 0;
54 
74  virtual size_t hash() const = 0;
75 
77  virtual state* clone() const = 0;
78 
88  virtual void destroy() const
89  {
90  delete this;
91  }
92 
93  protected:
98  virtual ~state()
99  {
100  }
101  };
102 
116  {
117  bool
118  operator()(const state* left, const state* right) const
119  {
120  assert(left);
121  return left->compare(right) < 0;
122  }
123  };
124 
139  {
140  bool
141  operator()(const state* left, const state* right) const
142  {
143  assert(left);
144  return 0 == left->compare(right);
145  }
146  };
147 
163  {
164  size_t
165  operator()(const state* that) const
166  {
167  assert(that);
168  return that->hash();
169  }
170  };
171 
172  typedef std::unordered_set<const state*,
173  state_ptr_hash, state_ptr_equal> state_set;
174 
175 
178  class SPOT_API state_unicity_table
179  {
180  state_set m;
181  public:
182 
191  const state* operator()(const state* s)
192  {
193  auto p = m.insert(s);
194  if (!p.second)
195  s->destroy();
196  return *p.first;
197  }
198 
203  const state* is_new(const state* s)
204  {
205  auto p = m.insert(s);
206  if (!p.second)
207  {
208  s->destroy();
209  return nullptr;
210  }
211  return *p.first;
212  }
213 
215  {
216  for (state_set::iterator i = m.begin(); i != m.end();)
217  {
218  // Advance the iterator before destroying its key. This
219  // avoid issues with old g++ implementations.
220  state_set::iterator old = i++;
221  (*old)->destroy();
222  }
223  }
224 
225  size_t
226  size()
227  {
228  return m.size();
229  }
230  };
231 
232 
233 
234  // Functions related to shared_ptr.
236 
237  typedef std::shared_ptr<const state> shared_state;
238 
239  inline void shared_state_deleter(state* s) { s->destroy(); }
240 
255  {
256  bool
257  operator()(shared_state left,
258  shared_state right) const
259  {
260  assert(left);
261  return left->compare(right.get()) < 0;
262  }
263  };
264 
281  {
282  bool
283  operator()(shared_state left,
284  shared_state right) const
285  {
286  assert(left);
287  return 0 == left->compare(right.get());
288  }
289  };
290 
308  {
309  size_t
310  operator()(shared_state that) const
311  {
312  assert(that);
313  return that->hash();
314  }
315  };
316 
317  typedef std::unordered_set<shared_state,
319  state_shared_ptr_equal> shared_state_set;
320 
329  class SPOT_API twa_succ_iterator
330  {
331  public:
332  virtual
334  {
335  }
336 
338 
339 
351  virtual bool first() = 0;
352 
359  virtual bool next() = 0;
360 
370  virtual bool done() const = 0;
371 
373 
375 
376 
386  virtual state* current_state() const = 0;
390  virtual bdd current_condition() const = 0;
393  virtual acc_cond::mark_t current_acceptance_conditions() const = 0;
394 
396  };
397 
398  namespace internal
399  {
400  struct SPOT_API succ_iterator
401  {
402  protected:
403  twa_succ_iterator* it_;
404  public:
405 
407  it_(it)
408  {
409  }
410 
411  bool operator==(succ_iterator o) const
412  {
413  return it_ == o.it_;
414  }
415 
416  bool operator!=(succ_iterator o) const
417  {
418  return it_ != o.it_;
419  }
420 
421  const twa_succ_iterator* operator*() const
422  {
423  return it_;
424  }
425 
426  void operator++()
427  {
428  if (!it_->next())
429  it_ = nullptr;
430  }
431  };
432  }
433 
443 
446 
480  class SPOT_API twa: public std::enable_shared_from_this<twa>
481  {
482  protected:
483  twa(const bdd_dict_ptr& d);
484  // Any iterator returned via release_iter.
485  mutable twa_succ_iterator* iter_cache_;
486  bdd_dict_ptr dict_;
487  public:
488 
489 #ifndef SWIG
491  {
492  protected:
493  const twa* aut_;
494  twa_succ_iterator* it_;
495  public:
496  succ_iterable(const twa* aut, twa_succ_iterator* it)
497  : aut_(aut), it_(it)
498  {
499  }
500 
502  : aut_(other.aut_), it_(other.it_)
503  {
504  other.it_ = nullptr;
505  }
506 
507  ~succ_iterable()
508  {
509  if (it_)
510  aut_->release_iter(it_);
511  }
512 
514  {
515  return it_->first() ? it_ : nullptr;
516  }
517 
519  {
520  return nullptr;
521  }
522  };
523 #endif
524 
525  virtual ~twa();
526 
532  virtual state* get_init_state() const = 0;
533 
539  virtual twa_succ_iterator*
540  succ_iter(const state* local_state) const = 0;
541 
542 #ifndef SWIG
548  succ(const state* s) const
549  {
550  return {this, succ_iter(s)};
551  }
552 #endif
553 
558  void release_iter(twa_succ_iterator* i) const
559  {
560  if (iter_cache_)
561  delete i;
562  else
563  iter_cache_ = i;
564  }
565 
579  bdd support_conditions(const state* state) const;
580 
588  bdd_dict_ptr get_dict() const
589  {
590  return dict_;
591  }
592 
597  virtual std::string format_state(const state* state) const = 0;
598 
615  virtual std::string
616  transition_annotation(const twa_succ_iterator* t) const;
617 
631  virtual state* project_state(const state* s,
632  const const_twa_ptr& t) const;
633 
634 
635  const acc_cond& acc() const
636  {
637  return acc_;
638  }
639 
640  acc_cond& acc()
641  {
642  return acc_;
643  }
644 
645  virtual bool is_empty() const;
646 
647  protected:
648  acc_cond acc_;
649 
650  void set_num_sets_(unsigned num)
651  {
652  if (num < acc_.num_sets())
653  {
654  acc_.~acc_cond();
655  new (&acc_) acc_cond;
656  }
657  acc_.add_sets(num - acc_.num_sets());
658  }
659 
660  public:
661  unsigned num_sets() const
662  {
663  return acc_.num_sets();
664  }
665 
666  const acc_cond::acc_code& get_acceptance() const
667  {
668  return acc_.get_acceptance();
669  }
670 
671  void set_acceptance(unsigned num, const acc_cond::acc_code& c)
672  {
673  set_num_sets_(num);
674  acc_.set_acceptance(c);
675  if (num == 0)
676  prop_state_based_acc();
677  }
678 
680  void copy_acceptance_of(const const_twa_ptr& a)
681  {
682  acc_ = a->acc();
683  unsigned num = acc_.num_sets();
684  if (num == 0)
685  prop_state_based_acc();
686  }
687 
688  void copy_ap_of(const const_twa_ptr& a)
689  {
690  get_dict()->register_all_propositions_of(a, this);
691  }
692 
693  void set_generalized_buchi(unsigned num)
694  {
695  set_num_sets_(num);
696  acc_.set_generalized_buchi();
697  if (num == 0)
698  prop_state_based_acc();
699  }
700 
701  acc_cond::mark_t set_buchi()
702  {
703  set_generalized_buchi(1);
704  return acc_.mark(0);
705  }
706 
707  protected:
709  virtual bdd compute_support_conditions(const state* state) const = 0;
710  mutable const state* last_support_conditions_input_;
711  private:
712  mutable bdd last_support_conditions_output_;
713 
714  protected:
715 
716  // Boolean properties. Beware: true means that the property
717  // holds, but false means the property is unknown.
718  struct bprop
719  {
720  bool state_based_acc:1; // State-based acceptance.
721  bool inherently_weak:1; // Weak automaton.
722  bool deterministic:1; // Deterministic automaton.
723  bool unambiguous:1; // Unambiguous automaton.
724  bool stutter_invariant:1; // Stutter invariant language.
725  bool stutter_sensitive:1; // Stutter sensitive language.
726  };
727  union
728  {
729  unsigned props;
730  bprop is;
731  };
732 
733 #ifndef SWIG
734  // Dynamic properties, are given with a name and a destructor function.
735  std::unordered_map<std::string,
736  std::pair<void*,
737  std::function<void(void*)>>> named_prop_;
738 #endif
739  void* get_named_prop_(std::string s) const;
740 
741  public:
742 
743 #ifndef SWIG
744  void set_named_prop(std::string s,
745  void* val, std::function<void(void*)> destructor);
746 
747  template<typename T>
748  void set_named_prop(std::string s, T* val)
749  {
750  set_named_prop(s, val, [](void *p) { delete static_cast<T*>(p); });
751  }
752 
753  template<typename T>
754  T* get_named_prop(std::string s) const
755  {
756  void* p = get_named_prop_(s);
757  if (!p)
758  return nullptr;
759  return static_cast<T*>(p);
760  }
761 #endif
762 
763  void release_named_properties()
764  {
765  // Destroy all named properties.
766  for (auto& np: named_prop_)
767  np.second.second(np.second.first);
768  named_prop_.clear();
769  }
770 
771  bool has_state_based_acc() const
772  {
773  return is.state_based_acc;
774  }
775 
776  void prop_state_based_acc(bool val = true)
777  {
778  is.state_based_acc = val;
779  }
780 
781  bool is_sba() const
782  {
783  return has_state_based_acc() && acc().is_buchi();
784  }
785 
786  bool is_inherently_weak() const
787  {
788  return is.inherently_weak;
789  }
790 
791  void prop_inherently_weak(bool val = true)
792  {
793  is.inherently_weak = val;
794  }
795 
796  bool is_deterministic() const
797  {
798  return is.deterministic;
799  }
800 
801  void prop_deterministic(bool val = true)
802  {
803  is.deterministic = val;
804  }
805 
806  bool is_unambiguous() const
807  {
808  return is.unambiguous;
809  }
810 
811  void prop_unambiguous(bool val = true)
812  {
813  is.unambiguous = val;
814  }
815 
816  bool is_stutter_invariant() const
817  {
818  return is.stutter_invariant;
819  }
820 
821  bool is_stutter_sensitive() const
822  {
823  return is.stutter_sensitive;
824  }
825 
826  void prop_stutter_invariant(bool val = true)
827  {
828  is.stutter_invariant = val;
829  }
830 
831  void prop_stutter_sensitive(bool val = true)
832  {
833  is.stutter_sensitive = val;
834  }
835 
836  struct prop_set
837  {
838  bool state_based;
839  bool inherently_weak;
840  bool deterministic;
841  bool stutter_inv;
842 
843  static prop_set all()
844  {
845  return { true, true, true, true };
846  }
847  };
848 
849  // There is no default value here on purpose. This way any time we
850  // add a new property we have to update every call to prop_copy().
851  void prop_copy(const const_twa_ptr& other, prop_set p)
852  {
853  if (p.state_based)
854  prop_state_based_acc(other->has_state_based_acc());
855  if (p.inherently_weak)
856  prop_inherently_weak(other->is_inherently_weak());
857  if (p.deterministic)
858  {
859  prop_deterministic(other->is_deterministic());
860  prop_unambiguous(other->is_unambiguous());
861  }
862  if (p.stutter_inv)
863  {
864  prop_stutter_invariant(other->is_stutter_invariant());
865  prop_stutter_sensitive(other->is_stutter_sensitive());
866  }
867  }
868 
869  void prop_keep(prop_set p)
870  {
871  if (!p.state_based)
872  prop_state_based_acc(false);
873  if (!p.inherently_weak)
874  prop_inherently_weak(false);
875  if (!p.deterministic)
876  {
877  prop_deterministic(false);
878  prop_unambiguous(false);
879  }
880  if (!p.stutter_inv)
881  {
882  prop_stutter_invariant(false);
883  prop_stutter_sensitive(false);
884  }
885  }
886 
887  };
888 
891 
894 
897 
900 
903 
906 
909 
912 }
virtual ~state()
Destructor.
Definition: twa.hh:98
Definition: public.hh:31
Definition: twa.hh:718
Definition: twa.hh:400
An Equivalence Relation for state*.
Definition: twa.hh:138
Render state pointers unique via a hash table.
Definition: twa.hh:178
SPOT_API bool is_deterministic(const const_twa_graph_ptr &aut)
Return true iff aut is deterministic.
A Transition-based ω-Automaton.
Definition: twa.hh:480
Abstract class for states.
Definition: twa.hh:40
Strict Weak Ordering for shared_state (shared_ptr).
Definition: twa.hh:254
Definition: twa.hh:490
Definition: twa.hh:836
virtual bool next()=0
Jump to the next successor (if any).
virtual bool first()=0
Position the iterator on the first successor (if any).
virtual void destroy() const
Release a state.
Definition: twa.hh:88
Hash Function for shared_state (shared_ptr).
Definition: twa.hh:307
Iterate over the successors of a state.
Definition: twa.hh:329
const state * operator()(const state *s)
Canonicalize state pointer.
Definition: twa.hh:191
const state * is_new(const state *s)
Canonicalize state pointer.
Definition: twa.hh:203
Hash Function for state*.
Definition: twa.hh:162
SPOT_API bool is_unambiguous(const const_twa_graph_ptr &aut)
Whether the automaton aut is unambiguous.
virtual int compare(const state *other) const =0
Compares two states (that come from the same automaton).
SPOT_API bool is_stutter_invariant(const ltl::formula *f)
Check if a formula has the stutter invariance property.
virtual size_t hash() const =0
Hash a state.
Strict Weak Ordering for state*.
Definition: twa.hh:115
Definition: acc.hh:34
An Equivalence Relation for shared_state (shared_ptr).
Definition: twa.hh:280

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on Wed Aug 26 2015 08:42:37 for spot by doxygen 1.8.8