spot 2.13
acc.hh
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
19#pragma once
20
21#include <functional>
22#include <sstream>
23#include <vector>
24#include <iostream>
25#include <algorithm>
26#include <numeric>
27#include <bddx.h>
28#include <tuple>
29#include <spot/misc/_config.h>
30#include <spot/misc/bitset.hh>
31#include <spot/misc/trival.hh>
32
33namespace spot
34{
35 namespace internal
36 {
37 class mark_container;
38
39 template<bool>
40 struct _32acc {};
41 template<>
42 struct _32acc<true>
43 {
44 SPOT_DEPRECATED("mark_t no longer relies on unsigned, stop using value_t")
45 typedef unsigned value_t;
46 };
47 }
48
51
60 class SPOT_API acc_cond
61 {
62#ifndef SWIG
63 private:
64 [[noreturn]] static void report_too_many_sets();
65#endif
66 public:
67
82 struct mark_t :
83 public internal::_32acc<SPOT_MAX_ACCSETS == 8*sizeof(unsigned)>
84 {
85 private:
86 // configure guarantees that SPOT_MAX_ACCSETS % (8*sizeof(unsigned)) == 0
87 typedef bitset<SPOT_MAX_ACCSETS / (8*sizeof(unsigned))> _value_t;
88 _value_t id;
89
90 mark_t(_value_t id) noexcept
91 : id(id)
92 {
93 }
94
95 public:
97 mark_t() = default;
98
99#ifndef SWIG
101 template<class iterator>
102 mark_t(const iterator& begin, const iterator& end)
103 : mark_t(_value_t::zero())
104 {
105 for (iterator i = begin; i != end; ++i)
106 if (SPOT_LIKELY(*i < SPOT_MAX_ACCSETS))
107 set(*i);
108 else
109 report_too_many_sets();
110 }
111
113 mark_t(std::initializer_list<unsigned> vals)
114 : mark_t(vals.begin(), vals.end())
115 {
116 }
117
118 SPOT_DEPRECATED("use brace initialization instead")
119 mark_t(unsigned i)
120 {
121 unsigned j = 0;
122 while (i)
123 {
124 if (i & 1U)
125 this->set(j);
126 ++j;
127 i >>= 1;
128 }
129 }
130#endif
131
137 constexpr static unsigned max_accsets()
138 {
139 return SPOT_MAX_ACCSETS;
140 }
141
147 static mark_t all()
148 {
149 return mark_t(_value_t::mone());
150 }
151
152 size_t hash() const noexcept
153 {
154 std::hash<decltype(id)> h;
155 return h(id);
156 }
157
158 SPOT_DEPRECATED("compare mark_t to mark_t, not to unsigned")
159 bool operator==(unsigned o) const
160 {
161 SPOT_ASSERT(o == 0U);
162 (void)o;
163 return !id;
164 }
165
166 SPOT_DEPRECATED("compare mark_t to mark_t, not to unsigned")
167 bool operator!=(unsigned o) const
168 {
169 SPOT_ASSERT(o == 0U);
170 (void)o;
171 return !!id;
172 }
173
174 bool operator==(mark_t o) const
175 {
176 return id == o.id;
177 }
178
179 bool operator!=(mark_t o) const
180 {
181 return id != o.id;
182 }
183
184 bool operator<(mark_t o) const
185 {
186 return id < o.id;
187 }
188
189 bool operator<=(mark_t o) const
190 {
191 return id <= o.id;
192 }
193
194 bool operator>(mark_t o) const
195 {
196 return id > o.id;
197 }
198
199 bool operator>=(mark_t o) const
200 {
201 return id >= o.id;
202 }
203
204 explicit operator bool() const
205 {
206 return !!id;
207 }
208
209 bool has(unsigned u) const
210 {
211 return !!this->operator&(mark_t({0}) << u);
212 }
213
214 void set(unsigned u)
215 {
216 id.set(u);
217 }
218
219 void clear(unsigned u)
220 {
221 id.clear(u);
222 }
223
224 mark_t& operator&=(mark_t r)
225 {
226 id &= r.id;
227 return *this;
228 }
229
230 mark_t& operator|=(mark_t r)
231 {
232 id |= r.id;
233 return *this;
234 }
235
236 mark_t& operator-=(mark_t r)
237 {
238 id &= ~r.id;
239 return *this;
240 }
241
242 mark_t& operator^=(mark_t r)
243 {
244 id ^= r.id;
245 return *this;
246 }
247
248 mark_t operator&(mark_t r) const
249 {
250 return id & r.id;
251 }
252
253 mark_t operator|(mark_t r) const
254 {
255 return id | r.id;
256 }
257
258 mark_t operator-(mark_t r) const
259 {
260 return id & ~r.id;
261 }
262
263 mark_t operator~() const
264 {
265 return ~id;
266 }
267
268 mark_t operator^(mark_t r) const
269 {
270 return id ^ r.id;
271 }
272
273#if SPOT_DEBUG || defined(SWIGPYTHON)
274# define SPOT_WRAP_OP(ins) \
275 try \
276 { \
277 ins; \
278 } \
279 catch (const std::runtime_error& e) \
280 { \
281 report_too_many_sets(); \
282 }
283#else
284# define SPOT_WRAP_OP(ins) ins;
285#endif
286 mark_t operator<<(unsigned i) const
287 {
288 SPOT_WRAP_OP(return id << i);
289 }
290
291 mark_t& operator<<=(unsigned i)
292 {
293 SPOT_WRAP_OP(id <<= i; return *this);
294 }
295
296 mark_t operator>>(unsigned i) const
297 {
298 SPOT_WRAP_OP(return id >> i);
299 }
300
301 mark_t& operator>>=(unsigned i)
302 {
303 SPOT_WRAP_OP(id >>= i; return *this);
304 }
305#undef SPOT_WRAP_OP
306
307 mark_t strip(mark_t y) const
308 {
309 // strip every bit of id that is marked in y
310 // 100101110100.strip(
311 // 001011001000)
312 // == 10 1 11 100
313 // == 10111100
314
315 auto xv = id; // 100101110100
316 auto yv = y.id; // 001011001000
317
318 while (yv && xv)
319 {
320 // Mask for everything after the last 1 in y
321 auto rm = (~yv) & (yv - 1); // 000000000111
322 // Mask for everything before the last 1 in y
323 auto lm = ~(yv ^ (yv - 1)); // 111111110000
324 xv = ((xv & lm) >> 1) | (xv & rm);
325 yv = (yv & lm) >> 1;
326 }
327 return xv;
328 }
329
332 bool subset(mark_t m) const
333 {
334 return !((*this) - m);
335 }
336
339 bool proper_subset(mark_t m) const
340 {
341 return *this != m && this->subset(m);
342 }
343
345 unsigned count() const
346 {
347 return id.count();
348 }
349
354 unsigned max_set() const
355 {
356 if (id)
357 return id.highest()+1;
358 else
359 return 0;
360 }
361
366 unsigned min_set() const
367 {
368 if (id)
369 return id.lowest()+1;
370 else
371 return 0;
372 }
373
379 {
380 return id & -id;
381 }
382
384 bool is_singleton() const
385 {
386#if __GNUC__
387 /* With GCC and Clang, count() is implemented using popcount. */
388 return count() == 1;
389#else
390 return id && !(id & (id - 1));
391#endif
392 }
393
395 bool has_many() const
396 {
397#if __GNUC__
398 /* With GCC and Clang, count() is implemented using popcount. */
399 return count() > 1;
400#else
401 return !!(id & (id - 1));
402#endif
403 }
404
408 mark_t& remove_some(unsigned n)
409 {
410 while (n--)
411 id &= id - 1;
412 return *this;
413 }
414
416 template<class iterator>
417 void fill(iterator here) const
418 {
419 auto a = *this;
420 unsigned level = 0;
421 while (a)
422 {
423 if (a.has(0))
424 *here++ = level;
425 ++level;
426 a >>= 1;
427 }
428 }
429
432
433 std::string as_string() const;
434 };
435
437 enum class acc_op : unsigned short
438 { Inf, Fin, InfNeg, FinNeg, And, Or };
439
448 {
449 mark_t mark;
450 struct {
451 acc_op op; // Operator
452 unsigned short size; // Size of the subtree (number of acc_word),
453 // not counting this node.
454 } sub;
455 };
456
469 struct SPOT_API acc_code: public std::vector<acc_word>
470 {
472 unit_propagation();
473
474 bool operator==(const acc_code& other) const
475 {
476 // We have two ways to represent t, unfortunately.
477 if (is_t() && other.is_t())
478 return true;
479 unsigned pos = size();
480 if (other.size() != pos)
481 return false;
482 while (pos > 0)
483 {
484 auto op = (*this)[pos - 1].sub.op;
485 auto sz = (*this)[pos - 1].sub.size;
486 if (other[pos - 1].sub.op != op ||
487 other[pos - 1].sub.size != sz)
488 return false;
489 switch (op)
490 {
491 case acc_cond::acc_op::And:
492 case acc_cond::acc_op::Or:
493 --pos;
494 break;
495 case acc_cond::acc_op::Inf:
496 case acc_cond::acc_op::InfNeg:
497 case acc_cond::acc_op::Fin:
498 case acc_cond::acc_op::FinNeg:
499 pos -= 2;
500 if (other[pos].mark != (*this)[pos].mark)
501 return false;
502 break;
503 }
504 }
505 return true;
506 };
507
508 bool operator<(const acc_code& other) const
509 {
510 // We have two ways to represent t, unfortunately.
511 if (is_t() && other.is_t())
512 return false;
513 unsigned pos = size();
514 auto osize = other.size();
515 if (pos < osize)
516 return true;
517 if (pos > osize)
518 return false;
519 while (pos > 0)
520 {
521 auto op = (*this)[pos - 1].sub.op;
522 auto oop = other[pos - 1].sub.op;
523 if (op < oop)
524 return true;
525 if (op > oop)
526 return false;
527 auto sz = (*this)[pos - 1].sub.size;
528 auto osz = other[pos - 1].sub.size;
529 if (sz < osz)
530 return true;
531 if (sz > osz)
532 return false;
533 switch (op)
534 {
535 case acc_cond::acc_op::And:
536 case acc_cond::acc_op::Or:
537 --pos;
538 break;
539 case acc_cond::acc_op::Inf:
540 case acc_cond::acc_op::InfNeg:
541 case acc_cond::acc_op::Fin:
542 case acc_cond::acc_op::FinNeg:
543 {
544 pos -= 2;
545 auto m = (*this)[pos].mark;
546 auto om = other[pos].mark;
547 if (m < om)
548 return true;
549 if (m > om)
550 return false;
551 break;
552 }
553 }
554 }
555 return false;
556 }
557
558 bool operator>(const acc_code& other) const
559 {
560 return other < *this;
561 }
562
563 bool operator<=(const acc_code& other) const
564 {
565 return !(other < *this);
566 }
567
568 bool operator>=(const acc_code& other) const
569 {
570 return !(*this < other);
571 }
572
573 bool operator!=(const acc_code& other) const
574 {
575 return !(*this == other);
576 }
577
582 bool is_t() const
583 {
584 // We store "t" as an empty condition, or as Inf({}).
585 unsigned s = size();
586 return s == 0 || ((*this)[s - 1].sub.op == acc_op::Inf
587 && !((*this)[s - 2].mark));
588 }
589
596 bool is_f() const
597 {
598 // We store "f" as Fin({}).
599 unsigned s = size();
600 return s > 1
601 && (*this)[s - 1].sub.op == acc_op::Fin && !((*this)[s - 2].mark);
602 }
603
610 static acc_code f()
611 {
612 acc_code res;
613 res.resize(2);
614 res[0].mark = {};
615 res[1].sub.op = acc_op::Fin;
616 res[1].sub.size = 1;
617 return res;
618 }
619
624 static acc_code t()
625 {
626 return {};
627 }
628
637 {
638 acc_code res;
639 res.resize(2);
640 res[0].mark = m;
641 res[1].sub.op = acc_op::Fin;
642 res[1].sub.size = 1;
643 return res;
644 }
645
646 static acc_code fin(std::initializer_list<unsigned> vals)
647 {
648 return fin(mark_t(vals));
649 }
651
669 {
670 acc_code res;
671 res.resize(2);
672 res[0].mark = m;
673 res[1].sub.op = acc_op::FinNeg;
674 res[1].sub.size = 1;
675 return res;
676 }
677
678 static acc_code fin_neg(std::initializer_list<unsigned> vals)
679 {
680 return fin_neg(mark_t(vals));
681 }
683
693 {
694 acc_code res;
695 res.resize(2);
696 res[0].mark = m;
697 res[1].sub.op = acc_op::Inf;
698 res[1].sub.size = 1;
699 return res;
700 }
701
702 static acc_code inf(std::initializer_list<unsigned> vals)
703 {
704 return inf(mark_t(vals));
705 }
707
725 {
726 acc_code res;
727 res.resize(2);
728 res[0].mark = m;
729 res[1].sub.op = acc_op::InfNeg;
730 res[1].sub.size = 1;
731 return res;
732 }
733
734 static acc_code inf_neg(std::initializer_list<unsigned> vals)
735 {
736 return inf_neg(mark_t(vals));
737 }
739
744 {
745 return inf({0});
746 }
747
752 {
753 return fin({0});
754 }
755
761 static acc_code generalized_buchi(unsigned n)
762 {
763 if (n == 0)
764 return inf({});
765 acc_cond::mark_t m = mark_t::all();
766 m >>= mark_t::max_accsets() - n;
767 return inf(m);
768 }
769
776 {
777 if (n == 0)
778 return fin({});
779 acc_cond::mark_t m = mark_t::all();
780 m >>= mark_t::max_accsets() - n;
781 return fin(m);
782 }
783
788 static acc_code rabin(unsigned n)
789 {
790 acc_cond::acc_code res = f();
791 while (n > 0)
792 {
793 res |= inf({2*n - 1}) & fin({2*n - 2});
794 --n;
795 }
796 return res;
797 }
798
803 static acc_code streett(unsigned n)
804 {
805 acc_cond::acc_code res = t();
806 while (n > 0)
807 {
808 res &= inf({2*n - 1}) | fin({2*n - 2});
809 --n;
810 }
811 return res;
812 }
813
826 template<class Iterator>
827 static acc_code generalized_rabin(Iterator begin, Iterator end)
828 {
829 acc_cond::acc_code res = f();
830 unsigned n = 0;
831 for (Iterator i = begin; i != end; ++i)
832 {
833 unsigned f = n++;
834 acc_cond::mark_t m = {};
835 for (unsigned ni = *i; ni > 0; --ni)
836 m.set(n++);
837 auto pair = inf(m) & fin({f});
838 std::swap(pair, res);
839 res |= std::move(pair);
840 }
841 return res;
842 }
843
851 static acc_code parity(bool is_max, bool is_odd, unsigned sets);
852 static acc_code parity_max(bool is_odd, unsigned sets)
853 {
854 return parity(true, is_odd, sets);
855 }
856 static acc_code parity_max_odd(unsigned sets)
857 {
858 return parity_max(true, sets);
859 }
860 static acc_code parity_max_even(unsigned sets)
861 {
862 return parity_max(false, sets);
863 }
864 static acc_code parity_min(bool is_odd, unsigned sets)
865 {
866 return parity(false, is_odd, sets);
867 }
868 static acc_code parity_min_odd(unsigned sets)
869 {
870 return parity_min(true, sets);
871 }
872 static acc_code parity_min_even(unsigned sets)
873 {
874 return parity_min(false, sets);
875 }
877
894 static acc_code random(unsigned n, double reuse = 0.0);
895
898 {
899 if (is_t() || r.is_f())
900 {
901 *this = r;
902 return *this;
903 }
904 if (is_f() || r.is_t())
905 return *this;
906 unsigned s = size() - 1;
907 unsigned rs = r.size() - 1;
908 // We want to group all Inf(x) operators:
909 // Inf(a) & Inf(b) = Inf(a & b)
910 if (((*this)[s].sub.op == acc_op::Inf
911 && r[rs].sub.op == acc_op::Inf)
912 || ((*this)[s].sub.op == acc_op::InfNeg
913 && r[rs].sub.op == acc_op::InfNeg))
914 {
915 (*this)[s - 1].mark |= r[rs - 1].mark;
916 return *this;
917 }
918
919 // In the more complex scenarios, left and right may both
920 // be conjunctions, and Inf(x) might be a member of each
921 // side. Find it if it exists.
922 // left_inf points to the left Inf mark if any.
923 // right_inf points to the right Inf mark if any.
924 acc_word* left_inf = nullptr;
925 if ((*this)[s].sub.op == acc_op::And)
926 {
927 auto start = &(*this)[s] - (*this)[s].sub.size;
928 auto pos = &(*this)[s] - 1;
929 pop_back();
930 while (pos > start)
931 {
932 if (pos->sub.op == acc_op::Inf)
933 {
934 left_inf = pos - 1;
935 break;
936 }
937 pos -= pos->sub.size + 1;
938 }
939 }
940 else if ((*this)[s].sub.op == acc_op::Inf)
941 {
942 left_inf = &(*this)[s - 1];
943 }
944
945 const acc_word* right_inf = nullptr;
946 auto right_end = &r.back();
947 if (right_end->sub.op == acc_op::And)
948 {
949 auto start = &r[0];
950 auto pos = --right_end;
951 while (pos > start)
952 {
953 if (pos->sub.op == acc_op::Inf)
954 {
955 right_inf = pos - 1;
956 break;
957 }
958 pos -= pos->sub.size + 1;
959 }
960 }
961 else if (right_end->sub.op == acc_op::Inf)
962 {
963 right_inf = right_end - 1;
964 }
965
966 acc_cond::mark_t carry = {};
967 if (left_inf && right_inf)
968 {
969 carry = left_inf->mark;
970 auto pos = left_inf - &(*this)[0];
971 erase(begin() + pos, begin() + pos + 2);
972 }
973 auto sz = size();
974 insert(end(), &r[0], right_end + 1);
975 if (carry)
976 (*this)[sz + (right_inf - &r[0])].mark |= carry;
977
978 acc_word w;
979 w.sub.op = acc_op::And;
980 w.sub.size = size();
981 emplace_back(w);
982 return *this;
983 }
984
987 {
988 acc_code res = *this;
989 res &= r;
990 return res;
991 }
992
993#ifndef SWIG
996 {
997 acc_code res = *this;
998 res &= r;
999 return res;
1000 }
1001#endif // SWIG
1002
1005 {
1006 if (is_t() || r.is_f())
1007 return *this;
1008 if (is_f() || r.is_t())
1009 {
1010 *this = r;
1011 return *this;
1012 }
1013 unsigned s = size() - 1;
1014 unsigned rs = r.size() - 1;
1015 // Fin(a) | Fin(b) = Fin(a | b)
1016 if (((*this)[s].sub.op == acc_op::Fin
1017 && r[rs].sub.op == acc_op::Fin)
1018 || ((*this)[s].sub.op == acc_op::FinNeg
1019 && r[rs].sub.op == acc_op::FinNeg))
1020 {
1021 (*this)[s - 1].mark |= r[rs - 1].mark;
1022 return *this;
1023 }
1024
1025 // In the more complex scenarios, left and right may both
1026 // be disjunctions, and Fin(x) might be a member of each
1027 // side. Find it if it exists.
1028 // left_inf points to the left Inf mark if any.
1029 // right_inf points to the right Inf mark if any.
1030 acc_word* left_fin = nullptr;
1031 if ((*this)[s].sub.op == acc_op::Or)
1032 {
1033 auto start = &(*this)[s] - (*this)[s].sub.size;
1034 auto pos = &(*this)[s] - 1;
1035 pop_back();
1036 while (pos > start)
1037 {
1038 if (pos->sub.op == acc_op::Fin)
1039 {
1040 left_fin = pos - 1;
1041 break;
1042 }
1043 pos -= pos->sub.size + 1;
1044 }
1045 }
1046 else if ((*this)[s].sub.op == acc_op::Fin)
1047 {
1048 left_fin = &(*this)[s - 1];
1049 }
1050
1051 const acc_word* right_fin = nullptr;
1052 auto right_end = &r.back();
1053 if (right_end->sub.op == acc_op::Or)
1054 {
1055 auto start = &r[0];
1056 auto pos = --right_end;
1057 while (pos > start)
1058 {
1059 if (pos->sub.op == acc_op::Fin)
1060 {
1061 right_fin = pos - 1;
1062 break;
1063 }
1064 pos -= pos->sub.size + 1;
1065 }
1066 }
1067 else if (right_end->sub.op == acc_op::Fin)
1068 {
1069 right_fin = right_end - 1;
1070 }
1071
1072 acc_cond::mark_t carry = {};
1073 if (left_fin && right_fin)
1074 {
1075 carry = left_fin->mark;
1076 auto pos = (left_fin - &(*this)[0]);
1077 this->erase(begin() + pos, begin() + pos + 2);
1078 }
1079 auto sz = size();
1080 insert(end(), &r[0], right_end + 1);
1081 if (carry)
1082 (*this)[sz + (right_fin - &r[0])].mark |= carry;
1083 acc_word w;
1084 w.sub.op = acc_op::Or;
1085 w.sub.size = size();
1086 emplace_back(w);
1087 return *this;
1088 }
1089
1090#ifndef SWIG
1093 {
1094 acc_code res = *this;
1095 res |= r;
1096 return res;
1097 }
1098#endif // SWIG
1099
1102 {
1103 acc_code res = *this;
1104 res |= r;
1105 return res;
1106 }
1107
1113 acc_code& operator<<=(unsigned sets)
1114 {
1115 if (SPOT_UNLIKELY(sets >= mark_t::max_accsets()))
1116 report_too_many_sets();
1117 if (empty())
1118 return *this;
1119 unsigned pos = size();
1120 do
1121 {
1122 switch ((*this)[pos - 1].sub.op)
1123 {
1124 case acc_cond::acc_op::And:
1125 case acc_cond::acc_op::Or:
1126 --pos;
1127 break;
1128 case acc_cond::acc_op::Inf:
1129 case acc_cond::acc_op::InfNeg:
1130 case acc_cond::acc_op::Fin:
1131 case acc_cond::acc_op::FinNeg:
1132 pos -= 2;
1133 (*this)[pos].mark <<= sets;
1134 break;
1135 }
1136 }
1137 while (pos > 0);
1138 return *this;
1139 }
1140
1144 acc_code operator<<(unsigned sets) const
1145 {
1146 acc_code res = *this;
1147 res <<= sets;
1148 return res;
1149 }
1150
1157 bool is_dnf() const;
1158
1165 bool is_cnf() const;
1166
1178
1186
1191 bdd to_bdd(const bdd* map) const;
1192
1201 std::vector<acc_code> top_disjuncts() const;
1202
1211 std::vector<acc_code> top_conjuncts() const;
1212
1224
1239
1253
1266
1271 int fin_one() const;
1272
1293 std::pair<int, acc_code> fin_one_extract() const;
1294
1313 std::tuple<int, acc_cond::acc_code, acc_cond::acc_code>
1315 std::tuple<int, acc_cond::acc_code, acc_cond::acc_code>
1318
1331 std::vector<std::vector<int>>
1332 missing(mark_t inf, bool accepting) const;
1333
1336 bool accepting(mark_t inf) const;
1337
1343 bool inf_satisfiable(mark_t inf) const;
1344
1357 mark_t always_present) const;
1358
1369 std::vector<unsigned> symmetries() const;
1370
1384 acc_code remove(acc_cond::mark_t rem, bool missing) const;
1385
1390 acc_code strip(acc_cond::mark_t rem, bool missing) const;
1393
1400
1403
1415 std::vector<std::pair<acc_cond::mark_t, acc_cond::mark_t>>
1417
1425
1427 std::pair<acc_cond::mark_t, acc_cond::mark_t> used_inf_fin_sets() const;
1428
1433 std::ostream&
1434 to_html(std::ostream& os,
1435 std::function<void(std::ostream&, int)>
1436 set_printer = nullptr) const;
1437
1442 std::ostream&
1443 to_text(std::ostream& os,
1444 std::function<void(std::ostream&, int)>
1445 set_printer = nullptr) const;
1446
1451 std::ostream&
1452 to_latex(std::ostream& os,
1453 std::function<void(std::ostream&, int)>
1454 set_printer = nullptr) const;
1455
1478 acc_code(const char* input);
1479
1484 {
1485 }
1486
1488 acc_code(const acc_word* other)
1489 : std::vector<acc_word>(other - other->sub.size, other + 1)
1490 {
1491 }
1492
1493 };
1494
1502 acc_cond(unsigned n_sets = 0, const acc_code& code = {})
1503 : num_(0U), all_({}), code_(code)
1504 {
1505 add_sets(n_sets);
1506 uses_fin_acceptance_ = check_fin_acceptance();
1507 }
1508
1513 acc_cond(const acc_code& code)
1514 : num_(0U), all_({}), code_(code)
1515 {
1516 add_sets(code.used_sets().max_set());
1517 uses_fin_acceptance_ = check_fin_acceptance();
1518 }
1519
1522 : num_(o.num_), all_(o.all_), code_(o.code_),
1523 uses_fin_acceptance_(o.uses_fin_acceptance_)
1524 {
1525 }
1526
1529 {
1530 num_ = o.num_;
1531 all_ = o.all_;
1532 code_ = o.code_;
1533 uses_fin_acceptance_ = o.uses_fin_acceptance_;
1534 return *this;
1535 }
1536
1537 ~acc_cond()
1538 {
1539 }
1540
1544 void set_acceptance(const acc_code& code)
1545 {
1546 code_ = code;
1547 uses_fin_acceptance_ = check_fin_acceptance();
1548 }
1549
1552 {
1553 return code_;
1554 }
1555
1558 {
1559 return code_;
1560 }
1561
1562 bool operator==(const acc_cond& other) const
1563 {
1564 if (other.num_sets() != num_)
1565 return false;
1566 const acc_code& ocode = other.get_acceptance();
1567 // We have two ways to represent t, unfortunately.
1568 return (ocode == code_ || (ocode.is_t() && code_.is_t()));
1569 }
1570
1571 bool operator!=(const acc_cond& other) const
1572 {
1573 return !(*this == other);
1574 }
1575
1578 {
1579 return uses_fin_acceptance_;
1580 }
1581
1583 bool is_t() const
1584 {
1585 return code_.is_t();
1586 }
1587
1592 bool is_all() const
1593 {
1594 return num_ == 0 && is_t();
1595 }
1596
1598 bool is_f() const
1599 {
1600 return code_.is_f();
1601 }
1602
1607 bool is_none() const
1608 {
1609 return num_ == 0 && is_f();
1610 }
1611
1616 bool is_buchi() const
1617 {
1618 unsigned s = code_.size();
1619 return num_ == 1 &&
1620 s == 2 && code_[1].sub.op == acc_op::Inf && code_[0].mark == all_sets();
1621 }
1622
1627 bool is_co_buchi() const
1628 {
1629 return num_ == 1 && is_generalized_co_buchi();
1630 }
1631
1635 {
1636 set_acceptance(inf(all_sets()));
1637 }
1638
1642 {
1643 set_acceptance(fin(all_sets()));
1644 }
1645
1651 {
1652 unsigned s = code_.size();
1653 return (s == 0 && num_ == 0) || (s == 2 && code_[1].sub.op == acc_op::Inf
1654 && code_[0].mark == all_sets());
1655 }
1656
1662 {
1663 unsigned s = code_.size();
1664 return (s == 2 &&
1665 code_[1].sub.op == acc_op::Fin && code_[0].mark == all_sets());
1666 }
1667
1679 int is_rabin() const;
1680
1692 int is_streett() const;
1693
1703 struct SPOT_API rs_pair
1704 {
1705#ifndef SWIG
1706 rs_pair() = default;
1707 rs_pair(const rs_pair&) = default;
1708 rs_pair& operator=(const rs_pair&) = default;
1709#endif
1710
1711 rs_pair(acc_cond::mark_t fin, acc_cond::mark_t inf) noexcept:
1712 fin(fin),
1713 inf(inf)
1714 {}
1715 acc_cond::mark_t fin;
1716 acc_cond::mark_t inf;
1717
1718 bool operator==(rs_pair o) const
1719 {
1720 return fin == o.fin && inf == o.inf;
1721 }
1722 bool operator!=(rs_pair o) const
1723 {
1724 return fin != o.fin || inf != o.inf;
1725 }
1726 bool operator<(rs_pair o) const
1727 {
1728 return fin < o.fin || (!(o.fin < fin) && inf < o.inf);
1729 }
1730 bool operator<=(rs_pair o) const
1731 {
1732 return !(o < *this);
1733 }
1734 bool operator>(rs_pair o) const
1735 {
1736 return o < *this;
1737 }
1738 bool operator>=(rs_pair o) const
1739 {
1740 return !(*this < o);
1741 }
1742 };
1753 bool is_streett_like(std::vector<rs_pair>& pairs) const;
1754
1765 bool is_rabin_like(std::vector<rs_pair>& pairs) const;
1766
1776 bool is_generalized_rabin(std::vector<unsigned>& pairs) const;
1777
1790 bool is_generalized_streett(std::vector<unsigned>& pairs) const;
1791
1801 bool is_parity(bool& max, bool& odd, bool equiv = false) const;
1802
1803
1806 bool is_parity() const
1807 {
1808 bool max;
1809 bool odd;
1810 return is_parity(max, odd);
1811 }
1812
1821 {
1822 return acc_cond(num_, code_.unit_propagation());
1823 }
1824
1825 // Return (true, m) if there exist some acceptance mark m that
1826 // does not satisfy the acceptance condition. Return (false, 0U)
1827 // otherwise.
1828 std::pair<bool, acc_cond::mark_t> unsat_mark() const
1829 {
1830 return sat_unsat_mark(false);
1831 }
1832 // Return (true, m) if there exist some acceptance mark m that
1833 // does satisfy the acceptance condition. Return (false, 0U)
1834 // otherwise.
1835 std::pair<bool, acc_cond::mark_t> sat_mark() const
1836 {
1837 return sat_unsat_mark(true);
1838 }
1839
1840 protected:
1841 bool check_fin_acceptance() const;
1842 std::pair<bool, acc_cond::mark_t> sat_unsat_mark(bool) const;
1843
1844 public:
1853 static acc_code inf(mark_t mark)
1854 {
1855 return acc_code::inf(mark);
1856 }
1857
1858 static acc_code inf(std::initializer_list<unsigned> vals)
1859 {
1860 return inf(mark_t(vals.begin(), vals.end()));
1861 }
1863
1881 {
1882 return acc_code::inf_neg(mark);
1883 }
1884
1885 static acc_code inf_neg(std::initializer_list<unsigned> vals)
1886 {
1887 return inf_neg(mark_t(vals.begin(), vals.end()));
1888 }
1890
1898 static acc_code fin(mark_t mark)
1899 {
1900 return acc_code::fin(mark);
1901 }
1902
1903 static acc_code fin(std::initializer_list<unsigned> vals)
1904 {
1905 return fin(mark_t(vals.begin(), vals.end()));
1906 }
1908
1926 {
1927 return acc_code::fin_neg(mark);
1928 }
1929
1930 static acc_code fin_neg(std::initializer_list<unsigned> vals)
1931 {
1932 return fin_neg(mark_t(vals.begin(), vals.end()));
1933 }
1935
1940 unsigned add_sets(unsigned num)
1941 {
1942 if (num == 0)
1943 return -1U;
1944 unsigned j = num_;
1945 num += j;
1946 if (num > mark_t::max_accsets())
1947 report_too_many_sets();
1948 // Make sure we do not update if we raised an exception.
1949 num_ = num;
1950 all_ = all_sets_();
1951 return j;
1952 }
1953
1958 unsigned add_set()
1959 {
1960 return add_sets(1);
1961 }
1962
1964 mark_t mark(unsigned u) const
1965 {
1966 SPOT_ASSERT(u < num_sets());
1967 return mark_t({u});
1968 }
1969
1974 mark_t comp(const mark_t& l) const
1975 {
1976 return all_ ^ l;
1977 }
1978
1981 {
1982 return all_;
1983 }
1984
1987 bool accepting(mark_t inf) const
1988 {
1989 return code_.accepting(inf);
1990 }
1991
1997 bool inf_satisfiable(mark_t inf) const
1998 {
1999 return code_.inf_satisfiable(inf);
2000 }
2001
2008 {
2009 return {num_sets(), code_.keep_one_inf_per_branch()};
2010 }
2011
2023 trival maybe_accepting(mark_t infinitely_often, mark_t always_present) const
2024 {
2025 return code_.maybe_accepting(infinitely_often, always_present);
2026 }
2027
2042
2043 // Deprecated since Spot 2.8
2044 SPOT_DEPRECATED("Use operator<< instead.")
2045 std::ostream& format(std::ostream& os, mark_t m) const;
2046
2047 // Deprecated since Spot 2.8
2048 SPOT_DEPRECATED("Use operator<< or mark_t::as_string() instead.")
2049 std::string format(mark_t m) const;
2050
2052 unsigned num_sets() const
2053 {
2054 return num_;
2055 }
2056
2064 template<class iterator>
2065 mark_t useless(iterator begin, iterator end) const
2066 {
2067 mark_t u = {}; // The set of useless sets
2068 for (unsigned x = 0; x < num_; ++x)
2069 {
2070 // Skip sets that are already known to be useless.
2071 if (u.has(x))
2072 continue;
2073 auto all = comp(u | mark_t({x}));
2074 // Iterate over all mark_t, and keep track of
2075 // set numbers that always appear with x.
2076 for (iterator y = begin; y != end; ++y)
2077 {
2078 const mark_t& v = *y;
2079 if (v.has(x))
2080 {
2081 all &= v;
2082 if (!all)
2083 break;
2084 }
2085 }
2086 u |= all;
2087 }
2088 return u;
2089 }
2090
2104 acc_cond remove(mark_t rem, bool missing) const
2105 {
2106 return {num_sets(), code_.remove(rem, missing)};
2107 }
2108
2113 acc_cond strip(mark_t rem, bool missing) const
2114 {
2115 return
2116 { num_sets() - (all_sets() & rem).count(), code_.strip(rem, missing) };
2117 }
2118
2121 {
2122 return {num_sets(), code_.force_inf(m)};
2123 }
2124
2128 {
2129 return {num_sets(), code_.remove(all_sets() - rem, true)};
2130 }
2131
2143 std::string name(const char* fmt = "alo") const;
2144
2159 {
2160 return code_.fin_unit();
2161 }
2162
2176 {
2177 return code_.mafins();
2178 }
2179
2192 {
2193 return code_.inf_unit();
2194 }
2195
2200 int fin_one() const
2201 {
2202 return code_.fin_one();
2203 }
2204
2225 std::pair<int, acc_cond> fin_one_extract() const
2226 {
2227 auto [f, c] = code_.fin_one_extract();
2228 return {f, {num_sets(), std::move(c)}};
2229 }
2230
2249 std::tuple<int, acc_cond, acc_cond>
2251 {
2252 auto [f, l, r] = code_.fin_unit_one_split();
2253 return {f, {num_sets(), std::move(l)}, {num_sets(), std::move(r)}};
2254 }
2255 std::tuple<int, acc_cond, acc_cond>
2257 {
2258 auto [f, l, r] = code_.fin_unit_one_split_improved();
2259 return {f, {num_sets(), std::move(l)}, {num_sets(), std::move(r)}};
2260 }
2262
2271 std::vector<acc_cond> top_disjuncts() const;
2272
2281 std::vector<acc_cond> top_conjuncts() const;
2282
2283 protected:
2284 mark_t all_sets_() const
2285 {
2286 return mark_t::all() >> (spot::acc_cond::mark_t::max_accsets() - num_);
2287 }
2288
2289 unsigned num_;
2290 mark_t all_;
2291 acc_code code_;
2292 bool uses_fin_acceptance_ = false;
2293
2294 };
2295
2297 typedef std::vector<acc_cond::rs_pair> rs_pairs;
2298
2299 // Creates view of pairs 'p' with restriction only to marks in 'm'
2300 explicit rs_pairs_view(const rs_pairs& p, const acc_cond::mark_t& m)
2301 : pairs_(p), view_marks_(m) {}
2302
2303 // Creates view of pairs without restriction to marks
2304 explicit rs_pairs_view(const rs_pairs& p)
2306
2307 acc_cond::mark_t infs() const
2308 {
2309 return do_view([&](const acc_cond::rs_pair& p)
2310 {
2311 return visible(p.inf) ? p.inf : acc_cond::mark_t({});
2312 });
2313 }
2314
2315 acc_cond::mark_t fins() const
2316 {
2317 return do_view([&](const acc_cond::rs_pair& p)
2318 {
2319 return visible(p.fin) ? p.fin : acc_cond::mark_t({});
2320 });
2321 }
2322
2323 acc_cond::mark_t fins_alone() const
2324 {
2325 return do_view([&](const acc_cond::rs_pair& p)
2326 {
2327 return !visible(p.inf) && visible(p.fin) ? p.fin
2328 : acc_cond::mark_t({});
2329 });
2330 }
2331
2332 acc_cond::mark_t infs_alone() const
2333 {
2334 return do_view([&](const acc_cond::rs_pair& p)
2335 {
2336 return !visible(p.fin) && visible(p.inf) ? p.inf
2337 : acc_cond::mark_t({});
2338 });
2339 }
2340
2341 acc_cond::mark_t paired_with_fin(unsigned mark) const
2342 {
2343 acc_cond::mark_t res = {};
2344 for (const auto& p: pairs_)
2345 if (p.fin.has(mark) && visible(p.fin) && visible(p.inf))
2346 res |= p.inf;
2347 return res;
2348 }
2349
2350 const rs_pairs& pairs() const
2351 {
2352 return pairs_;
2353 }
2354
2355 private:
2356 template<typename filter>
2357 acc_cond::mark_t do_view(const filter& filt) const
2358 {
2359 acc_cond::mark_t res = {};
2360 for (const auto& p: pairs_)
2361 res |= filt(p);
2362 return res;
2363 }
2364
2365 bool visible(const acc_cond::mark_t& v) const
2366 {
2367 return !!(view_marks_ & v);
2368 }
2369
2370 const rs_pairs& pairs_;
2371 acc_cond::mark_t view_marks_;
2372 };
2373
2374
2375 SPOT_API
2376 std::ostream& operator<<(std::ostream& os, const acc_cond& acc);
2377
2378 // The next two operators used to be declared as friend inside the
2379 // acc_cond::mark_t and acc_cond::acc_code, but Swig 4.2.1
2380 // introduced a bug with friend operators. See
2381 // https://github.com/swig/swig/issues/2845
2382
2383 SPOT_API
2384 std::ostream& operator<<(std::ostream& os, acc_cond::mark_t m);
2385
2387 SPOT_API
2388 std::ostream& operator<<(std::ostream& os,
2389 const acc_cond::acc_code& code);
2390
2392
2393 namespace internal
2394 {
2395 class SPOT_API mark_iterator
2396 {
2397 public:
2398 typedef unsigned value_type;
2399 typedef const value_type& reference;
2400 typedef const value_type* pointer;
2401 typedef std::ptrdiff_t difference_type;
2402 typedef std::forward_iterator_tag iterator_category;
2403
2404 mark_iterator() noexcept
2405 : m_({})
2406 {
2407 }
2408
2410 : m_(m)
2411 {
2412 }
2413
2414 bool operator==(mark_iterator m) const
2415 {
2416 return m_ == m.m_;
2417 }
2418
2419 bool operator!=(mark_iterator m) const
2420 {
2421 return m_ != m.m_;
2422 }
2423
2424 value_type operator*() const
2425 {
2426 SPOT_ASSERT(m_);
2427 return m_.min_set() - 1;
2428 }
2429
2430 mark_iterator& operator++()
2431 {
2432 m_.clear(this->operator*());
2433 return *this;
2434 }
2435
2436 mark_iterator operator++(int)
2437 {
2438 mark_iterator it = *this;
2439 ++(*this);
2440 return it;
2441 }
2442 private:
2444 };
2445
2446 class SPOT_API mark_container
2447 {
2448 public:
2450 : m_(m)
2451 {
2452 }
2453
2454 mark_iterator begin() const
2455 {
2456 return {m_};
2457 }
2458 mark_iterator end() const
2459 {
2460 return {};
2461 }
2462 private:
2464 };
2465 }
2466
2468 {
2469 return {*this};
2470 }
2471}
2472
2473namespace std
2474{
2475 template<>
2476 struct hash<spot::acc_cond::mark_t>
2477 {
2478 size_t operator()(spot::acc_cond::mark_t m) const noexcept
2479 {
2480 return m.hash();
2481 }
2482 };
2483}
An acceptance condition.
Definition: acc.hh:61
const acc_code & get_acceptance() const
Retrieve the acceptance formula.
Definition: acc.hh:1551
bool inf_satisfiable(mark_t inf) const
Assuming that we will visit at least all sets in inf, is there any chance that we will satisfy the co...
Definition: acc.hh:1997
mark_t all_sets() const
Construct a mark_t with all declared sets.
Definition: acc.hh:1980
static acc_code fin_neg(mark_t mark)
Construct a generalized co-Büchi acceptance for complemented sets.
Definition: acc.hh:1925
mark_t mafins() const
Find a Fin(i) that is mandatory.
Definition: acc.hh:2175
static acc_code inf_neg(mark_t mark)
Construct a generalized Büchi acceptance for complemented sets.
Definition: acc.hh:1880
acc_cond unit_propagation()
Remove superfluous Fin and Inf by unit propagation.
Definition: acc.hh:1820
void set_generalized_co_buchi()
Change the acceptance condition to generalized-co-Büchi, over all declared sets.
Definition: acc.hh:1641
std::pair< int, acc_cond > fin_one_extract() const
Return one acceptance set i that appears as Fin(i) in the condition, and all disjuncts containing it ...
Definition: acc.hh:2225
static acc_code fin(mark_t mark)
Construct a generalized co-Büchi acceptance.
Definition: acc.hh:1898
bool is_co_buchi() const
Whether the acceptance condition is "co-Büchi".
Definition: acc.hh:1627
bool accepting(mark_t inf) const
Check whether visiting exactly all sets inf infinitely often satisfies the acceptance condition.
Definition: acc.hh:1987
static acc_code inf(mark_t mark)
Construct a generalized Büchi acceptance.
Definition: acc.hh:1853
bool is_generalized_buchi() const
Whether the acceptance condition is "generalized-Büchi".
Definition: acc.hh:1650
static acc_code fin_neg(std::initializer_list< unsigned > vals)
Construct a generalized co-Büchi acceptance for complemented sets.
Definition: acc.hh:1930
static acc_code inf(std::initializer_list< unsigned > vals)
Construct a generalized Büchi acceptance.
Definition: acc.hh:1858
unsigned add_set()
Add a single set to the acceptance condition.
Definition: acc.hh:1958
bool is_parity(bool &max, bool &odd, bool equiv=false) const
check is the acceptance condition matches one of the four type of parity acceptance defined in the HO...
std::vector< acc_cond > top_disjuncts() const
Return the top-level disjuncts.
mark_t mark(unsigned u) const
Build a mark_t with a single set.
Definition: acc.hh:1964
void set_generalized_buchi()
Change the acceptance condition to generalized-Büchi, over all declared sets.
Definition: acc.hh:1634
acc_cond force_inf(mark_t m) const
For all x in m, replaces Fin(x) by false.
Definition: acc.hh:2120
acc_cond remove(mark_t rem, bool missing) const
Remove all the acceptance sets in rem.
Definition: acc.hh:2104
acc_op
Operators for acceptance formulas.
Definition: acc.hh:438
acc_cond(unsigned n_sets=0, const acc_code &code={})
Build an acceptance condition.
Definition: acc.hh:1502
unsigned add_sets(unsigned num)
Add more sets to the acceptance condition.
Definition: acc.hh:1940
bool is_parity() const
check is the acceptance condition matches one of the four type of parity acceptance defined in the HO...
Definition: acc.hh:1806
bool is_t() const
Whether the acceptance formula is "t" (true)
Definition: acc.hh:1583
bool is_generalized_rabin(std::vector< unsigned > &pairs) const
Is the acceptance condition generalized-Rabin?
mark_t comp(const mark_t &l) const
Complement a mark_t.
Definition: acc.hh:1974
acc_cond keep_one_inf_per_branch() const
Rewrite an acceptance condition by keeping at most one Inf(x) on each disjunctive branch.
Definition: acc.hh:2007
acc_cond & operator=(const acc_cond &o)
Copy an acceptance condition.
Definition: acc.hh:1528
acc_code & get_acceptance()
Retrieve the acceptance formula.
Definition: acc.hh:1557
static acc_code fin(std::initializer_list< unsigned > vals)
Construct a generalized co-Büchi acceptance.
Definition: acc.hh:1903
bool is_generalized_co_buchi() const
Whether the acceptance condition is "generalized-co-Büchi".
Definition: acc.hh:1661
std::tuple< int, acc_cond, acc_cond > fin_unit_one_split_improved() const
Split an acceptance condition, trying to select one unit-Fin.
Definition: acc.hh:2256
acc_cond restrict_to(mark_t rem) const
Restrict an acceptance condition to a subset of set numbers that are occurring at some point.
Definition: acc.hh:2127
trival maybe_accepting(mark_t infinitely_often, mark_t always_present) const
Check potential acceptance of an SCC.
Definition: acc.hh:2023
std::string name(const char *fmt="alo") const
Return the name of this acceptance condition, in the specified format.
bool is_none() const
Whether the acceptance condition is "none".
Definition: acc.hh:1607
void set_acceptance(const acc_code &code)
Change the acceptance formula.
Definition: acc.hh:1544
int is_rabin() const
Check if the acceptance condition matches the Rabin acceptance of the HOA format.
bool is_rabin_like(std::vector< rs_pair > &pairs) const
Test whether an acceptance condition is Rabin-like and returns each Rabin pair in an std::vector<rs_p...
mark_t accepting_sets(mark_t inf) const
Return an accepting subset of inf.
bool is_all() const
Whether the acceptance condition is "all".
Definition: acc.hh:1592
acc_cond strip(mark_t rem, bool missing) const
Remove acceptance sets, and shift set numbers.
Definition: acc.hh:2113
int fin_one() const
Return one acceptance set i that appear as Fin(i) in the condition.
Definition: acc.hh:2200
mark_t useless(iterator begin, iterator end) const
Compute useless acceptance sets given a list of mark_t that occur in an SCC.
Definition: acc.hh:2065
int is_streett() const
Check if the acceptance condition matches the Streett acceptance of the HOA format.
mark_t fin_unit() const
Find a Fin(i) that is a unit clause.
Definition: acc.hh:2158
bool is_generalized_streett(std::vector< unsigned > &pairs) const
Is the acceptance condition generalized-Streett?
acc_cond(const acc_code &code)
Build an acceptance condition.
Definition: acc.hh:1513
acc_cond(const acc_cond &o)
Copy an acceptance condition.
Definition: acc.hh:1521
static acc_code inf_neg(std::initializer_list< unsigned > vals)
Construct a generalized Büchi acceptance for complemented sets.
Definition: acc.hh:1885
bool is_streett_like(std::vector< rs_pair > &pairs) const
Test whether an acceptance condition is Streett-like and returns each Streett pair in an std::vector<...
bool is_buchi() const
Whether the acceptance condition is "Büchi".
Definition: acc.hh:1616
std::vector< acc_cond > top_conjuncts() const
Return the top-level conjuncts.
std::tuple< int, acc_cond, acc_cond > fin_unit_one_split() const
Split an acceptance condition, trying to select one unit-Fin.
Definition: acc.hh:2250
mark_t inf_unit() const
Find a Inf(i) that is a unit clause.
Definition: acc.hh:2191
bool uses_fin_acceptance() const
Whether the acceptance condition uses Fin terms.
Definition: acc.hh:1577
bool is_f() const
Whether the acceptance formula is "f" (false)
Definition: acc.hh:1598
unsigned num_sets() const
The number of sets used in the acceptance condition.
Definition: acc.hh:2052
Definition: bitset.hh:38
Definition: acc.hh:2447
Definition: acc.hh:2396
A class implementing Kleene's three-valued logic.
Definition: trival.hh:33
op
Operator types.
Definition: formula.hh:78
@ Or
(omega-Rational) Or
@ U
until
@ And
(omega-Rational) And
Definition: automata.hh:26
const mc_rvalue operator|(const mc_rvalue &lhs, const mc_rvalue &rhs)
This function helps to find the output value from a set of threads that may have different values.
Definition: mc.hh:130
An acceptance formula.
Definition: acc.hh:470
static acc_code parity_max(bool is_odd, unsigned sets)
Build a parity acceptance condition.
Definition: acc.hh:852
std::tuple< int, acc_cond::acc_code, acc_cond::acc_code > fin_unit_one_split() const
Split an acceptance condition, trying to select one unit-Fin.
std::vector< std::vector< int > > missing(mark_t inf, bool accepting) const
Help closing accepting or rejecting cycle.
mark_t mafins() const
Find a Fin(i) that is mandatory.
std::ostream & to_html(std::ostream &os, std::function< void(std::ostream &, int)> set_printer=nullptr) const
Print the acceptance formula as HTML.
static acc_code inf(mark_t m)
Construct a generalized Büchi acceptance.
Definition: acc.hh:692
acc_code to_cnf() const
Convert the acceptance formula into disjunctive normal form.
acc_code operator&(acc_code &&r) const
Conjunct the current condition with r.
Definition: acc.hh:995
acc_code force_inf(mark_t m) const
For all x in m, replaces Fin(x) by false.
static acc_code inf_neg(std::initializer_list< unsigned > vals)
Construct a generalized Büchi acceptance for complemented sets.
Definition: acc.hh:734
std::vector< std::pair< acc_cond::mark_t, acc_cond::mark_t > > useless_colors_patterns() const
Find patterns of useless colors.
trival maybe_accepting(mark_t infinitely_often, mark_t always_present) const
Check potential acceptance of an SCC.
acc_code operator|(const acc_code &r) const
Disjunct the current condition with r.
Definition: acc.hh:1101
std::vector< acc_code > top_conjuncts() const
Return the top-level conjuncts.
acc_code operator|(acc_code &&r) const
Disjunct the current condition with r.
Definition: acc.hh:1092
static acc_code fin(std::initializer_list< unsigned > vals)
Construct a generalized co-Büchi acceptance.
Definition: acc.hh:646
bool is_dnf() const
Whether the acceptance formula is in disjunctive normal form.
std::vector< acc_code > top_disjuncts() const
Return the top-level disjuncts.
acc_code operator&(const acc_code &r) const
Conjunct the current condition with r.
Definition: acc.hh:986
static acc_code inf(std::initializer_list< unsigned > vals)
Construct a generalized Büchi acceptance.
Definition: acc.hh:702
static acc_code parity_min_even(unsigned sets)
Build a parity acceptance condition.
Definition: acc.hh:872
static acc_code parity(bool is_max, bool is_odd, unsigned sets)
Build a parity acceptance condition.
mark_t used_once_sets() const
Return the sets that appears only once in the acceptance.
acc_code & operator<<=(unsigned sets)
Apply a left shift to all mark_t that appear in the condition.
Definition: acc.hh:1113
bool is_f() const
Is this the "false" acceptance condition?
Definition: acc.hh:596
static acc_code generalized_buchi(unsigned n)
Build a generalized-Büchi acceptance condition with n sets.
Definition: acc.hh:761
static acc_code parity_min_odd(unsigned sets)
Build a parity acceptance condition.
Definition: acc.hh:868
acc_code(const acc_word *other)
Copy a part of another acceptance formula.
Definition: acc.hh:1488
mark_t fin_unit() const
Find a Fin(i) that is a unit clause.
static acc_code parity_max_even(unsigned sets)
Build a parity acceptance condition.
Definition: acc.hh:860
static acc_code f()
Construct the "false" acceptance condition.
Definition: acc.hh:610
bool accepting(mark_t inf) const
Check whether visiting exactly all sets inf infinitely often satisfies the acceptance condition.
static acc_code parity_max_odd(unsigned sets)
Build a parity acceptance condition.
Definition: acc.hh:856
std::ostream & to_latex(std::ostream &os, std::function< void(std::ostream &, int)> set_printer=nullptr) const
Print the acceptance formula as LaTeX.
std::pair< int, acc_code > fin_one_extract() const
Return one acceptance set i that appears as Fin(i) in the condition, and all disjuncts containing it ...
bool is_t() const
Is this the "true" acceptance condition?
Definition: acc.hh:582
acc_code operator<<(unsigned sets) const
Apply a left shift to all mark_t that appear in the condition.
Definition: acc.hh:1144
static acc_code random(unsigned n, double reuse=0.0)
Build a random acceptance condition.
static acc_code rabin(unsigned n)
Build a Rabin condition with n pairs.
Definition: acc.hh:788
acc_code()
Build an empty acceptance formula.
Definition: acc.hh:1483
std::tuple< int, acc_cond::acc_code, acc_cond::acc_code > fin_unit_one_split_improved() const
Split an acceptance condition, trying to select one unit-Fin.
acc_code keep_one_inf_per_branch() const
Rewrite an acceptance condition by keeping at most one Inf(x) on each dijunctive branch.
static acc_code cobuchi()
Build a co-Büchi acceptance condition.
Definition: acc.hh:751
acc_code complement() const
Complement an acceptance formula.
static acc_code inf_neg(mark_t m)
Construct a generalized Büchi acceptance for complemented sets.
Definition: acc.hh:724
bdd to_bdd(const bdd *map) const
Convert the acceptance formula into a BDD.
std::ostream & to_text(std::ostream &os, std::function< void(std::ostream &, int)> set_printer=nullptr) const
Print the acceptance formula as text.
int fin_one() const
Return one acceptance set i that appears as Fin(i) in the condition.
acc_cond::mark_t used_sets() const
Return the set of sets appearing in the condition.
std::pair< acc_cond::mark_t, acc_cond::mark_t > used_inf_fin_sets() const
Return the sets used as Inf or Fin in the acceptance condition.
acc_code strip(acc_cond::mark_t rem, bool missing) const
Remove acceptance sets, and shift set numbers.
acc_code(const char *input)
Construct an acc_code from a string.
static acc_code fin_neg(std::initializer_list< unsigned > vals)
Construct a generalized co-Büchi acceptance for complemented sets.
Definition: acc.hh:678
acc_code & operator&=(const acc_code &r)
Conjunct the current condition in place with r.
Definition: acc.hh:897
mark_t inf_unit() const
Find a Inf(i) that is a unit clause.
static acc_code streett(unsigned n)
Build a Streett condition with n pairs.
Definition: acc.hh:803
static acc_code t()
Construct the "true" acceptance condition.
Definition: acc.hh:624
std::vector< unsigned > symmetries() const
compute the symmetry class of the acceptance sets.
static acc_code fin_neg(mark_t m)
Construct a generalized co-Büchi acceptance for complemented sets.
Definition: acc.hh:668
static acc_code parity_min(bool is_odd, unsigned sets)
Build a parity acceptance condition.
Definition: acc.hh:864
static acc_code fin(mark_t m)
Construct a generalized co-Büchi acceptance.
Definition: acc.hh:636
acc_code & operator|=(const acc_code &r)
Disjunct the current condition in place with r.
Definition: acc.hh:1004
bool inf_satisfiable(mark_t inf) const
Assuming that we will visit at least all sets in inf, is there any chance that we will satisfy the co...
bool is_cnf() const
Whether the acceptance formula is in conjunctive normal form.
static acc_code buchi()
Build a Büchi acceptance condition.
Definition: acc.hh:743
static acc_code generalized_co_buchi(unsigned n)
Build a generalized-co-Büchi acceptance condition with n sets.
Definition: acc.hh:775
acc_code remove(acc_cond::mark_t rem, bool missing) const
Remove all the acceptance sets in rem.
acc_code to_dnf() const
Convert the acceptance formula into disjunctive normal form.
static acc_code generalized_rabin(Iterator begin, Iterator end)
Build a generalized Rabin condition.
Definition: acc.hh:827
An acceptance mark.
Definition: acc.hh:84
static constexpr unsigned max_accsets()
The maximum number of acceptance sets supported by this implementation.
Definition: acc.hh:137
bool is_singleton() const
Whether the mark contains only one bit set.
Definition: acc.hh:384
mark_t lowest() const
A mark_t where all bits have been removed except the lowest one.
Definition: acc.hh:378
unsigned max_set() const
The number of the highest set used plus one.
Definition: acc.hh:354
mark_t & remove_some(unsigned n)
Remove n bits that where set.
Definition: acc.hh:408
static mark_t all()
A mark_t with all bits set to one.
Definition: acc.hh:147
spot::internal::mark_container sets() const
Returns some iterable object that contains the used sets.
Definition: acc.hh:2467
bool proper_subset(mark_t m) const
Whether the set of bits represented by *this is a proper subset of those represented by m.
Definition: acc.hh:339
mark_t(const iterator &begin, const iterator &end)
Create a mark_t from a range of set numbers.
Definition: acc.hh:102
unsigned count() const
Number of bits sets.
Definition: acc.hh:345
mark_t()=default
Initialize an empty mark_t.
mark_t(std::initializer_list< unsigned > vals)
Create a mark_t from a list of set numbers.
Definition: acc.hh:113
bool has_many() const
Whether the mark contains at least two bits set.
Definition: acc.hh:395
unsigned min_set() const
The number of the lowest set used plus one.
Definition: acc.hh:366
bool subset(mark_t m) const
Whether the set of bits represented by *this is a subset of those represented by m.
Definition: acc.hh:332
void fill(iterator here) const
Fill a container with the indices of the bits that are set.
Definition: acc.hh:417
Rabin/streett pairs used by is_rabin_like and is_streett_like.
Definition: acc.hh:1704
Definition: acc.hh:40
Definition: acc.hh:2296
A "node" in an acceptance formulas.
Definition: acc.hh:448

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