spot  1.99.4
 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 <vector>
34 #include "misc/casts.hh"
35 #include "misc/hash.hh"
36 #include "tl/formula.hh"
37 
38 namespace spot
39 {
42  class SPOT_API state
43  {
44  public:
55  virtual int compare(const state* other) const = 0;
56 
76  virtual size_t hash() const = 0;
77 
79  virtual state* clone() const = 0;
80 
90  virtual void destroy() const
91  {
92  delete this;
93  }
94 
95  protected:
100  virtual ~state()
101  {
102  }
103  };
104 
118  {
119  bool
120  operator()(const state* left, const state* right) const
121  {
122  assert(left);
123  return left->compare(right) < 0;
124  }
125  };
126 
141  {
142  bool
143  operator()(const state* left, const state* right) const
144  {
145  assert(left);
146  return 0 == left->compare(right);
147  }
148  };
149 
165  {
166  size_t
167  operator()(const state* that) const
168  {
169  assert(that);
170  return that->hash();
171  }
172  };
173 
174  typedef std::unordered_set<const state*,
175  state_ptr_hash, state_ptr_equal> state_set;
176 
177 
180  class SPOT_API state_unicity_table
181  {
182  state_set m;
183  public:
184 
193  const state* operator()(const state* s)
194  {
195  auto p = m.insert(s);
196  if (!p.second)
197  s->destroy();
198  return *p.first;
199  }
200 
205  const state* is_new(const state* s)
206  {
207  auto p = m.insert(s);
208  if (!p.second)
209  {
210  s->destroy();
211  return nullptr;
212  }
213  return *p.first;
214  }
215 
217  {
218  for (state_set::iterator i = m.begin(); i != m.end();)
219  {
220  // Advance the iterator before destroying its key. This
221  // avoid issues with old g++ implementations.
222  state_set::iterator old = i++;
223  (*old)->destroy();
224  }
225  }
226 
227  size_t
228  size()
229  {
230  return m.size();
231  }
232  };
233 
234 
235 
236  // Functions related to shared_ptr.
238 
239  typedef std::shared_ptr<const state> shared_state;
240 
241  inline void shared_state_deleter(state* s) { s->destroy(); }
242 
257  {
258  bool
259  operator()(shared_state left,
260  shared_state right) const
261  {
262  assert(left);
263  return left->compare(right.get()) < 0;
264  }
265  };
266 
283  {
284  bool
285  operator()(shared_state left,
286  shared_state right) const
287  {
288  assert(left);
289  return 0 == left->compare(right.get());
290  }
291  };
292 
310  {
311  size_t
312  operator()(shared_state that) const
313  {
314  assert(that);
315  return that->hash();
316  }
317  };
318 
319  typedef std::unordered_set<shared_state,
321  state_shared_ptr_equal> shared_state_set;
322 
331  class SPOT_API twa_succ_iterator
332  {
333  public:
334  virtual
336  {
337  }
338 
340 
341 
353  virtual bool first() = 0;
354 
361  virtual bool next() = 0;
362 
372  virtual bool done() const = 0;
373 
375 
377 
378 
388  virtual state* current_state() const = 0;
392  virtual bdd current_condition() const = 0;
395  virtual acc_cond::mark_t current_acceptance_conditions() const = 0;
396 
398  };
399 
400  namespace internal
401  {
402  struct SPOT_API succ_iterator
403  {
404  protected:
405  twa_succ_iterator* it_;
406  public:
407 
409  it_(it)
410  {
411  }
412 
413  bool operator==(succ_iterator o) const
414  {
415  return it_ == o.it_;
416  }
417 
418  bool operator!=(succ_iterator o) const
419  {
420  return it_ != o.it_;
421  }
422 
423  const twa_succ_iterator* operator*() const
424  {
425  return it_;
426  }
427 
428  void operator++()
429  {
430  if (!it_->next())
431  it_ = nullptr;
432  }
433  };
434  }
435 
445 
448 
482  class SPOT_API twa: public std::enable_shared_from_this<twa>
483  {
484  protected:
485  twa(const bdd_dict_ptr& d);
486  // Any iterator returned via release_iter.
487  mutable twa_succ_iterator* iter_cache_;
488  bdd_dict_ptr dict_;
489  public:
490 
491 #ifndef SWIG
493  {
494  protected:
495  const twa* aut_;
496  twa_succ_iterator* it_;
497  public:
498  succ_iterable(const twa* aut, twa_succ_iterator* it)
499  : aut_(aut), it_(it)
500  {
501  }
502 
504  : aut_(other.aut_), it_(other.it_)
505  {
506  other.it_ = nullptr;
507  }
508 
509  ~succ_iterable()
510  {
511  if (it_)
512  aut_->release_iter(it_);
513  }
514 
516  {
517  return it_->first() ? it_ : nullptr;
518  }
519 
521  {
522  return nullptr;
523  }
524  };
525 #endif
526 
527  virtual ~twa();
528 
534  virtual state* get_init_state() const = 0;
535 
541  virtual twa_succ_iterator*
542  succ_iter(const state* local_state) const = 0;
543 
544 #ifndef SWIG
550  succ(const state* s) const
551  {
552  return {this, succ_iter(s)};
553  }
554 #endif
555 
560  void release_iter(twa_succ_iterator* i) const
561  {
562  if (iter_cache_)
563  delete i;
564  else
565  iter_cache_ = i;
566  }
567 
581  bdd support_conditions(const state* state) const;
582 
590  bdd_dict_ptr get_dict() const
591  {
592  return dict_;
593  }
594 
598  int register_ap(formula ap)
599  {
600  aps_.push_back(ap);
601  int res = dict_->register_proposition(ap, this);
602  bddaps_ &= bdd_ithvar(res);
603  return res;
604  }
605 
609  int register_ap(std::string name)
610  {
611  return register_ap(formula::ap(name));
612  }
613 
616  const std::vector<formula>& ap() const
617  {
618  return aps_;
619  }
620 
621  bdd ap_var() const
622  {
623  return bddaps_;
624  }
625 
630  virtual std::string format_state(const state* state) const = 0;
631 
648  virtual std::string
649  transition_annotation(const twa_succ_iterator* t) const;
650 
664  virtual state* project_state(const state* s,
665  const const_twa_ptr& t) const;
666 
667 
668  const acc_cond& acc() const
669  {
670  return acc_;
671  }
672 
673  acc_cond& acc()
674  {
675  return acc_;
676  }
677 
678  virtual bool is_empty() const;
679 
680  protected:
681  acc_cond acc_;
682 
683  void set_num_sets_(unsigned num)
684  {
685  if (num < acc_.num_sets())
686  {
687  acc_.~acc_cond();
688  new (&acc_) acc_cond;
689  }
690  acc_.add_sets(num - acc_.num_sets());
691  }
692 
693  public:
694  unsigned num_sets() const
695  {
696  return acc_.num_sets();
697  }
698 
699  const acc_cond::acc_code& get_acceptance() const
700  {
701  return acc_.get_acceptance();
702  }
703 
704  void set_acceptance(unsigned num, const acc_cond::acc_code& c)
705  {
706  set_num_sets_(num);
707  acc_.set_acceptance(c);
708  if (num == 0)
709  prop_state_based_acc();
710  }
711 
713  void copy_acceptance_of(const const_twa_ptr& a)
714  {
715  acc_ = a->acc();
716  unsigned num = acc_.num_sets();
717  if (num == 0)
718  prop_state_based_acc();
719  }
720 
721  void copy_ap_of(const const_twa_ptr& a)
722  {
723  get_dict()->register_all_propositions_of(a, this);
724  for (auto f: a->ap())
725  this->register_ap(f);
726  }
727 
728  void set_generalized_buchi(unsigned num)
729  {
730  set_num_sets_(num);
731  acc_.set_generalized_buchi();
732  if (num == 0)
733  prop_state_based_acc();
734  }
735 
736  acc_cond::mark_t set_buchi()
737  {
738  set_generalized_buchi(1);
739  return acc_.mark(0);
740  }
741 
742  protected:
744  virtual bdd compute_support_conditions(const state* state) const = 0;
745  mutable const state* last_support_conditions_input_;
746  private:
747  mutable bdd last_support_conditions_output_;
748  std::vector<formula> aps_;
749  bdd bddaps_;
750 
751  protected:
752 
753  // Boolean properties. Beware: true means that the property
754  // holds, but false means the property is unknown.
755  struct bprop
756  {
757  bool state_based_acc:1; // State-based acceptance.
758  bool inherently_weak:1; // Weak automaton.
759  bool deterministic:1; // Deterministic automaton.
760  bool unambiguous:1; // Unambiguous automaton.
761  bool stutter_invariant:1; // Stutter invariant language.
762  bool stutter_sensitive:1; // Stutter sensitive language.
763  };
764  union
765  {
766  unsigned props;
767  bprop is;
768  };
769 
770 #ifndef SWIG
771  // Dynamic properties, are given with a name and a destructor function.
772  std::unordered_map<std::string,
773  std::pair<void*,
774  std::function<void(void*)>>> named_prop_;
775 #endif
776  void* get_named_prop_(std::string s) const;
777 
778  public:
779 
780 #ifndef SWIG
781  void set_named_prop(std::string s,
782  void* val, std::function<void(void*)> destructor);
783 
784  template<typename T>
785  void set_named_prop(std::string s, T* val)
786  {
787  set_named_prop(s, val, [](void *p) { delete static_cast<T*>(p); });
788  }
789 
790  template<typename T>
791  T* get_named_prop(std::string s) const
792  {
793  void* p = get_named_prop_(s);
794  if (!p)
795  return nullptr;
796  return static_cast<T*>(p);
797  }
798 #endif
799 
800  void release_named_properties()
801  {
802  // Destroy all named properties.
803  for (auto& np: named_prop_)
804  np.second.second(np.second.first);
805  named_prop_.clear();
806  }
807 
808  bool has_state_based_acc() const
809  {
810  return is.state_based_acc;
811  }
812 
813  void prop_state_based_acc(bool val = true)
814  {
815  is.state_based_acc = val;
816  }
817 
818  bool is_sba() const
819  {
820  return has_state_based_acc() && acc().is_buchi();
821  }
822 
823  bool is_inherently_weak() const
824  {
825  return is.inherently_weak;
826  }
827 
828  void prop_inherently_weak(bool val = true)
829  {
830  is.inherently_weak = val;
831  }
832 
833  bool is_deterministic() const
834  {
835  return is.deterministic;
836  }
837 
838  void prop_deterministic(bool val = true)
839  {
840  is.deterministic = val;
841  }
842 
843  bool is_unambiguous() const
844  {
845  return is.unambiguous;
846  }
847 
848  void prop_unambiguous(bool val = true)
849  {
850  is.unambiguous = val;
851  }
852 
853  bool is_stutter_invariant() const
854  {
855  return is.stutter_invariant;
856  }
857 
858  bool is_stutter_sensitive() const
859  {
860  return is.stutter_sensitive;
861  }
862 
863  void prop_stutter_invariant(bool val = true)
864  {
865  is.stutter_invariant = val;
866  }
867 
868  void prop_stutter_sensitive(bool val = true)
869  {
870  is.stutter_sensitive = val;
871  }
872 
873  struct prop_set
874  {
875  bool state_based;
876  bool inherently_weak;
877  bool deterministic;
878  bool stutter_inv;
879 
880  static prop_set all()
881  {
882  return { true, true, true, true };
883  }
884  };
885 
886  // There is no default value here on purpose. This way any time we
887  // add a new property we have to update every call to prop_copy().
888  void prop_copy(const const_twa_ptr& other, prop_set p)
889  {
890  if (p.state_based)
891  prop_state_based_acc(other->has_state_based_acc());
892  if (p.inherently_weak)
893  prop_inherently_weak(other->is_inherently_weak());
894  if (p.deterministic)
895  {
896  prop_deterministic(other->is_deterministic());
897  prop_unambiguous(other->is_unambiguous());
898  }
899  if (p.stutter_inv)
900  {
901  prop_stutter_invariant(other->is_stutter_invariant());
902  prop_stutter_sensitive(other->is_stutter_sensitive());
903  }
904  }
905 
906  void prop_keep(prop_set p)
907  {
908  if (!p.state_based)
909  prop_state_based_acc(false);
910  if (!p.inherently_weak)
911  prop_inherently_weak(false);
912  if (!p.deterministic)
913  {
914  prop_deterministic(false);
915  prop_unambiguous(false);
916  }
917  if (!p.stutter_inv)
918  {
919  prop_stutter_invariant(false);
920  prop_stutter_sensitive(false);
921  }
922  }
923 
924  };
925 
928 
931 
934 
937 
940 
943 
946 
949 }
virtual ~state()
Destructor.
Definition: twa.hh:100
Definition: graph.hh:31
Definition: twa.hh:755
Definition: twa.hh:402
bool is_deterministic(const const_twa_graph_ptr &aut)
Return true iff aut is deterministic.
An Equivalence Relation for state*.
Definition: twa.hh:140
Render state pointers unique via a hash table.
Definition: twa.hh:180
static formula ap(const std::string &name)
Build an atomic proposition.
Definition: formula.hh:701
A Transition-based ω-Automaton.
Definition: twa.hh:482
LTL/PSL formula interface.
Abstract class for states.
Definition: twa.hh:42
Strict Weak Ordering for shared_state (shared_ptr).
Definition: twa.hh:256
Definition: twa.hh:492
Definition: twa.hh:873
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:90
Hash Function for shared_state (shared_ptr).
Definition: twa.hh:309
Iterate over the successors of a state.
Definition: twa.hh:331
bool is_unambiguous(const const_twa_graph_ptr &aut)
Whether the automaton aut is unambiguous.
const state * operator()(const state *s)
Canonicalize state pointer.
Definition: twa.hh:193
const state * is_new(const state *s)
Canonicalize state pointer.
Definition: twa.hh:205
Hash Function for state*.
Definition: twa.hh:164
virtual int compare(const state *other) const =0
Compares two states (that come from the same automaton).
virtual size_t hash() const =0
Hash a state.
Strict Weak Ordering for state*.
Definition: twa.hh:117
Atomic proposition.
Definition: acc.hh:34
An Equivalence Relation for shared_state (shared_ptr).
Definition: twa.hh:282

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on Thu Oct 1 2015 05:49:14 for spot by doxygen 1.8.8