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

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on for spot by doxygen 1.15.0