spot 2.15
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 {
80 ff,
81 tt,
82 eword,
83 ap,
84 // unary operators
85 Not,
86 X,
87 F,
88 G,
89 Closure,
92 // binary operators
93 Xor,
94 Implies,
95 Equiv,
96 U,
97 R,
98 W,
99 M,
100 EConcat,
102 UConcat,
103 // n-ary operators
104 Or,
105 OrRat,
106 And,
107 AndRat,
108 AndNLM,
109 Concat,
110 Fusion,
111 // star-like operators
112 Star,
113 FStar,
115 // strong_X was introduced in Spot 2.9, but was hidden from the
116 // public API by default in order not to break existing code.
117 //
118 // Starting with Spot 2.13, strong_X will be part of the public
119 // API by default. If you have a switch case listing all possible
120 // operators, strong_X needs to be part of it. If you have code
121 // using Spot but that you also want to support versions older
122 // than 2.13, there are two ways to do that
123 //
124 // Option 1: define SPOT_USES_STRONG_X before including this file.
125 //
126 // #define SPOT_USES_STRONG_X 1
127 // #include <spot/tl/formula.hh>
128 //
129 // This will force any version of Spot since 2.9 to define
130 // strong_X. It won't work with older Spot versions, where
131 // strong_X did not exist.
132 //
133 // Option 2: make any code using strong_X conditional on
134 // SPOT_HAS_STRONG_X. Typically, a switch over all possible
135 // operators would include something like this:
136 //
137 // #if SPOT_HAS_STRONG_X
138 // case op::strong_X:
139 // /* do something */
140 // #endif
141 //
142 // The two options are not mutually exclusive. Using both allows
143 // you to use strong_X whenever it exists.
144 strong_X,
145 // The following two operators are new in Spot 2.15
146 // If you need to support an earlier version of Spot, you can
147 // use the SPOT_HAS_QUANTIFIERS variable.
148 //
149 // #if SPOT_HAS_QUANTIFIERS
150 // case op::exists:
151 // /* do something */
152 // case op::forall:
153 // /* do something */
154 // #endif
155 exists,
156 forall,
157 };
158
159#ifndef SWIG
166 class SPOT_API fnode final
167 {
168 public:
173 const fnode* clone() const
174 {
175 // Saturate.
176 ++refs_;
177 if (SPOT_UNLIKELY(!refs_))
178 saturated_ = 1;
179 return this;
180 }
181
187 void destroy() const
188 {
189 if (SPOT_LIKELY(refs_))
190 --refs_;
191 else if (SPOT_LIKELY(!saturated_))
192 // last reference to a node that is not a constant
193 destroy_aux();
194 }
195
197 static constexpr uint8_t unbounded()
198 {
199 return UINT8_MAX;
200 }
201
203 static const fnode* ap(const std::string& name);
205 static const fnode* unop(op o, const fnode* f);
207 static const fnode* binop(op o, const fnode* f, const fnode* g);
209 static const fnode* multop(op o, const fnode* f, const fnode* g);
211 static const fnode* multop(op o, std::vector<const fnode*> l);
213 template<op o>
214 static const fnode* multop_build_and_or(const fnode* left,
215 const fnode* right);
217 static const fnode* bunop(op o, const fnode* f,
218 unsigned min, unsigned max = unbounded());
219
221 static const fnode* nested_unop_range(op uo, op bo, unsigned min,
222 unsigned max, const fnode* f);
223
225 static const fnode* quantify(op quantifier,
226 const fnode* ap,
227 const fnode* f);
229 static const fnode* quantify(op quantifier,
230 std::vector<const fnode*> aps,
231 const fnode* f);
232
234 op kind() const
235 {
236 return op_;
237 }
238
240 std::string kindstr() const;
241
244 bool is(op o) const
245 {
246 return op_ == o;
247 }
248
249 bool is(op o1, op o2) const
250 {
251 return op_ == o1 || op_ == o2;
252 }
253
254 bool is(op o1, op o2, op o3) const
255 {
256 return op_ == o1 || op_ == o2 || op_ == o3;
257 }
258
259 bool is(op o1, op o2, op o3, op o4) const
260 {
261 return op_ == o1 || op_ == o2 || op_ == o3 || op_ == o4;
262 }
263
264 bool is(std::initializer_list<op> l) const
265 {
266 const fnode* n = this;
267 for (auto o: l)
268 {
269 if (!n->is(o))
270 return false;
271 n = n->nth(0);
272 }
273 return true;
274 }
276
278 const fnode* get_child_of(op o) const
279 {
280 if (op_ != o)
281 return nullptr;
282 if (SPOT_UNLIKELY(size_ != 1))
283 report_get_child_of_expecting_single_child_node();
284 return nth(0);
285 }
286
288 const fnode* get_child_of(std::initializer_list<op> l) const
289 {
290 auto c = this;
291 for (auto o: l)
292 {
293 c = c->get_child_of(o);
294 if (c == nullptr)
295 return c;
296 }
297 return c;
298 }
299
301 unsigned min() const
302 {
303 if (SPOT_UNLIKELY(op_ != op::FStar && op_ != op::Star))
304 report_min_invalid_arg();
305 return range_.min;
306 }
307
309 unsigned max() const
310 {
311 if (SPOT_UNLIKELY(op_ != op::FStar && op_ != op::Star))
312 report_max_invalid_arg();
313 return range_.max;
314 }
315
317 unsigned size() const
318 {
319 return size_;
320 }
321
323 bool is_leaf() const
324 {
325 return size_ == 0;
326 }
327
329 size_t id() const
330 {
331 return id_;
332 }
333
335 const fnode*const* begin() const
336 {
337 return children;
338 }
339
341 const fnode*const* end() const
342 {
343 return children + size();
344 }
345
347 const fnode* nth(unsigned i) const
348 {
349 if (SPOT_UNLIKELY(i >= size()))
350 report_non_existing_child();
351 const fnode* c = children[i];
352 SPOT_ASSUME(c != nullptr);
353 return c;
354 }
355
357 static const fnode* ff()
358 {
359 return ff_;
360 }
361
363 bool is_ff() const
364 {
365 return op_ == op::ff;
366 }
367
369 static const fnode* tt()
370 {
371 return tt_;
372 }
373
375 bool is_tt() const
376 {
377 return op_ == op::tt;
378 }
379
381 static const fnode* eword()
382 {
383 return ew_;
384 }
385
387 bool is_eword() const
388 {
389 return op_ == op::eword;
390 }
391
393 bool is_constant() const
394 {
395 return op_ == op::ff || op_ == op::tt || op_ == op::eword;
396 }
397
399 bool is_Kleene_star() const
400 {
401 if (op_ != op::Star)
402 return false;
403 return range_.min == 0 && range_.max == unbounded();
404 }
405
407 static const fnode* one_star()
408 {
409 if (!one_star_)
410 one_star_ = new fnode(op::Star, tt_, 0, unbounded(), true);
411 return one_star_;
412 }
413
415 static const fnode* one_plus()
416 {
417 if (!one_plus_)
418 one_plus_ = new fnode(op::Star, tt_, 1, unbounded(), true);
419 return one_plus_;
420 }
421
423 const std::string& ap_name() const;
424
426 unsigned apid() const
427 {
428 if (SPOT_UNLIKELY(op_ != op::ap))
429 report_apid_on_nonap();
430 return ap_id_;
431 }
432
434 std::ostream& dump(std::ostream& os) const;
435
437 const fnode* all_but(unsigned i) const;
438
440 unsigned boolean_count() const
441 {
442 unsigned pos = 0;
443 unsigned s = size();
444 while (pos < s && children[pos]->is_boolean())
445 ++pos;
446 return pos;
447 }
448
450 const fnode* boolean_operands(unsigned* width = nullptr) const;
451
462 static bool instances_check();
463
465 // Properties //
467
469 bool is_boolean() const
470 {
471 return is_.boolean;
472 }
473
476 {
477 return is_.sugar_free_boolean;
478 }
479
481 bool is_in_nenoform() const
482 {
483 return is_.in_nenoform;
484 }
485
488 {
489 return is_.syntactic_si;
490 }
491
493 bool is_sugar_free_ltl() const
494 {
495 return is_.sugar_free_ltl;
496 }
497
499 bool is_ltl_formula() const
500 {
501 return is_.ltl_formula;
502 }
503
505 bool is_psl_formula() const
506 {
507 return is_.psl_formula;
508 }
509
511 bool is_sere_formula() const
512 {
513 return is_.sere_formula;
514 }
515
517 bool is_finite() const
518 {
519 return is_.finite;
520 }
521
523 bool is_eventual() const
524 {
525 return is_.eventual;
526 }
527
529 bool is_universal() const
530 {
531 return is_.universal;
532 }
533
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 {
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:
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);
2001 SPOT_DEF_PROP(is_sugar_free_boolean);
2006 SPOT_DEF_PROP(is_in_nenoform);
2008 SPOT_DEF_PROP(is_syntactic_stutter_invariant);
2010 SPOT_DEF_PROP(is_sugar_free_ltl);
2012 SPOT_DEF_PROP(is_ltl_formula);
2014 SPOT_DEF_PROP(is_psl_formula);
2016 SPOT_DEF_PROP(is_sere_formula);
2019 SPOT_DEF_PROP(is_finite);
2027 SPOT_DEF_PROP(is_eventual);
2035 SPOT_DEF_PROP(is_universal);
2039 SPOT_DEF_PROP(is_syntactic_safety);
2043 SPOT_DEF_PROP(is_syntactic_guarantee);
2048 SPOT_DEF_PROP(is_delta1);
2053 SPOT_DEF_PROP(is_syntactic_obligation);
2055 SPOT_DEF_PROP(is_sigma2);
2057 SPOT_DEF_PROP(is_pi2);
2062 SPOT_DEF_PROP(is_syntactic_recurrence);
2067 SPOT_DEF_PROP(is_syntactic_persistence);
2072 SPOT_DEF_PROP(is_delta2);
2075 SPOT_DEF_PROP(is_marked);
2077 SPOT_DEF_PROP(accepts_eword);
2083 SPOT_DEF_PROP(has_lbt_atomic_props);
2092 SPOT_DEF_PROP(has_spin_atomic_props);
2094 SPOT_DEF_PROP(is_quantified);
2095#undef SPOT_DEF_PROP
2096
2100 template<typename Trans, typename... Args>
2101 formula map(Trans trans, Args&&... args)
2102 {
2103 switch (op o = kind())
2104 {
2105 case op::ff:
2106 case op::tt:
2107 case op::eword:
2108 case op::ap:
2109 return *this;
2110 case op::Not:
2111 case op::X:
2112#if SPOT_HAS_STRONG_X
2113 case op::strong_X:
2114#endif
2115 case op::F:
2116 case op::G:
2117 case op::Closure:
2118 case op::NegClosure:
2119 case op::NegClosureMarked:
2120 case op::first_match:
2121 {
2122 formula arg = (*this)[0];
2123 formula new_arg = trans(arg, std::forward<Args>(args)...);
2124 if (arg == new_arg)
2125 return *this;
2126 else
2127 return unop(o, new_arg);
2128 }
2129 case op::Xor:
2130 case op::Implies:
2131 case op::Equiv:
2132 case op::U:
2133 case op::R:
2134 case op::W:
2135 case op::M:
2136 case op::EConcat:
2137 case op::EConcatMarked:
2138 case op::UConcat:
2139 {
2140 formula left = (*this)[0];
2141 formula right = (*this)[1];
2142 formula new_left = trans(left, std::forward<Args>(args)...);
2143 formula new_right = trans(right, std::forward<Args>(args)...);
2144 if (left == new_left && right == new_right)
2145 return *this;
2146 else
2147 return binop(o, new_left, new_right);
2148 }
2149 case op::Or:
2150 case op::OrRat:
2151 case op::And:
2152 case op::AndRat:
2153 case op::AndNLM:
2154 case op::Concat:
2155 case op::Fusion:
2156 {
2157 std::vector<formula> tmp;
2158 bool changed = false;
2159 tmp.reserve(size());
2160 for (auto f: *this)
2161 {
2162 formula g = trans(f, std::forward<Args>(args)...);
2163 tmp.emplace_back(g);
2164 changed |= g != f;
2165 }
2166 if (!changed)
2167 return *this;
2168 else
2169 return multop(o, std::move(tmp));
2170 }
2171 case op::Star:
2172 case op::FStar:
2173 {
2174 formula arg = (*this)[0];
2175 formula new_arg = trans(arg, std::forward<Args>(args)...);
2176 if (arg == new_arg)
2177 return *this;
2178 else
2179 return bunop(o, new_arg, min(), max());
2180 }
2181 case op::exists:
2182 case op::forall:
2183 {
2184 std::vector<formula> tmp;
2185 unsigned sz = size();
2186 tmp.reserve(sz - 1);
2187 bool changed = false;
2188 for (unsigned i = 0; i < sz - 1; ++i)
2189 {
2190 formula c = (*this)[i];
2191 formula g = trans(c, std::forward<Args>(args)...);
2192 changed |= c != g;
2193 tmp.push_back(g);
2194 }
2195 formula c = (*this)[sz - 1];
2196 formula g = trans(c, std::forward<Args>(args)...);
2197 if (c == g && !changed)
2198 return *this;
2199 return quantify(o, std::move(tmp), g);
2200 }
2201 }
2202 SPOT_UNREACHABLE();
2203 }
2204
2213 template<typename Func, typename... Args>
2214 void traverse(Func func, Args&&... args)
2215 {
2216 if (func(*this, std::forward<Args>(args)...))
2217 return;
2218 for (auto f: *this)
2219 f.traverse(func, std::forward<Args>(args)...);
2220 }
2221
2222#ifndef SWIG
2223 [[noreturn]] static void report_message(const char* message);
2224 private:
2225 [[noreturn]] static void report_ap_invalid_arg();
2226#endif
2227 };
2228
2230 SPOT_API
2231 std::ostream& print_formula_props(std::ostream& out, const formula& f,
2232 bool abbreviated = false);
2233
2235 SPOT_API
2236 std::list<std::string> list_formula_props(const formula& f);
2237
2239 SPOT_API
2240 std::ostream& operator<<(std::ostream& os, const formula& f);
2241}
2242
2243#ifndef SWIG
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
std::ostream & dump(std::ostream &os) const
Print the formula for debugging.
Definition formula.hh:1942
unsigned boolean_count() const
number of Boolean children
Definition formula.hh:1966
bool is_leaf() const
Whether the formula is a leaf.
Definition formula.hh:1759
size_t id() const
Return the id of a formula.
Definition formula.hh:1772
static formula bunop(op o, formula &&f, unsigned min=0U, unsigned max=unbounded())
Define a bounded unary-operator (i.e. star-like)
Definition formula.hh:1470
formula map(Trans trans, Args &&... args)
Clone this node after applying trans to its children.
Definition formula.hh:2101
unsigned apid() const
Get the number of an atomic proposition.
Definition formula.hh:1933
static formula bunop(op o, const formula &f, unsigned min=0U, unsigned max=unbounded())
Define a bounded unary-operator (i.e. star-like)
Definition formula.hh:1462
static formula multop(op o, const formula &f, const formula &g)
Construct an n-ary operator.
Definition formula.hh:1326
static formula G(unsigned min_level, unsigned max_level, const formula &f)
Construct G[n:m].
Definition formula.hh:1145
static formula binop(op o, const formula &f, const formula &g)
Construct a binary operator.
Definition formula.hh:1181
bool is(op o) const
Return true if the formula is of kind o.
Definition formula.hh:1674
static formula multop(op o, std::vector< formula > &&l)
Construct an n-ary operator.
Definition formula.hh:1315
formula(formula &&f) noexcept
Move-construct a formula.
Definition formula.hh:888
formula(const fnode *f) noexcept
Create a formula from an fnode.
Definition formula.hh:858
bool is(op o1, op o2) const
Return true if the formula is of kind o1 or o2.
Definition formula.hh:1681
static formula one_plus()
Return a copy of the formula 1[+].
Definition formula.hh:1900
static formula sugar_delay(const formula &b, unsigned min, unsigned max)
Create the SERE a ##[n:m] b
static formula one_star()
Return a copy of the formula 1[*].
Definition formula.hh:1893
static unsigned apid_count() noexcept
1+maximum APID used by atomic propositions
unsigned min() const
Return start of the range for star-like operators.
Definition formula.hh:1736
static constexpr uint8_t unbounded()
Unbounded constant to use as end of range for bounded operators.
Definition formula.hh:1034
static formula unop(op o, formula &&f)
Build a unary operator.
Definition formula.hh:1067
static formula eword()
Return the empty word constant.
Definition formula.hh:1866
static formula multop(op o, formula &&f, const formula &g)
Construct an n-ary operator.
Definition formula.hh:1337
formula all_but(unsigned i) const
clone this formula, omitting child i
Definition formula.hh:1952
static formula ff()
Return the false constant.
Definition formula.hh:1842
static formula binop(op o, const formula &f, formula &&g)
Construct a binary operator.
Definition formula.hh:1187
const formula & operator=(std::nullptr_t)
Reset a formula to null.
Definition formula.hh:908
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 multop(op o, const std::vector< formula > &l)
Construct an n-ary operator.
Definition formula.hh:1304
unsigned size() const
Return the number of children.
Definition formula.hh:1750
static formula sugar_goto(const formula &b, unsigned min, unsigned max)
Create a SERE equivalent to b[->min..max]
bool is_tt() const
Whether the formula is the true constant.
Definition formula.hh:1860
bool is(op o1, op o2, op o3, op o4) const
Definition formula.hh:1694
std::string kindstr() const
Return the name of the top-most operator.
Definition formula.hh:1668
formula(const formula &f) noexcept
Clone a formula.
Definition formula.hh:880
formula_child_iterator end() const
Allow iterating over children.
Definition formula.hh:1829
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
static formula multop(op o, const formula &f, formula &&g)
Construct an n-ary operator.
Definition formula.hh:1332
static formula ap(const formula &a)
Build an atomic proposition from... an atomic proposition.
Definition formula.hh:1050
formula get_child_of(std::initializer_list< op > l) const
Remove all operators in l and return the child.
Definition formula.hh:1724
bool is_eword() const
Whether the formula is the empty word constant.
Definition formula.hh:1872
static formula sugar_delay(const formula &a, const formula &b, unsigned min, unsigned max)
Create the SERE a ##[n:m] b
void traverse(Func func, Args &&... args)
Apply func to each subformula.
Definition formula.hh:2214
static formula F(unsigned min_level, unsigned max_level, const formula &f)
Construct F[n:m].
Definition formula.hh:1134
formula(std::nullptr_t) noexcept
Create a null formula.
Definition formula.hh:868
static formula ap(const std::string &name)
Build an atomic proposition.
Definition formula.hh:1040
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
unsigned max() const
Return end of the range for star-like operators.
Definition formula.hh:1744
static formula X(unsigned level, const formula &f)
Construct an X[n].
Definition formula.hh:1104
bool is_ff() const
Whether the formula is the false constant.
Definition formula.hh:1848
static formula multop(op o, formula &&f, formula &&g)
Construct an n-ary operator.
Definition formula.hh:1342
formula_child_iterator begin() const
Allow iterating over children.
Definition formula.hh:1823
bool is_constant() const
Whether the formula is op::ff, op::tt, or op::eword.
Definition formula.hh:1878
~formula()
Destroy a formula.
Definition formula.hh:895
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_Kleene_star() const
Test whether the formula represent a Kleene star.
Definition formula.hh:1887
static formula binop(op o, formula &&f, const formula &g)
Construct a binary operator.
Definition formula.hh:1192
bool is_literal() const
Whether the formula is an atomic proposition or its negation.
Definition formula.hh:1908
static formula tt()
Return the true constant.
Definition formula.hh:1854
formula() noexcept
Default initialize a formula to nullptr.
Definition formula.hh:874
static formula sugar_equal(const formula &b, unsigned min, unsigned max)
Create the SERE b[=min..max]
static formula unop(op o, const formula &f)
Build a unary operator.
Definition formula.hh:1061
formula boolean_operands(unsigned *width=nullptr) const
return a clone of the current node, restricted to its Boolean children
Definition formula.hh:1984
static const formula nested_unop_range(op uo, op bo, unsigned min, unsigned max, formula f)
Nested operator construction (syntactic sugar).
Definition formula.hh:1595
op
Operator types.
Definition formula.hh:79
@ X
Next.
@ first_match
first_match(sere)
@ EConcatMarked
Seq, Marked.
@ Star
Star.
@ UConcat
Triggers.
@ Or
(omega-Rational) Or
@ Equiv
Equivalence.
@ NegClosure
Negated PSL Closure.
@ U
until
@ EConcat
Seq.
@ FStar
Fustion Star.
@ W
weak until
@ ap
Atomic proposition.
@ ff
False.
@ M
strong release (dual of weak until)
@ NegClosureMarked
marked version of the Negated PSL Closure
@ strong_X
strong Next
@ Xor
Exclusive Or.
@ F
Eventually.
@ OrRat
Rational Or.
@ Not
Negation.
@ tt
True.
@ Fusion
Fusion.
@ Closure
PSL Closure.
@ forall
universal quantification of AP
@ And
(omega-Rational) And
@ AndNLM
Non-Length-Matching Rational-And.
@ eword
Empty word.
@ AndRat
Rational And.
@ G
Globally.
@ exists
existential quantification of AP
@ R
release (dual of until)
@ Concat
Concatenation.
@ Implies
Implication.
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 Fri Feb 27 2015 10:00:07 for spot by doxygen 1.9.8