spot 2.14
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
70namespace spot
71{
72
73
76 enum class op: uint8_t
77 {
78 ff,
79 tt,
80 eword,
81 ap,
82 // unary operators
83 Not,
84 X,
85 F,
86 G,
87 Closure,
90 // binary operators
91 Xor,
92 Implies,
93 Equiv,
94 U,
95 R,
96 W,
97 M,
98 EConcat,
100 UConcat,
101 // n-ary operators
102 Or,
103 OrRat,
104 And,
105 AndRat,
106 AndNLM,
107 Concat,
108 Fusion,
109 // star-like operators
110 Star,
111 FStar,
113 // strong_X was introduced in Spot 2.9, but was hidden from the
114 // public API by default in order not to break existing code.
115 //
116 // Starting with Spot 2.13, strong_X will be part of the public
117 // API by default. If you have a switch case listing all possible
118 // operators, strong_X needs to be part of it. If you have code
119 // using Spot but that you also want to support versions older
120 // than 2.13, there are two ways to do that
121 //
122 // Option 1: define SPOT_USES_STRONG_X before including this file.
123 //
124 // #define SPOT_USES_STRONG_X 1
125 // #include <spot/tl/formula.hh>
126 //
127 // This will force any version of Spot since 2.9 to define
128 // strong_X. It won't work with older Spot versions, where
129 // strong_X did not exist.
130 //
131 // Option 2: make any code using strong_X conditional on
132 // SPOT_HAS_STRONG_X. Typically, a switch over all possible
133 // operators would include something like this:
134 //
135 // #if SPOT_HAS_STRONG_X
136 // case op::strong_X:
137 // /* do something */
138 // #endif
139 //
140 // The two options are not mutually exclusive. Using both allows
141 // you to use strong_X whenever it exists.
142 strong_X,
143 };
144
145#ifndef SWIG
152 class SPOT_API fnode final
153 {
154 public:
159 const fnode* clone() const
160 {
161 // Saturate.
162 ++refs_;
163 if (SPOT_UNLIKELY(!refs_))
164 saturated_ = 1;
165 return this;
166 }
167
173 void destroy() const
174 {
175 if (SPOT_LIKELY(refs_))
176 --refs_;
177 else if (SPOT_LIKELY(!saturated_))
178 // last reference to a node that is not a constant
179 destroy_aux();
180 }
181
183 static constexpr uint8_t unbounded()
184 {
185 return UINT8_MAX;
186 }
187
189 static const fnode* ap(const std::string& name);
191 static const fnode* unop(op o, const fnode* f);
193 static const fnode* binop(op o, const fnode* f, const fnode* g);
195 static const fnode* multop(op o, std::vector<const fnode*> l);
197 static const fnode* bunop(op o, const fnode* f,
198 unsigned min, unsigned max = unbounded());
199
201 static const fnode* nested_unop_range(op uo, op bo, unsigned min,
202 unsigned max, const fnode* f);
203
205 op kind() const
206 {
207 return op_;
208 }
209
211 std::string kindstr() const;
212
215 bool is(op o) const
216 {
217 return op_ == o;
218 }
219
220 bool is(op o1, op o2) const
221 {
222 return op_ == o1 || op_ == o2;
223 }
224
225 bool is(op o1, op o2, op o3) const
226 {
227 return op_ == o1 || op_ == o2 || op_ == o3;
228 }
229
230 bool is(op o1, op o2, op o3, op o4) const
231 {
232 return op_ == o1 || op_ == o2 || op_ == o3 || op_ == o4;
233 }
234
235 bool is(std::initializer_list<op> l) const
236 {
237 const fnode* n = this;
238 for (auto o: l)
239 {
240 if (!n->is(o))
241 return false;
242 n = n->nth(0);
243 }
244 return true;
245 }
247
249 const fnode* get_child_of(op o) const
250 {
251 if (op_ != o)
252 return nullptr;
253 if (SPOT_UNLIKELY(size_ != 1))
254 report_get_child_of_expecting_single_child_node();
255 return nth(0);
256 }
257
259 const fnode* get_child_of(std::initializer_list<op> l) const
260 {
261 auto c = this;
262 for (auto o: l)
263 {
264 c = c->get_child_of(o);
265 if (c == nullptr)
266 return c;
267 }
268 return c;
269 }
270
272 unsigned min() const
273 {
274 if (SPOT_UNLIKELY(op_ != op::FStar && op_ != op::Star))
275 report_min_invalid_arg();
276 return min_;
277 }
278
280 unsigned max() const
281 {
282 if (SPOT_UNLIKELY(op_ != op::FStar && op_ != op::Star))
283 report_max_invalid_arg();
284 return max_;
285 }
286
288 unsigned size() const
289 {
290 return size_;
291 }
292
294 bool is_leaf() const
295 {
296 return size_ == 0;
297 }
298
300 size_t id() const
301 {
302 return id_;
303 }
304
306 const fnode*const* begin() const
307 {
308 return children;
309 }
310
312 const fnode*const* end() const
313 {
314 return children + size();
315 }
316
318 const fnode* nth(unsigned i) const
319 {
320 if (SPOT_UNLIKELY(i >= size()))
321 report_non_existing_child();
322 const fnode* c = children[i];
323 SPOT_ASSUME(c != nullptr);
324 return c;
325 }
326
328 static const fnode* ff()
329 {
330 return ff_;
331 }
332
334 bool is_ff() const
335 {
336 return op_ == op::ff;
337 }
338
340 static const fnode* tt()
341 {
342 return tt_;
343 }
344
346 bool is_tt() const
347 {
348 return op_ == op::tt;
349 }
350
352 static const fnode* eword()
353 {
354 return ew_;
355 }
356
358 bool is_eword() const
359 {
360 return op_ == op::eword;
361 }
362
364 bool is_constant() const
365 {
366 return op_ == op::ff || op_ == op::tt || op_ == op::eword;
367 }
368
370 bool is_Kleene_star() const
371 {
372 if (op_ != op::Star)
373 return false;
374 return min_ == 0 && max_ == unbounded();
375 }
376
378 static const fnode* one_star()
379 {
380 if (!one_star_)
381 one_star_ = new fnode(op::Star, tt_, 0, unbounded(), true);
382 return one_star_;
383 }
384
386 static const fnode* one_plus()
387 {
388 if (!one_plus_)
389 one_plus_ = new fnode(op::Star, tt_, 1, unbounded(), true);
390 return one_plus_;
391 }
392
394 const std::string& ap_name() const;
395
397 std::ostream& dump(std::ostream& os) const;
398
400 const fnode* all_but(unsigned i) const;
401
403 unsigned boolean_count() const
404 {
405 unsigned pos = 0;
406 unsigned s = size();
407 while (pos < s && children[pos]->is_boolean())
408 ++pos;
409 return pos;
410 }
411
413 const fnode* boolean_operands(unsigned* width = nullptr) const;
414
425 static bool instances_check();
426
428 // Properties //
430
432 bool is_boolean() const
433 {
434 return is_.boolean;
435 }
436
439 {
440 return is_.sugar_free_boolean;
441 }
442
444 bool is_in_nenoform() const
445 {
446 return is_.in_nenoform;
447 }
448
451 {
452 return is_.syntactic_si;
453 }
454
456 bool is_sugar_free_ltl() const
457 {
458 return is_.sugar_free_ltl;
459 }
460
462 bool is_ltl_formula() const
463 {
464 return is_.ltl_formula;
465 }
466
468 bool is_psl_formula() const
469 {
470 return is_.psl_formula;
471 }
472
474 bool is_sere_formula() const
475 {
476 return is_.sere_formula;
477 }
478
480 bool is_finite() const
481 {
482 return is_.finite;
483 }
484
486 bool is_eventual() const
487 {
488 return is_.eventual;
489 }
490
492 bool is_universal() const
493 {
494 return is_.universal;
495 }
496
499 {
500 return is_.syntactic_safety;
501 }
502
505 {
506 return is_.syntactic_guarantee;
507 }
508
511 {
512 return is_.syntactic_obligation;
513 }
514
517 {
518 return is_.syntactic_recurrence;
519 }
520
523 {
524 return is_.syntactic_persistence;
525 }
526
528 bool is_marked() const
529 {
530 return !is_.not_marked;
531 }
532
534 bool accepts_eword() const
535 {
536 return is_.accepting_eword;
537 }
538
541 {
542 return is_.lbt_atomic_props;
543 }
544
547 {
548 return is_.spin_atomic_props;
549 }
550
552 bool is_sigma2() const
553 {
554 return is_.sigma2;
555 }
556
558 bool is_pi2() const
559 {
560 return is_.pi2;
561 }
562
564 bool is_delta1() const
565 {
566 return is_.delta1;
567 }
568
570 bool is_delta2() const
571 {
572 return is_.delta2;
573 }
574
575 private:
576 static size_t bump_next_id();
577 void setup_props(op o);
578 void destroy_aux() const;
579
580 [[noreturn]] static void report_non_existing_child();
581 [[noreturn]] static void report_too_many_children();
582 [[noreturn]] static void
583 report_get_child_of_expecting_single_child_node();
584 [[noreturn]] static void report_min_invalid_arg();
585 [[noreturn]] static void report_max_invalid_arg();
586
587 static const fnode* unique(fnode*);
588
589 // Destruction may only happen via destroy().
590 ~fnode() = default;
591 // Disallow copies.
592 fnode(const fnode&) = delete;
593 fnode& operator=(const fnode&) = delete;
594
595
596
597 template<class iter>
598 fnode(op o, iter begin, iter end, bool saturated = false)
599 // Clang has some optimization where is it able to combine the
600 // 4 movb initializing op_,min_,max_,saturated_ into a single
601 // movl. Also it can optimize the three byte-comparisons of
602 // is_Kleene_star() into a single masked 32-bit comparison.
603 // The latter optimization triggers warnings from valgrind if
604 // min_ and max_ are not initialized. So to benefit from the
605 // initialization optimization and the is_Kleene_star()
606 // optimization in Clang, we always initialize min_ and max_
607 // with this compiler. Do not do it the rest of the time,
608 // since the optimization is not done.
609 : op_(o),
610#if __llvm__
611 min_(0), max_(0),
612#endif
613 saturated_(saturated)
614 {
615 size_t s = std::distance(begin, end);
616 if (SPOT_UNLIKELY(s > (size_t) UINT16_MAX))
617 report_too_many_children();
618 size_ = s;
619 auto pos = children;
620 for (auto i = begin; i != end; ++i)
621 *pos++ = *i;
622 setup_props(o);
623 }
624
625 fnode(op o, std::initializer_list<const fnode*> l,
626 bool saturated = false)
627 : fnode(o, l.begin(), l.end(), saturated)
628 {
629 }
630
631 fnode(op o, const fnode* f, uint8_t min, uint8_t max,
632 bool saturated = false)
633 : op_(o), min_(min), max_(max), saturated_(saturated), size_(1)
634 {
635 children[0] = f;
636 setup_props(o);
637 }
638
639 static const fnode* ff_;
640 static const fnode* tt_;
641 static const fnode* ew_;
642 static const fnode* one_star_;
643 static const fnode* one_plus_;
644
645 op op_; // operator
646 uint8_t min_; // range minimum (for star-like operators)
647 uint8_t max_; // range maximum;
648 mutable uint8_t saturated_;
649 uint16_t size_; // number of children
650 mutable uint16_t refs_ = 0; // reference count - 1;
651 size_t id_; // Also used as hash.
652 static size_t next_id_;
653
654 struct ltl_prop
655 {
656 // All properties here should be expressed in such a a way
657 // that property(f && g) is just property(f)&property(g).
658 // This allows us to compute all properties of a compound
659 // formula in one operation.
660 //
661 // For instance we do not use a property that says "has
662 // temporal operator", because it would require an OR between
663 // the two arguments. Instead we have a property that
664 // says "no temporal operator", and that one is computed
665 // with an AND between the arguments.
666 //
667 // Also choose a name that makes sense when prefixed with
668 // "the formula is".
669 bool boolean:1; // No temporal operators.
670 bool sugar_free_boolean:1; // Only AND, OR, and NOT operators.
671 bool in_nenoform:1; // Negative Normal Form.
672 bool syntactic_si:1; // LTL-X or siPSL
673 bool sugar_free_ltl:1; // No F and G operators.
674 bool ltl_formula:1; // Only LTL operators.
675 bool psl_formula:1; // Only PSL operators.
676 bool sere_formula:1; // Only SERE operators.
677 bool finite:1; // Finite SERE formulae, or Bool+X forms.
678 bool eventual:1; // Purely eventual formula.
679 bool universal:1; // Purely universal formula.
680 bool syntactic_safety:1; // Syntactic Safety Property (S).
681 bool syntactic_guarantee:1; // Syntactic Guarantee Property (G).
682 bool syntactic_obligation:1; // Syntactic Obligation Property (O).
683 bool syntactic_recurrence:1; // Syntactic Recurrence Property (R).
684 bool syntactic_persistence:1; // Syntactic Persistence Property (P).
685 bool not_marked:1; // No occurrence of EConcatMarked.
686 bool accepting_eword:1; // Accepts the empty word.
687 bool lbt_atomic_props:1; // Use only atomic propositions like p42.
688 bool spin_atomic_props:1; // Use only spin-compatible atomic props.
689 bool delta1:1; // Boolean combination of (S) and (G).
690 bool sigma2:1; // Boolean comb. of (S) with X/F/U/M possibly applied.
691 bool pi2:1; // Boolean comb. of (G) with X/G/R/W possibly applied.
692 bool delta2:1; // Boolean combination of (Σ₂) and (Π₂).
693 };
694 union
695 {
696 // Use an unsigned for fast computation of all properties.
697 unsigned props;
698 ltl_prop is_;
699 };
700
701 const fnode* children[1];
702 };
703
705 SPOT_API
706 int atomic_prop_cmp(const fnode* f, const fnode* g);
707
708 class SPOT_API formula;
709
711 {
712 bool
713 operator()(const fnode* left, const fnode* right) const
714 {
715 SPOT_ASSERT(left);
716 SPOT_ASSERT(right);
717 if (left == right)
718 return false;
719
720 // We want Boolean formulae first.
721 bool lib = left->is_boolean();
722 if (lib != right->is_boolean())
723 return lib;
724
725 // We have two Boolean formulae
726 if (lib)
727 {
728 bool lconst = left->is_constant();
729 if (lconst != right->is_constant())
730 return lconst;
731 if (!lconst)
732 {
733 auto get_literal = [](const fnode* f) -> const fnode*
734 {
735 if (f->is(op::Not))
736 f = f->nth(0);
737 if (f->is(op::ap))
738 return f;
739 return nullptr;
740 };
741 // Literals should come first
742 const fnode* litl = get_literal(left);
743 const fnode* litr = get_literal(right);
744 if (!litl != !litr)
745 return litl;
746 if (litl)
747 {
748 // And they should be sorted alphabetically
749 int cmp = atomic_prop_cmp(litl, litr);
750 if (cmp)
751 return cmp < 0;
752 }
753 }
754 }
755
756 size_t l = left->id();
757 size_t r = right->id();
758 if (l != r)
759 return l < r;
760 // Because the hash code assigned to each formula is the
761 // number of formulae constructed so far, it is very unlikely
762 // that we will ever reach a case were two different formulae
763 // have the same hash. This will happen only ever with have
764 // produced 256**sizeof(size_t) formulae (i.e. max_count has
765 // looped back to 0 and started over). In that case we can
766 // order two formulas by looking at their text representation.
767 // We could be more efficient and look at their AST, but it's
768 // not worth the burden. (Also ordering pointers is ruled out
769 // because it breaks the determinism of the implementation.)
770 std::ostringstream old;
771 left->dump(old);
772 std::ostringstream ord;
773 right->dump(ord);
774 return old.str() < ord.str();
775 }
776
777 SPOT_API bool
778 operator()(const formula& left, const formula& right) const;
779};
780
781#endif // SWIG
782
785 class SPOT_API formula final
786 {
788 const fnode* ptr_;
789 public:
794 explicit formula(const fnode* f) noexcept
795 : ptr_(f)
796 {
797 }
798
804 formula(std::nullptr_t) noexcept
805 : ptr_(nullptr)
806 {
807 }
808
810 formula() noexcept
811 : ptr_(nullptr)
812 {
813 }
814
816 formula(const formula& f) noexcept
817 : ptr_(f.ptr_)
818 {
819 if (ptr_)
820 ptr_->clone();
821 }
822
824 formula(formula&& f) noexcept
825 : ptr_(f.ptr_)
826 {
827 f.ptr_ = nullptr;
828 }
829
832 {
833 if (ptr_)
834 ptr_->destroy();
835 }
836
844 const formula& operator=(std::nullptr_t)
845 {
846 this->~formula();
847 ptr_ = nullptr;
848 return *this;
849 }
850
851 const formula& operator=(const formula& f)
852 {
853 this->~formula();
854 if ((ptr_ = f.ptr_))
855 ptr_->clone();
856 return *this;
857 }
858
859 const formula& operator=(formula&& f) noexcept
860 {
861 std::swap(f.ptr_, ptr_);
862 return *this;
863 }
864
865 bool operator<(const formula& other) const noexcept
866 {
867 if (SPOT_UNLIKELY(!other.ptr_))
868 return false;
869 if (SPOT_UNLIKELY(!ptr_))
870 return true;
871 if (id() < other.id())
872 return true;
873 if (id() > other.id())
874 return false;
875 // The case where id()==other.id() but ptr_ != other.ptr_ is
876 // very unlikely (we would need to build more than UINT_MAX
877 // formulas), so let's just compare pointers, and ignore the
878 // fact that it may introduce some nondeterminism.
879 return ptr_ < other.ptr_;
880 }
881
882 bool operator<=(const formula& other) const noexcept
883 {
884 return *this == other || *this < other;
885 }
886
887 bool operator>(const formula& other) const noexcept
888 {
889 return !(*this <= other);
890 }
891
892 bool operator>=(const formula& other) const noexcept
893 {
894 return !(*this < other);
895 }
896
897 bool operator==(const formula& other) const noexcept
898 {
899 return other.ptr_ == ptr_;
900 }
901
902 bool operator==(std::nullptr_t) const noexcept
903 {
904 return ptr_ == nullptr;
905 }
906
907 bool operator!=(const formula& other) const noexcept
908 {
909 return other.ptr_ != ptr_;
910 }
911
912 bool operator!=(std::nullptr_t) const noexcept
913 {
914 return ptr_ != nullptr;
915 }
916
917 explicit operator bool() const noexcept
918 {
919 return ptr_ != nullptr;
920 }
921
923 // Forwarded functions //
925
927 static constexpr uint8_t unbounded()
928 {
929 return fnode::unbounded();
930 }
931
933 static formula ap(const std::string& name)
934 {
935 return formula(fnode::ap(name));
936 }
937
943 static formula ap(const formula& a)
944 {
945 if (SPOT_UNLIKELY(a.kind() != op::ap))
946 report_ap_invalid_arg();
947 return a;
948 }
949
954 static formula unop(op o, const formula& f)
955 {
956 return formula(fnode::unop(o, f.ptr_->clone()));
957 }
958
959#ifndef SWIG
960 static formula unop(op o, formula&& f)
961 {
962 return formula(fnode::unop(o, f.to_node_()));
963 }
964#endif // !SWIG
966
967#ifdef SWIG
968#define SPOT_DEF_UNOP(Name) \
969 static formula Name(const formula& f) \
970 { \
971 return unop(op::Name, f); \
972 }
973#else // !SWIG
974#define SPOT_DEF_UNOP(Name) \
975 static formula Name(const formula& f) \
976 { \
977 return unop(op::Name, f); \
978 } \
979 static formula Name(formula&& f) \
980 { \
981 return unop(op::Name, std::move(f)); \
982 }
983#endif // !SWIG
986 SPOT_DEF_UNOP(Not);
988
991 SPOT_DEF_UNOP(X);
993
997 static formula X(unsigned level, const formula& f)
998 {
999 return nested_unop_range(op::X, op::Or /* unused */, level, level, f);
1000 }
1001
1004 SPOT_DEF_UNOP(strong_X);
1006
1010 static formula strong_X(unsigned level, const formula& f)
1011 {
1012 return nested_unop_range(op::strong_X, op::Or /* unused */,
1013 level, level, f);
1014 }
1015
1018 SPOT_DEF_UNOP(F);
1020
1027 static formula F(unsigned min_level, unsigned max_level, const formula& f)
1028 {
1029 return nested_unop_range(op::X, op::Or, min_level, max_level, f);
1030 }
1031
1038 static formula G(unsigned min_level, unsigned max_level, const formula& f)
1039 {
1040 return nested_unop_range(op::X, op::And, min_level, max_level, f);
1041 }
1042
1045 SPOT_DEF_UNOP(G);
1047
1050 SPOT_DEF_UNOP(Closure);
1052
1055 SPOT_DEF_UNOP(NegClosure);
1057
1060 SPOT_DEF_UNOP(NegClosureMarked);
1062
1065 SPOT_DEF_UNOP(first_match);
1067#undef SPOT_DEF_UNOP
1068
1074 static formula binop(op o, const formula& f, const formula& g)
1075 {
1076 return formula(fnode::binop(o, f.ptr_->clone(), g.ptr_->clone()));
1077 }
1078
1079#ifndef SWIG
1080 static formula binop(op o, const formula& f, formula&& g)
1081 {
1082 return formula(fnode::binop(o, f.ptr_->clone(), g.to_node_()));
1083 }
1084
1085 static formula binop(op o, formula&& f, const formula& g)
1086 {
1087 return formula(fnode::binop(o, f.to_node_(), g.ptr_->clone()));
1088 }
1089
1090 static formula binop(op o, formula&& f, formula&& g)
1091 {
1092 return formula(fnode::binop(o, f.to_node_(), g.to_node_()));
1093 }
1095
1096#endif //SWIG
1097
1098#ifdef SWIG
1099#define SPOT_DEF_BINOP(Name) \
1100 static formula Name(const formula& f, const formula& g) \
1101 { \
1102 return binop(op::Name, f, g); \
1103 }
1104#else // !SWIG
1105#define SPOT_DEF_BINOP(Name) \
1106 static formula Name(const formula& f, const formula& g) \
1107 { \
1108 return binop(op::Name, f, g); \
1109 } \
1110 static formula Name(const formula& f, formula&& g) \
1111 { \
1112 return binop(op::Name, f, std::move(g)); \
1113 } \
1114 static formula Name(formula&& f, const formula& g) \
1115 { \
1116 return binop(op::Name, std::move(f), g); \
1117 } \
1118 static formula Name(formula&& f, formula&& g) \
1119 { \
1120 return binop(op::Name, std::move(f), std::move(g)); \
1121 }
1122#endif // !SWIG
1125 SPOT_DEF_BINOP(Xor);
1127
1130 SPOT_DEF_BINOP(Implies);
1132
1135 SPOT_DEF_BINOP(Equiv);
1137
1140 SPOT_DEF_BINOP(U);
1142
1145 SPOT_DEF_BINOP(R);
1147
1150 SPOT_DEF_BINOP(W);
1152
1155 SPOT_DEF_BINOP(M);
1157
1160 SPOT_DEF_BINOP(EConcat);
1162
1165 SPOT_DEF_BINOP(EConcatMarked);
1167
1170 SPOT_DEF_BINOP(UConcat);
1172#undef SPOT_DEF_BINOP
1173
1179 static formula multop(op o, const std::vector<formula>& l)
1180 {
1181 std::vector<const fnode*> tmp;
1182 tmp.reserve(l.size());
1183 for (auto f: l)
1184 if (f.ptr_)
1185 tmp.emplace_back(f.ptr_->clone());
1186 return formula(fnode::multop(o, std::move(tmp)));
1187 }
1188
1189#ifndef SWIG
1190 static formula multop(op o, std::vector<formula>&& l)
1191 {
1192 std::vector<const fnode*> tmp;
1193 tmp.reserve(l.size());
1194 for (auto f: l)
1195 if (f.ptr_)
1196 tmp.emplace_back(f.to_node_());
1197 return formula(fnode::multop(o, std::move(tmp)));
1198 }
1199#endif // !SWIG
1201
1202#ifdef SWIG
1203#define SPOT_DEF_MULTOP(Name) \
1204 static formula Name(const std::vector<formula>& l) \
1205 { \
1206 return multop(op::Name, l); \
1207 }
1208#else // !SWIG
1209#define SPOT_DEF_MULTOP(Name) \
1210 static formula Name(const std::vector<formula>& l) \
1211 { \
1212 return multop(op::Name, l); \
1213 } \
1214 \
1215 static formula Name(std::vector<formula>&& l) \
1216 { \
1217 return multop(op::Name, std::move(l)); \
1218 }
1219#endif // !SWIG
1222 SPOT_DEF_MULTOP(Or);
1224
1227 SPOT_DEF_MULTOP(OrRat);
1229
1232 SPOT_DEF_MULTOP(And);
1234
1237 SPOT_DEF_MULTOP(AndRat);
1239
1242 SPOT_DEF_MULTOP(AndNLM);
1244
1247 SPOT_DEF_MULTOP(Concat);
1249
1252 SPOT_DEF_MULTOP(Fusion);
1254#undef SPOT_DEF_MULTOP
1255
1260 static formula bunop(op o, const formula& f,
1261 unsigned min = 0U,
1262 unsigned max = unbounded())
1263 {
1264 return formula(fnode::bunop(o, f.ptr_->clone(), min, max));
1265 }
1266
1267#ifndef SWIG
1268 static formula bunop(op o, formula&& f,
1269 unsigned min = 0U,
1270 unsigned max = unbounded())
1271 {
1272 return formula(fnode::bunop(o, f.to_node_(), min, max));
1273 }
1274#endif // !SWIG
1276
1277#if SWIG
1278#define SPOT_DEF_BUNOP(Name) \
1279 static formula Name(const formula& f, \
1280 unsigned min = 0U, \
1281 unsigned max = unbounded()) \
1282 { \
1283 return bunop(op::Name, f, min, max); \
1284 }
1285#else // !SWIG
1286#define SPOT_DEF_BUNOP(Name) \
1287 static formula Name(const formula& f, \
1288 unsigned min = 0U, \
1289 unsigned max = unbounded()) \
1290 { \
1291 return bunop(op::Name, f, min, max); \
1292 } \
1293 static formula Name(formula&& f, \
1294 unsigned min = 0U, \
1295 unsigned max = unbounded()) \
1296 { \
1297 return bunop(op::Name, std::move(f), min, max); \
1298 }
1299#endif
1302 SPOT_DEF_BUNOP(Star);
1304
1310 SPOT_DEF_BUNOP(FStar);
1312#undef SPOT_DEF_BUNOP
1313
1325 static const formula nested_unop_range(op uo, op bo, unsigned min,
1326 unsigned max, formula f)
1327 {
1328 return formula(fnode::nested_unop_range(uo, bo, min, max,
1329 f.ptr_->clone()));
1330 }
1331
1337 static formula sugar_goto(const formula& b, unsigned min, unsigned max);
1338
1344 static formula sugar_equal(const formula& b, unsigned min, unsigned max);
1345
1367 static formula sugar_delay(const formula& a, const formula& b,
1368 unsigned min, unsigned max);
1369 static formula sugar_delay(const formula& b,
1370 unsigned min, unsigned max);
1372
1373#ifndef SWIG
1384 {
1385 auto tmp = ptr_;
1386 ptr_ = nullptr;
1387 return tmp;
1388 }
1389#endif
1390
1392 op kind() const
1393 {
1394 return ptr_->kind();
1395 }
1396
1398 std::string kindstr() const
1399 {
1400 return ptr_->kindstr();
1401 }
1402
1404 bool is(op o) const
1405 {
1406 return ptr_->is(o);
1407 }
1408
1409#ifndef SWIG
1411 bool is(op o1, op o2) const
1412 {
1413 return ptr_->is(o1, o2);
1414 }
1415
1417 bool is(op o1, op o2, op o3) const
1418 {
1419 return ptr_->is(o1, o2, o3);
1420 }
1421
1424 bool is(op o1, op o2, op o3, op o4) const
1425 {
1426 return ptr_->is(o1, o2, o3, o4);
1427 }
1428
1430 bool is(std::initializer_list<op> l) const
1431 {
1432 return ptr_->is(l);
1433 }
1434#endif
1435
1440 {
1441 auto f = ptr_->get_child_of(o);
1442 if (f)
1443 f->clone();
1444 return formula(f);
1445 }
1446
1447#ifndef SWIG
1454 formula get_child_of(std::initializer_list<op> l) const
1455 {
1456 auto f = ptr_->get_child_of(l);
1457 if (f)
1458 f->clone();
1459 return formula(f);
1460 }
1461#endif
1462
1466 unsigned min() const
1467 {
1468 return ptr_->min();
1469 }
1470
1474 unsigned max() const
1475 {
1476 return ptr_->max();
1477 }
1478
1480 unsigned size() const
1481 {
1482 return ptr_->size();
1483 }
1484
1489 bool is_leaf() const
1490 {
1491 return ptr_->is_leaf();
1492 }
1493
1502 size_t id() const
1503 {
1504 return ptr_->id();
1505 }
1506
1507#ifndef SWIG
1509 class SPOT_API formula_child_iterator final
1510 {
1511 const fnode*const* ptr_;
1512 public:
1514 : ptr_(nullptr)
1515 {
1516 }
1517
1518 formula_child_iterator(const fnode*const* f)
1519 : ptr_(f)
1520 {
1521 }
1522
1523 bool operator==(formula_child_iterator o)
1524 {
1525 return ptr_ == o.ptr_;
1526 }
1527
1528 bool operator!=(formula_child_iterator o)
1529 {
1530 return ptr_ != o.ptr_;
1531 }
1532
1533 formula operator*()
1534 {
1535 return formula((*ptr_)->clone());
1536 }
1537
1538 formula_child_iterator operator++()
1539 {
1540 ++ptr_;
1541 return *this;
1542 }
1543
1544 formula_child_iterator operator++(int)
1545 {
1546 auto tmp = *this;
1547 ++ptr_;
1548 return tmp;
1549 }
1550 };
1551
1554 {
1555 return ptr_->begin();
1556 }
1557
1560 {
1561 return ptr_->end();
1562 }
1563
1565 formula operator[](unsigned i) const
1566 {
1567 return formula(ptr_->nth(i)->clone());
1568 }
1569#endif
1570
1572 static formula ff()
1573 {
1574 return formula(fnode::ff());
1575 }
1576
1578 bool is_ff() const
1579 {
1580 return ptr_->is_ff();
1581 }
1582
1584 static formula tt()
1585 {
1586 return formula(fnode::tt());
1587 }
1588
1590 bool is_tt() const
1591 {
1592 return ptr_->is_tt();
1593 }
1594
1597 {
1598 return formula(fnode::eword());
1599 }
1600
1602 bool is_eword() const
1603 {
1604 return ptr_->is_eword();
1605 }
1606
1608 bool is_constant() const
1609 {
1610 return ptr_->is_constant();
1611 }
1612
1617 bool is_Kleene_star() const
1618 {
1619 return ptr_->is_Kleene_star();
1620 }
1621
1624 {
1625 // no need to clone, 1[*] is not reference counted
1626 return formula(fnode::one_star());
1627 }
1628
1631 {
1632 // no need to clone, 1[+] is not reference counted
1633 return formula(fnode::one_plus());
1634 }
1635
1638 bool is_literal() const
1639 {
1640 return (is(op::ap) ||
1641 // If f is in nenoform, Not can only occur in front of
1642 // an atomic proposition. So this way we do not have
1643 // to check the type of the child.
1644 (is(op::Not) && is_boolean() && is_in_nenoform()));
1645 }
1646
1650 const std::string& ap_name() const
1651 {
1652 return ptr_->ap_name();
1653 }
1654
1659 std::ostream& dump(std::ostream& os) const
1660 {
1661 return ptr_->dump(os);
1662 }
1663
1669 formula all_but(unsigned i) const
1670 {
1671 return formula(ptr_->all_but(i));
1672 }
1673
1683 unsigned boolean_count() const
1684 {
1685 return ptr_->boolean_count();
1686 }
1687
1701 formula boolean_operands(unsigned* width = nullptr) const
1702 {
1703 return formula(ptr_->boolean_operands(width));
1704 }
1705
1706#define SPOT_DEF_PROP(Name) \
1707 bool Name() const \
1708 { \
1709 return ptr_->Name(); \
1710 }
1712 // Properties //
1714
1716 SPOT_DEF_PROP(is_boolean);
1718 SPOT_DEF_PROP(is_sugar_free_boolean);
1723 SPOT_DEF_PROP(is_in_nenoform);
1725 SPOT_DEF_PROP(is_syntactic_stutter_invariant);
1727 SPOT_DEF_PROP(is_sugar_free_ltl);
1729 SPOT_DEF_PROP(is_ltl_formula);
1731 SPOT_DEF_PROP(is_psl_formula);
1733 SPOT_DEF_PROP(is_sere_formula);
1736 SPOT_DEF_PROP(is_finite);
1744 SPOT_DEF_PROP(is_eventual);
1752 SPOT_DEF_PROP(is_universal);
1756 SPOT_DEF_PROP(is_syntactic_safety);
1760 SPOT_DEF_PROP(is_syntactic_guarantee);
1765 SPOT_DEF_PROP(is_delta1);
1770 SPOT_DEF_PROP(is_syntactic_obligation);
1772 SPOT_DEF_PROP(is_sigma2);
1774 SPOT_DEF_PROP(is_pi2);
1779 SPOT_DEF_PROP(is_syntactic_recurrence);
1784 SPOT_DEF_PROP(is_syntactic_persistence);
1789 SPOT_DEF_PROP(is_delta2);
1792 SPOT_DEF_PROP(is_marked);
1794 SPOT_DEF_PROP(accepts_eword);
1800 SPOT_DEF_PROP(has_lbt_atomic_props);
1809 SPOT_DEF_PROP(has_spin_atomic_props);
1810#undef SPOT_DEF_PROP
1811
1815 template<typename Trans, typename... Args>
1816 formula map(Trans trans, Args&&... args)
1817 {
1818 switch (op o = kind())
1819 {
1820 case op::ff:
1821 case op::tt:
1822 case op::eword:
1823 case op::ap:
1824 return *this;
1825 case op::Not:
1826 case op::X:
1827#if SPOT_HAS_STRONG_X
1828 case op::strong_X:
1829#endif
1830 case op::F:
1831 case op::G:
1832 case op::Closure:
1833 case op::NegClosure:
1835 case op::first_match:
1836 return unop(o, trans((*this)[0], std::forward<Args>(args)...));
1837 case op::Xor:
1838 case op::Implies:
1839 case op::Equiv:
1840 case op::U:
1841 case op::R:
1842 case op::W:
1843 case op::M:
1844 case op::EConcat:
1845 case op::EConcatMarked:
1846 case op::UConcat:
1847 {
1848 formula tmp = trans((*this)[0], std::forward<Args>(args)...);
1849 return binop(o, tmp,
1850 trans((*this)[1], std::forward<Args>(args)...));
1851 }
1852 case op::Or:
1853 case op::OrRat:
1854 case op::And:
1855 case op::AndRat:
1856 case op::AndNLM:
1857 case op::Concat:
1858 case op::Fusion:
1859 {
1860 std::vector<formula> tmp;
1861 tmp.reserve(size());
1862 for (auto f: *this)
1863 tmp.emplace_back(trans(f, std::forward<Args>(args)...));
1864 return multop(o, std::move(tmp));
1865 }
1866 case op::Star:
1867 case op::FStar:
1868 return bunop(o, trans((*this)[0], std::forward<Args>(args)...),
1869 min(), max());
1870 }
1871 SPOT_UNREACHABLE();
1872 }
1873
1882 template<typename Func, typename... Args>
1883 void traverse(Func func, Args&&... args)
1884 {
1885 if (func(*this, std::forward<Args>(args)...))
1886 return;
1887 for (auto f: *this)
1888 f.traverse(func, std::forward<Args>(args)...);
1889 }
1890
1891 private:
1892#ifndef SWIG
1893 [[noreturn]] static void report_ap_invalid_arg();
1894#endif
1895 };
1896
1898 SPOT_API
1899 std::ostream& print_formula_props(std::ostream& out, const formula& f,
1900 bool abbreviated = false);
1901
1903 SPOT_API
1904 std::list<std::string> list_formula_props(const formula& f);
1905
1907 SPOT_API
1908 std::ostream& operator<<(std::ostream& os, const formula& f);
1909}
1910
1911#ifndef SWIG
1912namespace std
1913{
1914 template <>
1915 struct hash<spot::formula>
1916 {
1917 size_t operator()(const spot::formula& x) const noexcept
1918 {
1919 return x.id();
1920 }
1921 };
1922}
1923#endif
Actual storage for formula nodes.
Definition: formula.hh:153
bool is_pi2() const
Definition: formula.hh:558
std::string kindstr() const
const fnode * boolean_operands(unsigned *width=nullptr) const
bool is_boolean() const
Definition: formula.hh:432
size_t id() const
Definition: formula.hh:300
bool is_ff() const
Definition: formula.hh:334
bool is_sugar_free_boolean() const
Definition: formula.hh:438
bool is_Kleene_star() const
Definition: formula.hh:370
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:312
unsigned min() const
Definition: formula.hh:272
bool is_syntactic_safety() const
Definition: formula.hh:498
bool is_syntactic_stutter_invariant() const
Definition: formula.hh:450
static const fnode * binop(op o, const fnode *f, const fnode *g)
bool is_delta2() const
Definition: formula.hh:570
unsigned size() const
Definition: formula.hh:288
static constexpr uint8_t unbounded()
Definition: formula.hh:183
const fnode * get_child_of(std::initializer_list< op > l) const
Definition: formula.hh:259
unsigned max() const
Definition: formula.hh:280
const fnode * get_child_of(op o) const
Definition: formula.hh:249
const fnode * all_but(unsigned i) const
bool accepts_eword() const
Definition: formula.hh:534
bool is_eventual() const
Definition: formula.hh:486
bool is(op o1, op o2, op o3, op o4) const
Definition: formula.hh:230
static bool instances_check()
safety check for the reference counters
bool is_leaf() const
Definition: formula.hh:294
bool has_spin_atomic_props() const
Definition: formula.hh:546
bool is_eword() const
Definition: formula.hh:358
bool is(op o1, op o2, op o3) const
Definition: formula.hh:225
op kind() const
Definition: formula.hh:205
const fnode * clone() const
Clone an fnode.
Definition: formula.hh:159
bool has_lbt_atomic_props() const
Definition: formula.hh:540
bool is_sugar_free_ltl() const
Definition: formula.hh:456
const std::string & ap_name() const
bool is_syntactic_persistence() const
Definition: formula.hh:522
unsigned boolean_count() const
Definition: formula.hh:403
static const fnode * tt()
Definition: formula.hh:340
bool is_universal() const
Definition: formula.hh:492
bool is_tt() const
Definition: formula.hh:346
bool is_constant() const
Definition: formula.hh:364
bool is_syntactic_recurrence() const
Definition: formula.hh:516
bool is(std::initializer_list< op > l) const
Definition: formula.hh:235
bool is_syntactic_obligation() const
Definition: formula.hh:510
static const fnode * unop(op o, const fnode *f)
const fnode * nth(unsigned i) const
Definition: formula.hh:318
bool is_ltl_formula() const
Definition: formula.hh:462
static const fnode * ff()
Definition: formula.hh:328
bool is_finite() const
Definition: formula.hh:480
bool is_sigma2() const
Definition: formula.hh:552
bool is_psl_formula() const
Definition: formula.hh:468
bool is_delta1() const
Definition: formula.hh:564
static const fnode * eword()
Definition: formula.hh:352
bool is_marked() const
Definition: formula.hh:528
std::ostream & dump(std::ostream &os) const
void destroy() const
Dereference an fnode.
Definition: formula.hh:173
static const fnode * one_plus()
Definition: formula.hh:386
static const fnode * ap(const std::string &name)
bool is(op o1, op o2) const
Definition: formula.hh:220
bool is_in_nenoform() const
Definition: formula.hh:444
static const fnode * bunop(op o, const fnode *f, unsigned min, unsigned max=unbounded())
bool is_syntactic_guarantee() const
Definition: formula.hh:504
static const fnode * multop(op o, std::vector< const fnode * > l)
bool is_sere_formula() const
Definition: formula.hh:474
static const fnode * one_star()
Definition: formula.hh:378
const fnode *const * begin() const
Definition: formula.hh:306
bool is(op o) const
Definition: formula.hh:215
Allow iterating over children.
Definition: formula.hh:1510
Main class for temporal logic formula.
Definition: formula.hh:786
std::ostream & dump(std::ostream &os) const
Print the formula for debugging.
Definition: formula.hh:1659
unsigned boolean_count() const
number of Boolean children
Definition: formula.hh:1683
bool is_leaf() const
Whether the formula is a leaf.
Definition: formula.hh:1489
size_t id() const
Return the id of a formula.
Definition: formula.hh:1502
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:1268
formula map(Trans trans, Args &&... args)
Clone this node after applying trans to its children.
Definition: formula.hh:1816
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:1260
static formula G(unsigned min_level, unsigned max_level, const formula &f)
Construct G[n:m].
Definition: formula.hh:1038
static formula binop(op o, const formula &f, const formula &g)
Construct a binary operator.
Definition: formula.hh:1074
bool is(op o) const
Return true if the formula is of kind o.
Definition: formula.hh:1404
static formula multop(op o, std::vector< formula > &&l)
Construct an n-ary operator.
Definition: formula.hh:1190
formula(formula &&f) noexcept
Move-construct a formula.
Definition: formula.hh:824
formula(const fnode *f) noexcept
Create a formula from an fnode.
Definition: formula.hh:794
bool is(op o1, op o2) const
Return true if the formula is of kind o1 or o2.
Definition: formula.hh:1411
static formula one_plus()
Return a copy of the formula 1[+].
Definition: formula.hh:1630
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:1623
unsigned min() const
Return start of the range for star-like operators.
Definition: formula.hh:1466
static constexpr uint8_t unbounded()
Unbounded constant to use as end of range for bounded operators.
Definition: formula.hh:927
static formula unop(op o, formula &&f)
Build a unary operator.
Definition: formula.hh:960
static formula eword()
Return the empty word constant.
Definition: formula.hh:1596
formula all_but(unsigned i) const
clone this formula, omitting child i
Definition: formula.hh:1669
static formula ff()
Return the false constant.
Definition: formula.hh:1572
static formula binop(op o, const formula &f, formula &&g)
Construct a binary operator.
Definition: formula.hh:1080
const formula & operator=(std::nullptr_t)
Reset a formula to null.
Definition: formula.hh:844
op kind() const
Return top-most operator.
Definition: formula.hh:1392
const std::string & ap_name() const
Print the name of an atomic proposition.
Definition: formula.hh:1650
static formula multop(op o, const std::vector< formula > &l)
Construct an n-ary operator.
Definition: formula.hh:1179
unsigned size() const
Return the number of children.
Definition: formula.hh:1480
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:1590
bool is(op o1, op o2, op o3, op o4) const
Definition: formula.hh:1424
std::string kindstr() const
Return the name of the top-most operator.
Definition: formula.hh:1398
formula(const formula &f) noexcept
Clone a formula.
Definition: formula.hh:816
formula_child_iterator end() const
Allow iterating over children.
Definition: formula.hh:1559
const fnode * to_node_()
Return the underlying pointer to the formula.
Definition: formula.hh:1383
static formula binop(op o, formula &&f, formula &&g)
Construct a binary operator.
Definition: formula.hh:1090
static formula ap(const formula &a)
Build an atomic proposition from... an atomic proposition.
Definition: formula.hh:943
formula get_child_of(std::initializer_list< op > l) const
Remove all operators in l and return the child.
Definition: formula.hh:1454
bool is_eword() const
Whether the formula is the empty word constant.
Definition: formula.hh:1602
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:1883
static formula F(unsigned min_level, unsigned max_level, const formula &f)
Construct F[n:m].
Definition: formula.hh:1027
formula(std::nullptr_t) noexcept
Create a null formula.
Definition: formula.hh:804
static formula ap(const std::string &name)
Build an atomic proposition.
Definition: formula.hh:933
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:1417
unsigned max() const
Return end of the range for star-like operators.
Definition: formula.hh:1474
static formula X(unsigned level, const formula &f)
Construct an X[n].
Definition: formula.hh:997
bool is_ff() const
Whether the formula is the false constant.
Definition: formula.hh:1578
formula_child_iterator begin() const
Allow iterating over children.
Definition: formula.hh:1553
bool is_constant() const
Whether the formula is op::ff, op::tt, or op::eword.
Definition: formula.hh:1608
~formula()
Destroy a formula.
Definition: formula.hh:831
formula get_child_of(op o) const
Remove operator o and return the child.
Definition: formula.hh:1439
bool is(std::initializer_list< op > l) const
Return true if the formulas nests all the operators in l.
Definition: formula.hh:1430
formula operator[](unsigned i) const
Return children number i.
Definition: formula.hh:1565
static formula strong_X(unsigned level, const formula &f)
Construct a strong_X[n].
Definition: formula.hh:1010
bool is_Kleene_star() const
Test whether the formula represent a Kleene star.
Definition: formula.hh:1617
static formula binop(op o, formula &&f, const formula &g)
Construct a binary operator.
Definition: formula.hh:1085
bool is_literal() const
Whether the formula is an atomic proposition or its negation.
Definition: formula.hh:1638
static formula tt()
Return the true constant.
Definition: formula.hh:1584
formula() noexcept
Default initialize a formula to nullptr.
Definition: formula.hh:810
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:954
formula boolean_operands(unsigned *width=nullptr) const
return a clone of the current node, restricted to its Boolean children
Definition: formula.hh:1701
static const formula nested_unop_range(op uo, op bo, unsigned min, unsigned max, formula f)
Nested operator construction (syntactic sugar).
Definition: formula.hh:1325
op
Operator types.
Definition: formula.hh:77
@ 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.
@ And
(omega-Rational) And
@ AndNLM
Non-Length-Matching Rational-And.
@ eword
Empty word.
@ AndRat
Rational And.
@ G
Globally.
@ R
release (dual of until)
@ Concat
Concatenation.
@ Implies
Implication.
bool is_universal(const const_twa_graph_ptr &aut)
Return true iff aut is universal.
Definition: automata.hh:26
int atomic_prop_cmp(const fnode *f, const fnode *g)
Order two atomic propositions.
std::list< std::string > list_formula_props(const formula &f)
List the properties of formula f.
std::ostream & print_formula_props(std::ostream &out, const formula &f, bool abbreviated=false)
Print the properties of formula f on stream out.
Definition: formula.hh:711

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.4