spot  2.16
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 
47 
48 #include <spot/misc/common.hh>
49 #include <memory>
50 #include <cstdint>
51 #include <initializer_list>
52 #include <cassert>
53 #include <vector>
54 #include <string>
55 #include <iterator>
56 #include <iosfwd>
57 #include <sstream>
58 #include <list>
59 #include <cstddef>
60 #include <limits>
61 
62 // strong_X was conditionally defined starting with version 2.9.
63 // You had to "#define SPOT_USES_STRONG_X 1" before including this
64 // file to get the definition. Since Spot 2.13, it is always defined,
65 // so users may have to update their code. The following macro
66 // is only defined when strong_X exists.
67 #ifndef SWIG
68 # define SPOT_HAS_STRONG_X 1
69 // This was defined since 2.9 along with SPOT_HAS_STRONG_X when
70 // SPOT_USES_STRONG_X was defined so we are keeping it just in case
71 // someone depends on it.
72 # define SPOT_WANT_STRONG_X 1
73 // This was defined in Spot 2.15 when exists/forall where introduced.
75 # define SPOT_HAS_QUANTIFIERS 1
76 #endif // !defined SWIG
77 
78 namespace spot
79 {
80 
81 
84  enum class op: uint8_t
85  {
86  ff,
87  tt,
88  eword,
89  ap,
90  // unary operators
91  Not,
92  X,
93  F,
94  G,
95  Closure,
96  NegClosure,
98  // binary operators
99  Xor,
100  Implies,
101  Equiv,
102  U,
103  R,
104  W,
105  M,
106  EConcat,
107  EConcatMarked,
108  UConcat,
109  // n-ary operators
110  Or,
111  OrRat,
112  And,
113  AndRat,
114  AndNLM,
115  Concat,
116  Fusion,
117  // star-like operators
118  Star,
119  FStar,
120  first_match,
121  // strong_X was introduced in Spot 2.9, but was hidden from the
122  // public API by default in order not to break existing code.
123  //
124  // Starting with Spot 2.13, strong_X will be part of the public
125  // API by default. If you have a switch case listing all possible
126  // operators, strong_X needs to be part of it. If you have code
127  // using Spot but that you also want to support versions older
128  // than 2.13, there are two ways to do that
129  //
130  // Option 1: define SPOT_USES_STRONG_X before including this file.
131  //
132  // #define SPOT_USES_STRONG_X 1
133  // #include <spot/tl/formula.hh>
134  //
135  // This will force any version of Spot since 2.9 to define
136  // strong_X. It won't work with older Spot versions, where
137  // strong_X did not exist.
138  //
139  // Option 2: make any code using strong_X conditional on
140  // SPOT_HAS_STRONG_X. Typically, a switch over all possible
141  // operators would include something like this:
142  //
143  // #if SPOT_HAS_STRONG_X
144  // case op::strong_X:
145  // /* do something */
146  // #endif
147  //
148  // The two options are not mutually exclusive. Using both allows
149  // you to use strong_X whenever it exists.
150  strong_X,
151  // The following two operators are new in Spot 2.15
152  // If you need to support an earlier version of Spot, you can
153  // use the SPOT_HAS_QUANTIFIERS variable.
154  //
155  // #if SPOT_HAS_QUANTIFIERS
156  // case op::exists:
157  // /* do something */
158  // case op::forall:
159  // /* do something */
160  // #endif
161  exists,
162  forall,
163  };
164 
165 #ifndef SWIG
172  class SPOT_API fnode final
173  {
174  public:
179  const fnode* clone() const
180  {
181  // Saturate.
182  ++refs_;
183  if (SPOT_UNLIKELY(!refs_))
184  saturated_ = 1;
185  return this;
186  }
187 
193  void destroy() const
194  {
195  if (SPOT_LIKELY(refs_))
196  --refs_;
197  else if (SPOT_LIKELY(!saturated_))
198  // last reference to a node that is not a constant
199  destroy_aux();
200  }
201 
203  static constexpr uint16_t unbounded()
204  {
205  return UINT16_MAX;
206  }
207 
209  static const fnode* ap(const std::string& name);
211  static const fnode* unop(op o, const fnode* f);
213  static const fnode* binop(op o, const fnode* f, const fnode* g);
215  static const fnode* multop(op o, const fnode* f, const fnode* g);
217  static const fnode* multop(op o, std::vector<const fnode*> l);
219  template<op o>
220  static const fnode* multop_build_and_or(const fnode* left,
221  const fnode* right);
223  static const fnode* bunop(op o, const fnode* f,
224  unsigned min, unsigned max = unbounded());
225 
227  static const fnode* nested_unop_range(op uo, op bo, unsigned min,
228  unsigned max, const fnode* f);
229 
231  static const fnode* quantify(op quantifier,
232  const fnode* ap,
233  const fnode* f);
235  static const fnode* quantify(op quantifier,
236  std::vector<const fnode*> aps,
237  const fnode* f);
238 
240  op kind() const
241  {
242  return op_;
243  }
244 
246  std::string kindstr() const;
247 
250  bool is(op o) const
251  {
252  return op_ == o;
253  }
254 
255  bool is(op o1, op o2) const
256  {
257  return op_ == o1 || op_ == o2;
258  }
259 
260  bool is(op o1, op o2, op o3) const
261  {
262  return op_ == o1 || op_ == o2 || op_ == o3;
263  }
264 
265  bool is(op o1, op o2, op o3, op o4) const
266  {
267  return op_ == o1 || op_ == o2 || op_ == o3 || op_ == o4;
268  }
269 
270  bool is(std::initializer_list<op> l) const
271  {
272  const fnode* n = this;
273  for (auto o: l)
274  {
275  if (!n->is(o))
276  return false;
277  n = n->nth(0);
278  }
279  return true;
280  }
282 
284  const fnode* get_child_of(op o) const
285  {
286  if (op_ != o)
287  return nullptr;
288  if (SPOT_UNLIKELY(size_ != 1))
289  report_get_child_of_expecting_single_child_node();
290  return nth(0);
291  }
292 
294  const fnode* get_child_of(std::initializer_list<op> l) const
295  {
296  auto c = this;
297  for (auto o: l)
298  {
299  c = c->get_child_of(o);
300  if (c == nullptr)
301  return c;
302  }
303  return c;
304  }
305 
307  unsigned min() const
308  {
309  if (SPOT_UNLIKELY(op_ != op::FStar && op_ != op::Star))
310  report_min_invalid_arg();
311  return range_.min;
312  }
313 
315  unsigned max() const
316  {
317  if (SPOT_UNLIKELY(op_ != op::FStar && op_ != op::Star))
318  report_max_invalid_arg();
319  return range_.max;
320  }
321 
323  unsigned size() const
324  {
325  return size_;
326  }
327 
329  bool is_leaf() const
330  {
331  return size_ == 0;
332  }
333 
335  size_t id() const
336  {
337  return id_;
338  }
339 
341  const fnode*const* begin() const
342  {
343  return children;
344  }
345 
347  const fnode*const* end() const
348  {
349  return children + size();
350  }
351 
353  const fnode* nth(unsigned i) const
354  {
355  if (SPOT_UNLIKELY(i >= size()))
356  report_non_existing_child();
357  const fnode* c = children[i];
358  SPOT_ASSUME(c != nullptr);
359  return c;
360  }
361 
363  static const fnode* ff()
364  {
365  return ff_;
366  }
367 
369  bool is_ff() const
370  {
371  return op_ == op::ff;
372  }
373 
375  static const fnode* tt()
376  {
377  return tt_;
378  }
379 
381  bool is_tt() const
382  {
383  return op_ == op::tt;
384  }
385 
387  static const fnode* eword()
388  {
389  return ew_;
390  }
391 
393  bool is_eword() const
394  {
395  return op_ == op::eword;
396  }
397 
399  bool is_constant() const
400  {
401  return op_ == op::ff || op_ == op::tt || op_ == op::eword;
402  }
403 
405  bool is_Kleene_star() const
406  {
407  if (op_ != op::Star)
408  return false;
409  return range_.min == 0 && range_.max == unbounded();
410  }
411 
413  static const fnode* one_star()
414  {
415  if (!one_star_)
416  one_star_ = new fnode(op::Star, tt_, 0, unbounded(), true);
417  return one_star_;
418  }
419 
421  static const fnode* one_plus()
422  {
423  if (!one_plus_)
424  one_plus_ = new fnode(op::Star, tt_, 1, unbounded(), true);
425  return one_plus_;
426  }
427 
429  const std::string& ap_name() const;
430 
432  unsigned apid() const
433  {
434  if (SPOT_UNLIKELY(op_ != op::ap))
435  report_apid_on_nonap();
436  return ap_id_;
437  }
438 
440  std::ostream& dump(std::ostream& os) const;
441 
443  const fnode* all_but(unsigned i) const;
444 
446  unsigned boolean_count() const
447  {
448  unsigned pos = 0;
449  unsigned s = size();
450  while (pos < s && children[pos]->is_boolean())
451  ++pos;
452  return pos;
453  }
454 
456  const fnode* boolean_operands(unsigned* width = nullptr) const;
457 
468  static bool instances_check();
469 
471  // Properties //
473 
475  bool is_boolean() const
476  {
477  return is_.boolean;
478  }
479 
482  {
483  return is_.sugar_free_boolean;
484  }
485 
487  bool is_in_nenoform() const
488  {
489  return is_.in_nenoform;
490  }
491 
494  {
495  return is_.syntactic_si;
496  }
497 
499  bool is_sugar_free_ltl() const
500  {
501  return is_.sugar_free_ltl;
502  }
503 
505  bool is_ltl_formula() const
506  {
507  return is_.ltl_formula;
508  }
509 
511  bool is_psl_formula() const
512  {
513  return is_.psl_formula;
514  }
515 
517  bool is_sere_formula() const
518  {
519  return is_.sere_formula;
520  }
521 
523  bool is_finite() const
524  {
525  return is_.finite;
526  }
527 
529  bool is_eventual() const
530  {
531  return is_.eventual;
532  }
533 
535  bool is_universal() const
536  {
537  return is_.universal;
538  }
539 
541  bool is_syntactic_safety() const
542  {
543  return is_.syntactic_safety;
544  }
545 
548  {
549  return is_.syntactic_guarantee;
550  }
551 
554  {
555  return is_.syntactic_obligation;
556  }
557 
560  {
561  return is_.syntactic_recurrence;
562  }
563 
566  {
567  return is_.syntactic_persistence;
568  }
569 
571  bool is_marked() const
572  {
573  return !is_.not_marked;
574  }
575 
577  bool accepts_eword() const
578  {
579  return is_.accepting_eword;
580  }
581 
583  bool has_lbt_atomic_props() const
584  {
585  return is_.lbt_atomic_props;
586  }
587 
590  {
591  return is_.spin_atomic_props;
592  }
593 
595  bool is_sigma2() const
596  {
597  return is_.sigma2;
598  }
599 
601  bool is_pi2() const
602  {
603  return is_.pi2;
604  }
605 
607  bool is_delta1() const
608  {
609  return is_.delta1;
610  }
611 
613  bool is_delta2() const
614  {
615  return is_.delta2;
616  }
617 
619  bool is_quantified() const
620  {
621  return is_.quantified;
622  }
623 
624  private:
625  static size_t bump_next_id();
626  void setup_props(op o);
627  void destroy_aux() const;
628 
629 #ifndef SWIG
630  [[noreturn]] static void report_non_existing_child();
631  [[noreturn]] static void report_too_many_children();
632  [[noreturn]] static void
633  report_get_child_of_expecting_single_child_node();
634  [[noreturn]] static void report_min_invalid_arg();
635  [[noreturn]] static void report_max_invalid_arg();
636  [[noreturn]] static void report_apid_on_nonap();
637 #endif
638 
639  static const fnode* unique(fnode*);
640  static const fnode* multop_sorted(op o, std::vector<const fnode*>&& l);
641 
642  // Destruction may only happen via destroy().
643  ~fnode() = default;
644  // Disallow copies.
645  fnode(const fnode&) = delete;
646  fnode& operator=(const fnode&) = delete;
647 
648 
649 
650  template<class iter>
651  fnode(op o, iter begin, iter end, bool saturated = false)
652  : op_(o), saturated_(saturated)
653  {
654  size_t s = std::distance(begin, end);
655  if (SPOT_UNLIKELY(s > (size_t) UINT16_MAX))
656  report_too_many_children();
657  size_ = s;
658  auto pos = children;
659  for (auto i = begin; i != end; ++i)
660  *pos++ = *i;
661  setup_props(o);
662  }
663 
664  fnode(op o, std::initializer_list<const fnode*> l,
665  bool saturated = false)
666  : fnode(o, l.begin(), l.end(), saturated)
667  {
668  }
669 
670  fnode(op o, const fnode* f, unsigned min, unsigned max,
671  bool saturated = false)
672  : op_(o), saturated_(saturated), size_(1)
673  {
674  range_.min = min;
675  range_.max = max;
676  children[0] = f;
677  setup_props(o);
678  }
679 
680  fnode(op o, uint16_t apid, bool saturated = false)
681  : op_(o), saturated_(saturated), size_(0)
682  {
683  ap_id_ = apid;
684  setup_props(o);
685  }
686 
687  static const fnode* ff_;
688  static const fnode* tt_;
689  static const fnode* ew_;
690  static const fnode* one_star_;
691  static const fnode* one_plus_;
692 
693  op op_; // operator
694  mutable uint8_t saturated_;
695  mutable uint16_t refs_ = 0; // reference count - 1;
696  uint16_t size_; // number of children
697  size_t id_; // also used as hash.
698  struct range_t
699  {
700  uint16_t min; // range minimum (for star-like operators)
701  uint16_t max; // range maximum;
702  };
703  union
704  {
705  range_t range_;
706  uint16_t ap_id_; // id for atomic proposition
707  };
708  static size_t next_id_;
709 
710  struct ltl_prop
711  {
712  // All properties here should be expressed in such a way
713  // that property(f && g) is just property(f)&property(g).
714  // This allows us to compute all properties of a compound
715  // formula in one operation.
716  //
717  // For instance we do not use a property that says "has
718  // temporal operator", because it would require an OR between
719  // the two arguments. Instead we have a property that
720  // says "no temporal operator", and that one is computed
721  // with an AND between the arguments.
722  //
723  // Also choose a name that makes sense when prefixed with
724  // "the formula is".
725  bool boolean:1; // No temporal operators.
726  bool sugar_free_boolean:1; // Only AND, OR, and NOT operators.
727  bool in_nenoform:1; // Negative Normal Form.
728  bool syntactic_si:1; // LTL-X or siPSL
729  bool sugar_free_ltl:1; // No F and G operators.
730  bool ltl_formula:1; // Only LTL operators.
731  bool psl_formula:1; // Only PSL operators.
732  bool sere_formula:1; // Only SERE operators.
733  bool finite:1; // Finite SERE formulas, or Bool+X forms.
734  bool eventual:1; // Purely eventual formula.
735  bool universal:1; // Purely universal formula.
736  bool syntactic_safety:1; // Syntactic Safety Property (S).
737  bool syntactic_guarantee:1; // Syntactic Guarantee Property (G).
738  bool syntactic_obligation:1; // Syntactic Obligation Property (O).
739  bool syntactic_recurrence:1; // Syntactic Recurrence Property (R).
740  bool syntactic_persistence:1; // Syntactic Persistence Property (P).
741  bool not_marked:1; // No occurrence of EConcatMarked.
742  bool accepting_eword:1; // Accepts the empty word.
743  bool lbt_atomic_props:1; // Use only atomic propositions like p42.
744  bool spin_atomic_props:1; // Use only spin-compatible atomic props.
745  bool delta1:1; // Boolean combination of (S) and (G).
746  bool sigma2:1; // Boolean comb. of (S) with X/F/U/M possibly applied.
747  bool pi2:1; // Boolean comb. of (G) with X/G/R/W possibly applied.
748  bool delta2:1; // Boolean combination of (Σ₂) and (Π₂).
749  bool quantified:1; // Use forall/exists
750  };
751  union
752  {
753  // Use an unsigned for fast computation of all properties.
754  unsigned props;
755  ltl_prop is_;
756  };
757 
758  const fnode* children[1];
759  };
760 
762  SPOT_API
763  int atomic_prop_cmp(const fnode* f, const fnode* g);
764 
765  class SPOT_API formula;
766 
770  {
772  bool
773  operator()(const fnode* left, const fnode* right) const
774  {
775  SPOT_ASSERT(left);
776  SPOT_ASSERT(right);
777  if (left == right)
778  return false;
779 
780  // We want Boolean formulas first.
781  bool lib = left->is_boolean();
782  if (lib != right->is_boolean())
783  return lib;
784 
785  // We have two Boolean formulas
786  if (lib)
787  {
788  bool lconst = left->is_constant();
789  if (lconst != right->is_constant())
790  return lconst;
791  if (!lconst)
792  {
793  auto get_literal = [](const fnode* f) -> const fnode*
794  {
795  if (f->is(op::Not))
796  f = f->nth(0);
797  if (f->is(op::ap))
798  return f;
799  return nullptr;
800  };
801  // Literals should come first
802  const fnode* litl = get_literal(left);
803  const fnode* litr = get_literal(right);
804  if (!litl != !litr)
805  return litl;
806  if (litl)
807  {
808  // And they should be sorted alphabetically
809  int cmp = atomic_prop_cmp(litl, litr);
810  if (cmp)
811  return cmp < 0;
812  }
813  }
814  }
815 
816  size_t l = left->id();
817  size_t r = right->id();
818  if (l != r)
819  return l < r;
820  // Because the id() assigned to each formula is the
821  // number of formulas constructed so far, it is very unlikely
822  // that we will ever reach a case where two different formulas
823  // have the same hash. This will happen only ever with have
824  // produced 256**sizeof(size_t) formulas (i.e. max_count has
825  // looped back to 0 and started over). In that case we can
826  // order two formulas by looking at their text representation.
827  // We could be more efficient and look at their AST, but it's
828  // not worth the burden. (Also ordering pointers is ruled out
829  // because it breaks the determinism of the implementation.)
830  std::ostringstream old;
831  left->dump(old);
832  std::ostringstream ord;
833  right->dump(ord);
834  return old.str() < ord.str();
835  }
836 
838  SPOT_API bool
839  operator()(const formula& left, const formula& right) const;
840 };
841 
842 #endif // SWIG
843 
846  class SPOT_API formula final
847  {
848  friend struct formula_ptr_less_than_bool_first;
849  const fnode* ptr_;
850  public:
855  explicit formula(const fnode* f) noexcept
856  : ptr_(f)
857  {
858  }
859 
865  formula(std::nullptr_t) noexcept
866  : ptr_(nullptr)
867  {
868  }
869 
871  formula() noexcept
872  : ptr_(nullptr)
873  {
874  }
875 
877  formula(const formula& f) noexcept
878  : ptr_(f.ptr_)
879  {
880  if (ptr_)
881  ptr_->clone();
882  }
883 
885  formula(formula&& f) noexcept
886  : ptr_(f.ptr_)
887  {
888  f.ptr_ = nullptr;
889  }
890 
893  {
894  if (ptr_)
895  ptr_->destroy();
896  }
897 
905  const formula& operator=(std::nullptr_t)
906  {
907  this->~formula();
908  ptr_ = nullptr;
909  return *this;
910  }
911 
913  const formula& operator=(const formula& f)
914  {
915  this->~formula();
916  if ((ptr_ = f.ptr_))
917  ptr_->clone();
918  return *this;
919  }
920 
922  const formula& operator=(formula&& f) noexcept
923  {
924  std::swap(f.ptr_, ptr_);
925  return *this;
926  }
927 
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 
947  bool operator<=(const formula& other) const noexcept
948  {
949  return *this == other || *this < other;
950  }
951 
953  bool operator>(const formula& other) const noexcept
954  {
955  return !(*this <= other);
956  }
957 
959  bool operator>=(const formula& other) const noexcept
960  {
961  return !(*this < other);
962  }
963 
966  bool operator==(const formula& other) const noexcept
967  {
968  return other.ptr_ == ptr_;
969  }
970 
972  bool operator==(std::nullptr_t) const noexcept
973  {
974  return ptr_ == nullptr;
975  }
976 
978  bool operator!=(const formula& other) const noexcept
979  {
980  return other.ptr_ != ptr_;
981  }
982 
984  bool operator!=(std::nullptr_t) const noexcept
985  {
986  return ptr_ != nullptr;
987  }
988 
990  explicit operator bool() const noexcept
991  {
992  return ptr_ != nullptr;
993  }
994 
1010  static unsigned apid_count() noexcept;
1015  static bool is_valid_apid(unsigned id) noexcept;
1018  static const std::string& apname_from_apid(unsigned id);
1021  static formula ap_from_apid(unsigned id);
1029  static std::vector<formula> apid_map();
1030 
1032  void throw_if_quantified(const char* message)
1033  {
1034  if (SPOT_UNLIKELY(is_quantified()))
1035  report_message(message);
1036  }
1037 
1039  // Forwarded functions //
1041 
1043  static constexpr unsigned unbounded()
1044  {
1045  return fnode::unbounded();
1046  }
1047 
1049  static formula ap(const std::string& name)
1050  {
1051  return formula(fnode::ap(name));
1052  }
1053 
1059  static formula ap(const formula& a)
1060  {
1061  if (SPOT_UNLIKELY(a.kind() != op::ap))
1062  report_ap_invalid_arg();
1063  return a;
1064  }
1065 
1070  static formula unop(op o, const formula& f)
1071  {
1072  return formula(fnode::unop(o, f.ptr_->clone()));
1073  }
1074 
1075 #ifndef SWIG
1076  static formula unop(op o, formula&& f)
1077  {
1078  return formula(fnode::unop(o, f.to_node_()));
1079  }
1080 #endif // !SWIG
1082 
1084 #ifdef SWIG
1085 #define SPOT_DEF_UNOP(Name) \
1086  static formula Name(const formula& f) \
1087  { \
1088  return unop(op::Name, f); \
1089  }
1090 #else // !SWIG
1091 #define SPOT_DEF_UNOP(Name) \
1092  static formula Name(const formula& f) \
1093  { \
1094  return unop(op::Name, f); \
1095  } \
1096  static formula Name(formula&& f) \
1097  { \
1098  return unop(op::Name, std::move(f)); \
1099  }
1100 #endif // !SWIG
1104  SPOT_DEF_UNOP(Not);
1106 
1111 
1115  static formula X(unsigned level, const formula& f)
1116  {
1117  return nested_unop_range(op::X, op::Or /* unused */, level, level, f);
1118  }
1119 
1122  SPOT_DEF_UNOP(strong_X);
1124 
1128  static formula strong_X(unsigned level, const formula& f)
1129  {
1130  return nested_unop_range(op::strong_X, op::Or /* unused */,
1131  level, level, f);
1132  }
1133 
1138 
1145  static formula F(unsigned min_level, unsigned max_level, const formula& f)
1146  {
1147  return nested_unop_range(op::X, op::Or, min_level, max_level, f);
1148  }
1149 
1156  static formula G(unsigned min_level, unsigned max_level, const formula& f)
1157  {
1158  return nested_unop_range(op::X, op::And, min_level, max_level, f);
1159  }
1160 
1165 
1168  SPOT_DEF_UNOP(Closure);
1170 
1173  SPOT_DEF_UNOP(NegClosure);
1175 
1178  SPOT_DEF_UNOP(NegClosureMarked);
1180 
1183  SPOT_DEF_UNOP(first_match);
1185 #undef SPOT_DEF_UNOP
1186 
1192  static formula binop(op o, const formula& f, const formula& g)
1193  {
1194  return formula(fnode::binop(o, f.ptr_->clone(), g.ptr_->clone()));
1195  }
1196 
1197 #ifndef SWIG
1198  static formula binop(op o, const formula& f, formula&& g)
1199  {
1200  return formula(fnode::binop(o, f.ptr_->clone(), g.to_node_()));
1201  }
1202 
1203  static formula binop(op o, formula&& f, const formula& g)
1204  {
1205  return formula(fnode::binop(o, f.to_node_(), g.ptr_->clone()));
1206  }
1207 
1208  static formula binop(op o, formula&& f, formula&& g)
1209  {
1210  return formula(fnode::binop(o, f.to_node_(), g.to_node_()));
1211  }
1212 #endif //SWIG
1214 
1216 #ifdef SWIG
1217 #define SPOT_DEF_BINOP(Name) \
1218  static formula Name(const formula& f, const formula& g) \
1219  { \
1220  return binop(op::Name, f, g); \
1221  }
1222 #else // !SWIG
1223 #define SPOT_DEF_BINOP(Name) \
1224  static formula Name(const formula& f, const formula& g) \
1225  { \
1226  return binop(op::Name, f, g); \
1227  } \
1228  static formula Name(const formula& f, formula&& g) \
1229  { \
1230  return binop(op::Name, f, std::move(g)); \
1231  } \
1232  static formula Name(formula&& f, const formula& g) \
1233  { \
1234  return binop(op::Name, std::move(f), g); \
1235  } \
1236  static formula Name(formula&& f, formula&& g) \
1237  { \
1238  return binop(op::Name, std::move(f), std::move(g)); \
1239  }
1240 #endif // !SWIG
1244  SPOT_DEF_BINOP(Xor);
1246 
1249  SPOT_DEF_BINOP(Implies);
1251 
1256 
1261 
1266 
1271 
1276 
1279  SPOT_DEF_BINOP(EConcat);
1281 
1284  SPOT_DEF_BINOP(EConcatMarked);
1286 
1289  SPOT_DEF_BINOP(UConcat);
1291 #undef SPOT_DEF_BINOP
1292 
1316  static formula multop(op o, const std::vector<formula>& l)
1317  {
1318  std::vector<const fnode*> tmp;
1319  tmp.reserve(l.size());
1320  for (auto f: l)
1321  if (f.ptr_)
1322  tmp.emplace_back(f.ptr_->clone());
1323  return formula(fnode::multop(o, std::move(tmp)));
1324  }
1325 
1326 #ifndef SWIG
1327  static formula multop(op o, std::vector<formula>&& l)
1328  {
1329  std::vector<const fnode*> tmp;
1330  tmp.reserve(l.size());
1331  for (auto f: l)
1332  if (f.ptr_)
1333  tmp.emplace_back(f.to_node_());
1334  return formula(fnode::multop(o, std::move(tmp)));
1335  }
1336 #endif // !SWIG
1337 
1338  static formula multop(op o, const formula& f, const formula& g)
1339  {
1340  return formula(fnode::multop(o, f.ptr_->clone(), g.ptr_->clone()));
1341  }
1342 
1343 #ifndef SWIG
1344  static formula multop(op o, const formula& f, formula&& g)
1345  {
1346  return formula(fnode::multop(o, f.ptr_->clone(), g.to_node_()));
1347  }
1348 
1349  static formula multop(op o, formula&& f, const formula& g)
1350  {
1351  return formula(fnode::multop(o, f.to_node_(), g.ptr_->clone()));
1352  }
1353 
1354  static formula multop(op o, formula&& f, formula&& g)
1355  {
1356  return formula(fnode::multop(o, f.to_node_(), g.to_node_()));
1357  }
1358 #endif // !SWIG
1360 
1362 #ifdef SWIG
1363 #define SPOT_DEF_MULTOP(Name) \
1364  static formula Name(const std::vector<formula>& l) \
1365  { \
1366  return multop(op::Name, l); \
1367  } \
1368  \
1369  static formula Name(const formula& left, const formula& right) \
1370  { \
1371  return multop(op::Name, left, right); \
1372  }
1373 #else // !SWIG
1374 #define SPOT_DEF_MULTOP(Name) \
1375  static formula Name(const std::vector<formula>& l) \
1376  { \
1377  return multop(op::Name, l); \
1378  } \
1379  \
1380  static formula Name(std::vector<formula>&& l) \
1381  { \
1382  return multop(op::Name, std::move(l)); \
1383  } \
1384  \
1385  static formula Name(const formula& left, const formula& right) \
1386  { \
1387  return multop(op::Name, left, right); \
1388  }
1389 #endif // !SWIG
1390 #ifdef SWIG
1391 #define SPOT_DEF_MULTOP2(Name) \
1392  static formula Name(const std::vector<formula>& l) \
1393  { \
1394  return multop(op::Name, l); \
1395  } \
1396  \
1397  static formula Name(const formula& left, const formula& right) \
1398  { \
1399  return formula(fnode::multop_build_and_or<op::Name> \
1400  (left->ptr_->clone(), right->ptr_->clone()); \
1401  }
1402 #else // !SWIG
1403 #define SPOT_DEF_MULTOP2(Name) \
1404  static formula Name(const std::vector<formula>& l) \
1405  { \
1406  return multop(op::Name, l); \
1407  } \
1408  \
1409  static formula Name(std::vector<formula>&& l) \
1410  { \
1411  return multop(op::Name, std::move(l)); \
1412  } \
1413  \
1414  static formula Name(const formula& left, const formula& right) \
1415  { \
1416  return formula(fnode::multop_build_and_or<op::Name> \
1417  (left.ptr_->clone(), right.ptr_->clone())); \
1418  } \
1419  static formula Name(const formula& left, formula&& right) \
1420  { \
1421  return formula(fnode::multop_build_and_or<op::Name> \
1422  (left.ptr_->clone(), right.to_node_())); \
1423  } \
1424  static formula Name(formula&& left, const formula& right) \
1425  { \
1426  return formula(fnode::multop_build_and_or<op::Name> \
1427  (left.to_node_(), right.ptr_->clone())); \
1428  } \
1429  static formula Name(formula&& left, formula&& right) \
1430  { \
1431  return formula(fnode::multop_build_and_or<op::Name> \
1432  (left.to_node_(), right.to_node_())); \
1433  }
1434 #endif // !SWIG
1438  SPOT_DEF_MULTOP2(Or);
1440 
1445 
1450 
1455 
1460 
1465 
1470 #undef SPOT_DEF_MULTOP
1471 
1476  static formula bunop(op o, const formula& f,
1477  unsigned min = 0U,
1478  unsigned max = unbounded())
1479  {
1480  return formula(fnode::bunop(o, f.ptr_->clone(), min, max));
1481  }
1482 
1483 #ifndef SWIG
1484  static formula bunop(op o, formula&& f,
1485  unsigned min = 0U,
1486  unsigned max = unbounded())
1487  {
1488  return formula(fnode::bunop(o, f.to_node_(), min, max));
1489  }
1490 #endif // !SWIG
1492 
1494 #if SWIG
1495 #define SPOT_DEF_BUNOP(Name) \
1496  static formula Name(const formula& f, \
1497  unsigned min = 0U, \
1498  unsigned max = unbounded()) \
1499  { \
1500  return bunop(op::Name, f, min, max); \
1501  }
1502 #else // !SWIG
1503 #define SPOT_DEF_BUNOP(Name) \
1504  static formula Name(const formula& f, \
1505  unsigned min = 0U, \
1506  unsigned max = unbounded()) \
1507  { \
1508  return bunop(op::Name, f, min, max); \
1509  } \
1510  static formula Name(formula&& f, \
1511  unsigned min = 0U, \
1512  unsigned max = unbounded()) \
1513  { \
1514  return bunop(op::Name, std::move(f), min, max); \
1515  }
1516 #endif
1522 
1530 #undef SPOT_DEF_BUNOP
1531 
1536  static formula quantify(op quantifier,
1537  formula&& ap,
1538  formula&& f)
1539  {
1540  return formula(fnode::quantify(quantifier,
1541  ap.to_node_(),
1542  f.to_node_()));
1543  }
1544 
1545  static formula quantify(op quantifier,
1546  const formula& ap,
1547  const formula& f)
1548  {
1549  return formula(fnode::quantify(quantifier,
1550  ap.ptr_->clone(),
1551  f.ptr_->clone()));
1552  }
1553 
1554  static formula quantify(op quantifier,
1555  const std::vector<formula>& aps,
1556  const formula& f)
1557  {
1558  std::vector<const fnode*> tmp;
1559  tmp.reserve(aps.size() + 1);
1560  for (auto a: aps)
1561  if (a.ptr_)
1562  tmp.emplace_back(a.to_node_());
1563  return formula(fnode::quantify(quantifier, std::move(tmp),
1564  f.ptr_->clone()));
1565  }
1566 
1567 #ifndef SWIG
1568  static formula quantify(op quantifier,
1569  std::vector<formula>&& aps,
1570  const formula& f)
1571  {
1572  std::vector<const fnode*> tmp;
1573  tmp.reserve(aps.size() + 1);
1574  for (auto a: aps)
1575  if (a.ptr_)
1576  tmp.emplace_back(a.to_node_());
1577  return formula(fnode::quantify(quantifier, std::move(tmp),
1578  f.ptr_->clone()));
1579  }
1581 #endif // !SWIG
1582 
1584 #define SPOT_DEF_QUANTIFY(Name) \
1585  static formula Name(const std::vector<formula>& aps, const formula& f) \
1586  { \
1587  return quantify(op::Name, aps, f); \
1588  } \
1589  \
1590  static formula Name(const formula& ap, const formula& f) \
1591  { \
1592  return quantify(op::Name, ap, f); \
1593  }
1595 
1600 
1605 #undef SPOT_DEF_QUANTIFY
1606 
1618  static const formula nested_unop_range(op uo, op bo, unsigned min,
1619  unsigned max, formula f)
1620  {
1621  return formula(fnode::nested_unop_range(uo, bo, min, max,
1622  f.ptr_->clone()));
1623  }
1624 
1630  static formula sugar_goto(const formula& b, unsigned min, unsigned max);
1631 
1637  static formula sugar_equal(const formula& b, unsigned min, unsigned max);
1638 
1660  static formula sugar_delay(const formula& a, const formula& b,
1661  unsigned min, unsigned max);
1662  static formula sugar_delay(const formula& b,
1663  unsigned min, unsigned max);
1665 
1666 #ifndef SWIG
1676  const fnode* to_node_()
1677  {
1678  auto tmp = ptr_;
1679  ptr_ = nullptr;
1680  return tmp;
1681  }
1682 #endif
1683 
1685  op kind() const
1686  {
1687  return ptr_->kind();
1688  }
1689 
1691  std::string kindstr() const
1692  {
1693  return ptr_->kindstr();
1694  }
1695 
1697  bool is(op o) const
1698  {
1699  return ptr_->is(o);
1700  }
1701 
1702 #ifndef SWIG
1704  bool is(op o1, op o2) const
1705  {
1706  return ptr_->is(o1, o2);
1707  }
1708 
1710  bool is(op o1, op o2, op o3) const
1711  {
1712  return ptr_->is(o1, o2, o3);
1713  }
1714 
1717  bool is(op o1, op o2, op o3, op o4) const
1718  {
1719  return ptr_->is(o1, o2, o3, o4);
1720  }
1721 
1723  bool is(std::initializer_list<op> l) const
1724  {
1725  return ptr_->is(l);
1726  }
1727 #endif
1728 
1733  {
1734  auto f = ptr_->get_child_of(o);
1735  if (f)
1736  f->clone();
1737  return formula(f);
1738  }
1739 
1740 #ifndef SWIG
1747  formula get_child_of(std::initializer_list<op> l) const
1748  {
1749  auto f = ptr_->get_child_of(l);
1750  if (f)
1751  f->clone();
1752  return formula(f);
1753  }
1754 #endif
1755 
1759  unsigned min() const
1760  {
1761  return ptr_->min();
1762  }
1763 
1767  unsigned max() const
1768  {
1769  return ptr_->max();
1770  }
1771 
1773  unsigned size() const
1774  {
1775  return ptr_->size();
1776  }
1777 
1782  bool is_leaf() const
1783  {
1784  return ptr_->is_leaf();
1785  }
1786 
1795  size_t id() const
1796  {
1797  return ptr_->id();
1798  }
1799 
1800 #ifndef SWIG
1802  class SPOT_API formula_child_iterator final
1803  {
1804  const fnode*const* ptr_;
1805  public:
1807  : ptr_(nullptr)
1808  {
1809  }
1810 
1813  : ptr_(f)
1814  {
1815  }
1816 
1819  {
1820  return ptr_ == o.ptr_;
1821  }
1822 
1825  {
1826  return ptr_ != o.ptr_;
1827  }
1828 
1831  {
1832  return formula((*ptr_)->clone());
1833  }
1834 
1837  {
1838  ++ptr_;
1839  return *this;
1840  }
1841 
1844  {
1845  auto tmp = *this;
1846  ++ptr_;
1847  return tmp;
1848  }
1849  };
1850 
1853  {
1854  return ptr_->begin();
1855  }
1856 
1859  {
1860  return ptr_->end();
1861  }
1862 
1864  formula operator[](unsigned i) const
1865  {
1866  return formula(ptr_->nth(i)->clone());
1867  }
1868 #endif
1869 
1871  static formula ff()
1872  {
1873  return formula(fnode::ff());
1874  }
1875 
1877  bool is_ff() const
1878  {
1879  return ptr_->is_ff();
1880  }
1881 
1883  static formula tt()
1884  {
1885  return formula(fnode::tt());
1886  }
1887 
1889  bool is_tt() const
1890  {
1891  return ptr_->is_tt();
1892  }
1893 
1895  static formula eword()
1896  {
1897  return formula(fnode::eword());
1898  }
1899 
1901  bool is_eword() const
1902  {
1903  return ptr_->is_eword();
1904  }
1905 
1907  bool is_constant() const
1908  {
1909  return ptr_->is_constant();
1910  }
1911 
1916  bool is_Kleene_star() const
1917  {
1918  return ptr_->is_Kleene_star();
1919  }
1920 
1923  {
1924  // no need to clone, 1[*] is not reference counted
1925  return formula(fnode::one_star());
1926  }
1927 
1930  {
1931  // no need to clone, 1[+] is not reference counted
1932  return formula(fnode::one_plus());
1933  }
1934 
1937  bool is_literal() const
1938  {
1939  return (is(op::ap) ||
1940  // If f is in nenoform, Not can only occur in front of
1941  // an atomic proposition. So this way we do not have
1942  // to check the type of the child.
1943  (is(op::Not) && is_boolean() && is_in_nenoform()));
1944  }
1945 
1949  const std::string& ap_name() const
1950  {
1951  return ptr_->ap_name();
1952  }
1953 
1962  unsigned apid() const
1963  {
1964  return ptr_->apid();
1965  }
1966 
1971  std::ostream& dump(std::ostream& os) const
1972  {
1973  return ptr_->dump(os);
1974  }
1975 
1981  formula all_but(unsigned i) const
1982  {
1983  return formula(ptr_->all_but(i));
1984  }
1985 
1995  unsigned boolean_count() const
1996  {
1997  return ptr_->boolean_count();
1998  }
1999 
2013  formula boolean_operands(unsigned* width = nullptr) const
2014  {
2015  return formula(ptr_->boolean_operands(width));
2016  }
2017 
2019 #define SPOT_DEF_PROP(Name) \
2020  bool Name() const \
2021  { \
2022  return ptr_->Name(); \
2023  }
2026  // Properties //
2028 
2030  SPOT_DEF_PROP(is_boolean);
2032  SPOT_DEF_PROP(is_sugar_free_boolean);
2037  SPOT_DEF_PROP(is_in_nenoform);
2039  SPOT_DEF_PROP(is_syntactic_stutter_invariant);
2041  SPOT_DEF_PROP(is_sugar_free_ltl);
2043  SPOT_DEF_PROP(is_ltl_formula);
2045  SPOT_DEF_PROP(is_psl_formula);
2047  SPOT_DEF_PROP(is_sere_formula);
2050  SPOT_DEF_PROP(is_finite);
2058  SPOT_DEF_PROP(is_eventual);
2070  SPOT_DEF_PROP(is_syntactic_safety);
2074  SPOT_DEF_PROP(is_syntactic_guarantee);
2079  SPOT_DEF_PROP(is_delta1);
2084  SPOT_DEF_PROP(is_syntactic_obligation);
2086  SPOT_DEF_PROP(is_sigma2);
2088  SPOT_DEF_PROP(is_pi2);
2093  SPOT_DEF_PROP(is_syntactic_recurrence);
2098  SPOT_DEF_PROP(is_syntactic_persistence);
2103  SPOT_DEF_PROP(is_delta2);
2106  SPOT_DEF_PROP(is_marked);
2108  SPOT_DEF_PROP(accepts_eword);
2114  SPOT_DEF_PROP(has_lbt_atomic_props);
2123  SPOT_DEF_PROP(has_spin_atomic_props);
2125  SPOT_DEF_PROP(is_quantified);
2126 #undef SPOT_DEF_PROP
2127 
2131  template<typename Trans, typename... Args>
2132  formula map(Trans trans, Args&&... args)
2133  {
2134  switch (op o = kind())
2135  {
2136  case op::ff:
2137  case op::tt:
2138  case op::eword:
2139  case op::ap:
2140  return *this;
2141  case op::Not:
2142  case op::X:
2143 #if SPOT_HAS_STRONG_X
2144  case op::strong_X:
2145 #endif
2146  case op::F:
2147  case op::G:
2148  case op::Closure:
2149  case op::NegClosure:
2150  case op::NegClosureMarked:
2151  case op::first_match:
2152  {
2153  formula arg = (*this)[0];
2154  formula new_arg = trans(arg, std::forward<Args>(args)...);
2155  if (arg == new_arg)
2156  return *this;
2157  else
2158  return unop(o, new_arg);
2159  }
2160  case op::Xor:
2161  case op::Implies:
2162  case op::Equiv:
2163  case op::U:
2164  case op::R:
2165  case op::W:
2166  case op::M:
2167  case op::EConcat:
2168  case op::EConcatMarked:
2169  case op::UConcat:
2170  {
2171  formula left = (*this)[0];
2172  formula right = (*this)[1];
2173  formula new_left = trans(left, std::forward<Args>(args)...);
2174  formula new_right = trans(right, std::forward<Args>(args)...);
2175  if (left == new_left && right == new_right)
2176  return *this;
2177  else
2178  return binop(o, new_left, new_right);
2179  }
2180  case op::Or:
2181  case op::OrRat:
2182  case op::And:
2183  case op::AndRat:
2184  case op::AndNLM:
2185  case op::Concat:
2186  case op::Fusion:
2187  {
2188  std::vector<formula> tmp;
2189  bool changed = false;
2190  tmp.reserve(size());
2191  for (auto f: *this)
2192  {
2193  formula g = trans(f, std::forward<Args>(args)...);
2194  tmp.emplace_back(g);
2195  changed |= g != f;
2196  }
2197  if (!changed)
2198  return *this;
2199  else
2200  return multop(o, std::move(tmp));
2201  }
2202  case op::Star:
2203  case op::FStar:
2204  {
2205  formula arg = (*this)[0];
2206  formula new_arg = trans(arg, std::forward<Args>(args)...);
2207  if (arg == new_arg)
2208  return *this;
2209  else
2210  return bunop(o, new_arg, min(), max());
2211  }
2212  case op::exists:
2213  case op::forall:
2214  {
2215  std::vector<formula> tmp;
2216  unsigned sz = size();
2217  tmp.reserve(sz - 1);
2218  bool changed = false;
2219  for (unsigned i = 0; i < sz - 1; ++i)
2220  {
2221  formula c = (*this)[i];
2222  formula g = trans(c, std::forward<Args>(args)...);
2223  changed |= c != g;
2224  tmp.push_back(g);
2225  }
2226  formula c = (*this)[sz - 1];
2227  formula g = trans(c, std::forward<Args>(args)...);
2228  if (c == g && !changed)
2229  return *this;
2230  return quantify(o, std::move(tmp), g);
2231  }
2232  }
2233  SPOT_UNREACHABLE();
2234  }
2235 
2244  template<typename Func, typename... Args>
2245  void traverse(Func func, Args&&... args)
2246  {
2247  if (func(*this, std::forward<Args>(args)...))
2248  return;
2249  for (auto f: *this)
2250  f.traverse(func, std::forward<Args>(args)...);
2251  }
2252 
2253 #ifndef SWIG
2255  [[noreturn]] static void report_message(const char* message);
2256  private:
2257  [[noreturn]] static void report_ap_invalid_arg();
2258 #endif
2259  };
2260 
2262  SPOT_API
2263  std::ostream& print_formula_props(std::ostream& out, const formula& f,
2264  bool abbreviated = false);
2265 
2267  SPOT_API
2268  std::list<std::string> list_formula_props(const formula& f);
2269 
2271  SPOT_API
2272  std::ostream& operator<<(std::ostream& os, const formula& f);
2273 }
2274 
2275 #ifndef SWIG
2276 namespace std
2277 {
2279  template <>
2280  struct hash<spot::formula>
2281  {
2283  size_t operator()(const spot::formula& x) const noexcept
2284  {
2285  return x.id();
2286  }
2287  };
2288 }
2289 #endif
Actual storage for formula nodes.
Definition: formula.hh:173
bool is_pi2() const
Definition: formula.hh:601
const fnode *const * begin() const
Definition: formula.hh:341
const fnode *const * end() const
Definition: formula.hh:347
std::string kindstr() const
std::ostream & dump(std::ostream &os) const
bool is_boolean() const
Definition: formula.hh:475
size_t id() const
Definition: formula.hh:335
bool is_ff() const
Definition: formula.hh:369
static constexpr uint16_t unbounded()
Definition: formula.hh:203
bool is_sugar_free_boolean() const
Definition: formula.hh:481
bool is_Kleene_star() const
Definition: formula.hh:405
unsigned min() const
Definition: formula.hh:307
bool is_syntactic_safety() const
Definition: formula.hh:541
bool is_syntactic_stutter_invariant() const
Definition: formula.hh:493
bool is_delta2() const
Definition: formula.hh:613
unsigned size() const
Definition: formula.hh:323
static const fnode * eword()
Definition: formula.hh:387
const fnode * get_child_of(op o) const
Definition: formula.hh:284
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:315
static const fnode * ff()
Definition: formula.hh:363
const fnode * boolean_operands(unsigned *width=nullptr) const
bool accepts_eword() const
Definition: formula.hh:577
bool is_eventual() const
Definition: formula.hh:529
const std::string & ap_name() const
bool is(op o1, op o2, op o3, op o4) const
Definition: formula.hh:265
static bool instances_check()
safety check for the reference counters
bool is_leaf() const
Definition: formula.hh:329
bool has_spin_atomic_props() const
Definition: formula.hh:589
bool is_eword() const
Definition: formula.hh:393
static const fnode * tt()
Definition: formula.hh:375
bool is(op o1, op o2, op o3) const
Definition: formula.hh:260
op kind() const
Definition: formula.hh:240
bool has_lbt_atomic_props() const
Definition: formula.hh:583
unsigned apid() const
Definition: formula.hh:432
bool is_sugar_free_ltl() const
Definition: formula.hh:499
bool is_syntactic_persistence() const
Definition: formula.hh:565
static const fnode * nested_unop_range(op uo, op bo, unsigned min, unsigned max, const fnode *f)
unsigned boolean_count() const
Definition: formula.hh:446
bool is_universal() const
Definition: formula.hh:535
bool is_tt() const
Definition: formula.hh:381
const fnode * get_child_of(std::initializer_list< op > l) const
Definition: formula.hh:294
static const fnode * one_plus()
Definition: formula.hh:421
const fnode * nth(unsigned i) const
Definition: formula.hh:353
bool is_constant() const
Definition: formula.hh:399
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:413
const fnode * all_but(unsigned i) const
bool is_syntactic_recurrence() const
Definition: formula.hh:559
bool is(std::initializer_list< op > l) const
Definition: formula.hh:270
bool is_syntactic_obligation() const
Definition: formula.hh:553
bool is_quantified() const
Definition: formula.hh:619
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:505
bool is_finite() const
Definition: formula.hh:523
bool is_sigma2() const
Definition: formula.hh:595
bool is_psl_formula() const
Definition: formula.hh:511
bool is_delta1() const
Definition: formula.hh:607
static const fnode * multop(op o, std::vector< const fnode * > l)
bool is_marked() const
Definition: formula.hh:571
void destroy() const
Dereference an fnode.
Definition: formula.hh:193
static const fnode * bunop(op o, const fnode *f, unsigned min, unsigned max=unbounded())
bool is(op o1, op o2) const
Definition: formula.hh:255
bool is_in_nenoform() const
Definition: formula.hh:487
static const fnode * ap(const std::string &name)
bool is_syntactic_guarantee() const
Definition: formula.hh:547
bool is_sere_formula() const
Definition: formula.hh:517
const fnode * clone() const
Clone an fnode.
Definition: formula.hh:179
bool is(op o) const
Definition: formula.hh:250
Allow iterating over children.
Definition: formula.hh:1803
formula_child_iterator operator++(int)
Post-increment.
Definition: formula.hh:1843
formula operator*()
Dereference to the child formula.
Definition: formula.hh:1830
formula_child_iterator(const fnode *const *f)
Construct from a raw fnode pointer array position.
Definition: formula.hh:1812
bool operator!=(formula_child_iterator o)
Iterator inequality.
Definition: formula.hh:1824
bool operator==(formula_child_iterator o)
Iterator equality.
Definition: formula.hh:1818
formula_child_iterator operator++()
Pre-increment.
Definition: formula.hh:1836
Main class for temporal logic formula.
Definition: formula.hh:847
SPOT_DEF_BUNOP(FStar)
Create SERE for f[:*min..max]
const formula & operator=(formula &&f) noexcept
Move-assignment operator.
Definition: formula.hh:922
SPOT_DEF_PROP(is_finite)
Whether a SERE describes a finite language, or an LTL formula uses no temporal operator but X.
SPOT_DEF_PROP(is_delta1)
Whether a PSL/LTL formula is in the Δ₁ syntactic fragment.
unsigned boolean_count() const
number of Boolean children
Definition: formula.hh:1995
bool operator!=(const formula &other) const noexcept
Inequality comparison.
Definition: formula.hh:978
SPOT_DEF_BINOP(Equiv)
Construct an <-> formula.
bool is_leaf() const
Whether the formula is a leaf.
Definition: formula.hh:1782
size_t id() const
Return the id of a formula.
Definition: formula.hh:1795
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:1484
formula map(Trans trans, Args &&... args)
Clone this node after applying trans to its children.
Definition: formula.hh:2132
unsigned apid() const
Get the number of an atomic proposition.
Definition: formula.hh:1962
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:1476
static formula multop(op o, const formula &f, const formula &g)
Construct an n-ary operator.
Definition: formula.hh:1338
SPOT_DEF_PROP(is_delta2)
Whether a PSL/LTL formula is in the Δ₂ syntactic fragment.
static formula G(unsigned min_level, unsigned max_level, const formula &f)
Construct G[n:m].
Definition: formula.hh:1156
SPOT_DEF_PROP(is_syntactic_guarantee)
Whether a PSL/LTL formula is syntactic guarantee property.
static formula binop(op o, const formula &f, const formula &g)
Construct a binary operator.
Definition: formula.hh:1192
bool is(op o) const
Return true if the formula is of kind o.
Definition: formula.hh:1697
SPOT_DEF_MULTOP(OrRat)
Construct an Or SERE.
static formula multop(op o, std::vector< formula > &&l)
Construct an n-ary operator.
Definition: formula.hh:1327
SPOT_DEF_PROP(is_psl_formula)
Whether the formula uses only PSL operators.
SPOT_DEF_PROP(is_syntactic_stutter_invariant)
Whether the formula is syntactically stutter_invariant.
formula(formula &&f) noexcept
Move-construct a formula.
Definition: formula.hh:885
SPOT_DEF_QUANTIFY(exists)
Create formula for exists ap : f
SPOT_DEF_PROP(is_marked)
Whether the formula has an occurrence of EConcatMarked or NegClosureMarked.
SPOT_DEF_UNOP(NegClosureMarked)
Construct a marked negated PSL Closure.
formula(const fnode *f) noexcept
Create a formula from an fnode.
Definition: formula.hh:855
static void report_message(const char *message)
Report a fatal formula error message and abort.
SPOT_DEF_PROP(is_in_nenoform)
Whether the formula is in negative normal form.
bool is(op o1, op o2) const
Return true if the formula is of kind o1 or o2.
Definition: formula.hh:1704
static formula one_plus()
Return a copy of the formula 1[+].
Definition: formula.hh:1929
SPOT_DEF_BINOP(Implies)
Construct an -> formula.
static formula sugar_delay(const formula &b, unsigned min, unsigned max)
Create the SERE a ##[n:m] b
SPOT_DEF_PROP(is_sigma2)
Whether a PSL/LTL formula is in Σ₂
static formula quantify(op quantifier, formula &&ap, formula &&f)
Create a quantified formula (∃ or ∀ over an atomic proposition).
Definition: formula.hh:1536
static formula quantify(op quantifier, std::vector< formula > &&aps, const formula &f)
Create a quantified formula (∃ or ∀ over an atomic proposition).
Definition: formula.hh:1568
SPOT_DEF_UNOP(X)
Construct an X.
SPOT_DEF_PROP(has_spin_atomic_props)
Whether the formula has spin-compatible atomic propositions.
SPOT_DEF_MULTOP(Concat)
Construct a Concatenation SERE.
SPOT_DEF_BINOP(W)
Construct a W formula.
SPOT_DEF_QUANTIFY(forall)
Create formula for forall ap : f
static formula one_star()
Return a copy of the formula 1[*].
Definition: formula.hh:1922
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:1759
SPOT_DEF_UNOP(Closure)
Construct a PSL Closure.
bool operator==(const formula &other) const noexcept
Definition: formula.hh:966
bool operator<=(const formula &other) const noexcept
Less-than-or-equal comparison.
Definition: formula.hh:947
const formula & operator=(const formula &f)
Copy-assignment operator.
Definition: formula.hh:913
SPOT_DEF_MULTOP(AndRat)
Construct an And SERE.
SPOT_DEF_UNOP(first_match)
Construct first_match(sere)
static formula unop(op o, formula &&f)
Build a unary operator.
Definition: formula.hh:1076
SPOT_DEF_PROP(is_eventual)
Whether the formula is purely eventual.
static formula eword()
Return the empty word constant.
Definition: formula.hh:1895
SPOT_DEF_UNOP(G)
Construct a G.
static formula multop(op o, formula &&f, const formula &g)
Construct an n-ary operator.
Definition: formula.hh:1349
SPOT_DEF_PROP(is_syntactic_safety)
Whether a PSL/LTL formula is syntactic safety property.
SPOT_DEF_UNOP(NegClosure)
Construct a negated PSL Closure.
SPOT_DEF_PROP(is_sugar_free_boolean)
Whether the formula use only AND, OR, and NOT operators.
formula all_but(unsigned i) const
clone this formula, omitting child i
Definition: formula.hh:1981
static formula ff()
Return the false constant.
Definition: formula.hh:1871
SPOT_DEF_BINOP(EConcat)
Construct a <>-> PSL formula.
static formula quantify(op quantifier, const std::vector< formula > &aps, const formula &f)
Create a quantified formula (∃ or ∀ over an atomic proposition).
Definition: formula.hh:1554
static formula binop(op o, const formula &f, formula &&g)
Construct a binary operator.
Definition: formula.hh:1198
op kind() const
Return top-most operator.
Definition: formula.hh:1685
static formula multop(op o, const std::vector< formula > &l)
Construct an n-ary operator.
Definition: formula.hh:1316
unsigned size() const
Return the number of children.
Definition: formula.hh:1773
static formula sugar_goto(const formula &b, unsigned min, unsigned max)
Create a SERE equivalent to b[->min..max]
SPOT_DEF_PROP(accepts_eword)
Whether the formula accepts [*0].
bool is_tt() const
Whether the formula is the true constant.
Definition: formula.hh:1889
bool is(op o1, op o2, op o3, op o4) const
Definition: formula.hh:1717
SPOT_DEF_PROP(is_pi2)
Whether a PSL/LTL formula is in Π₂
std::string kindstr() const
Return the name of the top-most operator.
Definition: formula.hh:1691
SPOT_DEF_BUNOP(Star)
Create SERE for f[*min..max]
bool operator>(const formula &other) const noexcept
Greater-than comparison.
Definition: formula.hh:953
bool operator>=(const formula &other) const noexcept
Greater-than-or-equal comparison.
Definition: formula.hh:959
formula(const formula &f) noexcept
Clone a formula.
Definition: formula.hh:877
SPOT_DEF_PROP(is_quantified)
Whether a PSL/LTL formula has ∃/∀ quantifiers.
formula_child_iterator end() const
Allow iterating over children.
Definition: formula.hh:1858
SPOT_DEF_UNOP(strong_X)
Construct a strong_X.
static formula binop(op o, formula &&f, formula &&g)
Construct a binary operator.
Definition: formula.hh:1208
static formula multop(op o, const formula &f, formula &&g)
Construct an n-ary operator.
Definition: formula.hh:1344
static formula ap(const formula &a)
Build an atomic proposition from... an atomic proposition.
Definition: formula.hh:1059
formula get_child_of(std::initializer_list< op > l) const
Remove all operators in l and return the child.
Definition: formula.hh:1747
bool is_eword() const
Whether the formula is the empty word constant.
Definition: formula.hh:1901
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:2245
static formula F(unsigned min_level, unsigned max_level, const formula &f)
Construct F[n:m].
Definition: formula.hh:1145
formula(std::nullptr_t) noexcept
Create a null formula.
Definition: formula.hh:865
static formula ap(const std::string &name)
Build an atomic proposition.
Definition: formula.hh:1049
SPOT_DEF_PROP(is_syntactic_recurrence)
Whether a PSL/LTL formula is syntactic recurrence property.
const std::string & ap_name() const
Get the name of an atomic proposition.
Definition: formula.hh:1949
SPOT_DEF_BINOP(M)
Construct an M formula.
SPOT_DEF_PROP(is_syntactic_persistence)
Whether a PSL/LTL formula is syntactic persistence property.
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:1710
SPOT_DEF_PROP(is_syntactic_obligation)
Whether a PSL/LTL formula is syntactic obligation property.
const formula & operator=(std::nullptr_t)
Reset a formula to null.
Definition: formula.hh:905
unsigned max() const
Return end of the range for star-like operators.
Definition: formula.hh:1767
static formula X(unsigned level, const formula &f)
Construct an X[n].
Definition: formula.hh:1115
SPOT_DEF_BINOP(R)
Construct an R formula.
SPOT_DEF_MULTOP2(And)
Construct an And formula.
bool is_ff() const
Whether the formula is the false constant.
Definition: formula.hh:1877
SPOT_DEF_BINOP(U)
Construct a U formula.
static formula multop(op o, formula &&f, formula &&g)
Construct an n-ary operator.
Definition: formula.hh:1354
SPOT_DEF_PROP(is_boolean)
Whether the formula use only boolean operators.
SPOT_DEF_BINOP(EConcatMarked)
Construct a marked <>-> PSL formula.
bool operator<(const formula &other) const noexcept
Less-than comparison (based on unique formula id).
Definition: formula.hh:929
formula_child_iterator begin() const
Allow iterating over children.
Definition: formula.hh:1852
bool is_constant() const
Whether the formula is op::ff, op::tt, or op::eword.
Definition: formula.hh:1907
~formula()
Destroy a formula.
Definition: formula.hh:892
SPOT_DEF_PROP(is_universal)
Whether a formula is purely universal.
std::ostream & dump(std::ostream &os) const
Print the formula for debugging.
Definition: formula.hh:1971
formula get_child_of(op o) const
Remove operator o and return the child.
Definition: formula.hh:1732
const fnode * to_node_()
Return the underlying pointer to the formula.
Definition: formula.hh:1676
bool is(std::initializer_list< op > l) const
Return true if the formulas nests all the operators in l.
Definition: formula.hh:1723
SPOT_DEF_UNOP(F)
Construct an F.
SPOT_DEF_PROP(has_lbt_atomic_props)
Whether the formula has only LBT-compatible atomic propositions.
SPOT_DEF_PROP(is_sere_formula)
Whether the formula uses only SERE operators.
formula operator[](unsigned i) const
Return children number i.
Definition: formula.hh:1864
static formula strong_X(unsigned level, const formula &f)
Construct a strong_X[n].
Definition: formula.hh:1128
static formula quantify(op quantifier, const formula &ap, const formula &f)
Create a quantified formula (∃ or ∀ over an atomic proposition).
Definition: formula.hh:1545
SPOT_DEF_MULTOP(AndNLM)
Construct a non-length-matching And SERE.
bool is_Kleene_star() const
Test whether the formula represent a Kleene star.
Definition: formula.hh:1916
SPOT_DEF_PROP(is_sugar_free_ltl)
Whether the formula avoids the F and G operators.
static formula binop(op o, formula &&f, const formula &g)
Construct a binary operator.
Definition: formula.hh:1203
bool is_literal() const
Whether the formula is an atomic proposition or its negation.
Definition: formula.hh:1937
SPOT_DEF_MULTOP(Fusion)
Construct a Fusion SERE.
static formula tt()
Return the true constant.
Definition: formula.hh:1883
bool operator!=(std::nullptr_t) const noexcept
Check whether the formula is non-null.
Definition: formula.hh:984
bool operator==(std::nullptr_t) const noexcept
Check whether the formula is null.
Definition: formula.hh:972
formula() noexcept
Default initialize a formula to None.
Definition: formula.hh:871
static formula sugar_equal(const formula &b, unsigned min, unsigned max)
Create the SERE b[=min..max]
static constexpr unsigned unbounded()
Unbounded constant to use as end of range for bounded operators.
Definition: formula.hh:1043
static formula unop(op o, const formula &f)
Build a unary operator.
Definition: formula.hh:1070
formula boolean_operands(unsigned *width=nullptr) const
return a clone of the current node, restricted to its Boolean children
Definition: formula.hh:2013
SPOT_DEF_PROP(is_ltl_formula)
Whether the formula uses only LTL operators.
SPOT_DEF_BINOP(UConcat)
Construct a []-> PSL formula.
static const formula nested_unop_range(op uo, op bo, unsigned min, unsigned max, formula f)
Nested operator construction (syntactic sugar).
Definition: formula.hh:1618
op
Operator types.
Definition: formula.hh:85
@ 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
Fusion 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::ostream & operator<<(std::ostream &os, const mc_algorithm &ma)
Print an mc_algorithm value to a stream.
Definition: mc.hh:74
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.
Comparator for formula pointers that orders Boolean formulas before others.
Definition: formula.hh:770
bool operator()(const formula &left, const formula &right) const
Compare two formula objects, Boolean formulas ordered first.
bool operator()(const fnode *left, const fnode *right) const
Compare two fnode pointers, Boolean formulas ordered first.
Definition: formula.hh:773
size_t operator()(const spot::formula &x) const noexcept
Compute hash of a formula using its unique identifier.
Definition: formula.hh:2283

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