spot  1.99.7
twa.hh
1 // -*- coding: utf-8 -*-
2 // Copyright (C) 2009, 2011, 2013, 2014, 2015, 2016 Laboratoire de
3 // Recherche 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 <spot/twa/fwd.hh>
26 #include <spot/twa/acc.hh>
27 #include <spot/twa/bdddict.hh>
28 #include <cassert>
29 #include <memory>
30 #include <unordered_map>
31 #include <functional>
32 #include <array>
33 #include <vector>
34 #include <spot/misc/casts.hh>
35 #include <spot/misc/hash.hh>
36 #include <spot/tl/formula.hh>
37 #include <spot/misc/trival.hh>
38 
39 namespace spot
40 {
43  class SPOT_API state
44  {
45  public:
56  virtual int compare(const state* other) const = 0;
57 
77  virtual size_t hash() const = 0;
78 
80  virtual state* clone() const = 0;
81 
91  virtual void destroy() const
92  {
93  delete this;
94  }
95 
96  protected:
101  virtual ~state()
102  {
103  }
104  };
105 
119  {
120  bool
121  operator()(const state* left, const state* right) const
122  {
123  assert(left);
124  return left->compare(right) < 0;
125  }
126  };
127 
142  {
143  bool
144  operator()(const state* left, const state* right) const
145  {
146  assert(left);
147  return 0 == left->compare(right);
148  }
149  };
150 
166  {
167  size_t
168  operator()(const state* that) const
169  {
170  assert(that);
171  return that->hash();
172  }
173  };
174 
175  typedef std::unordered_set<const state*,
176  state_ptr_hash, state_ptr_equal> state_set;
177 
178 
181  class SPOT_API state_unicity_table
182  {
183  state_set m;
184  public:
185 
194  const state* operator()(const state* s)
195  {
196  auto p = m.insert(s);
197  if (!p.second)
198  s->destroy();
199  return *p.first;
200  }
201 
206  const state* is_new(const state* s)
207  {
208  auto p = m.insert(s);
209  if (!p.second)
210  {
211  s->destroy();
212  return nullptr;
213  }
214  return *p.first;
215  }
216 
218  {
219  for (state_set::iterator i = m.begin(); i != m.end();)
220  {
221  // Advance the iterator before destroying its key. This
222  // avoid issues with old g++ implementations.
223  state_set::iterator old = i++;
224  (*old)->destroy();
225  }
226  }
227 
228  size_t
229  size()
230  {
231  return m.size();
232  }
233  };
234 
235 
236 
237  // Functions related to shared_ptr.
239 
240  typedef std::shared_ptr<const state> shared_state;
241 
242  inline void shared_state_deleter(state* s) { s->destroy(); }
243 
258  {
259  bool
260  operator()(shared_state left,
261  shared_state right) const
262  {
263  assert(left);
264  return left->compare(right.get()) < 0;
265  }
266  };
267 
284  {
285  bool
286  operator()(shared_state left,
287  shared_state right) const
288  {
289  assert(left);
290  return 0 == left->compare(right.get());
291  }
292  };
293 
311  {
312  size_t
313  operator()(shared_state that) const
314  {
315  assert(that);
316  return that->hash();
317  }
318  };
319 
320  typedef std::unordered_set<shared_state,
322  state_shared_ptr_equal> shared_state_set;
323 
332  class SPOT_API twa_succ_iterator
333  {
334  public:
335  virtual
337  {
338  }
339 
341 
342 
354  virtual bool first() = 0;
355 
362  virtual bool next() = 0;
363 
373  virtual bool done() const = 0;
374 
376 
378 
379 
389  virtual const state* dst() const = 0;
393  virtual bdd cond() const = 0;
396  virtual acc_cond::mark_t acc() const = 0;
397 
399  };
400 
401  namespace internal
402  {
403  struct SPOT_API succ_iterator
404  {
405  protected:
406  twa_succ_iterator* it_;
407  public:
408 
410  it_(it)
411  {
412  }
413 
414  bool operator==(succ_iterator o) const
415  {
416  return it_ == o.it_;
417  }
418 
419  bool operator!=(succ_iterator o) const
420  {
421  return it_ != o.it_;
422  }
423 
424  const twa_succ_iterator* operator*() const
425  {
426  return it_;
427  }
428 
429  void operator++()
430  {
431  if (!it_->next())
432  it_ = nullptr;
433  }
434  };
435  }
436 
446 
449 
483  class SPOT_API twa: public std::enable_shared_from_this<twa>
484  {
485  protected:
486  twa(const bdd_dict_ptr& d);
487  // Any iterator returned via release_iter.
488  mutable twa_succ_iterator* iter_cache_;
489  bdd_dict_ptr dict_;
490  public:
491 
492 #ifndef SWIG
494  {
495  protected:
496  const twa* aut_;
497  twa_succ_iterator* it_;
498  public:
499  succ_iterable(const twa* aut, twa_succ_iterator* it)
500  : aut_(aut), it_(it)
501  {
502  }
503 
505  : aut_(other.aut_), it_(other.it_)
506  {
507  other.it_ = nullptr;
508  }
509 
510  ~succ_iterable()
511  {
512  if (it_)
513  aut_->release_iter(it_);
514  }
515 
517  {
518  return it_->first() ? it_ : nullptr;
519  }
520 
522  {
523  return nullptr;
524  }
525  };
526 #endif
527 
528  virtual ~twa();
529 
535  virtual const state* get_init_state() const = 0;
536 
542  virtual twa_succ_iterator*
543  succ_iter(const state* local_state) const = 0;
544 
545 #ifndef SWIG
551  succ(const state* s) const
552  {
553  return {this, succ_iter(s)};
554  }
555 #endif
556 
561  void release_iter(twa_succ_iterator* i) const
562  {
563  if (iter_cache_)
564  delete i;
565  else
566  iter_cache_ = i;
567  }
568 
582  bdd support_conditions(const state* state) const;
583 
591  bdd_dict_ptr get_dict() const
592  {
593  return dict_;
594  }
595 
599  int register_ap(formula ap)
600  {
601  int res = dict_->has_registered_proposition(ap, this);
602  if (res < 0)
603  {
604  aps_.push_back(ap);
605  res = dict_->register_proposition(ap, this);
606  bddaps_ &= bdd_ithvar(res);
607  }
608  return res;
609  }
610 
614  int register_ap(std::string name)
615  {
616  return register_ap(formula::ap(name));
617  }
618 
621  const std::vector<formula>& ap() const
622  {
623  return aps_;
624  }
625 
626  bdd ap_var() const
627  {
628  return bddaps_;
629  }
630 
635  virtual std::string format_state(const state* state) const = 0;
636 
653  virtual std::string
654  transition_annotation(const twa_succ_iterator* t) const;
655 
669  virtual state* project_state(const state* s,
670  const const_twa_ptr& t) const;
671 
672 
673  const acc_cond& acc() const
674  {
675  return acc_;
676  }
677 
678  acc_cond& acc()
679  {
680  return acc_;
681  }
682 
683  virtual bool is_empty() const;
684 
685  protected:
686  acc_cond acc_;
687 
688  void set_num_sets_(unsigned num)
689  {
690  if (num < acc_.num_sets())
691  {
692  acc_.~acc_cond();
693  new (&acc_) acc_cond;
694  }
695  acc_.add_sets(num - acc_.num_sets());
696  }
697 
698  public:
699  unsigned num_sets() const
700  {
701  return acc_.num_sets();
702  }
703 
704  const acc_cond::acc_code& get_acceptance() const
705  {
706  return acc_.get_acceptance();
707  }
708 
709  void set_acceptance(unsigned num, const acc_cond::acc_code& c)
710  {
711  set_num_sets_(num);
712  acc_.set_acceptance(c);
713  if (num == 0)
714  prop_state_acc(true);
715  }
716 
718  void copy_acceptance_of(const const_twa_ptr& a)
719  {
720  acc_ = a->acc();
721  unsigned num = acc_.num_sets();
722  if (num == 0)
723  prop_state_acc(true);
724  }
725 
726  void copy_ap_of(const const_twa_ptr& a)
727  {
728  for (auto f: a->ap())
729  this->register_ap(f);
730  }
731 
732  void set_generalized_buchi(unsigned num)
733  {
734  set_num_sets_(num);
735  acc_.set_generalized_buchi();
736  if (num == 0)
737  prop_state_acc(true);
738  }
739 
740  acc_cond::mark_t set_buchi()
741  {
742  set_generalized_buchi(1);
743  return acc_.mark(0);
744  }
745 
746  protected:
748  virtual bdd compute_support_conditions(const state* state) const = 0;
749  mutable const state* last_support_conditions_input_;
750  private:
751  mutable bdd last_support_conditions_output_;
752  std::vector<formula> aps_;
753  bdd bddaps_;
754 
755  protected:
756 
757  // Boolean properties. Beware: true means that the property
758  // holds, but false means the property is unknown.
759  struct bprop
760  {
761  trival::repr_t state_based_acc:2; // State-based acceptance.
762  trival::repr_t inherently_weak:2; // Inherently Weak automaton.
763  trival::repr_t weak:2; // Weak automaton.
764  trival::repr_t terminal:2; // Terminal automaton.
765  trival::repr_t deterministic:2; // Deterministic automaton.
766  trival::repr_t unambiguous:2; // Unambiguous automaton.
767  trival::repr_t stutter_invariant:2; // Stutter invariant language.
768  };
769  union
770  {
771  unsigned props;
772  bprop is;
773  };
774 
775 #ifndef SWIG
776  // Dynamic properties, are given with a name and a destructor function.
777  std::unordered_map<std::string,
778  std::pair<void*,
779  std::function<void(void*)>>> named_prop_;
780 #endif
781  void* get_named_prop_(std::string s) const;
782 
783  public:
784 
785 #ifndef SWIG
786  void set_named_prop(std::string s,
787  void* val, std::function<void(void*)> destructor);
788 
789  template<typename T>
790  void set_named_prop(std::string s, T* val)
791  {
792  set_named_prop(s, val, [](void *p) { delete static_cast<T*>(p); });
793  }
794 
795  template<typename T>
796  T* get_named_prop(std::string s) const
797  {
798  void* p = get_named_prop_(s);
799  if (!p)
800  return nullptr;
801  return static_cast<T*>(p);
802  }
803 #endif
804 
805  void release_named_properties()
806  {
807  // Destroy all named properties.
808  for (auto& np: named_prop_)
809  np.second.second(np.second.first);
810  named_prop_.clear();
811  }
812 
813  trival prop_state_acc() const
814  {
815  return is.state_based_acc;
816  }
817 
818  void prop_state_acc(trival val)
819  {
820  is.state_based_acc = val.val();
821  }
822 
823  trival is_sba() const
824  {
825  return prop_state_acc() && acc().is_buchi();
826  }
827 
828  trival prop_inherently_weak() const
829  {
830  return is.inherently_weak;
831  }
832 
833  void prop_inherently_weak(trival val)
834  {
835  is.inherently_weak = val.val();
836  if (!val)
837  is.terminal = is.weak = val.val();
838  }
839 
840  trival prop_terminal() const
841  {
842  return is.terminal;
843  }
844 
845  void prop_terminal(trival val)
846  {
847  is.terminal = val.val();
848  if (val)
849  is.inherently_weak = is.weak = val.val();
850  }
851 
852  trival prop_weak() const
853  {
854  return is.weak;
855  }
856 
857  void prop_weak(trival val)
858  {
859  is.weak = val.val();
860  if (val)
861  is.inherently_weak = val.val();
862  if (!val)
863  is.terminal = val.val();
864  }
865 
866  trival prop_deterministic() const
867  {
868  return is.deterministic;
869  }
870 
871  void prop_deterministic(trival val)
872  {
873  is.deterministic = val.val();
874  if (val)
875  // deterministic implies unambiguous
876  is.unambiguous = val.val();
877  }
878 
879  trival prop_unambiguous() const
880  {
881  return is.unambiguous;
882  }
883 
884  void prop_unambiguous(trival val)
885  {
886  is.unambiguous = val.val();
887  if (!val)
888  is.deterministic = val.val();
889  }
890 
891  trival prop_stutter_invariant() const
892  {
893  return is.stutter_invariant;
894  }
895 
896  void prop_stutter_invariant(trival val)
897  {
898  is.stutter_invariant = val.val();
899  }
900 
901  struct prop_set
902  {
903  bool state_based;
904  bool inherently_weak; // and weak
905  bool deterministic; // and unambiguous
906  bool stutter_inv; // and stutter_sensitive
907 
908  static prop_set all()
909  {
910  return { true, true, true, true };
911  }
912  };
913 
914  // There is no default value here on purpose. This way any time we
915  // add a new property we have to update every call to prop_copy().
916  void prop_copy(const const_twa_ptr& other, prop_set p)
917  {
918  if (p.state_based)
919  prop_state_acc(other->prop_state_acc());
920  if (p.inherently_weak)
921  {
922  prop_terminal(other->prop_terminal());
923  prop_weak(other->prop_weak());
924  prop_inherently_weak(other->prop_inherently_weak());
925  }
926  if (p.deterministic)
927  {
928  prop_deterministic(other->prop_deterministic());
929  prop_unambiguous(other->prop_unambiguous());
930  }
931  if (p.stutter_inv)
932  prop_stutter_invariant(other->prop_stutter_invariant());
933  }
934 
935  void prop_keep(prop_set p)
936  {
937  if (!p.state_based)
938  prop_state_acc(trival::maybe());
939  if (!p.inherently_weak)
940  {
941  prop_terminal(trival::maybe());
942  prop_weak(trival::maybe());
943  prop_inherently_weak(trival::maybe());
944  }
945  if (!p.deterministic)
946  {
947  prop_deterministic(trival::maybe());
948  prop_unambiguous(trival::maybe());
949  }
950  if (!p.stutter_inv)
951  prop_stutter_invariant(trival::maybe());
952  }
953 
954  };
955 
958 
961 
964 
967 
970 
973 
976 
979 }
virtual ~state()
Destructor.
Definition: twa.hh:101
Definition: graph.hh:32
Definition: twa.hh:759
Definition: twa.hh:403
An Equivalence Relation for state*.
Definition: twa.hh:141
Render state pointers unique via a hash table.
Definition: twa.hh:181
static formula ap(const std::string &name)
Build an atomic proposition.
Definition: formula.hh:705
A Transition-based ω-Automaton.
Definition: twa.hh:483
LTL/PSL formula interface.
Abstract class for states.
Definition: twa.hh:43
Strict Weak Ordering for shared_state (shared_ptr).
Definition: twa.hh:257
Definition: twa.hh:493
Definition: twa.hh:901
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:91
Hash Function for shared_state (shared_ptr).
Definition: twa.hh:310
Iterate over the successors of a state.
Definition: twa.hh:332
const state * operator()(const state *s)
Canonicalize state pointer.
Definition: twa.hh:194
const state * is_new(const state *s)
Canonicalize state pointer.
Definition: twa.hh:206
Hash Function for state*.
Definition: twa.hh:165
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:118
Atomic proposition.
Definition: acc.hh:34
An Equivalence Relation for shared_state (shared_ptr).
Definition: twa.hh:283

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on Fri Jan 15 2016 13:01:50 for spot by doxygen 1.8.9.1