spot 2.16
Loading...
Searching...
No Matches
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
78namespace 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,
98 // binary operators
99 Xor,
100 Implies,
101 Equiv,
102 U,
103 R,
104 W,
105 M,
106 EConcat,
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,
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
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
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 {
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
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
1251
1256
1261
1266
1271
1276
1281
1284 SPOT_DEF_BINOP(EConcatMarked);
1286
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
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
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);
2066 SPOT_DEF_PROP(is_universal);
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);
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
2276namespace 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
std::string kindstr() const
const fnode * boolean_operands(unsigned *width=nullptr) 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
static const fnode * nested_unop_range(op uo, op bo, unsigned min, unsigned max, const fnode *f)
const fnode *const * end() const
Definition formula.hh:347
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
static const fnode * quantify(op quantifier, const fnode *ap, const fnode *f)
static const fnode * binop(op o, const fnode *f, const fnode *g)
bool is_delta2() const
Definition formula.hh:613
unsigned size() const
Definition formula.hh:323
const fnode * get_child_of(std::initializer_list< op > l) const
Definition formula.hh:294
unsigned max() const
Definition formula.hh:315
const fnode * get_child_of(op o) const
Definition formula.hh:284
const fnode * all_but(unsigned i) const
bool accepts_eword() const
Definition formula.hh:577
bool is_eventual() const
Definition formula.hh:529
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
bool is(op o1, op o2, op o3) const
Definition formula.hh:260
op kind() const
Definition formula.hh:240
const fnode * clone() const
Clone an fnode.
Definition formula.hh:179
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
const std::string & ap_name() const
bool is_syntactic_persistence() const
Definition formula.hh:565
unsigned boolean_count() const
Definition formula.hh:446
static const fnode * tt()
Definition formula.hh:375
bool is_universal() const
Definition formula.hh:535
bool is_tt() const
Definition formula.hh:381
bool is_constant() const
Definition formula.hh:399
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)
const fnode * nth(unsigned i) const
Definition formula.hh:353
bool is_ltl_formula() const
Definition formula.hh:505
static const fnode * multop(op o, const fnode *f, const fnode *g)
static const fnode * quantify(op quantifier, std::vector< const fnode * > aps, const fnode *f)
static const fnode * ff()
Definition formula.hh:363
bool is_finite() const
Definition formula.hh:523
static const fnode * multop_build_and_or(const fnode *left, const fnode *right)
fast path for binary and/or
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 * eword()
Definition formula.hh:387
bool is_marked() const
Definition formula.hh:571
std::ostream & dump(std::ostream &os) const
void destroy() const
Dereference an fnode.
Definition formula.hh:193
static const fnode * one_plus()
Definition formula.hh:421
static const fnode * ap(const std::string &name)
bool is(op o1, op o2) const
Definition formula.hh:255
bool is_in_nenoform() const
Definition formula.hh:487
static const fnode * bunop(op o, const fnode *f, unsigned min, unsigned max=unbounded())
bool is_syntactic_guarantee() const
Definition formula.hh:547
static const fnode * multop(op o, std::vector< const fnode * > l)
bool is_sere_formula() const
Definition formula.hh:517
static const fnode * one_star()
Definition formula.hh:413
const fnode *const * begin() const
Definition formula.hh:341
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]
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.
std::ostream & dump(std::ostream &os) const
Print the formula for debugging.
Definition formula.hh:1971
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
const formula & operator=(const formula &f)
Copy-assignment operator.
Definition formula.hh:913
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
const formula & operator=(formula &&f) noexcept
Move-assignment operator.
Definition formula.hh:922
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
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
const formula & operator=(std::nullptr_t)
Reset a formula to null.
Definition formula.hh:905
op kind() const
Return top-most operator.
Definition formula.hh:1685
const std::string & ap_name() const
Get the name of an atomic proposition.
Definition formula.hh:1949
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
const fnode * to_node_()
Return the underlying pointer to the formula.
Definition formula.hh:1676
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.
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.
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.
formula get_child_of(op o) const
Remove operator o and return the child.
Definition formula.hh:1732
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.
Definition automata.hh:26
std::ostream & operator<<(std::ostream &os, const mc_algorithm &ma)
Print an mc_algorithm value to a stream.
Definition mc.hh:74
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.
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.8