spot  1.99.9
formula.hh
Go to the documentation of this file.
1 // -*- coding: utf-8 -*-
2 // Copyright (C) 2015, 2016 Laboratoire de Recherche et Développement de
3 // l'Epita (LRDE).
4 //
5 // This file is part of Spot, a model checking library.
6 //
7 // Spot is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // Spot is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 
22 #pragma once
23 
30 
33 
36 
39 
42 
43 #include <spot/misc/common.hh>
44 #include <memory>
45 #include <cstdint>
46 #include <initializer_list>
47 #include <cassert>
48 #include <vector>
49 #include <string>
50 #include <iterator>
51 #include <iosfwd>
52 #include <sstream>
53 #include <list>
54 #include <cstddef>
55 #include <initializer_list>
56 #include <limits>
57 
58 namespace spot
59 {
62  enum class op: uint8_t
63  {
64  ff,
65  tt,
66  eword,
67  ap,
68  // unary operators
69  Not,
70  X,
71  F,
72  G,
73  Closure,
74  NegClosure,
76  // binary operators
77  Xor,
78  Implies,
79  Equiv,
80  U,
81  R,
82  W,
83  M,
84  EConcat,
86  UConcat,
87  // n-ary operators
88  Or,
89  OrRat,
90  And,
91  AndRat,
92  AndNLM,
93  Concat,
94  Fusion,
95  // star-like operators
96  Star,
97  FStar,
98  };
99 
100 #ifndef SWIG
101  class SPOT_API fnode final
108  {
109  public:
110  const fnode* clone() const
111  {
112  // Saturate.
113  ++refs_;
114  if (SPOT_UNLIKELY(!refs_))
115  saturated_ = 1;
116  return this;
117  }
118 
119  void destroy() const
120  {
121  if (SPOT_LIKELY(refs_))
122  --refs_;
123  else if (SPOT_LIKELY(id_ > 2) && SPOT_LIKELY(!saturated_))
124  // last reference to a node that is not a constant
125  destroy_aux();
126  }
127 
128  static constexpr uint8_t unbounded()
129  {
130  return UINT8_MAX;
131  }
132 
133  static const fnode* ap(const std::string& name);
134  static const fnode* unop(op o, const fnode* f);
135  static const fnode* binop(op o, const fnode* f, const fnode* g);
136  static const fnode* multop(op o, std::vector<const fnode*> l);
137  static const fnode* bunop(op o, const fnode* f,
138  uint8_t min, uint8_t max = unbounded());
139 
140  op kind() const
141  {
142  return op_;
143  }
144 
145  std::string kindstr() const;
146 
147  bool is(op o) const
148  {
149  return op_ == o;
150  }
151 
152  bool is(op o1, op o2) const
153  {
154  return op_ == o1 || op_ == o2;
155  }
156 
157  bool is(std::initializer_list<op> l) const
158  {
159  const fnode* n = this;
160  for (auto o: l)
161  {
162  if (!n->is(o))
163  return false;
164  n = n->nth(0);
165  }
166  return true;
167  }
168 
169  const fnode* get_child_of(op o) const
170  {
171  if (op_ != o)
172  return nullptr;
173  assert(size_ == 1);
174  return nth(0);
175  }
176 
177  const fnode* get_child_of(std::initializer_list<op> l) const
178  {
179  auto c = this;
180  for (auto o: l)
181  {
182  c = c->get_child_of(o);
183  if (c == nullptr)
184  return c;
185  }
186  return c;
187  }
188 
189  unsigned min() const
190  {
191  assert(op_ == op::FStar || op_ == op::Star);
192  return min_;
193  }
194 
195  unsigned max() const
196  {
197  assert(op_ == op::FStar || op_ == op::Star);
198  return max_;
199  }
200 
201  unsigned size() const
202  {
203  return size_;
204  }
205 
206  size_t id() const
207  {
208  return id_;
209  }
210 
211  const fnode*const* begin() const
212  {
213  return children;
214  }
215 
216  const fnode*const* end() const
217  {
218  return children + size();
219  }
220 
221  const fnode* nth(unsigned i) const
222  {
223  if (i >= size())
224  throw std::runtime_error("access to non-existing child");
225  return children[i];
226  }
227 
228  static const fnode* ff()
229  {
230  return ff_;
231  }
232 
233  bool is_ff() const
234  {
235  return op_ == op::ff;
236  }
237 
238  static const fnode* tt()
239  {
240  return tt_;
241  }
242 
243  bool is_tt() const
244  {
245  return op_ == op::tt;
246  }
247 
248  static const fnode* eword()
249  {
250  return ew_;
251  }
252 
253  bool is_eword() const
254  {
255  return op_ == op::eword;
256  }
257 
258  bool is_constant() const
259  {
260  return op_ == op::ff || op_ == op::tt || op_ == op::eword;
261  }
262 
263  bool is_Kleene_star() const
264  {
265  if (op_ != op::Star)
266  return false;
267  return min_ == 0 && max_ == unbounded();
268  }
269 
270  static const fnode* one_star()
271  {
272  if (!one_star_)
273  one_star_ = bunop(op::Star, tt(), 0);
274  return one_star_;
275  }
276 
277  const std::string& ap_name() const;
278  std::ostream& dump(std::ostream& os) const;
279 
280  const fnode* all_but(unsigned i) const;
281 
282  unsigned boolean_count() const
283  {
284  unsigned pos = 0;
285  unsigned s = size();
286  while (pos < s && children[pos]->is_boolean())
287  ++pos;
288  return pos;
289  }
290 
291  const fnode* boolean_operands(unsigned* width = nullptr) const;
292 
295  static bool instances_check();
296 
298  // Properties //
300 
301  bool is_boolean() const
302  {
303  return is_.boolean;
304  }
305 
306  bool is_sugar_free_boolean() const
307  {
308  return is_.sugar_free_boolean;
309  }
310 
311  bool is_in_nenoform() const
312  {
313  return is_.in_nenoform;
314  }
315 
316  bool is_syntactic_stutter_invariant() const
317  {
318  return is_.syntactic_si;
319  }
320 
321  bool is_sugar_free_ltl() const
322  {
323  return is_.sugar_free_ltl;
324  }
325 
326  bool is_ltl_formula() const
327  {
328  return is_.ltl_formula;
329  }
330 
331  bool is_psl_formula() const
332  {
333  return is_.psl_formula;
334  }
335 
336  bool is_sere_formula() const
337  {
338  return is_.sere_formula;
339  }
340 
341  bool is_finite() const
342  {
343  return is_.finite;
344  }
345 
346  bool is_eventual() const
347  {
348  return is_.eventual;
349  }
350 
351  bool is_universal() const
352  {
353  return is_.universal;
354  }
355 
356  bool is_syntactic_safety() const
357  {
358  return is_.syntactic_safety;
359  }
360 
361  bool is_syntactic_guarantee() const
362  {
363  return is_.syntactic_guarantee;
364  }
365 
366  bool is_syntactic_obligation() const
367  {
368  return is_.syntactic_obligation;
369  }
370 
371  bool is_syntactic_recurrence() const
372  {
373  return is_.syntactic_recurrence;
374  }
375 
376  bool is_syntactic_persistence() const
377  {
378  return is_.syntactic_persistence;
379  }
380 
381  bool is_marked() const
382  {
383  return !is_.not_marked;
384  }
385 
386  bool accepts_eword() const
387  {
388  return is_.accepting_eword;
389  }
390 
391  bool has_lbt_atomic_props() const
392  {
393  return is_.lbt_atomic_props;
394  }
395 
396  bool has_spin_atomic_props() const
397  {
398  return is_.spin_atomic_props;
399  }
400 
401  private:
402  void setup_props(op o);
403  void destroy_aux() const;
404 
405  static const fnode* unique(const fnode*);
406 
407  // Destruction may only happen via destroy().
408  ~fnode() = default;
409  // Disallow copies.
410  fnode(const fnode&) = delete;
411  fnode& operator=(const fnode&) = delete;
412 
413 
414 
415  template<class iter>
416  fnode(op o, iter begin, iter end)
417  {
418  size_t s = std::distance(begin, end);
419  if (s > (size_t) UINT16_MAX)
420  throw std::runtime_error("too many children for formula");
421  size_ = s;
422  auto pos = children;
423  for (auto i = begin; i != end; ++i)
424  *pos++ = *i;
425  setup_props(o);
426  }
427 
428  fnode(op o, std::initializer_list<const fnode*> l)
429  : fnode(o, l.begin(), l.end())
430  {
431  }
432 
433  fnode(op o, const fnode* f, uint8_t min, uint8_t max)
434  {
435  size_ = 1;
436  children[0] = f;
437  min_ = min;
438  max_ = max;
439  setup_props(o);
440  }
441 
442  static const fnode* ff_;
443  static const fnode* tt_;
444  static const fnode* ew_;
445  static const fnode* one_star_;
446 
447  op op_; // operator
448  uint8_t min_; // range minimum (for star-like operators)
449  uint8_t max_; // range maximum;
450  mutable uint8_t saturated_ = 0;
451  uint16_t size_; // number of children
452  mutable uint16_t refs_ = 0; // reference count - 1;
453  size_t id_; // Also used as hash.
454  static size_t next_id_;
455 
456  struct ltl_prop
457  {
458  // All properties here should be expressed in such a a way
459  // that property(f && g) is just property(f)&property(g).
460  // This allows us to compute all properties of a compound
461  // formula in one operation.
462  //
463  // For instance we do not use a property that says "has
464  // temporal operator", because it would require an OR between
465  // the two arguments. Instead we have a property that
466  // says "no temporal operator", and that one is computed
467  // with an AND between the arguments.
468  //
469  // Also choose a name that makes sense when prefixed with
470  // "the formula is".
471  bool boolean:1; // No temporal operators.
472  bool sugar_free_boolean:1; // Only AND, OR, and NOT operators.
473  bool in_nenoform:1; // Negative Normal Form.
474  bool syntactic_si:1; // LTL-X or siPSL
475  bool sugar_free_ltl:1; // No F and G operators.
476  bool ltl_formula:1; // Only LTL operators.
477  bool psl_formula:1; // Only PSL operators.
478  bool sere_formula:1; // Only SERE operators.
479  bool finite:1; // Finite SERE formulae, or Bool+X forms.
480  bool eventual:1; // Purely eventual formula.
481  bool universal:1; // Purely universal formula.
482  bool syntactic_safety:1; // Syntactic Safety Property.
483  bool syntactic_guarantee:1; // Syntactic Guarantee Property.
484  bool syntactic_obligation:1; // Syntactic Obligation Property.
485  bool syntactic_recurrence:1; // Syntactic Recurrence Property.
486  bool syntactic_persistence:1; // Syntactic Persistence Property.
487  bool not_marked:1; // No occurrence of EConcatMarked.
488  bool accepting_eword:1; // Accepts the empty word.
489  bool lbt_atomic_props:1; // Use only atomic propositions like p42.
490  bool spin_atomic_props:1; // Use only spin-compatible atomic props.
491  };
492  union
493  {
494  // Use an unsigned for fast computation of all properties.
495  unsigned props;
496  ltl_prop is_;
497  };
498 
499  const fnode* children[1];
500  };
501 
503  SPOT_API
504  int atomic_prop_cmp(const fnode* f, const fnode* g);
505 
507  {
508  bool
509  operator()(const fnode* left, const fnode* right) const
510  {
511  assert(left);
512  assert(right);
513  if (left == right)
514  return false;
515 
516  // We want Boolean formulae first.
517  bool lib = left->is_boolean();
518  if (lib != right->is_boolean())
519  return lib;
520 
521  // We have two Boolean formulae
522  if (lib)
523  {
524  bool lconst = left->is_constant();
525  if (lconst != right->is_constant())
526  return lconst;
527  if (!lconst)
528  {
529  auto get_literal = [](const fnode* f) -> const fnode*
530  {
531  if (f->is(op::Not))
532  f = f->nth(0);
533  if (f->is(op::ap))
534  return f;
535  return nullptr;
536  };
537  // Literals should come first
538  const fnode* litl = get_literal(left);
539  const fnode* litr = get_literal(right);
540  if (!litl != !litr)
541  return litl;
542  if (litl)
543  {
544  // And they should be sorted alphabetically
545  int cmp = atomic_prop_cmp(litl, litr);
546  if (cmp)
547  return cmp < 0;
548  }
549  }
550  }
551 
552  size_t l = left->id();
553  size_t r = right->id();
554  if (l != r)
555  return l < r;
556  // Because the hash code assigned to each formula is the
557  // number of formulae constructed so far, it is very unlikely
558  // that we will ever reach a case were two different formulae
559  // have the same hash. This will happen only ever with have
560  // produced 256**sizeof(size_t) formulae (i.e. max_count has
561  // looped back to 0 and started over). In that case we can
562  // order two formulas by looking at their text representation.
563  // We could be more efficient and look at their AST, but it's
564  // not worth the burden. (Also ordering pointers is ruled out
565  // because it breaks the determinism of the implementation.)
566  std::ostringstream old;
567  left->dump(old);
568  std::ostringstream ord;
569  right->dump(ord);
570  return old.str() < ord.str();
571  }
572  };
573 
574 #endif // SWIG
575 
578  class SPOT_API formula final
579  {
580  const fnode* ptr_;
581  public:
582  explicit formula(const fnode* f) noexcept
583  : ptr_(f)
584  {
585  }
586 
587  formula(std::nullptr_t) noexcept
588  : ptr_(nullptr)
589  {
590  }
591 
592  formula() noexcept
593  : ptr_(nullptr)
594  {
595  }
596 
597  formula(const formula& f) noexcept
598  : ptr_(f.ptr_)
599  {
600  if (ptr_)
601  ptr_->clone();
602  }
603 
604  formula(formula&& f) noexcept
605  : ptr_(f.ptr_)
606  {
607  f.ptr_ = nullptr;
608  }
609 
610  ~formula()
611  {
612  if (ptr_)
613  ptr_->destroy();
614  }
615 
616  const formula& operator=(std::nullptr_t)
617  {
618  this->~formula();
619  ptr_ = nullptr;
620  return *this;
621  }
622 
623  const formula& operator=(const formula& f)
624  {
625  this->~formula();
626  if ((ptr_ = f.ptr_))
627  ptr_->clone();
628  return *this;
629  }
630 
631  const formula& operator=(formula&& f) noexcept
632  {
633  std::swap(f.ptr_, ptr_);
634  return *this;
635  }
636 
637  bool operator<(const formula& other) const noexcept
638  {
639  if (SPOT_UNLIKELY(!other.ptr_))
640  return false;
641  if (SPOT_UNLIKELY(!ptr_))
642  return true;
643  if (id() < other.id())
644  return true;
645  if (id() > other.id())
646  return false;
647  // The case where id()==other.id() but ptr_ != other.ptr_ is
648  // very unlikely (we would need to build more that UINT_MAX
649  // formulas), so let's just compare pointer, and ignore the fact
650  // that it may give some nondeterminism.
651  return ptr_ < other.ptr_;
652  }
653 
654  bool operator<=(const formula& other) const noexcept
655  {
656  return *this == other || *this < other;
657  }
658 
659  bool operator>(const formula& other) const noexcept
660  {
661  return !(*this <= other);
662  }
663 
664  bool operator>=(const formula& other) const noexcept
665  {
666  return !(*this < other);
667  }
668 
669  bool operator==(const formula& other) const noexcept
670  {
671  return other.ptr_ == ptr_;
672  }
673 
674  bool operator==(std::nullptr_t) const noexcept
675  {
676  return ptr_ == nullptr;
677  }
678 
679  bool operator!=(const formula& other) const noexcept
680  {
681  return other.ptr_ != ptr_;
682  }
683 
684  bool operator!=(std::nullptr_t) const noexcept
685  {
686  return ptr_ != nullptr;
687  }
688 
689  operator bool() const
690  {
691  return ptr_ != nullptr;
692  }
693 
695  // Forwarded functions //
697 
699  static constexpr uint8_t unbounded()
700  {
701  return fnode::unbounded();
702  }
703 
705  static formula ap(const std::string& name)
706  {
707  return formula(fnode::ap(name));
708  }
709 
714  static formula unop(op o, const formula& f)
715  {
716  return formula(fnode::unop(o, f.ptr_->clone()));
717  }
718 
719 #ifndef SWIG
720  static formula unop(op o, formula&& f)
721  {
722  return formula(fnode::unop(o, f.to_node_()));
723  }
724 #endif // !SWIG
725 
727 #ifdef SWIG
728 #define SPOT_DEF_UNOP(Name) \
729  static formula Name(const formula& f) \
730  { \
731  return unop(op::Name, f); \
732  }
733 #else // !SWIG
734 #define SPOT_DEF_UNOP(Name) \
735  static formula Name(const formula& f) \
736  { \
737  return unop(op::Name, f); \
738  } \
739  static formula Name(formula&& f) \
740  { \
741  return unop(op::Name, std::move(f)); \
742  }
743 #endif // !SWIG
744  SPOT_DEF_UNOP(Not);
748 
751  SPOT_DEF_UNOP(X);
753 
756  SPOT_DEF_UNOP(F);
758 
761  SPOT_DEF_UNOP(G);
763 
766  SPOT_DEF_UNOP(Closure);
768 
771  SPOT_DEF_UNOP(NegClosure);
773 
776  SPOT_DEF_UNOP(NegClosureMarked);
778 #undef SPOT_DEF_UNOP
779 
785  static formula binop(op o, const formula& f, const formula& g)
786  {
787  return formula(fnode::binop(o, f.ptr_->clone(), g.ptr_->clone()));
788  }
789 
790 #ifndef SWIG
791  static formula binop(op o, const formula& f, formula&& g)
792  {
793  return formula(fnode::binop(o, f.ptr_->clone(), g.to_node_()));
794  }
795 
796  static formula binop(op o, formula&& f, const formula& g)
797  {
798  return formula(fnode::binop(o, f.to_node_(), g.ptr_->clone()));
799  }
800 
801  static formula binop(op o, formula&& f, formula&& g)
802  {
803  return formula(fnode::binop(o, f.to_node_(), g.to_node_()));
804  }
806 
807 #endif //SWIG
808 
809 #ifdef SWIG
810 #define SPOT_DEF_BINOP(Name) \
811  static formula Name(const formula& f, const formula& g) \
812  { \
813  return binop(op::Name, f, g); \
814  }
815 #else // !SWIG
816 #define SPOT_DEF_BINOP(Name) \
817  static formula Name(const formula& f, const formula& g) \
818  { \
819  return binop(op::Name, f, g); \
820  } \
821  static formula Name(const formula& f, formula&& g) \
822  { \
823  return binop(op::Name, f, std::move(g)); \
824  } \
825  static formula Name(formula&& f, const formula& g) \
826  { \
827  return binop(op::Name, std::move(f), g); \
828  } \
829  static formula Name(formula&& f, formula&& g) \
830  { \
831  return binop(op::Name, std::move(f), std::move(g)); \
832  }
833 #endif // !SWIG
834  SPOT_DEF_BINOP(Xor);
838 
841  SPOT_DEF_BINOP(Implies);
843 
846  SPOT_DEF_BINOP(Equiv);
848 
851  SPOT_DEF_BINOP(U);
853 
856  SPOT_DEF_BINOP(R);
858 
861  SPOT_DEF_BINOP(W);
863 
866  SPOT_DEF_BINOP(M);
868 
871  SPOT_DEF_BINOP(EConcat);
873 
876  SPOT_DEF_BINOP(EConcatMarked);
878 
881  SPOT_DEF_BINOP(UConcat);
883 #undef SPOT_DEF_BINOP
884 
890  static formula multop(op o, const std::vector<formula>& l)
891  {
892  std::vector<const fnode*> tmp;
893  tmp.reserve(l.size());
894  for (auto f: l)
895  if (f.ptr_)
896  tmp.push_back(f.ptr_->clone());
897  return formula(fnode::multop(o, std::move(tmp)));
898  }
899 
900 #ifndef SWIG
901  static formula multop(op o, std::vector<formula>&& l)
902  {
903  std::vector<const fnode*> tmp;
904  tmp.reserve(l.size());
905  for (auto f: l)
906  if (f.ptr_)
907  tmp.push_back(f.to_node_());
908  return formula(fnode::multop(o, std::move(tmp)));
909  }
910 #endif // !SWIG
911 
913 #ifdef SWIG
914 #define SPOT_DEF_MULTOP(Name) \
915  static formula Name(const std::vector<formula>& l) \
916  { \
917  return multop(op::Name, l); \
918  }
919 #else // !SWIG
920 #define SPOT_DEF_MULTOP(Name) \
921  static formula Name(const std::vector<formula>& l) \
922  { \
923  return multop(op::Name, l); \
924  } \
925  \
926  static formula Name(std::vector<formula>&& l) \
927  { \
928  return multop(op::Name, std::move(l)); \
929  }
930 #endif // !SWIG
931  SPOT_DEF_MULTOP(Or);
935 
938  SPOT_DEF_MULTOP(OrRat);
940 
943  SPOT_DEF_MULTOP(And);
945 
948  SPOT_DEF_MULTOP(AndRat);
950 
953  SPOT_DEF_MULTOP(AndNLM);
955 
958  SPOT_DEF_MULTOP(Concat);
960 
963  SPOT_DEF_MULTOP(Fusion);
965 #undef SPOT_DEF_MULTOP
966 
971  static formula bunop(op o, const formula& f,
972  uint8_t min = 0U,
973  uint8_t max = unbounded())
974  {
975  return formula(fnode::bunop(o, f.ptr_->clone(), min, max));
976  }
977 
978 #ifndef SWIG
979  static formula bunop(op o, formula&& f,
980  uint8_t min = 0U,
981  uint8_t max = unbounded())
982  {
983  return formula(fnode::bunop(o, f.to_node_(), min, max));
984  }
985 #endif // !SWIG
986 
988 #if SWIG
989 #define SPOT_DEF_BUNOP(Name) \
990  static formula Name(const formula& f, \
991  uint8_t min = 0U, \
992  uint8_t max = unbounded()) \
993  { \
994  return bunop(op::Name, f, min, max); \
995  }
996 #else // !SWIG
997 #define SPOT_DEF_BUNOP(Name) \
998  static formula Name(const formula& f, \
999  uint8_t min = 0U, \
1000  uint8_t max = unbounded()) \
1001  { \
1002  return bunop(op::Name, f, min, max); \
1003  } \
1004  static formula Name(formula&& f, \
1005  uint8_t min = 0U, \
1006  uint8_t max = unbounded()) \
1007  { \
1008  return bunop(op::Name, std::move(f), min, max); \
1009  }
1010 #endif
1011  SPOT_DEF_BUNOP(Star);
1015 
1020 
1035  SPOT_DEF_BUNOP(FStar);
1038 #undef SPOT_DEF_BUNOP
1039 
1045  static formula sugar_goto(const formula& b, uint8_t min, uint8_t max);
1046 
1052  static formula sugar_equal(const formula& b, uint8_t min, uint8_t max);
1053 
1054 #ifndef SWIG
1055  const fnode* to_node_()
1065  {
1066  auto tmp = ptr_;
1067  ptr_ = nullptr;
1068  return tmp;
1069  }
1070 #endif
1071 
1073  op kind() const
1074  {
1075  return ptr_->kind();
1076  }
1077 
1079  std::string kindstr() const
1080  {
1081  return ptr_->kindstr();
1082  }
1083 
1085  bool is(op o) const
1086  {
1087  return ptr_->is(o);
1088  }
1089 
1090 #ifndef SWIG
1091  bool is(op o1, op o2) const
1093  {
1094  return ptr_->is(o1, o2);
1095  }
1096 
1098  bool is(std::initializer_list<op> l) const
1099  {
1100  return ptr_->is(l);
1101  }
1102 #endif
1103 
1108  {
1109  auto f = ptr_->get_child_of(o);
1110  if (f)
1111  f->clone();
1112  return formula(f);
1113  }
1114 
1115 #ifndef SWIG
1116  formula get_child_of(std::initializer_list<op> l) const
1123  {
1124  auto f = ptr_->get_child_of(l);
1125  if (f)
1126  f->clone();
1127  return formula(f);
1128  }
1129 #endif
1130 
1134  unsigned min() const
1135  {
1136  return ptr_->min();
1137  }
1138 
1142  unsigned max() const
1143  {
1144  return ptr_->max();
1145  }
1146 
1148  unsigned size() const
1149  {
1150  return ptr_->size();
1151  }
1152 
1161  size_t id() const
1162  {
1163  return ptr_->id();
1164  }
1165 
1166 #ifndef SWIG
1167  class SPOT_API formula_child_iterator final
1169  {
1170  const fnode*const* ptr_;
1171  public:
1172  formula_child_iterator()
1173  : ptr_(nullptr)
1174  {
1175  }
1176 
1177  formula_child_iterator(const fnode*const* f)
1178  : ptr_(f)
1179  {
1180  }
1181 
1182  bool operator==(formula_child_iterator o)
1183  {
1184  return ptr_ == o.ptr_;
1185  }
1186 
1187  bool operator!=(formula_child_iterator o)
1188  {
1189  return ptr_ != o.ptr_;
1190  }
1191 
1192  formula operator*()
1193  {
1194  return formula((*ptr_)->clone());
1195  }
1196 
1197  formula_child_iterator operator++()
1198  {
1199  ++ptr_;
1200  return *this;
1201  }
1202 
1203  formula_child_iterator operator++(int)
1204  {
1205  auto tmp = *this;
1206  ++ptr_;
1207  return tmp;
1208  }
1209  };
1210 
1212  formula_child_iterator begin() const
1213  {
1214  return ptr_->begin();
1215  }
1216 
1218  formula_child_iterator end() const
1219  {
1220  return ptr_->end();
1221  }
1222 
1224  formula operator[](unsigned i) const
1225  {
1226  return formula(ptr_->nth(i)->clone());
1227  }
1228 #endif
1229 
1231  static formula ff()
1232  {
1233  return formula(fnode::ff());
1234  }
1235 
1237  bool is_ff() const
1238  {
1239  return ptr_->is_ff();
1240  }
1241 
1243  static formula tt()
1244  {
1245  return formula(fnode::tt());
1246  }
1247 
1249  bool is_tt() const
1250  {
1251  return ptr_->is_tt();
1252  }
1253 
1255  static formula eword()
1256  {
1257  return formula(fnode::eword());
1258  }
1259 
1261  bool is_eword() const
1262  {
1263  return ptr_->is_eword();
1264  }
1265 
1267  bool is_constant() const
1268  {
1269  return ptr_->is_constant();
1270  }
1271 
1276  bool is_Kleene_star() const
1277  {
1278  return ptr_->is_Kleene_star();
1279  }
1280 
1283  {
1284  return formula(fnode::one_star()->clone());
1285  }
1286 
1289  bool is_literal()
1290  {
1291  return (is(op::ap) ||
1292  // If f is in nenoform, Not can only occur in front of
1293  // an atomic proposition. So this way we do not have
1294  // to check the type of the child.
1295  (is(op::Not) && is_boolean() && is_in_nenoform()));
1296  }
1297 
1301  const std::string& ap_name() const
1302  {
1303  return ptr_->ap_name();
1304  }
1305 
1310  std::ostream& dump(std::ostream& os) const
1311  {
1312  return ptr_->dump(os);
1313  }
1314 
1320  formula all_but(unsigned i) const
1321  {
1322  return formula(ptr_->all_but(i));
1323  }
1324 
1334  unsigned boolean_count() const
1335  {
1336  return ptr_->boolean_count();
1337  }
1338 
1352  formula boolean_operands(unsigned* width = nullptr) const
1353  {
1354  return formula(ptr_->boolean_operands(width));
1355  }
1356 
1357 #define SPOT_DEF_PROP(Name) \
1358  bool Name() const \
1359  { \
1360  return ptr_->Name(); \
1361  }
1362  // Properties //
1365 
1367  SPOT_DEF_PROP(is_boolean);
1369  SPOT_DEF_PROP(is_sugar_free_boolean);
1374  SPOT_DEF_PROP(is_in_nenoform);
1376  SPOT_DEF_PROP(is_syntactic_stutter_invariant);
1378  SPOT_DEF_PROP(is_sugar_free_ltl);
1380  SPOT_DEF_PROP(is_ltl_formula);
1382  SPOT_DEF_PROP(is_psl_formula);
1384  SPOT_DEF_PROP(is_sere_formula);
1387  SPOT_DEF_PROP(is_finite);
1391 
1405  SPOT_DEF_PROP(is_eventual);
1412 
1426  SPOT_DEF_PROP(is_universal);
1431  SPOT_DEF_PROP(is_syntactic_safety);
1433  SPOT_DEF_PROP(is_syntactic_guarantee);
1435  SPOT_DEF_PROP(is_syntactic_obligation);
1437  SPOT_DEF_PROP(is_syntactic_recurrence);
1439  SPOT_DEF_PROP(is_syntactic_persistence);
1442  SPOT_DEF_PROP(is_marked);
1444  SPOT_DEF_PROP(accepts_eword);
1450  SPOT_DEF_PROP(has_lbt_atomic_props);
1459  SPOT_DEF_PROP(has_spin_atomic_props);
1460 #undef SPOT_DEF_PROP
1461 
1463  template<typename Trans>
1464  formula map(Trans trans)
1465  {
1466  switch (op o = kind())
1467  {
1468  case op::ff:
1469  case op::tt:
1470  case op::eword:
1471  case op::ap:
1472  return *this;
1473  case op::Not:
1474  case op::X:
1475  case op::F:
1476  case op::G:
1477  case op::Closure:
1478  case op::NegClosure:
1479  case op::NegClosureMarked:
1480  return unop(o, trans((*this)[0]));
1481  case op::Xor:
1482  case op::Implies:
1483  case op::Equiv:
1484  case op::U:
1485  case op::R:
1486  case op::W:
1487  case op::M:
1488  case op::EConcat:
1489  case op::EConcatMarked:
1490  case op::UConcat:
1491  {
1492  formula tmp = trans((*this)[0]);
1493  return binop(o, tmp, trans((*this)[1]));
1494  }
1495  case op::Or:
1496  case op::OrRat:
1497  case op::And:
1498  case op::AndRat:
1499  case op::AndNLM:
1500  case op::Concat:
1501  case op::Fusion:
1502  {
1503  std::vector<formula> tmp;
1504  tmp.reserve(size());
1505  for (auto f: *this)
1506  tmp.push_back(trans(f));
1507  return multop(o, std::move(tmp));
1508  }
1509  case op::Star:
1510  case op::FStar:
1511  return bunop(o, trans((*this)[0]), min(), max());
1512  }
1513  SPOT_UNREACHABLE();
1514  }
1515 
1521  template<typename Func>
1522  void traverse(Func func)
1523  {
1524  if (func(*this))
1525  return;
1526  for (auto f: *this)
1527  f.traverse(func);
1528  }
1529  };
1530 
1532  SPOT_API
1533  std::ostream& print_formula_props(std::ostream& out, const formula& f,
1534  bool abbreviated = false);
1535 
1537  SPOT_API
1538  std::list<std::string> list_formula_props(const formula& f);
1539 
1541  SPOT_API
1542  std::ostream& operator<<(std::ostream& os, const formula& f);
1543 }
1544 
1545 #ifndef SWIG
1546 namespace std
1547 {
1548  template <>
1549  struct hash<spot::formula>
1550  {
1551  size_t operator()(const spot::formula& x) const noexcept
1552  {
1553  return x.id();
1554  }
1555  };
1556 }
1557 #endif
static formula multop(op o, const std::vector< formula > &l)
Construct an n-ary operator.
Definition: formula.hh:890
Definition: graph.hh:32
static formula one_star()
Return a copy of the formula 1[*].
Definition: formula.hh:1282
bool is_constant() const
Whether the formula is op::ff, op::tt, or op::eword.
Definition: formula.hh:1267
std::ostream & dump(std::ostream &os) const
Print the formula for debugging.
Definition: formula.hh:1310
static formula binop(op o, formula &&f, formula &&g)
Construct a binary operator.
Definition: formula.hh:801
formula get_child_of(op o) const
Remove operator o and return the child.
Definition: formula.hh:1107
formula all_but(unsigned i) const
clone this formula, omitting child i
Definition: formula.hh:1320
PSL Closure.
unsigned max() const
Return end of the range for star-like operators.
Definition: formula.hh:1142
const std::string & ap_name() const
Print the name of an atomic proposition.
Definition: formula.hh:1301
bool is_tt() const
Whether the formula is the true constant.
Definition: formula.hh:1249
static formula ap(const std::string &name)
Build an atomic proposition.
Definition: formula.hh:705
unsigned size() const
Return the number of children.
Definition: formula.hh:1148
static formula tt()
Return the true constant.
Definition: formula.hh:1243
unsigned boolean_count() const
number of Boolean children
Definition: formula.hh:1334
Definition: formula.hh:1546
Empty word.
static formula binop(op o, formula &&f, const formula &g)
Construct a binary operator.
Definition: formula.hh:796
static formula binop(op o, const formula &f, formula &&g)
Construct a binary operator.
Definition: formula.hh:791
Concatenation.
unsigned min() const
Return start of the range for star-like operators.
Definition: formula.hh:1134
Main class for temporal logic formula.
Definition: formula.hh:578
int atomic_prop_cmp(const fnode *f, const fnode *g)
Order two atomic propositions.
Globally.
release (dual of until)
bool is_literal()
Whether the formula is an atomic proposition or its negation.
Definition: formula.hh:1289
formula boolean_operands(unsigned *width=nullptr) const
return a clone of the current node, restricted to its Boolean children
Definition: formula.hh:1352
static formula unop(op o, formula &&f)
Build a unary operator.
Definition: formula.hh:720
bool is_ff() const
Whether the formula is the false constant.
Definition: formula.hh:1237
Fustion Star.
weak until
static formula ff()
Return the false constant.
Definition: formula.hh:1231
std::list< std::string > list_formula_props(const formula &f)
List the properties of formula f.
static formula multop(op o, std::vector< formula > &&l)
Construct an n-ary operator.
Definition: formula.hh:901
formula operator[](unsigned i) const
Return children number i.
Definition: formula.hh:1224
Equivalence.
Non-Length-Matching Rational-And.
std::ostream & print_formula_props(std::ostream &out, const formula &f, bool abbreviated=false)
Print the properties of formula f on stream out.
static formula bunop(op o, formula &&f, uint8_t min=0U, uint8_t max=unbounded())
Define a bounded unary-operator (i.e. star-like)
Definition: formula.hh:979
Exclusive Or.
marked version of the Negated PSL Clusure
static formula eword()
Return the empty word constant.
Definition: formula.hh:1255
op kind() const
Return top-most operator.
Definition: formula.hh:1073
bool is(op o) const
Return true if the formula is of kind o.
Definition: formula.hh:1085
Definition: formula.hh:506
formula map(Trans trans)
Clone this node after applying trans to its children.
Definition: formula.hh:1464
bool is_Kleene_star() const
Test whether the formula represent a Kleene star.
Definition: formula.hh:1276
(omega-Rational) Or
static constexpr uint8_t unbounded()
Unbounded constant to use as end of range for bounded operators.
Definition: formula.hh:699
Negation.
const fnode * to_node_()
Return the underlying pointer to the formula.
Definition: formula.hh:1064
formula_child_iterator begin() const
Allow iterating over children.
Definition: formula.hh:1212
op
Operator types.
Definition: formula.hh:62
static formula unop(op o, const formula &f)
Build a unary operator.
Definition: formula.hh:714
static formula bunop(op o, const formula &f, uint8_t min=0U, uint8_t max=unbounded())
Define a bounded unary-operator (i.e. star-like)
Definition: formula.hh:971
Implication.
formula_child_iterator end() const
Allow iterating over children.
Definition: formula.hh:1218
size_t id() const
Return the id of a formula.
Definition: formula.hh:1161
Negated PSL Closure.
Rational And.
static formula binop(op o, const formula &f, const formula &g)
Construct a binary operator.
Definition: formula.hh:785
bool is(std::initializer_list< op > l) const
Return true if the formulas nests all the operators in l.
Definition: formula.hh:1098
strong release (dual of weak until)
void traverse(Func func)
Apply func to each subformula.
Definition: formula.hh:1522
Atomic proposition.
Eventually.
std::string kindstr() const
Return the name of the top-most operator.
Definition: formula.hh:1079
(omega-Rational) And
bool is_eword() const
Whether the formula is the empty word constant.
Definition: formula.hh:1261
Rational Or.

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on Sun Mar 13 2016 15:52:49 for spot by doxygen 1.8.11