spot  1.99.4
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
formula.hh
Go to the documentation of this file.
1 // -*- coding: utf-8 -*-
2 // Copyright (C) 2015 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 "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 
57 namespace spot
58 {
61  enum class op: uint8_t
62  {
63  ff,
64  tt,
65  eword,
66  ap,
67  // unary operators
68  Not,
69  X,
70  F,
71  G,
72  Closure,
73  NegClosure,
75  // binary operators
76  Xor,
77  Implies,
78  Equiv,
79  U,
80  R,
81  W,
82  M,
83  EConcat,
85  UConcat,
86  // n-ary operators
87  Or,
88  OrRat,
89  And,
90  AndRat,
91  AndNLM,
92  Concat,
93  Fusion,
94  // star-like operators
95  Star,
96  FStar,
97  };
98 
99 #ifndef SWIG
100  class SPOT_API fnode final
107  {
108  public:
109  const fnode* clone() const
110  {
111  ++refs_;
112  return this;
113  }
114 
115  void destroy() const
116  {
117  // last reference to a node that is not a constant?
118  if (SPOT_UNLIKELY(!refs_ && id_ > 2))
119  destroy_aux();
120  else
121  --refs_;
122  }
123 
124  static constexpr uint8_t unbounded()
125  {
126  return UINT8_MAX;
127  }
128 
129  static const fnode* ap(const std::string& name);
130  static const fnode* unop(op o, const fnode* f);
131  static const fnode* binop(op o, const fnode* f, const fnode* g);
132  static const fnode* multop(op o, std::vector<const fnode*> l);
133  static const fnode* bunop(op o, const fnode* f,
134  uint8_t min, uint8_t max = unbounded());
135 
136  op kind() const
137  {
138  return op_;
139  }
140 
141  std::string kindstr() const;
142 
143  bool is(op o) const
144  {
145  return op_ == o;
146  }
147 
148  bool is(op o1, op o2) const
149  {
150  return op_ == o1 || op_ == o2;
151  }
152 
153  bool is(std::initializer_list<op> l) const
154  {
155  const fnode* n = this;
156  for (auto o: l)
157  {
158  if (!n->is(o))
159  return false;
160  n = n->nth(0);
161  }
162  return true;
163  }
164 
165  const fnode* get_child_of(op o) const
166  {
167  if (op_ != o)
168  return nullptr;
169  assert(size_ == 1);
170  return nth(0);
171  }
172 
173  const fnode* get_child_of(std::initializer_list<op> l) const
174  {
175  auto c = this;
176  for (auto o: l)
177  {
178  c = c->get_child_of(o);
179  if (c == nullptr)
180  return c;
181  }
182  return c;
183  }
184 
185  unsigned min() const
186  {
187  assert(op_ == op::FStar || op_ == op::Star);
188  return min_;
189  }
190 
191  unsigned max() const
192  {
193  assert(op_ == op::FStar || op_ == op::Star);
194  return max_;
195  }
196 
197  unsigned size() const
198  {
199  return size_;
200  }
201 
202  size_t id() const
203  {
204  return id_;
205  }
206 
207  const fnode*const* begin() const
208  {
209  return children;
210  }
211 
212  const fnode*const* end() const
213  {
214  return children + size();
215  }
216 
217  const fnode* nth(unsigned i) const
218  {
219  if (i >= size())
220  throw std::runtime_error("access to non-existing child");
221  return children[i];
222  }
223 
224  static const fnode* ff()
225  {
226  return ff_;
227  }
228 
229  bool is_ff() const
230  {
231  return op_ == op::ff;
232  }
233 
234  static const fnode* tt()
235  {
236  return tt_;
237  }
238 
239  bool is_tt() const
240  {
241  return op_ == op::tt;
242  }
243 
244  static const fnode* eword()
245  {
246  return ew_;
247  }
248 
249  bool is_eword() const
250  {
251  return op_ == op::eword;
252  }
253 
254  bool is_constant() const
255  {
256  return op_ == op::ff || op_ == op::tt || op_ == op::eword;
257  }
258 
259  bool is_Kleene_star() const
260  {
261  if (op_ != op::Star)
262  return false;
263  return min_ == 0 && max_ == unbounded();
264  }
265 
266  static const fnode* one_star()
267  {
268  if (!one_star_)
269  one_star_ = bunop(op::Star, tt(), 0);
270  return one_star_;
271  }
272 
273  const std::string& ap_name() const;
274  std::ostream& dump(std::ostream& os) const;
275 
276  const fnode* all_but(unsigned i) const;
277 
278  unsigned boolean_count() const
279  {
280  unsigned pos = 0;
281  unsigned s = size();
282  while (pos < s && children[pos]->is_boolean())
283  ++pos;
284  return pos;
285  }
286 
287  const fnode* boolean_operands(unsigned* width = nullptr) const;
288 
291  static bool instances_check();
292 
294  // Properties //
296 
297  bool is_boolean() const
298  {
299  return is_.boolean;
300  }
301 
302  bool is_sugar_free_boolean() const
303  {
304  return is_.sugar_free_boolean;
305  }
306 
307  bool is_in_nenoform() const
308  {
309  return is_.in_nenoform;
310  }
311 
312  bool is_syntactic_stutter_invariant() const
313  {
314  return is_.syntactic_si;
315  }
316 
317  bool is_sugar_free_ltl() const
318  {
319  return is_.sugar_free_ltl;
320  }
321 
322  bool is_ltl_formula() const
323  {
324  return is_.ltl_formula;
325  }
326 
327  bool is_psl_formula() const
328  {
329  return is_.psl_formula;
330  }
331 
332  bool is_sere_formula() const
333  {
334  return is_.sere_formula;
335  }
336 
337  bool is_finite() const
338  {
339  return is_.finite;
340  }
341 
342  bool is_eventual() const
343  {
344  return is_.eventual;
345  }
346 
347  bool is_universal() const
348  {
349  return is_.universal;
350  }
351 
352  bool is_syntactic_safety() const
353  {
354  return is_.syntactic_safety;
355  }
356 
357  bool is_syntactic_guarantee() const
358  {
359  return is_.syntactic_guarantee;
360  }
361 
362  bool is_syntactic_obligation() const
363  {
364  return is_.syntactic_obligation;
365  }
366 
367  bool is_syntactic_recurrence() const
368  {
369  return is_.syntactic_recurrence;
370  }
371 
372  bool is_syntactic_persistence() const
373  {
374  return is_.syntactic_persistence;
375  }
376 
377  bool is_marked() const
378  {
379  return !is_.not_marked;
380  }
381 
382  bool accepts_eword() const
383  {
384  return is_.accepting_eword;
385  }
386 
387  bool has_lbt_atomic_props() const
388  {
389  return is_.lbt_atomic_props;
390  }
391 
392  bool has_spin_atomic_props() const
393  {
394  return is_.spin_atomic_props;
395  }
396 
397  private:
398  void setup_props(op o);
399  void destroy_aux() const;
400 
401  static const fnode* unique(const fnode*);
402 
403  // Destruction may only happen via destroy().
404  ~fnode() = default;
405  // Disallow copies.
406  fnode(const fnode&) = delete;
407  fnode& operator=(const fnode&) = delete;
408 
409 
410 
411  template<class iter>
412  fnode(op o, iter begin, iter end)
413  {
414  size_t s = std::distance(begin, end);
415  if (s > (size_t) UINT16_MAX)
416  throw std::runtime_error("too many children for formula");
417  size_ = s;
418  auto pos = children;
419  for (auto i = begin; i != end; ++i)
420  *pos++ = *i;
421  setup_props(o);
422  }
423 
424  fnode(op o, std::initializer_list<const fnode*> l)
425  : fnode(o, l.begin(), l.end())
426  {
427  }
428 
429  fnode(op o, const fnode* f, uint8_t min, uint8_t max)
430  {
431  size_ = 1;
432  children[0] = f;
433  min_ = min;
434  max_ = max;
435  setup_props(o);
436  }
437 
438  static const fnode* ff_;
439  static const fnode* tt_;
440  static const fnode* ew_;
441  static const fnode* one_star_;
442 
443  op op_; // operator
444  uint8_t min_; // range minimum (for star-like operators)
445  uint8_t max_; // range maximum;
446  //uint8_t unused_;
447  uint16_t size_; // number of children
448  mutable uint16_t refs_ = 0; // reference count - 1;
449  size_t id_; // Also used as hash.
450  static size_t next_id_;
451 
452  struct ltl_prop
453  {
454  // All properties here should be expressed in such a a way
455  // that property(f && g) is just property(f)&property(g).
456  // This allows us to compute all properties of a compound
457  // formula in one operation.
458  //
459  // For instance we do not use a property that says "has
460  // temporal operator", because it would require an OR between
461  // the two arguments. Instead we have a property that
462  // says "no temporal operator", and that one is computed
463  // with an AND between the arguments.
464  //
465  // Also choose a name that makes sense when prefixed with
466  // "the formula is".
467  bool boolean:1; // No temporal operators.
468  bool sugar_free_boolean:1; // Only AND, OR, and NOT operators.
469  bool in_nenoform:1; // Negative Normal Form.
470  bool syntactic_si:1; // LTL-X or siPSL
471  bool sugar_free_ltl:1; // No F and G operators.
472  bool ltl_formula:1; // Only LTL operators.
473  bool psl_formula:1; // Only PSL operators.
474  bool sere_formula:1; // Only SERE operators.
475  bool finite:1; // Finite SERE formulae, or Bool+X forms.
476  bool eventual:1; // Purely eventual formula.
477  bool universal:1; // Purely universal formula.
478  bool syntactic_safety:1; // Syntactic Safety Property.
479  bool syntactic_guarantee:1; // Syntactic Guarantee Property.
480  bool syntactic_obligation:1; // Syntactic Obligation Property.
481  bool syntactic_recurrence:1; // Syntactic Recurrence Property.
482  bool syntactic_persistence:1; // Syntactic Persistence Property.
483  bool not_marked:1; // No occurrence of EConcatMarked.
484  bool accepting_eword:1; // Accepts the empty word.
485  bool lbt_atomic_props:1; // Use only atomic propositions like p42.
486  bool spin_atomic_props:1; // Use only spin-compatible atomic props.
487  };
488  union
489  {
490  // Use an unsigned for fast computation of all properties.
491  unsigned props;
492  ltl_prop is_;
493  };
494 
495  const fnode* children[1];
496  };
497 
499  SPOT_API
500  int atomic_prop_cmp(const fnode* f, const fnode* g);
501 
503  {
504  bool
505  operator()(const fnode* left, const fnode* right) const
506  {
507  assert(left);
508  assert(right);
509  if (left == right)
510  return false;
511 
512  // We want Boolean formulae first.
513  bool lib = left->is_boolean();
514  if (lib != right->is_boolean())
515  return lib;
516 
517  // We have two Boolean formulae
518  if (lib)
519  {
520  bool lconst = left->is_constant();
521  if (lconst != right->is_constant())
522  return lconst;
523  if (!lconst)
524  {
525  auto get_literal = [](const fnode* f) -> const fnode*
526  {
527  if (f->is(op::Not))
528  f = f->nth(0);
529  if (f->is(op::ap))
530  return f;
531  return nullptr;
532  };
533  // Literals should come first
534  const fnode* litl = get_literal(left);
535  const fnode* litr = get_literal(right);
536  if (!litl != !litr)
537  return litl;
538  if (litl)
539  {
540  // And they should be sorted alphabetically
541  int cmp = atomic_prop_cmp(litl, litr);
542  if (cmp)
543  return cmp < 0;
544  }
545  }
546  }
547 
548  size_t l = left->id();
549  size_t r = right->id();
550  if (l != r)
551  return l < r;
552  // Because the hash code assigned to each formula is the
553  // number of formulae constructed so far, it is very unlikely
554  // that we will ever reach a case were two different formulae
555  // have the same hash. This will happen only ever with have
556  // produced 256**sizeof(size_t) formulae (i.e. max_count has
557  // looped back to 0 and started over). In that case we can
558  // order two formulas by looking at their text representation.
559  // We could be more efficient and look at their AST, but it's
560  // not worth the burden. (Also ordering pointers is ruled out
561  // because it breaks the determinism of the implementation.)
562  std::ostringstream old;
563  left->dump(old);
564  std::ostringstream ord;
565  right->dump(ord);
566  return old.str() < ord.str();
567  }
568  };
569 
570 #endif // SWIG
571 
574  class SPOT_API formula final
575  {
576  const fnode* ptr_;
577  public:
578  explicit formula(const fnode* f) noexcept
579  : ptr_(f)
580  {
581  }
582 
583  formula(std::nullptr_t) noexcept
584  : ptr_(nullptr)
585  {
586  }
587 
588  formula() noexcept
589  : ptr_(nullptr)
590  {
591  }
592 
593  formula(const formula& f) noexcept
594  : ptr_(f.ptr_)
595  {
596  if (ptr_)
597  ptr_->clone();
598  }
599 
600  formula(formula&& f) noexcept
601  : ptr_(f.ptr_)
602  {
603  f.ptr_ = nullptr;
604  }
605 
606  ~formula()
607  {
608  if (ptr_)
609  ptr_->destroy();
610  }
611 
612  const formula& operator=(std::nullptr_t)
613  {
614  this->~formula();
615  ptr_ = nullptr;
616  return *this;
617  }
618 
619  const formula& operator=(const formula& f)
620  {
621  this->~formula();
622  if ((ptr_ = f.ptr_))
623  ptr_->clone();
624  return *this;
625  }
626 
627  const formula& operator=(formula&& f) noexcept
628  {
629  std::swap(f.ptr_, ptr_);
630  return *this;
631  }
632 
633  bool operator<(const formula& other) const noexcept
634  {
635  if (SPOT_UNLIKELY(!other.ptr_))
636  return false;
637  if (SPOT_UNLIKELY(!ptr_))
638  return true;
639  if (id() < other.id())
640  return true;
641  if (id() > other.id())
642  return false;
643  // The case where id()==other.id() but ptr_ != other.ptr_ is
644  // very unlikely (we would need to build more that UINT_MAX
645  // formulas), so let's just compare pointer, and ignore the fact
646  // that it may give some nondeterminism.
647  return ptr_ < other.ptr_;
648  }
649 
650  bool operator<=(const formula& other) const noexcept
651  {
652  return *this == other || *this < other;
653  }
654 
655  bool operator>(const formula& other) const noexcept
656  {
657  return !(*this <= other);
658  }
659 
660  bool operator>=(const formula& other) const noexcept
661  {
662  return !(*this < other);
663  }
664 
665  bool operator==(const formula& other) const noexcept
666  {
667  return other.ptr_ == ptr_;
668  }
669 
670  bool operator==(std::nullptr_t) const noexcept
671  {
672  return ptr_ == nullptr;
673  }
674 
675  bool operator!=(const formula& other) const noexcept
676  {
677  return other.ptr_ != ptr_;
678  }
679 
680  bool operator!=(std::nullptr_t) const noexcept
681  {
682  return ptr_ != nullptr;
683  }
684 
685  operator bool() const
686  {
687  return ptr_ != nullptr;
688  }
689 
691  // Forwarded functions //
693 
695  static constexpr uint8_t unbounded()
696  {
697  return fnode::unbounded();
698  }
699 
701  static formula ap(const std::string& name)
702  {
703  return formula(fnode::ap(name));
704  }
705 
710  static formula unop(op o, const formula& f)
711  {
712  return formula(fnode::unop(o, f.ptr_->clone()));
713  }
714 
715 #ifndef SWIG
716  static formula unop(op o, formula&& f)
717  {
718  return formula(fnode::unop(o, f.to_node_()));
719  }
720 #endif // !SWIG
721 
723 #ifdef SWIG
724 #define SPOT_DEF_UNOP(Name) \
725  static formula Name(const formula& f) \
726  { \
727  return unop(op::Name, f); \
728  }
729 #else // !SWIG
730 #define SPOT_DEF_UNOP(Name) \
731  static formula Name(const formula& f) \
732  { \
733  return unop(op::Name, f); \
734  } \
735  static formula Name(formula&& f) \
736  { \
737  return unop(op::Name, std::move(f)); \
738  }
739 #endif // !SWIG
740  SPOT_DEF_UNOP(Not);
744 
747  SPOT_DEF_UNOP(X);
749 
752  SPOT_DEF_UNOP(F);
754 
757  SPOT_DEF_UNOP(G);
759 
762  SPOT_DEF_UNOP(Closure);
764 
767  SPOT_DEF_UNOP(NegClosure);
769 
772  SPOT_DEF_UNOP(NegClosureMarked);
774 #undef SPOT_DEF_UNOP
775 
780  static formula binop(op o, const formula& f, const formula& g)
781  {
782  return formula(fnode::binop(o, f.ptr_->clone(), g.ptr_->clone()));
783  }
784 
785 #ifndef SWIG
786  static formula binop(op o, const formula& f, formula&& g)
787  {
788  return formula(fnode::binop(o, f.ptr_->clone(), g.to_node_()));
789  }
790 
791  static formula binop(op o, formula&& f, const formula& g)
792  {
793  return formula(fnode::binop(o, f.to_node_(), g.ptr_->clone()));
794  }
795 
796  static formula binop(op o, formula&& f, formula&& g)
797  {
798  return formula(fnode::binop(o, f.to_node_(), g.to_node_()));
799  }
800 #endif //SWIG
801 
802 #ifdef SWIG
803 #define SPOT_DEF_BINOP(Name) \
804  static formula Name(const formula& f, const formula& g) \
805  { \
806  return binop(op::Name, f, g); \
807  }
808 #else // !SWIG
809 #define SPOT_DEF_BINOP(Name) \
810  static formula Name(const formula& f, const formula& g) \
811  { \
812  return binop(op::Name, f, g); \
813  } \
814  static formula Name(const formula& f, formula&& g) \
815  { \
816  return binop(op::Name, f, std::move(g)); \
817  } \
818  static formula Name(formula&& f, const formula& g) \
819  { \
820  return binop(op::Name, std::move(f), g); \
821  } \
822  static formula Name(formula&& f, formula&& g) \
823  { \
824  return binop(op::Name, std::move(f), std::move(g)); \
825  }
826 #endif // !SWIG
827  SPOT_DEF_BINOP(Xor);
831 
834  SPOT_DEF_BINOP(Implies);
836 
839  SPOT_DEF_BINOP(Equiv);
841 
844  SPOT_DEF_BINOP(U);
846 
849  SPOT_DEF_BINOP(R);
851 
854  SPOT_DEF_BINOP(W);
856 
859  SPOT_DEF_BINOP(M);
861 
864  SPOT_DEF_BINOP(EConcat);
866 
869  SPOT_DEF_BINOP(EConcatMarked);
871 
874  SPOT_DEF_BINOP(UConcat);
876 #undef SPOT_DEF_BINOP
877 
883  static formula multop(op o, const std::vector<formula>& l)
884  {
885  std::vector<const fnode*> tmp;
886  tmp.reserve(l.size());
887  for (auto f: l)
888  if (f.ptr_)
889  tmp.push_back(f.ptr_->clone());
890  return formula(fnode::multop(o, std::move(tmp)));
891  }
892 
893 #ifndef SWIG
894  static formula multop(op o, std::vector<formula>&& l)
895  {
896  std::vector<const fnode*> tmp;
897  tmp.reserve(l.size());
898  for (auto f: l)
899  if (f.ptr_)
900  tmp.push_back(f.to_node_());
901  return formula(fnode::multop(o, std::move(tmp)));
902  }
903 #endif // !SWIG
904 
906 #ifdef SWIG
907 #define SPOT_DEF_MULTOP(Name) \
908  static formula Name(const std::vector<formula>& l) \
909  { \
910  return multop(op::Name, l); \
911  }
912 #else // !SWIG
913 #define SPOT_DEF_MULTOP(Name) \
914  static formula Name(const std::vector<formula>& l) \
915  { \
916  return multop(op::Name, l); \
917  } \
918  \
919  static formula Name(std::vector<formula>&& l) \
920  { \
921  return multop(op::Name, std::move(l)); \
922  }
923 #endif // !SWIG
924  SPOT_DEF_MULTOP(Or);
928 
931  SPOT_DEF_MULTOP(OrRat);
933 
936  SPOT_DEF_MULTOP(And);
938 
941  SPOT_DEF_MULTOP(AndRat);
943 
946  SPOT_DEF_MULTOP(AndNLM);
948 
951  SPOT_DEF_MULTOP(Concat);
953 
956  SPOT_DEF_MULTOP(Fusion);
958 #undef SPOT_DEF_MULTOP
959 
964  static formula bunop(op o, const formula& f,
965  uint8_t min = 0U,
966  uint8_t max = unbounded())
967  {
968  return formula(fnode::bunop(o, f.ptr_->clone(), min, max));
969  }
970 
971 #ifndef SWIG
972  static formula bunop(op o, formula&& f,
973  uint8_t min = 0U,
974  uint8_t max = unbounded())
975  {
976  return formula(fnode::bunop(o, f.to_node_(), min, max));
977  }
978 #endif // !SWIG
979 
981 #if SWIG
982 #define SPOT_DEF_BUNOP(Name) \
983  static formula Name(const formula& f, \
984  uint8_t min = 0U, \
985  uint8_t max = unbounded()) \
986  { \
987  return bunop(op::Name, f, min, max); \
988  }
989 #else // !SWIG
990 #define SPOT_DEF_BUNOP(Name) \
991  static formula Name(const formula& f, \
992  uint8_t min = 0U, \
993  uint8_t max = unbounded()) \
994  { \
995  return bunop(op::Name, f, min, max); \
996  } \
997  static formula Name(formula&& f, \
998  uint8_t min = 0U, \
999  uint8_t max = unbounded()) \
1000  { \
1001  return bunop(op::Name, std::move(f), min, max); \
1002  }
1003 #endif
1004  SPOT_DEF_BUNOP(Star);
1008 
1013 
1028  SPOT_DEF_BUNOP(FStar);
1031 #undef SPOT_DEF_BUNOP
1032 
1038  static formula sugar_goto(const formula& b, uint8_t min, uint8_t max);
1039 
1045  static formula sugar_equal(const formula& b, uint8_t min, uint8_t max);
1046 
1047 #ifndef SWIG
1048  const fnode* to_node_()
1058  {
1059  auto tmp = ptr_;
1060  ptr_ = nullptr;
1061  return tmp;
1062  }
1063 #endif
1064 
1066  op kind() const
1067  {
1068  return ptr_->kind();
1069  }
1070 
1072  std::string kindstr() const
1073  {
1074  return ptr_->kindstr();
1075  }
1076 
1078  bool is(op o) const
1079  {
1080  return ptr_->is(o);
1081  }
1082 
1083 #ifndef SWIG
1084  bool is(op o1, op o2) const
1086  {
1087  return ptr_->is(o1, o2);
1088  }
1089 
1091  bool is(std::initializer_list<op> l) const
1092  {
1093  return ptr_->is(l);
1094  }
1095 #endif
1096 
1101  {
1102  auto f = ptr_->get_child_of(o);
1103  if (f)
1104  f->clone();
1105  return formula(f);
1106  }
1107 
1108 #ifndef SWIG
1109  formula get_child_of(std::initializer_list<op> l) const
1116  {
1117  auto f = ptr_->get_child_of(l);
1118  if (f)
1119  f->clone();
1120  return formula(f);
1121  }
1122 #endif
1123 
1127  unsigned min() const
1128  {
1129  return ptr_->min();
1130  }
1131 
1135  unsigned max() const
1136  {
1137  return ptr_->max();
1138  }
1139 
1141  unsigned size() const
1142  {
1143  return ptr_->size();
1144  }
1145 
1154  size_t id() const
1155  {
1156  return ptr_->id();
1157  }
1158 
1159 #ifndef SWIG
1160  class SPOT_API formula_child_iterator final
1162  {
1163  const fnode*const* ptr_;
1164  public:
1165  formula_child_iterator()
1166  : ptr_(nullptr)
1167  {
1168  }
1169 
1170  formula_child_iterator(const fnode*const* f)
1171  : ptr_(f)
1172  {
1173  }
1174 
1175  bool operator==(formula_child_iterator o)
1176  {
1177  return ptr_ == o.ptr_;
1178  }
1179 
1180  bool operator!=(formula_child_iterator o)
1181  {
1182  return ptr_ != o.ptr_;
1183  }
1184 
1185  formula operator*()
1186  {
1187  return formula((*ptr_)->clone());
1188  }
1189 
1190  formula_child_iterator operator++()
1191  {
1192  ++ptr_;
1193  return *this;
1194  }
1195 
1196  formula_child_iterator operator++(int)
1197  {
1198  auto tmp = *this;
1199  ++ptr_;
1200  return tmp;
1201  }
1202  };
1203 
1206  {
1207  return ptr_->begin();
1208  }
1209 
1212  {
1213  return ptr_->end();
1214  }
1215 
1217  formula operator[](unsigned i) const
1218  {
1219  return formula(ptr_->nth(i)->clone());
1220  }
1221 #endif
1222 
1224  static formula ff()
1225  {
1226  return formula(fnode::ff());
1227  }
1228 
1230  bool is_ff() const
1231  {
1232  return ptr_->is_ff();
1233  }
1234 
1236  static formula tt()
1237  {
1238  return formula(fnode::tt());
1239  }
1240 
1242  bool is_tt() const
1243  {
1244  return ptr_->is_tt();
1245  }
1246 
1248  static formula eword()
1249  {
1250  return formula(fnode::eword());
1251  }
1252 
1254  bool is_eword() const
1255  {
1256  return ptr_->is_eword();
1257  }
1258 
1260  bool is_constant() const
1261  {
1262  return ptr_->is_constant();
1263  }
1264 
1269  bool is_Kleene_star() const
1270  {
1271  return ptr_->is_Kleene_star();
1272  }
1273 
1276  {
1277  return formula(fnode::one_star()->clone());
1278  }
1279 
1282  bool is_literal()
1283  {
1284  return (is(op::ap) ||
1285  // If f is in nenoform, Not can only occur in front of
1286  // an atomic proposition. So this way we do not have
1287  // to check the type of the child.
1288  (is(op::Not) && is_boolean() && is_in_nenoform()));
1289  }
1290 
1294  const std::string& ap_name() const
1295  {
1296  return ptr_->ap_name();
1297  }
1298 
1303  std::ostream& dump(std::ostream& os) const
1304  {
1305  return ptr_->dump(os);
1306  }
1307 
1313  formula all_but(unsigned i) const
1314  {
1315  return formula(ptr_->all_but(i));
1316  }
1317 
1327  unsigned boolean_count() const
1328  {
1329  return ptr_->boolean_count();
1330  }
1331 
1345  formula boolean_operands(unsigned* width = nullptr) const
1346  {
1347  return formula(ptr_->boolean_operands(width));
1348  }
1349 
1350 #define SPOT_DEF_PROP(Name) \
1351  bool Name() const \
1352  { \
1353  return ptr_->Name(); \
1354  }
1355  // Properties //
1358 
1360  SPOT_DEF_PROP(is_boolean);
1362  SPOT_DEF_PROP(is_sugar_free_boolean);
1367  SPOT_DEF_PROP(is_in_nenoform);
1369  SPOT_DEF_PROP(is_syntactic_stutter_invariant);
1371  SPOT_DEF_PROP(is_sugar_free_ltl);
1373  SPOT_DEF_PROP(is_ltl_formula);
1375  SPOT_DEF_PROP(is_psl_formula);
1377  SPOT_DEF_PROP(is_sere_formula);
1380  SPOT_DEF_PROP(is_finite);
1384 
1398  SPOT_DEF_PROP(is_eventual);
1405 
1419  SPOT_DEF_PROP(is_universal);
1424  SPOT_DEF_PROP(is_syntactic_safety);
1426  SPOT_DEF_PROP(is_syntactic_guarantee);
1428  SPOT_DEF_PROP(is_syntactic_obligation);
1430  SPOT_DEF_PROP(is_syntactic_recurrence);
1432  SPOT_DEF_PROP(is_syntactic_persistence);
1435  SPOT_DEF_PROP(is_marked);
1437  SPOT_DEF_PROP(accepts_eword);
1443  SPOT_DEF_PROP(has_lbt_atomic_props);
1452  SPOT_DEF_PROP(has_spin_atomic_props);
1453 #undef SPOT_DEF_PROP
1454 
1456  template<typename Trans>
1457  formula map(Trans trans)
1458  {
1459  switch (op o = kind())
1460  {
1461  case op::ff:
1462  case op::tt:
1463  case op::eword:
1464  case op::ap:
1465  return *this;
1466  case op::Not:
1467  case op::X:
1468  case op::F:
1469  case op::G:
1470  case op::Closure:
1471  case op::NegClosure:
1472  case op::NegClosureMarked:
1473  return unop(o, trans((*this)[0]));
1474  case op::Xor:
1475  case op::Implies:
1476  case op::Equiv:
1477  case op::U:
1478  case op::R:
1479  case op::W:
1480  case op::M:
1481  case op::EConcat:
1482  case op::EConcatMarked:
1483  case op::UConcat:
1484  {
1485  formula tmp = trans((*this)[0]);
1486  return binop(o, tmp, trans((*this)[1]));
1487  }
1488  case op::Or:
1489  case op::OrRat:
1490  case op::And:
1491  case op::AndRat:
1492  case op::AndNLM:
1493  case op::Concat:
1494  case op::Fusion:
1495  {
1496  std::vector<formula> tmp;
1497  tmp.reserve(size());
1498  for (auto f: *this)
1499  tmp.push_back(trans(f));
1500  return multop(o, std::move(tmp));
1501  }
1502  case op::Star:
1503  case op::FStar:
1504  return bunop(o, trans((*this)[0]), min(), max());
1505  }
1506  SPOT_UNREACHABLE();
1507  }
1508 
1514  template<typename Func>
1515  void traverse(Func func)
1516  {
1517  if (func(*this))
1518  return;
1519  for (auto f: *this)
1520  f.traverse(func);
1521  }
1522  };
1523 
1525  SPOT_API
1526  std::ostream& print_formula_props(std::ostream& out, const formula& f,
1527  bool abbreviated = false);
1528 
1530  SPOT_API
1531  std::list<std::string> list_formula_props(const formula& f);
1532 
1534  SPOT_API
1535  std::ostream& operator<<(std::ostream& os, const formula& f);
1536 }
1537 
1538 #ifndef SWIG
1539 namespace std
1540 {
1541  template <>
1542  struct hash<spot::formula>
1543  {
1544  size_t operator()(const spot::formula& x) const noexcept
1545  {
1546  return x.id();
1547  }
1548  };
1549 }
1550 #endif
static formula multop(op o, const std::vector< formula > &l)
Construct an n-ary operator.
Definition: formula.hh:883
Definition: graph.hh:31
static formula one_star()
Return a copy of the formula 1[*].
Definition: formula.hh:1275
bool is_constant() const
Whether the formula is op::ff, op::tt, or op::eword.
Definition: formula.hh:1260
std::ostream & dump(std::ostream &os) const
Print the formula for debugging.
Definition: formula.hh:1303
formula get_child_of(op o) const
Remove operator o and return the child.
Definition: formula.hh:1100
formula all_but(unsigned i) const
clone this formula, omitting child i
Definition: formula.hh:1313
PSL Closure.
unsigned max() const
Return end of the range for star-like operators.
Definition: formula.hh:1135
const std::string & ap_name() const
Print the name of an atomic proposition.
Definition: formula.hh:1294
bool is_tt() const
Whether the formula is the true constant.
Definition: formula.hh:1242
static formula ap(const std::string &name)
Build an atomic proposition.
Definition: formula.hh:701
unsigned size() const
Return the number of children.
Definition: formula.hh:1141
static formula tt()
Return the true constant.
Definition: formula.hh:1236
unsigned boolean_count() const
number of Boolean children
Definition: formula.hh:1327
Definition: formula.hh:1539
Empty word.
Concatenation.
unsigned min() const
Return start of the range for star-like operators.
Definition: formula.hh:1127
Main class for temporal logic formula.
Definition: formula.hh:574
Globally.
release (dual of until)
bool is_literal()
Whether the formula is an atomic proposition or its negation.
Definition: formula.hh:1282
formula boolean_operands(unsigned *width=nullptr) const
return a clone of the current node, restricted to its Boolean children
Definition: formula.hh:1345
bool is_ff() const
Whether the formula is the false constant.
Definition: formula.hh:1230
Fustion Star.
weak until
static formula ff()
Return the false constant.
Definition: formula.hh:1224
formula operator[](unsigned i) const
Return children number i.
Definition: formula.hh:1217
Equivalence.
Non-Length-Matching Rational-And.
Allow iterating over children.
Definition: formula.hh:1161
Exclusive Or.
marked version of the Negated PSL Clusure
static formula eword()
Return the empty word constant.
Definition: formula.hh:1248
op kind() const
Return top-most operator.
Definition: formula.hh:1066
bool is(op o) const
Return true if the formula is of kind o.
Definition: formula.hh:1078
Definition: formula.hh:502
formula map(Trans trans)
Clone this node after applying trans to its children.
Definition: formula.hh:1457
bool is_Kleene_star() const
Test whether the formula represent a Kleene star.
Definition: formula.hh:1269
(omega-Rational) Or
static constexpr uint8_t unbounded()
Unbounded constant to use as end of range for bounded operators.
Definition: formula.hh:695
Negation.
const fnode * to_node_()
Return the underlying pointer to the formula.
Definition: formula.hh:1057
formula_child_iterator begin() const
Allow iterating over children.
Definition: formula.hh:1205
op
Operator types.
Definition: formula.hh:61
static formula unop(op o, const formula &f)
Build a unary operator.
Definition: formula.hh:710
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:964
Implication.
formula_child_iterator end() const
Allow iterating over children.
Definition: formula.hh:1211
Actual storage for formula nodes.
Definition: formula.hh:106
size_t id() const
Return the id of a formula.
Definition: formula.hh:1154
Negated PSL Closure.
Rational And.
static formula binop(op o, const formula &f, const formula &g)
Construct a binary operator.
Definition: formula.hh:780
bool is(std::initializer_list< op > l) const
Return true if the formulas nests all the operators in l.
Definition: formula.hh:1091
strong release (dual of weak until)
void traverse(Func func)
Apply func to each subformula.
Definition: formula.hh:1515
Atomic proposition.
Eventually.
std::string kindstr() const
Return the name of the top-most operator.
Definition: formula.hh:1072
(omega-Rational) And
bool is_eword() const
Whether the formula is the empty word constant.
Definition: formula.hh:1254
Rational Or.

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