spot  1.99.4a
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 
399  virtual void fire_all() const
400  { }
401 
404  virtual bool all_enabled() const
405  {
406  return true;
407  }
408 
410  };
411 
412  namespace internal
413  {
414  struct SPOT_API succ_iterator
415  {
416  protected:
417  twa_succ_iterator* it_;
418  public:
419 
421  it_(it)
422  {
423  }
424 
425  bool operator==(succ_iterator o) const
426  {
427  return it_ == o.it_;
428  }
429 
430  bool operator!=(succ_iterator o) const
431  {
432  return it_ != o.it_;
433  }
434 
435  const twa_succ_iterator* operator*() const
436  {
437  return it_;
438  }
439 
440  void operator++()
441  {
442  if (!it_->next())
443  it_ = nullptr;
444  }
445  };
446  }
447 
457 
460 
494  class SPOT_API twa: public std::enable_shared_from_this<twa>
495  {
496  protected:
497  twa(const bdd_dict_ptr& d);
498  // Any iterator returned via release_iter.
499  mutable twa_succ_iterator* iter_cache_;
500  bdd_dict_ptr dict_;
501  public:
502 
503 #ifndef SWIG
505  {
506  protected:
507  const twa* aut_;
508  twa_succ_iterator* it_;
509  public:
510  succ_iterable(const twa* aut, twa_succ_iterator* it)
511  : aut_(aut), it_(it)
512  {
513  }
514 
516  : aut_(other.aut_), it_(other.it_)
517  {
518  other.it_ = nullptr;
519  }
520 
521  ~succ_iterable()
522  {
523  if (it_)
524  aut_->release_iter(it_);
525  }
526 
528  {
529  return it_->first() ? it_ : nullptr;
530  }
531 
533  {
534  return nullptr;
535  }
536  };
537 #endif
538 
539  virtual ~twa();
540 
546  virtual state* get_init_state() const = 0;
547 
553  virtual twa_succ_iterator*
554  succ_iter(const state* local_state) const = 0;
555 
556 #ifndef SWIG
562  succ(const state* s) const
563  {
564  return {this, succ_iter(s)};
565  }
566 #endif
567 
572  void release_iter(twa_succ_iterator* i) const
573  {
574  if (iter_cache_)
575  delete i;
576  else
577  iter_cache_ = i;
578  }
579 
593  bdd support_conditions(const state* state) const;
594 
602  bdd_dict_ptr get_dict() const
603  {
604  return dict_;
605  }
606 
610  int register_ap(formula ap)
611  {
612  aps_.push_back(ap);
613  int res = dict_->register_proposition(ap, this);
614  bddaps_ &= bdd_ithvar(res);
615  return res;
616  }
617 
621  int register_ap(std::string name)
622  {
623  return register_ap(formula::ap(name));
624  }
625 
628  const std::vector<formula>& ap() const
629  {
630  return aps_;
631  }
632 
633  bdd ap_var() const
634  {
635  return bddaps_;
636  }
637 
642  virtual std::string format_state(const state* state) const = 0;
643 
660  virtual std::string
661  transition_annotation(const twa_succ_iterator* t) const;
662 
676  virtual state* project_state(const state* s,
677  const const_twa_ptr& t) const;
678 
679 
680  const acc_cond& acc() const
681  {
682  return acc_;
683  }
684 
685  acc_cond& acc()
686  {
687  return acc_;
688  }
689 
690  virtual bool is_empty() const;
691 
692  protected:
693  acc_cond acc_;
694 
695  void set_num_sets_(unsigned num)
696  {
697  if (num < acc_.num_sets())
698  {
699  acc_.~acc_cond();
700  new (&acc_) acc_cond;
701  }
702  acc_.add_sets(num - acc_.num_sets());
703  }
704 
705  public:
706  unsigned num_sets() const
707  {
708  return acc_.num_sets();
709  }
710 
711  const acc_cond::acc_code& get_acceptance() const
712  {
713  return acc_.get_acceptance();
714  }
715 
716  void set_acceptance(unsigned num, const acc_cond::acc_code& c)
717  {
718  set_num_sets_(num);
719  acc_.set_acceptance(c);
720  if (num == 0)
721  prop_state_based_acc();
722  }
723 
725  void copy_acceptance_of(const const_twa_ptr& a)
726  {
727  acc_ = a->acc();
728  unsigned num = acc_.num_sets();
729  if (num == 0)
730  prop_state_based_acc();
731  }
732 
733  void copy_ap_of(const const_twa_ptr& a)
734  {
735  get_dict()->register_all_propositions_of(a, this);
736  for (auto f: a->ap())
737  this->register_ap(f);
738  }
739 
740  void set_generalized_buchi(unsigned num)
741  {
742  set_num_sets_(num);
743  acc_.set_generalized_buchi();
744  if (num == 0)
745  prop_state_based_acc();
746  }
747 
748  acc_cond::mark_t set_buchi()
749  {
750  set_generalized_buchi(1);
751  return acc_.mark(0);
752  }
753 
754  protected:
756  virtual bdd compute_support_conditions(const state* state) const = 0;
757  mutable const state* last_support_conditions_input_;
758  private:
759  mutable bdd last_support_conditions_output_;
760  std::vector<formula> aps_;
761  bdd bddaps_;
762 
763  protected:
764 
765  // Boolean properties. Beware: true means that the property
766  // holds, but false means the property is unknown.
767  struct bprop
768  {
769  bool state_based_acc:1; // State-based acceptance.
770  bool inherently_weak:1; // Weak automaton.
771  bool deterministic:1; // Deterministic automaton.
772  bool unambiguous:1; // Unambiguous automaton.
773  bool stutter_invariant:1; // Stutter invariant language.
774  bool stutter_sensitive:1; // Stutter sensitive language.
775  };
776  union
777  {
778  unsigned props;
779  bprop is;
780  };
781 
782 #ifndef SWIG
783  // Dynamic properties, are given with a name and a destructor function.
784  std::unordered_map<std::string,
785  std::pair<void*,
786  std::function<void(void*)>>> named_prop_;
787 #endif
788  void* get_named_prop_(std::string s) const;
789 
790  public:
791 
792 #ifndef SWIG
793  void set_named_prop(std::string s,
794  void* val, std::function<void(void*)> destructor);
795 
796  template<typename T>
797  void set_named_prop(std::string s, T* val)
798  {
799  set_named_prop(s, val, [](void *p) { delete static_cast<T*>(p); });
800  }
801 
802  template<typename T>
803  T* get_named_prop(std::string s) const
804  {
805  void* p = get_named_prop_(s);
806  if (!p)
807  return nullptr;
808  return static_cast<T*>(p);
809  }
810 #endif
811 
812  void release_named_properties()
813  {
814  // Destroy all named properties.
815  for (auto& np: named_prop_)
816  np.second.second(np.second.first);
817  named_prop_.clear();
818  }
819 
820  bool has_state_based_acc() const
821  {
822  return is.state_based_acc;
823  }
824 
825  void prop_state_based_acc(bool val = true)
826  {
827  is.state_based_acc = val;
828  }
829 
830  bool is_sba() const
831  {
832  return has_state_based_acc() && acc().is_buchi();
833  }
834 
835  bool is_inherently_weak() const
836  {
837  return is.inherently_weak;
838  }
839 
840  void prop_inherently_weak(bool val = true)
841  {
842  is.inherently_weak = val;
843  }
844 
845  bool is_deterministic() const
846  {
847  return is.deterministic;
848  }
849 
850  void prop_deterministic(bool val = true)
851  {
852  is.deterministic = val;
853  }
854 
855  bool is_unambiguous() const
856  {
857  return is.unambiguous;
858  }
859 
860  void prop_unambiguous(bool val = true)
861  {
862  is.unambiguous = val;
863  }
864 
865  bool is_stutter_invariant() const
866  {
867  return is.stutter_invariant;
868  }
869 
870  bool is_stutter_sensitive() const
871  {
872  return is.stutter_sensitive;
873  }
874 
875  void prop_stutter_invariant(bool val = true)
876  {
877  is.stutter_invariant = val;
878  }
879 
880  void prop_stutter_sensitive(bool val = true)
881  {
882  is.stutter_sensitive = val;
883  }
884 
885  struct prop_set
886  {
887  bool state_based;
888  bool inherently_weak;
889  bool deterministic;
890  bool stutter_inv;
891 
892  static prop_set all()
893  {
894  return { true, true, true, true };
895  }
896  };
897 
898  // There is no default value here on purpose. This way any time we
899  // add a new property we have to update every call to prop_copy().
900  void prop_copy(const const_twa_ptr& other, prop_set p)
901  {
902  if (p.state_based)
903  prop_state_based_acc(other->has_state_based_acc());
904  if (p.inherently_weak)
905  prop_inherently_weak(other->is_inherently_weak());
906  if (p.deterministic)
907  {
908  prop_deterministic(other->is_deterministic());
909  prop_unambiguous(other->is_unambiguous());
910  }
911  if (p.stutter_inv)
912  {
913  prop_stutter_invariant(other->is_stutter_invariant());
914  prop_stutter_sensitive(other->is_stutter_sensitive());
915  }
916  }
917 
918  void prop_keep(prop_set p)
919  {
920  if (!p.state_based)
921  prop_state_based_acc(false);
922  if (!p.inherently_weak)
923  prop_inherently_weak(false);
924  if (!p.deterministic)
925  {
926  prop_deterministic(false);
927  prop_unambiguous(false);
928  }
929  if (!p.stutter_inv)
930  {
931  prop_stutter_invariant(false);
932  prop_stutter_sensitive(false);
933  }
934  }
935 
936  };
937 
940 
943 
946 
949 
952 
955 
958 
961 }
virtual ~state()
Destructor.
Definition: twa.hh:100
Definition: graph.hh:32
Definition: twa.hh:767
Definition: twa.hh:414
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:705
A Transition-based ω-Automaton.
Definition: twa.hh:494
LTL/PSL formula interface.
Abstract class for states.
Definition: twa.hh:42
Strict Weak Ordering for shared_state (shared_ptr).
Definition: twa.hh:256
virtual bool all_enabled() const
this method is only usefull if partial order reductions are enabled to check wether all states have b...
Definition: twa.hh:404
Definition: twa.hh:504
Definition: twa.hh:885
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 void fire_all() const
this method is only usefull if partial order reductions are enabled
Definition: twa.hh:399
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 Sun Oct 11 2015 10:50:08 for spot by doxygen 1.8.9.1