spot  2.15.1
formula.hh
Go to the documentation of this file.
1 // -*- coding: utf-8 -*-
2 // Copyright (C) by the Spot authors, see the AUTHORS file for details.
3 //
4 // This file is part of Spot, a model checking library.
5 //
6 // Spot is free software; you can redistribute it and/or modify it
7 // under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // Spot is distributed in the hope that it will be useful, but WITHOUT
12 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 // License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 
21 #pragma once
22 
29 
32 
35 
38 
41 
44 
45 #include <spot/misc/common.hh>
46 #include <memory>
47 #include <cstdint>
48 #include <initializer_list>
49 #include <cassert>
50 #include <vector>
51 #include <string>
52 #include <iterator>
53 #include <iosfwd>
54 #include <sstream>
55 #include <list>
56 #include <cstddef>
57 #include <limits>
58 
59 // strong_X was conditionally defined starting with version 2.9.
60 // You had to "#define SPOT_USES_STRONG_X 1" before including this
61 // file to get the definition. Since Spot 2.13, it is always defined,
62 // so users may have to update their code. The following macro
63 // is only defined when strong_X exists.
64 # define SPOT_HAS_STRONG_X 1
65 // This was defined since 2.9 along with SPOT_HAS_STRONG_X when
66 // SPOT_USES_STRONG_X was defined so we are keeping it just in case
67 // someone depends on it.
68 # define SPOT_WANT_STRONG_X 1
69 // This was defined in Spot 2.15 when exists/forall where introduced.
70 # define SPOT_HAS_QUANTIFIERS 1
71 
72 namespace spot
73 {
74 
75 
78  enum class op: uint8_t
79  {
80  ff,
81  tt,
82  eword,
83  ap,
84  // unary operators
85  Not,
86  X,
87  F,
88  G,
89  Closure,
90  NegClosure,
92  // binary operators
93  Xor,
94  Implies,
95  Equiv,
96  U,
97  R,
98  W,
99  M,
100  EConcat,
101  EConcatMarked,
102  UConcat,
103  // n-ary operators
104  Or,
105  OrRat,
106  And,
107  AndRat,
108  AndNLM,
109  Concat,
110  Fusion,
111  // star-like operators
112  Star,
113  FStar,
114  first_match,
115  // strong_X was introduced in Spot 2.9, but was hidden from the
116  // public API by default in order not to break existing code.
117  //
118  // Starting with Spot 2.13, strong_X will be part of the public
119  // API by default. If you have a switch case listing all possible
120  // operators, strong_X needs to be part of it. If you have code
121  // using Spot but that you also want to support versions older
122  // than 2.13, there are two ways to do that
123  //
124  // Option 1: define SPOT_USES_STRONG_X before including this file.
125  //
126  // #define SPOT_USES_STRONG_X 1
127  // #include <spot/tl/formula.hh>
128  //
129  // This will force any version of Spot since 2.9 to define
130  // strong_X. It won't work with older Spot versions, where
131  // strong_X did not exist.
132  //
133  // Option 2: make any code using strong_X conditional on
134  // SPOT_HAS_STRONG_X. Typically, a switch over all possible
135  // operators would include something like this:
136  //
137  // #if SPOT_HAS_STRONG_X
138  // case op::strong_X:
139  // /* do something */
140  // #endif
141  //
142  // The two options are not mutually exclusive. Using both allows
143  // you to use strong_X whenever it exists.
144  strong_X,
145  // The following two operators are new in Spot 2.15
146  // If you need to support an earlier version of Spot, you can
147  // use the SPOT_HAS_QUANTIFIERS variable.
148  //
149  // #if SPOT_HAS_QUANTIFIERS
150  // case op::exists:
151  // /* do something */
152  // case op::forall:
153  // /* do something */
154  // #endif
155  exists,
156  forall,
157  };
158 
159 #ifndef SWIG
166  class SPOT_API fnode final
167  {
168  public:
173  const fnode* clone() const
174  {
175  // Saturate.
176  ++refs_;
177  if (SPOT_UNLIKELY(!refs_))
178  saturated_ = 1;
179  return this;
180  }
181 
187  void destroy() const
188  {
189  if (SPOT_LIKELY(refs_))
190  --refs_;
191  else if (SPOT_LIKELY(!saturated_))
192  // last reference to a node that is not a constant
193  destroy_aux();
194  }
195 
197  static constexpr uint8_t unbounded()
198  {
199  return UINT8_MAX;
200  }
201 
203  static const fnode* ap(const std::string& name);
205  static const fnode* unop(op o, const fnode* f);
207  static const fnode* binop(op o, const fnode* f, const fnode* g);
209  static const fnode* multop(op o, const fnode* f, const fnode* g);
211  static const fnode* multop(op o, std::vector<const fnode*> l);
213  template<op o>
214  static const fnode* multop_build_and_or(const fnode* left,
215  const fnode* right);
217  static const fnode* bunop(op o, const fnode* f,
218  unsigned min, unsigned max = unbounded());
219 
221  static const fnode* nested_unop_range(op uo, op bo, unsigned min,
222  unsigned max, const fnode* f);
223 
225  static const fnode* quantify(op quantifier,
226  const fnode* ap,
227  const fnode* f);
229  static const fnode* quantify(op quantifier,
230  std::vector<const fnode*> aps,
231  const fnode* f);
232 
234  op kind() const
235  {
236  return op_;
237  }
238 
240  std::string kindstr() const;
241 
244  bool is(op o) const
245  {
246  return op_ == o;
247  }
248 
249  bool is(op o1, op o2) const
250  {
251  return op_ == o1 || op_ == o2;
252  }
253 
254  bool is(op o1, op o2, op o3) const
255  {
256  return op_ == o1 || op_ == o2 || op_ == o3;
257  }
258 
259  bool is(op o1, op o2, op o3, op o4) const
260  {
261  return op_ == o1 || op_ == o2 || op_ == o3 || op_ == o4;
262  }
263 
264  bool is(std::initializer_list<op> l) const
265  {
266  const fnode* n = this;
267  for (auto o: l)
268  {
269  if (!n->is(o))
270  return false;
271  n = n->nth(0);
272  }
273  return true;
274  }
276 
278  const fnode* get_child_of(op o) const
279  {
280  if (op_ != o)
281  return nullptr;
282  if (SPOT_UNLIKELY(size_ != 1))
283  report_get_child_of_expecting_single_child_node();
284  return nth(0);
285  }
286 
288  const fnode* get_child_of(std::initializer_list<op> l) const
289  {
290  auto c = this;
291  for (auto o: l)
292  {
293  c = c->get_child_of(o);
294  if (c == nullptr)
295  return c;
296  }
297  return c;
298  }
299 
301  unsigned min() const
302  {
303  if (SPOT_UNLIKELY(op_ != op::FStar && op_ != op::Star))
304  report_min_invalid_arg();
305  return range_.min;
306  }
307 
309  unsigned max() const
310  {
311  if (SPOT_UNLIKELY(op_ != op::FStar && op_ != op::Star))
312  report_max_invalid_arg();
313  return range_.max;
314  }
315 
317  unsigned size() const
318  {
319  return size_;
320  }
321 
323  bool is_leaf() const
324  {
325  return size_ == 0;
326  }
327 
329  size_t id() const
330  {
331  return id_;
332  }
333 
335  const fnode*const* begin() const
336  {
337  return children;
338  }
339 
341  const fnode*const* end() const
342  {
343  return children + size();
344  }
345 
347  const fnode* nth(unsigned i) const
348  {
349  if (SPOT_UNLIKELY(i >= size()))
350  report_non_existing_child();
351  const fnode* c = children[i];
352  SPOT_ASSUME(c != nullptr);
353  return c;
354  }
355 
357  static const fnode* ff()
358  {
359  return ff_;
360  }
361 
363  bool is_ff() const
364  {
365  return op_ == op::ff;
366  }
367 
369  static const fnode* tt()
370  {
371  return tt_;
372  }
373 
375  bool is_tt() const
376  {
377  return op_ == op::tt;
378  }
379 
381  static const fnode* eword()
382  {
383  return ew_;
384  }
385 
387  bool is_eword() const
388  {
389  return op_ == op::eword;
390  }
391 
393  bool is_constant() const
394  {
395  return op_ == op::ff || op_ == op::tt || op_ == op::eword;
396  }
397 
399  bool is_Kleene_star() const
400  {
401  if (op_ != op::Star)
402  return false;
403  return range_.min == 0 && range_.max == unbounded();
404  }
405 
407  static const fnode* one_star()
408  {
409  if (!one_star_)
410  one_star_ = new fnode(op::Star, tt_, 0, unbounded(), true);
411  return one_star_;
412  }
413 
415  static const fnode* one_plus()
416  {
417  if (!one_plus_)
418  one_plus_ = new fnode(op::Star, tt_, 1, unbounded(), true);
419  return one_plus_;
420  }
421 
423  const std::string& ap_name() const;
424 
426  unsigned apid() const
427  {
428  if (SPOT_UNLIKELY(op_ != op::ap))
429  report_apid_on_nonap();
430  return ap_id_;
431  }
432 
434  std::ostream& dump(std::ostream& os) const;
435 
437  const fnode* all_but(unsigned i) const;
438 
440  unsigned boolean_count() const
441  {
442  unsigned pos = 0;
443  unsigned s = size();
444  while (pos < s && children[pos]->is_boolean())
445  ++pos;
446  return pos;
447  }
448 
450  const fnode* boolean_operands(unsigned* width = nullptr) const;
451 
462  static bool instances_check();
463 
465  // Properties //
467 
469  bool is_boolean() const
470  {
471  return is_.boolean;
472  }
473 
476  {
477  return is_.sugar_free_boolean;
478  }
479 
481  bool is_in_nenoform() const
482  {
483  return is_.in_nenoform;
484  }
485 
488  {
489  return is_.syntactic_si;
490  }
491 
493  bool is_sugar_free_ltl() const
494  {
495  return is_.sugar_free_ltl;
496  }
497 
499  bool is_ltl_formula() const
500  {
501  return is_.ltl_formula;
502  }
503 
505  bool is_psl_formula() const
506  {
507  return is_.psl_formula;
508  }
509 
511  bool is_sere_formula() const
512  {
513  return is_.sere_formula;
514  }
515 
517  bool is_finite() const
518  {
519  return is_.finite;
520  }
521 
523  bool is_eventual() const
524  {
525  return is_.eventual;
526  }
527 
529  bool is_universal() const
530  {
531  return is_.universal;
532  }
533 
535  bool is_syntactic_safety() const
536  {
537  return is_.syntactic_safety;
538  }
539 
542  {
543  return is_.syntactic_guarantee;
544  }
545 
548  {
549  return is_.syntactic_obligation;
550  }
551 
554  {
555  return is_.syntactic_recurrence;
556  }
557 
560  {
561  return is_.syntactic_persistence;
562  }
563 
565  bool is_marked() const
566  {
567  return !is_.not_marked;
568  }
569 
571  bool accepts_eword() const
572  {
573  return is_.accepting_eword;
574  }
575 
577  bool has_lbt_atomic_props() const
578  {
579  return is_.lbt_atomic_props;
580  }
581 
584  {
585  return is_.spin_atomic_props;
586  }
587 
589  bool is_sigma2() const
590  {
591  return is_.sigma2;
592  }
593 
595  bool is_pi2() const
596  {
597  return is_.pi2;
598  }
599 
601  bool is_delta1() const
602  {
603  return is_.delta1;
604  }
605 
607  bool is_delta2() const
608  {
609  return is_.delta2;
610  }
611 
613  bool is_quantified() const
614  {
615  return is_.quantified;
616  }
617 
618  private:
619  static size_t bump_next_id();
620  void setup_props(op o);
621  void destroy_aux() const;
622 
623  [[noreturn]] static void report_non_existing_child();
624  [[noreturn]] static void report_too_many_children();
625  [[noreturn]] static void
626  report_get_child_of_expecting_single_child_node();
627  [[noreturn]] static void report_min_invalid_arg();
628  [[noreturn]] static void report_max_invalid_arg();
629  [[noreturn]] static void report_apid_on_nonap();
630 
631  static const fnode* unique(fnode*);
632  static const fnode* multop_sorted(op o, std::vector<const fnode*>&& l);
633 
634  // Destruction may only happen via destroy().
635  ~fnode() = default;
636  // Disallow copies.
637  fnode(const fnode&) = delete;
638  fnode& operator=(const fnode&) = delete;
639 
640 
641 
642  template<class iter>
643  fnode(op o, iter begin, iter end, bool saturated = false)
644  // Clang has some optimization where is it able to combine the
645  // 4 movb initializing op_,ap_id_,saturated_ into a single
646  // movl. Also it can optimize the three byte-comparisons of
647  // is_Kleene_star() into a single masked 32-bit comparison.
648  // The latter optimization triggers warnings from valgrind if
649  // min&max (aka ap_id_) are not initialized. So to benefit
650  // from the initialization optimization and the
651  // is_Kleene_star() optimization in Clang, we always
652  // initialize ap_id_ with this compiler. Do not do it the
653  // rest of the time, since the optimization is not done.
654  : op_(o),
655 #if __llvm__
656  saturated_(saturated), ap_id_(0)
657 #else
658  saturated_(saturated)
659 #endif
660  {
661  size_t s = std::distance(begin, end);
662  if (SPOT_UNLIKELY(s > (size_t) UINT16_MAX))
663  report_too_many_children();
664  size_ = s;
665  auto pos = children;
666  for (auto i = begin; i != end; ++i)
667  *pos++ = *i;
668  setup_props(o);
669  }
670 
671  fnode(op o, std::initializer_list<const fnode*> l,
672  bool saturated = false)
673  : fnode(o, l.begin(), l.end(), saturated)
674  {
675  }
676 
677  fnode(op o, const fnode* f, uint8_t min, uint8_t max,
678  bool saturated = false)
679  : op_(o), saturated_(saturated), size_(1)
680  {
681  range_.min = min;
682  range_.max = max;
683  children[0] = f;
684  setup_props(o);
685  }
686 
687  fnode(op o, uint16_t apid, bool saturated = false)
688  : op_(o), saturated_(saturated), size_(0)
689  {
690  ap_id_ = apid;
691  setup_props(o);
692  }
693 
694  static const fnode* ff_;
695  static const fnode* tt_;
696  static const fnode* ew_;
697  static const fnode* one_star_;
698  static const fnode* one_plus_;
699 
700  op op_; // operator
701  mutable uint8_t saturated_;
702  struct range_t
703  {
704  uint8_t min; // range minimum (for star-like operators)
705  uint8_t max; // range maximum;
706  };
707  union
708  {
709  range_t range_;
710  uint16_t ap_id_; // id for atomic proposition
711  };
712  uint16_t size_; // number of children
713  mutable uint16_t refs_ = 0; // reference count - 1;
714  size_t id_; // also used as hash.
715  static size_t next_id_;
716 
717  struct ltl_prop
718  {
719  // All properties here should be expressed in such a way
720  // that property(f && g) is just property(f)&property(g).
721  // This allows us to compute all properties of a compound
722  // formula in one operation.
723  //
724  // For instance we do not use a property that says "has
725  // temporal operator", because it would require an OR between
726  // the two arguments. Instead we have a property that
727  // says "no temporal operator", and that one is computed
728  // with an AND between the arguments.
729  //
730  // Also choose a name that makes sense when prefixed with
731  // "the formula is".
732  bool boolean:1; // No temporal operators.
733  bool sugar_free_boolean:1; // Only AND, OR, and NOT operators.
734  bool in_nenoform:1; // Negative Normal Form.
735  bool syntactic_si:1; // LTL-X or siPSL
736  bool sugar_free_ltl:1; // No F and G operators.
737  bool ltl_formula:1; // Only LTL operators.
738  bool psl_formula:1; // Only PSL operators.
739  bool sere_formula:1; // Only SERE operators.
740  bool finite:1; // Finite SERE formulas, or Bool+X forms.
741  bool eventual:1; // Purely eventual formula.
742  bool universal:1; // Purely universal formula.
743  bool syntactic_safety:1; // Syntactic Safety Property (S).
744  bool syntactic_guarantee:1; // Syntactic Guarantee Property (G).
745  bool syntactic_obligation:1; // Syntactic Obligation Property (O).
746  bool syntactic_recurrence:1; // Syntactic Recurrence Property (R).
747  bool syntactic_persistence:1; // Syntactic Persistence Property (P).
748  bool not_marked:1; // No occurrence of EConcatMarked.
749  bool accepting_eword:1; // Accepts the empty word.
750  bool lbt_atomic_props:1; // Use only atomic propositions like p42.
751  bool spin_atomic_props:1; // Use only spin-compatible atomic props.
752  bool delta1:1; // Boolean combination of (S) and (G).
753  bool sigma2:1; // Boolean comb. of (S) with X/F/U/M possibly applied.
754  bool pi2:1; // Boolean comb. of (G) with X/G/R/W possibly applied.
755  bool delta2:1; // Boolean combination of (Σ₂) and (Π₂).
756  bool quantified:1; // Use forall/exists
757  };
758  union
759  {
760  // Use an unsigned for fast computation of all properties.
761  unsigned props;
762  ltl_prop is_;
763  };
764 
765  const fnode* children[1];
766  };
767 
769  SPOT_API
770  int atomic_prop_cmp(const fnode* f, const fnode* g);
771 
772  class SPOT_API formula;
773 
775  {
776  bool
777  operator()(const fnode* left, const fnode* right) const
778  {
779  SPOT_ASSERT(left);
780  SPOT_ASSERT(right);
781  if (left == right)
782  return false;
783 
784  // We want Boolean formulas first.
785  bool lib = left->is_boolean();
786  if (lib != right->is_boolean())
787  return lib;
788 
789  // We have two Boolean formulas
790  if (lib)
791  {
792  bool lconst = left->is_constant();
793  if (lconst != right->is_constant())
794  return lconst;
795  if (!lconst)
796  {
797  auto get_literal = [](const fnode* f) -> const fnode*
798  {
799  if (f->is(op::Not))
800  f = f->nth(0);
801  if (f->is(op::ap))
802  return f;
803  return nullptr;
804  };
805  // Literals should come first
806  const fnode* litl = get_literal(left);
807  const fnode* litr = get_literal(right);
808  if (!litl != !litr)
809  return litl;
810  if (litl)
811  {
812  // And they should be sorted alphabetically
813  int cmp = atomic_prop_cmp(litl, litr);
814  if (cmp)
815  return cmp < 0;
816  }
817  }
818  }
819 
820  size_t l = left->id();
821  size_t r = right->id();
822  if (l != r)
823  return l < r;
824  // Because the id() assigned to each formula is the
825  // number of formulas constructed so far, it is very unlikely
826  // that we will ever reach a case were two different formulas
827  // have the same hash. This will happen only ever with have
828  // produced 256**sizeof(size_t) formulas (i.e. max_count has
829  // looped back to 0 and started over). In that case we can
830  // order two formulas by looking at their text representation.
831  // We could be more efficient and look at their AST, but it's
832  // not worth the burden. (Also ordering pointers is ruled out
833  // because it breaks the determinism of the implementation.)
834  std::ostringstream old;
835  left->dump(old);
836  std::ostringstream ord;
837  right->dump(ord);
838  return old.str() < ord.str();
839  }
840 
841  SPOT_API bool
842  operator()(const formula& left, const formula& right) const;
843 };
844 
845 #endif // SWIG
846 
849  class SPOT_API formula final
850  {
851  friend struct formula_ptr_less_than_bool_first;
852  const fnode* ptr_;
853  public:
858  explicit formula(const fnode* f) noexcept
859  : ptr_(f)
860  {
861  }
862 
868  formula(std::nullptr_t) noexcept
869  : ptr_(nullptr)
870  {
871  }
872 
874  formula() noexcept
875  : ptr_(nullptr)
876  {
877  }
878 
880  formula(const formula& f) noexcept
881  : ptr_(f.ptr_)
882  {
883  if (ptr_)
884  ptr_->clone();
885  }
886 
888  formula(formula&& f) noexcept
889  : ptr_(f.ptr_)
890  {
891  f.ptr_ = nullptr;
892  }
893 
896  {
897  if (ptr_)
898  ptr_->destroy();
899  }
900 
908  const formula& operator=(std::nullptr_t)
909  {
910  this->~formula();
911  ptr_ = nullptr;
912  return *this;
913  }
914 
915  const formula& operator=(const formula& f)
916  {
917  this->~formula();
918  if ((ptr_ = f.ptr_))
919  ptr_->clone();
920  return *this;
921  }
922 
923  const formula& operator=(formula&& f) noexcept
924  {
925  std::swap(f.ptr_, ptr_);
926  return *this;
927  }
928 
929  bool operator<(const formula& other) const noexcept
930  {
931  if (SPOT_UNLIKELY(!other.ptr_))
932  return false;
933  if (SPOT_UNLIKELY(!ptr_))
934  return true;
935  if (id() < other.id())
936  return true;
937  if (id() > other.id())
938  return false;
939  // The case where id()==other.id() but ptr_ != other.ptr_ is
940  // very unlikely (we would need to build more than UINT_MAX
941  // formulas), so let's just compare pointers, and ignore the
942  // fact that it may introduce some nondeterminism.
943  return ptr_ < other.ptr_;
944  }
945 
946  bool operator<=(const formula& other) const noexcept
947  {
948  return *this == other || *this < other;
949  }
950 
951  bool operator>(const formula& other) const noexcept
952  {
953  return !(*this <= other);
954  }
955 
956  bool operator>=(const formula& other) const noexcept
957  {
958  return !(*this < other);
959  }
960 
961  bool operator==(const formula& other) const noexcept
962  {
963  return other.ptr_ == ptr_;
964  }
965 
966  bool operator==(std::nullptr_t) const noexcept
967  {
968  return ptr_ == nullptr;
969  }
970 
971  bool operator!=(const formula& other) const noexcept
972  {
973  return other.ptr_ != ptr_;
974  }
975 
976  bool operator!=(std::nullptr_t) const noexcept
977  {
978  return ptr_ != nullptr;
979  }
980 
981  explicit operator bool() const noexcept
982  {
983  return ptr_ != nullptr;
984  }
985 
1001  static unsigned apid_count() noexcept;
1006  static bool is_valid_apid(unsigned id) noexcept;
1009  static const std::string& apname_from_apid(unsigned id);
1012  static formula ap_from_apid(unsigned id);
1020  static std::vector<formula> apid_map();
1021 
1023  void throw_if_quantified(const char* message)
1024  {
1025  if (SPOT_UNLIKELY(is_quantified()))
1026  report_message(message);
1027  }
1028 
1030  // Forwarded functions //
1032 
1034  static constexpr uint8_t unbounded()
1035  {
1036  return fnode::unbounded();
1037  }
1038 
1040  static formula ap(const std::string& name)
1041  {
1042  return formula(fnode::ap(name));
1043  }
1044 
1050  static formula ap(const formula& a)
1051  {
1052  if (SPOT_UNLIKELY(a.kind() != op::ap))
1053  report_ap_invalid_arg();
1054  return a;
1055  }
1056 
1061  static formula unop(op o, const formula& f)
1062  {
1063  return formula(fnode::unop(o, f.ptr_->clone()));
1064  }
1065 
1066 #ifndef SWIG
1067  static formula unop(op o, formula&& f)
1068  {
1069  return formula(fnode::unop(o, f.to_node_()));
1070  }
1071 #endif // !SWIG
1073 
1074 #ifdef SWIG
1075 #define SPOT_DEF_UNOP(Name) \
1076  static formula Name(const formula& f) \
1077  { \
1078  return unop(op::Name, f); \
1079  }
1080 #else // !SWIG
1081 #define SPOT_DEF_UNOP(Name) \
1082  static formula Name(const formula& f) \
1083  { \
1084  return unop(op::Name, f); \
1085  } \
1086  static formula Name(formula&& f) \
1087  { \
1088  return unop(op::Name, std::move(f)); \
1089  }
1090 #endif // !SWIG
1093  SPOT_DEF_UNOP(Not);
1095 
1098  SPOT_DEF_UNOP(X);
1100 
1104  static formula X(unsigned level, const formula& f)
1105  {
1106  return nested_unop_range(op::X, op::Or /* unused */, level, level, f);
1107  }
1108 
1111  SPOT_DEF_UNOP(strong_X);
1113 
1117  static formula strong_X(unsigned level, const formula& f)
1118  {
1119  return nested_unop_range(op::strong_X, op::Or /* unused */,
1120  level, level, f);
1121  }
1122 
1125  SPOT_DEF_UNOP(F);
1127 
1134  static formula F(unsigned min_level, unsigned max_level, const formula& f)
1135  {
1136  return nested_unop_range(op::X, op::Or, min_level, max_level, f);
1137  }
1138 
1145  static formula G(unsigned min_level, unsigned max_level, const formula& f)
1146  {
1147  return nested_unop_range(op::X, op::And, min_level, max_level, f);
1148  }
1149 
1152  SPOT_DEF_UNOP(G);
1154 
1157  SPOT_DEF_UNOP(Closure);
1159 
1162  SPOT_DEF_UNOP(NegClosure);
1164 
1167  SPOT_DEF_UNOP(NegClosureMarked);
1169 
1172  SPOT_DEF_UNOP(first_match);
1174 #undef SPOT_DEF_UNOP
1175 
1181  static formula binop(op o, const formula& f, const formula& g)
1182  {
1183  return formula(fnode::binop(o, f.ptr_->clone(), g.ptr_->clone()));
1184  }
1185 
1186 #ifndef SWIG
1187  static formula binop(op o, const formula& f, formula&& g)
1188  {
1189  return formula(fnode::binop(o, f.ptr_->clone(), g.to_node_()));
1190  }
1191 
1192  static formula binop(op o, formula&& f, const formula& g)
1193  {
1194  return formula(fnode::binop(o, f.to_node_(), g.ptr_->clone()));
1195  }
1196 
1197  static formula binop(op o, formula&& f, formula&& g)
1198  {
1199  return formula(fnode::binop(o, f.to_node_(), g.to_node_()));
1200  }
1201 #endif //SWIG
1203 
1204 
1205 #ifdef SWIG
1206 #define SPOT_DEF_BINOP(Name) \
1207  static formula Name(const formula& f, const formula& g) \
1208  { \
1209  return binop(op::Name, f, g); \
1210  }
1211 #else // !SWIG
1212 #define SPOT_DEF_BINOP(Name) \
1213  static formula Name(const formula& f, const formula& g) \
1214  { \
1215  return binop(op::Name, f, g); \
1216  } \
1217  static formula Name(const formula& f, formula&& g) \
1218  { \
1219  return binop(op::Name, f, std::move(g)); \
1220  } \
1221  static formula Name(formula&& f, const formula& g) \
1222  { \
1223  return binop(op::Name, std::move(f), g); \
1224  } \
1225  static formula Name(formula&& f, formula&& g) \
1226  { \
1227  return binop(op::Name, std::move(f), std::move(g)); \
1228  }
1229 #endif // !SWIG
1232  SPOT_DEF_BINOP(Xor);
1234 
1237  SPOT_DEF_BINOP(Implies);
1239 
1242  SPOT_DEF_BINOP(Equiv);
1244 
1247  SPOT_DEF_BINOP(U);
1249 
1252  SPOT_DEF_BINOP(R);
1254 
1257  SPOT_DEF_BINOP(W);
1259 
1262  SPOT_DEF_BINOP(M);
1264 
1267  SPOT_DEF_BINOP(EConcat);
1269 
1272  SPOT_DEF_BINOP(EConcatMarked);
1274 
1277  SPOT_DEF_BINOP(UConcat);
1279 #undef SPOT_DEF_BINOP
1280 
1304  static formula multop(op o, const std::vector<formula>& l)
1305  {
1306  std::vector<const fnode*> tmp;
1307  tmp.reserve(l.size());
1308  for (auto f: l)
1309  if (f.ptr_)
1310  tmp.emplace_back(f.ptr_->clone());
1311  return formula(fnode::multop(o, std::move(tmp)));
1312  }
1313 
1314 #ifndef SWIG
1315  static formula multop(op o, std::vector<formula>&& l)
1316  {
1317  std::vector<const fnode*> tmp;
1318  tmp.reserve(l.size());
1319  for (auto f: l)
1320  if (f.ptr_)
1321  tmp.emplace_back(f.to_node_());
1322  return formula(fnode::multop(o, std::move(tmp)));
1323  }
1324 #endif // !SWIG
1325 
1326  static formula multop(op o, const formula& f, const formula& g)
1327  {
1328  return formula(fnode::multop(o, f.ptr_->clone(), g.ptr_->clone()));
1329  }
1330 
1331 #ifndef SWIG
1332  static formula multop(op o, const formula& f, formula&& g)
1333  {
1334  return formula(fnode::multop(o, f.ptr_->clone(), g.to_node_()));
1335  }
1336 
1337  static formula multop(op o, formula&& f, const formula& g)
1338  {
1339  return formula(fnode::multop(o, f.to_node_(), g.ptr_->clone()));
1340  }
1341 
1342  static formula multop(op o, formula&& f, formula&& g)
1343  {
1344  return formula(fnode::multop(o, f.to_node_(), g.to_node_()));
1345  }
1346 #endif // !SWIG
1348 
1349 #ifdef SWIG
1350 #define SPOT_DEF_MULTOP(Name) \
1351  static formula Name(const std::vector<formula>& l) \
1352  { \
1353  return multop(op::Name, l); \
1354  } \
1355  \
1356  static formula Name(const formula& left, const formula& right) \
1357  { \
1358  return multop(op::Name, left, right); \
1359  }
1360 #else // !SWIG
1361 #define SPOT_DEF_MULTOP(Name) \
1362  static formula Name(const std::vector<formula>& l) \
1363  { \
1364  return multop(op::Name, l); \
1365  } \
1366  \
1367  static formula Name(std::vector<formula>&& l) \
1368  { \
1369  return multop(op::Name, std::move(l)); \
1370  } \
1371  \
1372  static formula Name(const formula& left, const formula& right) \
1373  { \
1374  return multop(op::Name, left, right); \
1375  }
1376 #endif // !SWIG
1377 #ifdef SWIG
1378 #define SPOT_DEF_MULTOP2(Name) \
1379  static formula Name(const std::vector<formula>& l) \
1380  { \
1381  return multop(op::Name, l); \
1382  } \
1383  \
1384  static formula Name(const formula& left, const formula& right) \
1385  { \
1386  return formula(fnode::multop_build_and_or<op::Name> \
1387  (left->ptr_->clone(), right->ptr_->clone()); \
1388  }
1389 #else // !SWIG
1390 #define SPOT_DEF_MULTOP2(Name) \
1391  static formula Name(const std::vector<formula>& l) \
1392  { \
1393  return multop(op::Name, l); \
1394  } \
1395  \
1396  static formula Name(std::vector<formula>&& l) \
1397  { \
1398  return multop(op::Name, std::move(l)); \
1399  } \
1400  \
1401  static formula Name(const formula& left, const formula& right) \
1402  { \
1403  return formula(fnode::multop_build_and_or<op::Name> \
1404  (left.ptr_->clone(), right.ptr_->clone())); \
1405  } \
1406  static formula Name(const formula& left, formula&& right) \
1407  { \
1408  return formula(fnode::multop_build_and_or<op::Name> \
1409  (left.ptr_->clone(), right.to_node_())); \
1410  } \
1411  static formula Name(formula&& left, const formula& right) \
1412  { \
1413  return formula(fnode::multop_build_and_or<op::Name> \
1414  (left.to_node_(), right.ptr_->clone())); \
1415  } \
1416  static formula Name(formula&& left, formula&& right) \
1417  { \
1418  return formula(fnode::multop_build_and_or<op::Name> \
1419  (left.to_node_(), right.to_node_())); \
1420  }
1421 #endif // !SWIG
1424  SPOT_DEF_MULTOP2(Or);
1426 
1429  SPOT_DEF_MULTOP(OrRat);
1431 
1434  SPOT_DEF_MULTOP2(And);
1436 
1439  SPOT_DEF_MULTOP(AndRat);
1441 
1444  SPOT_DEF_MULTOP(AndNLM);
1446 
1449  SPOT_DEF_MULTOP(Concat);
1451 
1454  SPOT_DEF_MULTOP(Fusion);
1456 #undef SPOT_DEF_MULTOP
1457 
1462  static formula bunop(op o, const formula& f,
1463  unsigned min = 0U,
1464  unsigned max = unbounded())
1465  {
1466  return formula(fnode::bunop(o, f.ptr_->clone(), min, max));
1467  }
1468 
1469 #ifndef SWIG
1470  static formula bunop(op o, formula&& f,
1471  unsigned min = 0U,
1472  unsigned max = unbounded())
1473  {
1474  return formula(fnode::bunop(o, f.to_node_(), min, max));
1475  }
1476 #endif // !SWIG
1478 
1479 #if SWIG
1480 #define SPOT_DEF_BUNOP(Name) \
1481  static formula Name(const formula& f, \
1482  unsigned min = 0U, \
1483  unsigned max = unbounded()) \
1484  { \
1485  return bunop(op::Name, f, min, max); \
1486  }
1487 #else // !SWIG
1488 #define SPOT_DEF_BUNOP(Name) \
1489  static formula Name(const formula& f, \
1490  unsigned min = 0U, \
1491  unsigned max = unbounded()) \
1492  { \
1493  return bunop(op::Name, f, min, max); \
1494  } \
1495  static formula Name(formula&& f, \
1496  unsigned min = 0U, \
1497  unsigned max = unbounded()) \
1498  { \
1499  return bunop(op::Name, std::move(f), min, max); \
1500  }
1501 #endif
1504  SPOT_DEF_BUNOP(Star);
1506 
1512  SPOT_DEF_BUNOP(FStar);
1514 #undef SPOT_DEF_BUNOP
1515 
1516  static formula quantify(op quantifier,
1517  formula&& ap,
1518  formula&& f)
1519  {
1520  return formula(fnode::quantify(quantifier,
1521  ap.to_node_(),
1522  f.to_node_()));
1523  }
1524 
1525  static formula quantify(op quantifier,
1526  const formula& ap,
1527  const formula& f)
1528  {
1529  return formula(fnode::quantify(quantifier,
1530  ap.ptr_->clone(),
1531  f.ptr_->clone()));
1532  }
1533 
1534  static formula quantify(op quantifier,
1535  const std::vector<formula>& aps,
1536  const formula& f)
1537  {
1538  std::vector<const fnode*> tmp;
1539  tmp.reserve(aps.size() + 1);
1540  for (auto a: aps)
1541  if (a.ptr_)
1542  tmp.emplace_back(a.to_node_());
1543  return formula(fnode::quantify(quantifier, std::move(tmp),
1544  f.ptr_->clone()));
1545  }
1546 
1547 #ifndef SWIG
1548  static formula quantify(op quantifier,
1549  std::vector<formula>&& aps,
1550  const formula& f)
1551  {
1552  std::vector<const fnode*> tmp;
1553  tmp.reserve(aps.size() + 1);
1554  for (auto a: aps)
1555  if (a.ptr_)
1556  tmp.emplace_back(a.to_node_());
1557  return formula(fnode::quantify(quantifier, std::move(tmp),
1558  f.ptr_->clone()));
1559  }
1560 #endif // !SWIG
1561 
1562 #define SPOT_DEF_QUANTIFY(Name) \
1563  static formula Name(const std::vector<formula>& aps, const formula& f) \
1564  { \
1565  return quantify(op::Name, aps, f); \
1566  } \
1567  \
1568  static formula Name(const formula& ap, const formula& f) \
1569  { \
1570  return quantify(op::Name, ap, f); \
1571  }
1572 
1575  SPOT_DEF_QUANTIFY(exists);
1577 
1580  SPOT_DEF_QUANTIFY(forall);
1582 #undef SPOT_DEF_QUANTIFY
1583 
1595  static const formula nested_unop_range(op uo, op bo, unsigned min,
1596  unsigned max, formula f)
1597  {
1598  return formula(fnode::nested_unop_range(uo, bo, min, max,
1599  f.ptr_->clone()));
1600  }
1601 
1607  static formula sugar_goto(const formula& b, unsigned min, unsigned max);
1608 
1614  static formula sugar_equal(const formula& b, unsigned min, unsigned max);
1615 
1637  static formula sugar_delay(const formula& a, const formula& b,
1638  unsigned min, unsigned max);
1639  static formula sugar_delay(const formula& b,
1640  unsigned min, unsigned max);
1642 
1643 #ifndef SWIG
1653  const fnode* to_node_()
1654  {
1655  auto tmp = ptr_;
1656  ptr_ = nullptr;
1657  return tmp;
1658  }
1659 #endif
1660 
1662  op kind() const
1663  {
1664  return ptr_->kind();
1665  }
1666 
1668  std::string kindstr() const
1669  {
1670  return ptr_->kindstr();
1671  }
1672 
1674  bool is(op o) const
1675  {
1676  return ptr_->is(o);
1677  }
1678 
1679 #ifndef SWIG
1681  bool is(op o1, op o2) const
1682  {
1683  return ptr_->is(o1, o2);
1684  }
1685 
1687  bool is(op o1, op o2, op o3) const
1688  {
1689  return ptr_->is(o1, o2, o3);
1690  }
1691 
1694  bool is(op o1, op o2, op o3, op o4) const
1695  {
1696  return ptr_->is(o1, o2, o3, o4);
1697  }
1698 
1700  bool is(std::initializer_list<op> l) const
1701  {
1702  return ptr_->is(l);
1703  }
1704 #endif
1705 
1710  {
1711  auto f = ptr_->get_child_of(o);
1712  if (f)
1713  f->clone();
1714  return formula(f);
1715  }
1716 
1717 #ifndef SWIG
1724  formula get_child_of(std::initializer_list<op> l) const
1725  {
1726  auto f = ptr_->get_child_of(l);
1727  if (f)
1728  f->clone();
1729  return formula(f);
1730  }
1731 #endif
1732 
1736  unsigned min() const
1737  {
1738  return ptr_->min();
1739  }
1740 
1744  unsigned max() const
1745  {
1746  return ptr_->max();
1747  }
1748 
1750  unsigned size() const
1751  {
1752  return ptr_->size();
1753  }
1754 
1759  bool is_leaf() const
1760  {
1761  return ptr_->is_leaf();
1762  }
1763 
1772  size_t id() const
1773  {
1774  return ptr_->id();
1775  }
1776 
1777 #ifndef SWIG
1779  class SPOT_API formula_child_iterator final
1780  {
1781  const fnode*const* ptr_;
1782  public:
1784  : ptr_(nullptr)
1785  {
1786  }
1787 
1788  formula_child_iterator(const fnode*const* f)
1789  : ptr_(f)
1790  {
1791  }
1792 
1793  bool operator==(formula_child_iterator o)
1794  {
1795  return ptr_ == o.ptr_;
1796  }
1797 
1798  bool operator!=(formula_child_iterator o)
1799  {
1800  return ptr_ != o.ptr_;
1801  }
1802 
1803  formula operator*()
1804  {
1805  return formula((*ptr_)->clone());
1806  }
1807 
1808  formula_child_iterator operator++()
1809  {
1810  ++ptr_;
1811  return *this;
1812  }
1813 
1814  formula_child_iterator operator++(int)
1815  {
1816  auto tmp = *this;
1817  ++ptr_;
1818  return tmp;
1819  }
1820  };
1821 
1824  {
1825  return ptr_->begin();
1826  }
1827 
1830  {
1831  return ptr_->end();
1832  }
1833 
1835  formula operator[](unsigned i) const
1836  {
1837  return formula(ptr_->nth(i)->clone());
1838  }
1839 #endif
1840 
1842  static formula ff()
1843  {
1844  return formula(fnode::ff());
1845  }
1846 
1848  bool is_ff() const
1849  {
1850  return ptr_->is_ff();
1851  }
1852 
1854  static formula tt()
1855  {
1856  return formula(fnode::tt());
1857  }
1858 
1860  bool is_tt() const
1861  {
1862  return ptr_->is_tt();
1863  }
1864 
1866  static formula eword()
1867  {
1868  return formula(fnode::eword());
1869  }
1870 
1872  bool is_eword() const
1873  {
1874  return ptr_->is_eword();
1875  }
1876 
1878  bool is_constant() const
1879  {
1880  return ptr_->is_constant();
1881  }
1882 
1887  bool is_Kleene_star() const
1888  {
1889  return ptr_->is_Kleene_star();
1890  }
1891 
1894  {
1895  // no need to clone, 1[*] is not reference counted
1896  return formula(fnode::one_star());
1897  }
1898 
1901  {
1902  // no need to clone, 1[+] is not reference counted
1903  return formula(fnode::one_plus());
1904  }
1905 
1908  bool is_literal() const
1909  {
1910  return (is(op::ap) ||
1911  // If f is in nenoform, Not can only occur in front of
1912  // an atomic proposition. So this way we do not have
1913  // to check the type of the child.
1914  (is(op::Not) && is_boolean() && is_in_nenoform()));
1915  }
1916 
1920  const std::string& ap_name() const
1921  {
1922  return ptr_->ap_name();
1923  }
1924 
1933  unsigned apid() const
1934  {
1935  return ptr_->apid();
1936  }
1937 
1942  std::ostream& dump(std::ostream& os) const
1943  {
1944  return ptr_->dump(os);
1945  }
1946 
1952  formula all_but(unsigned i) const
1953  {
1954  return formula(ptr_->all_but(i));
1955  }
1956 
1966  unsigned boolean_count() const
1967  {
1968  return ptr_->boolean_count();
1969  }
1970 
1984  formula boolean_operands(unsigned* width = nullptr) const
1985  {
1986  return formula(ptr_->boolean_operands(width));
1987  }
1988 
1989 #define SPOT_DEF_PROP(Name) \
1990  bool Name() const \
1991  { \
1992  return ptr_->Name(); \
1993  }
1995  // Properties //
1997 
1999  SPOT_DEF_PROP(is_boolean);
2001  SPOT_DEF_PROP(is_sugar_free_boolean);
2006  SPOT_DEF_PROP(is_in_nenoform);
2008  SPOT_DEF_PROP(is_syntactic_stutter_invariant);
2010  SPOT_DEF_PROP(is_sugar_free_ltl);
2012  SPOT_DEF_PROP(is_ltl_formula);
2014  SPOT_DEF_PROP(is_psl_formula);
2016  SPOT_DEF_PROP(is_sere_formula);
2019  SPOT_DEF_PROP(is_finite);
2027  SPOT_DEF_PROP(is_eventual);
2035  SPOT_DEF_PROP(is_universal);
2039  SPOT_DEF_PROP(is_syntactic_safety);
2043  SPOT_DEF_PROP(is_syntactic_guarantee);
2048  SPOT_DEF_PROP(is_delta1);
2053  SPOT_DEF_PROP(is_syntactic_obligation);
2055  SPOT_DEF_PROP(is_sigma2);
2057  SPOT_DEF_PROP(is_pi2);
2062  SPOT_DEF_PROP(is_syntactic_recurrence);
2067  SPOT_DEF_PROP(is_syntactic_persistence);
2072  SPOT_DEF_PROP(is_delta2);
2075  SPOT_DEF_PROP(is_marked);
2077  SPOT_DEF_PROP(accepts_eword);
2083  SPOT_DEF_PROP(has_lbt_atomic_props);
2092  SPOT_DEF_PROP(has_spin_atomic_props);
2094  SPOT_DEF_PROP(is_quantified);
2095 #undef SPOT_DEF_PROP
2096 
2100  template<typename Trans, typename... Args>
2101  formula map(Trans trans, Args&&... args)
2102  {
2103  switch (op o = kind())
2104  {
2105  case op::ff:
2106  case op::tt:
2107  case op::eword:
2108  case op::ap:
2109  return *this;
2110  case op::Not:
2111  case op::X:
2112 #if SPOT_HAS_STRONG_X
2113  case op::strong_X:
2114 #endif
2115  case op::F:
2116  case op::G:
2117  case op::Closure:
2118  case op::NegClosure:
2119  case op::NegClosureMarked:
2120  case op::first_match:
2121  {
2122  formula arg = (*this)[0];
2123  formula new_arg = trans(arg, std::forward<Args>(args)...);
2124  if (arg == new_arg)
2125  return *this;
2126  else
2127  return unop(o, new_arg);
2128  }
2129  case op::Xor:
2130  case op::Implies:
2131  case op::Equiv:
2132  case op::U:
2133  case op::R:
2134  case op::W:
2135  case op::M:
2136  case op::EConcat:
2137  case op::EConcatMarked:
2138  case op::UConcat:
2139  {
2140  formula left = (*this)[0];
2141  formula right = (*this)[1];
2142  formula new_left = trans(left, std::forward<Args>(args)...);
2143  formula new_right = trans(right, std::forward<Args>(args)...);
2144  if (left == new_left && right == new_right)
2145  return *this;
2146  else
2147  return binop(o, new_left, new_right);
2148  }
2149  case op::Or:
2150  case op::OrRat:
2151  case op::And:
2152  case op::AndRat:
2153  case op::AndNLM:
2154  case op::Concat:
2155  case op::Fusion:
2156  {
2157  std::vector<formula> tmp;
2158  bool changed = false;
2159  tmp.reserve(size());
2160  for (auto f: *this)
2161  {
2162  formula g = trans(f, std::forward<Args>(args)...);
2163  tmp.emplace_back(g);
2164  changed |= g != f;
2165  }
2166  if (!changed)
2167  return *this;
2168  else
2169  return multop(o, std::move(tmp));
2170  }
2171  case op::Star:
2172  case op::FStar:
2173  {
2174  formula arg = (*this)[0];
2175  formula new_arg = trans(arg, std::forward<Args>(args)...);
2176  if (arg == new_arg)
2177  return *this;
2178  else
2179  return bunop(o, new_arg, min(), max());
2180  }
2181  case op::exists:
2182  case op::forall:
2183  {
2184  std::vector<formula> tmp;
2185  unsigned sz = size();
2186  tmp.reserve(sz - 1);
2187  bool changed = false;
2188  for (unsigned i = 0; i < sz - 1; ++i)
2189  {
2190  formula c = (*this)[i];
2191  formula g = trans(c, std::forward<Args>(args)...);
2192  changed |= c != g;
2193  tmp.push_back(g);
2194  }
2195  formula c = (*this)[sz - 1];
2196  formula g = trans(c, std::forward<Args>(args)...);
2197  if (c == g && !changed)
2198  return *this;
2199  return quantify(o, std::move(tmp), g);
2200  }
2201  }
2202  SPOT_UNREACHABLE();
2203  }
2204 
2213  template<typename Func, typename... Args>
2214  void traverse(Func func, Args&&... args)
2215  {
2216  if (func(*this, std::forward<Args>(args)...))
2217  return;
2218  for (auto f: *this)
2219  f.traverse(func, std::forward<Args>(args)...);
2220  }
2221 
2222 #ifndef SWIG
2223  [[noreturn]] static void report_message(const char* message);
2224  private:
2225  [[noreturn]] static void report_ap_invalid_arg();
2226 #endif
2227  };
2228 
2230  SPOT_API
2231  std::ostream& print_formula_props(std::ostream& out, const formula& f,
2232  bool abbreviated = false);
2233 
2235  SPOT_API
2236  std::list<std::string> list_formula_props(const formula& f);
2237 
2239  SPOT_API
2240  std::ostream& operator<<(std::ostream& os, const formula& f);
2241 }
2242 
2243 #ifndef SWIG
2244 namespace std
2245 {
2246  template <>
2247  struct hash<spot::formula>
2248  {
2249  size_t operator()(const spot::formula& x) const noexcept
2250  {
2251  return x.id();
2252  }
2253  };
2254 }
2255 #endif
Actual storage for formula nodes.
Definition: formula.hh:167
bool is_pi2() const
Definition: formula.hh:595
const fnode *const * begin() const
Definition: formula.hh:335
const fnode *const * end() const
Definition: formula.hh:341
std::string kindstr() const
std::ostream & dump(std::ostream &os) const
bool is_boolean() const
Definition: formula.hh:469
size_t id() const
Definition: formula.hh:329
bool is_ff() const
Definition: formula.hh:363
bool is_sugar_free_boolean() const
Definition: formula.hh:475
bool is_Kleene_star() const
Definition: formula.hh:399
unsigned min() const
Definition: formula.hh:301
bool is_syntactic_safety() const
Definition: formula.hh:535
bool is_syntactic_stutter_invariant() const
Definition: formula.hh:487
bool is_delta2() const
Definition: formula.hh:607
unsigned size() const
Definition: formula.hh:317
static constexpr uint8_t unbounded()
Definition: formula.hh:197
static const fnode * eword()
Definition: formula.hh:381
const fnode * get_child_of(op o) const
Definition: formula.hh:278
static const fnode * multop_build_and_or(const fnode *left, const fnode *right)
fast path for binary and/or
unsigned max() const
Definition: formula.hh:309
static const fnode * ff()
Definition: formula.hh:357
const fnode * boolean_operands(unsigned *width=nullptr) const
bool accepts_eword() const
Definition: formula.hh:571
bool is_eventual() const
Definition: formula.hh:523
const std::string & ap_name() const
bool is(op o1, op o2, op o3, op o4) const
Definition: formula.hh:259
static bool instances_check()
safety check for the reference counters
bool is_leaf() const
Definition: formula.hh:323
bool has_spin_atomic_props() const
Definition: formula.hh:583
bool is_eword() const
Definition: formula.hh:387
static const fnode * tt()
Definition: formula.hh:369
bool is(op o1, op o2, op o3) const
Definition: formula.hh:254
op kind() const
Definition: formula.hh:234
bool has_lbt_atomic_props() const
Definition: formula.hh:577
unsigned apid() const
Definition: formula.hh:426
bool is_sugar_free_ltl() const
Definition: formula.hh:493
bool is_syntactic_persistence() const
Definition: formula.hh:559
static const fnode * nested_unop_range(op uo, op bo, unsigned min, unsigned max, const fnode *f)
unsigned boolean_count() const
Definition: formula.hh:440
bool is_universal() const
Definition: formula.hh:529
bool is_tt() const
Definition: formula.hh:375
const fnode * get_child_of(std::initializer_list< op > l) const
Definition: formula.hh:288
static const fnode * one_plus()
Definition: formula.hh:415
const fnode * nth(unsigned i) const
Definition: formula.hh:347
bool is_constant() const
Definition: formula.hh:393
static const fnode * binop(op o, const fnode *f, const fnode *g)
static const fnode * multop(op o, const fnode *f, const fnode *g)
static const fnode * quantify(op quantifier, const fnode *ap, const fnode *f)
static const fnode * one_star()
Definition: formula.hh:407
const fnode * all_but(unsigned i) const
bool is_syntactic_recurrence() const
Definition: formula.hh:553
bool is(std::initializer_list< op > l) const
Definition: formula.hh:264
bool is_syntactic_obligation() const
Definition: formula.hh:547
bool is_quantified() const
Definition: formula.hh:613
static const fnode * unop(op o, const fnode *f)
static const fnode * quantify(op quantifier, std::vector< const fnode * > aps, const fnode *f)
bool is_ltl_formula() const
Definition: formula.hh:499
bool is_finite() const
Definition: formula.hh:517
bool is_sigma2() const
Definition: formula.hh:589
bool is_psl_formula() const
Definition: formula.hh:505
bool is_delta1() const
Definition: formula.hh:601
static const fnode * multop(op o, std::vector< const fnode * > l)
bool is_marked() const
Definition: formula.hh:565
void destroy() const
Dereference an fnode.
Definition: formula.hh:187
static const fnode * bunop(op o, const fnode *f, unsigned min, unsigned max=unbounded())
bool is(op o1, op o2) const
Definition: formula.hh:249
bool is_in_nenoform() const
Definition: formula.hh:481
static const fnode * ap(const std::string &name)
bool is_syntactic_guarantee() const
Definition: formula.hh:541
bool is_sere_formula() const
Definition: formula.hh:511
const fnode * clone() const
Clone an fnode.
Definition: formula.hh:173
bool is(op o) const
Definition: formula.hh:244
Allow iterating over children.
Definition: formula.hh:1780
Main class for temporal logic formula.
Definition: formula.hh:850
unsigned boolean_count() const
number of Boolean children
Definition: formula.hh:1966
bool is_leaf() const
Whether the formula is a leaf.
Definition: formula.hh:1759
size_t id() const
Return the id of a formula.
Definition: formula.hh:1772
static formula bunop(op o, formula &&f, unsigned min=0U, unsigned max=unbounded())
Define a bounded unary-operator (i.e. star-like)
Definition: formula.hh:1470
formula map(Trans trans, Args &&... args)
Clone this node after applying trans to its children.
Definition: formula.hh:2101
unsigned apid() const
Get the number of an atomic proposition.
Definition: formula.hh:1933
static formula bunop(op o, const formula &f, unsigned min=0U, unsigned max=unbounded())
Define a bounded unary-operator (i.e. star-like)
Definition: formula.hh:1462
static formula multop(op o, const formula &f, const formula &g)
Construct an n-ary operator.
Definition: formula.hh:1326
static formula G(unsigned min_level, unsigned max_level, const formula &f)
Construct G[n:m].
Definition: formula.hh:1145
static formula binop(op o, const formula &f, const formula &g)
Construct a binary operator.
Definition: formula.hh:1181
bool is(op o) const
Return true if the formula is of kind o.
Definition: formula.hh:1674
static formula multop(op o, std::vector< formula > &&l)
Construct an n-ary operator.
Definition: formula.hh:1315
formula(formula &&f) noexcept
Move-construct a formula.
Definition: formula.hh:888
formula(const fnode *f) noexcept
Create a formula from an fnode.
Definition: formula.hh:858
bool is(op o1, op o2) const
Return true if the formula is of kind o1 or o2.
Definition: formula.hh:1681
static formula one_plus()
Return a copy of the formula 1[+].
Definition: formula.hh:1900
static formula sugar_delay(const formula &b, unsigned min, unsigned max)
Create the SERE a ##[n:m] b
static formula one_star()
Return a copy of the formula 1[*].
Definition: formula.hh:1893
static unsigned apid_count() noexcept
1+maximum APID used by atomic propositions
unsigned min() const
Return start of the range for star-like operators.
Definition: formula.hh:1736
static constexpr uint8_t unbounded()
Unbounded constant to use as end of range for bounded operators.
Definition: formula.hh:1034
static formula unop(op o, formula &&f)
Build a unary operator.
Definition: formula.hh:1067
static formula eword()
Return the empty word constant.
Definition: formula.hh:1866
static formula multop(op o, formula &&f, const formula &g)
Construct an n-ary operator.
Definition: formula.hh:1337
formula all_but(unsigned i) const
clone this formula, omitting child i
Definition: formula.hh:1952
static formula ff()
Return the false constant.
Definition: formula.hh:1842
static formula binop(op o, const formula &f, formula &&g)
Construct a binary operator.
Definition: formula.hh:1187
op kind() const
Return top-most operator.
Definition: formula.hh:1662
static formula multop(op o, const std::vector< formula > &l)
Construct an n-ary operator.
Definition: formula.hh:1304
unsigned size() const
Return the number of children.
Definition: formula.hh:1750
static formula sugar_goto(const formula &b, unsigned min, unsigned max)
Create a SERE equivalent to b[->min..max]
bool is_tt() const
Whether the formula is the true constant.
Definition: formula.hh:1860
bool is(op o1, op o2, op o3, op o4) const
Definition: formula.hh:1694
std::string kindstr() const
Return the name of the top-most operator.
Definition: formula.hh:1668
formula(const formula &f) noexcept
Clone a formula.
Definition: formula.hh:880
formula_child_iterator end() const
Allow iterating over children.
Definition: formula.hh:1829
static formula binop(op o, formula &&f, formula &&g)
Construct a binary operator.
Definition: formula.hh:1197
static formula multop(op o, const formula &f, formula &&g)
Construct an n-ary operator.
Definition: formula.hh:1332
static formula ap(const formula &a)
Build an atomic proposition from... an atomic proposition.
Definition: formula.hh:1050
formula get_child_of(std::initializer_list< op > l) const
Remove all operators in l and return the child.
Definition: formula.hh:1724
bool is_eword() const
Whether the formula is the empty word constant.
Definition: formula.hh:1872
static formula sugar_delay(const formula &a, const formula &b, unsigned min, unsigned max)
Create the SERE a ##[n:m] b
void traverse(Func func, Args &&... args)
Apply func to each subformula.
Definition: formula.hh:2214
static formula F(unsigned min_level, unsigned max_level, const formula &f)
Construct F[n:m].
Definition: formula.hh:1134
formula(std::nullptr_t) noexcept
Create a null formula.
Definition: formula.hh:868
static formula ap(const std::string &name)
Build an atomic proposition.
Definition: formula.hh:1040
const std::string & ap_name() const
Get the name of an atomic proposition.
Definition: formula.hh:1920
bool is(op o1, op o2, op o3) const
Return true if the formula is of kind o1 or o2 or o3.
Definition: formula.hh:1687
const formula & operator=(std::nullptr_t)
Reset a formula to null.
Definition: formula.hh:908
unsigned max() const
Return end of the range for star-like operators.
Definition: formula.hh:1744
static formula X(unsigned level, const formula &f)
Construct an X[n].
Definition: formula.hh:1104
bool is_ff() const
Whether the formula is the false constant.
Definition: formula.hh:1848
static formula multop(op o, formula &&f, formula &&g)
Construct an n-ary operator.
Definition: formula.hh:1342
formula_child_iterator begin() const
Allow iterating over children.
Definition: formula.hh:1823
bool is_constant() const
Whether the formula is op::ff, op::tt, or op::eword.
Definition: formula.hh:1878
~formula()
Destroy a formula.
Definition: formula.hh:895
std::ostream & dump(std::ostream &os) const
Print the formula for debugging.
Definition: formula.hh:1942
formula get_child_of(op o) const
Remove operator o and return the child.
Definition: formula.hh:1709
const fnode * to_node_()
Return the underlying pointer to the formula.
Definition: formula.hh:1653
bool is(std::initializer_list< op > l) const
Return true if the formulas nests all the operators in l.
Definition: formula.hh:1700
formula operator[](unsigned i) const
Return children number i.
Definition: formula.hh:1835
static formula strong_X(unsigned level, const formula &f)
Construct a strong_X[n].
Definition: formula.hh:1117
bool is_Kleene_star() const
Test whether the formula represent a Kleene star.
Definition: formula.hh:1887
static formula binop(op o, formula &&f, const formula &g)
Construct a binary operator.
Definition: formula.hh:1192
bool is_literal() const
Whether the formula is an atomic proposition or its negation.
Definition: formula.hh:1908
static formula tt()
Return the true constant.
Definition: formula.hh:1854
formula() noexcept
Default initialize a formula to nullptr.
Definition: formula.hh:874
static formula sugar_equal(const formula &b, unsigned min, unsigned max)
Create the SERE b[=min..max]
static formula unop(op o, const formula &f)
Build a unary operator.
Definition: formula.hh:1061
formula boolean_operands(unsigned *width=nullptr) const
return a clone of the current node, restricted to its Boolean children
Definition: formula.hh:1984
static const formula nested_unop_range(op uo, op bo, unsigned min, unsigned max, formula f)
Nested operator construction (syntactic sugar).
Definition: formula.hh:1595
op
Operator types.
Definition: formula.hh:79
@ X
Next.
@ first_match
first_match(sere)
@ EConcatMarked
Seq, Marked.
@ Star
Star.
@ UConcat
Triggers.
@ Or
(omega-Rational) Or
@ Equiv
Equivalence.
@ NegClosure
Negated PSL Closure.
@ U
until
@ EConcat
Seq.
@ FStar
Fustion Star.
@ W
weak until
@ ap
Atomic proposition.
@ ff
False.
@ M
strong release (dual of weak until)
@ NegClosureMarked
marked version of the Negated PSL Closure
@ strong_X
strong Next
@ Xor
Exclusive Or.
@ F
Eventually.
@ OrRat
Rational Or.
@ Not
Negation.
@ tt
True.
@ Fusion
Fusion.
@ Closure
PSL Closure.
@ forall
universal quantification of AP
@ And
(omega-Rational) And
@ AndNLM
Non-Length-Matching Rational-And.
@ eword
Empty word.
@ AndRat
Rational And.
@ G
Globally.
@ exists
existential quantification of AP
@ R
release (dual of until)
@ Concat
Concatenation.
@ Implies
Implication.
bool is_universal(const const_twa_graph_ptr &aut)
Return true iff aut is universal.
Definition: automata.hh:26
int atomic_prop_cmp(const fnode *f, const fnode *g)
Order two atomic propositions.
std::list< std::string > list_formula_props(const formula &f)
List the properties of formula f.
std::ostream & print_formula_props(std::ostream &out, const formula &f, bool abbreviated=false)
Print the properties of formula f on stream out.
Definition: formula.hh:775

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on Fri Feb 27 2015 10:00:07 for spot by doxygen 1.9.1