spot  2.16
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 <limits>
23 #include <sstream>
24 #include <stdexcept>
25 #include <vector>
26 #include <iostream>
27 #include <algorithm>
28 #include <numeric>
29 #include <bddx.h>
30 #include <tuple>
31 #include <spot/misc/_config.h>
32 #include <spot/misc/bitset.hh>
33 #include <spot/misc/trival.hh>
34 
35 namespace spot
36 {
37  namespace internal
38  {
39  class mark_container;
40  }
41 
44 
53  class SPOT_API acc_cond
54  {
55 #ifndef SWIG
56  private:
57  [[noreturn]] static void report_too_many_sets();
58 #endif
59  public:
60 
75  struct mark_t
76  {
77  private:
78  // configure guarantees that SPOT_MAX_ACCSETS % (8*sizeof(unsigned)) == 0
79  typedef bitset<SPOT_MAX_ACCSETS / (8*sizeof(unsigned))> _value_t;
80  _value_t id;
81 
82  mark_t(_value_t id) noexcept
83  : id(id)
84  {
85  }
86 
87  public:
89  mark_t() = default;
90 
91 #ifndef SWIG
93  template<class iterator>
94  mark_t(const iterator& begin, const iterator& end)
95  : mark_t(_value_t::zero())
96  {
97  for (iterator i = begin; i != end; ++i)
98  if (SPOT_LIKELY(*i < SPOT_MAX_ACCSETS))
99  set(*i);
100  else
101  report_too_many_sets();
102  }
103 
105  mark_t(std::initializer_list<unsigned> vals)
106  : mark_t(vals.begin(), vals.end())
107  {
108  }
109 #endif
110 
116  constexpr static unsigned max_accsets()
117  {
118  return SPOT_MAX_ACCSETS;
119  }
120 
126  static mark_t all()
127  {
128  return mark_t(_value_t::mone());
129  }
130 
132  size_t hash() const noexcept
133  {
134  std::hash<decltype(id)> h;
135  return h(id);
136  }
137 
139  bool operator==(mark_t o) const
140  {
141  return id == o.id;
142  }
143 
145  bool operator!=(mark_t o) const
146  {
147  return id != o.id;
148  }
149 
151  bool operator<(mark_t o) const
152  {
153  return id < o.id;
154  }
155 
157  bool operator<=(mark_t o) const
158  {
159  return id <= o.id;
160  }
161 
163  bool operator>(mark_t o) const
164  {
165  return id > o.id;
166  }
167 
169  bool operator>=(mark_t o) const
170  {
171  return id >= o.id;
172  }
173 
175  explicit operator bool() const
176  {
177  return !!id;
178  }
179 
181  bool has(unsigned u) const
182  {
183  return !!this->operator&(mark_t({0}) << u);
184  }
185 
187  void set(unsigned u)
188  {
189  id.set(u);
190  }
191 
193  void clear(unsigned u)
194  {
195  id.clear(u);
196  }
197 
200  {
201  id &= r.id;
202  return *this;
203  }
204 
207  {
208  id |= r.id;
209  return *this;
210  }
211 
214  {
215  id &= ~r.id;
216  return *this;
217  }
218 
221  {
222  id ^= r.id;
223  return *this;
224  }
225 
228  {
229  return id & r.id;
230  }
231 
234  {
235  return id | r.id;
236  }
237 
240  {
241  return id & ~r.id;
242  }
243 
246  {
247  return ~id;
248  }
249 
252  {
253  return id ^ r.id;
254  }
255 
256 #if SPOT_DEBUG || defined(SWIGPYTHON)
257 # define SPOT_WRAP_OP(ins) \
258  try \
259  { \
260  ins; \
261  } \
262  catch (const std::runtime_error& e) \
263  { \
264  report_too_many_sets(); \
265  }
266 #else
267 # define SPOT_WRAP_OP(ins) ins;
268 #endif
270  mark_t operator<<(unsigned i) const
271  {
272  SPOT_WRAP_OP(return id << i);
273  }
274 
276  mark_t& operator<<=(unsigned i)
277  {
278  SPOT_WRAP_OP(id <<= i; return *this);
279  }
280 
282  mark_t operator>>(unsigned i) const
283  {
284  SPOT_WRAP_OP(return id >> i);
285  }
286 
288  mark_t& operator>>=(unsigned i)
289  {
290  SPOT_WRAP_OP(id >>= i; return *this);
291  }
292 #undef SPOT_WRAP_OP
293 
298  mark_t strip(mark_t y) const
299  {
300  // strip every bit of id that is marked in y
301  // 100101110100.strip(
302  // 001011001000)
303  // == 10 1 11 100
304  // == 10111100
305 
306  auto xv = id; // 100101110100
307  auto yv = y.id; // 001011001000
308 
309  while (yv && xv)
310  {
311  // Mask for everything after the last 1 in y
312  auto rm = (~yv) & (yv - 1); // 000000000111
313  // Mask for everything before the last 1 in y
314  auto lm = ~(yv ^ (yv - 1)); // 111111110000
315  xv = ((xv & lm) >> 1) | (xv & rm);
316  yv = (yv & lm) >> 1;
317  }
318  return xv;
319  }
320 
323  bool subset(mark_t m) const
324  {
325  return !((*this) - m);
326  }
327 
330  bool proper_subset(mark_t m) const
331  {
332  return *this != m && this->subset(m);
333  }
334 
336  unsigned count() const
337  {
338  return id.count();
339  }
340 
345  unsigned max_set() const
346  {
347  if (id)
348  return id.highest()+1;
349  else
350  return 0;
351  }
352 
357  unsigned min_set() const
358  {
359  if (id)
360  return id.lowest()+1;
361  else
362  return 0;
363  }
364 
369  mark_t lowest() const
370  {
371  return id & -id;
372  }
373 
375  bool is_singleton() const
376  {
377 #if __GNUC__
378  /* With GCC and Clang, count() is implemented using popcount. */
379  return count() == 1;
380 #else
381  return id && !(id & (id - 1));
382 #endif
383  }
384 
386  bool has_many() const
387  {
388 #if __GNUC__
389  /* With GCC and Clang, count() is implemented using popcount. */
390  return count() > 1;
391 #else
392  return !!(id & (id - 1));
393 #endif
394  }
395 
399  mark_t& remove_some(unsigned n)
400  {
401  while (n--)
402  id &= id - 1;
403  return *this;
404  }
405 
407  template<class iterator>
408  void fill(iterator here) const;
409 
411  spot::internal::mark_container sets() const;
412 
414  std::string as_string() const;
415  };
416 
418  enum class acc_op : unsigned
419  { Inf, Fin, InfNeg, FinNeg, And, Or };
420 
428  union acc_word
429  {
431  struct {
439  unsigned size:24;
440  } sub;
441  };
442 
455  struct SPOT_API acc_code: public std::vector<acc_word>
456  {
458  acc_code
460 
462  bool operator==(const acc_code& other) const
463  {
464  // We have two ways to represent t, unfortunately.
465  if (is_t() && other.is_t())
466  return true;
467  unsigned pos = size();
468  if (other.size() != pos)
469  return false;
470  while (pos > 0)
471  {
472  auto op = (*this)[pos - 1].sub.op;
473  auto sz = (*this)[pos - 1].sub.size;
474  if (other[pos - 1].sub.op != op ||
475  other[pos - 1].sub.size != sz)
476  return false;
477  switch (op)
478  {
479  case acc_cond::acc_op::And:
480  case acc_cond::acc_op::Or:
481  --pos;
482  break;
483  case acc_cond::acc_op::Inf:
484  case acc_cond::acc_op::InfNeg:
485  case acc_cond::acc_op::Fin:
486  case acc_cond::acc_op::FinNeg:
487  pos -= 2;
488  if (other[pos].mark != (*this)[pos].mark)
489  return false;
490  break;
491  }
492  }
493  return true;
494  };
495 
497  bool operator<(const acc_code& other) const
498  {
499  // We have two ways to represent t, unfortunately.
500  if (is_t() && other.is_t())
501  return false;
502  unsigned pos = size();
503  auto osize = other.size();
504  if (pos < osize)
505  return true;
506  if (pos > osize)
507  return false;
508  while (pos > 0)
509  {
510  auto op = (*this)[pos - 1].sub.op;
511  auto oop = other[pos - 1].sub.op;
512  if (op < oop)
513  return true;
514  if (op > oop)
515  return false;
516  auto sz = (*this)[pos - 1].sub.size;
517  auto osz = other[pos - 1].sub.size;
518  if (sz < osz)
519  return true;
520  if (sz > osz)
521  return false;
522  switch (op)
523  {
524  case acc_cond::acc_op::And:
525  case acc_cond::acc_op::Or:
526  --pos;
527  break;
528  case acc_cond::acc_op::Inf:
529  case acc_cond::acc_op::InfNeg:
530  case acc_cond::acc_op::Fin:
531  case acc_cond::acc_op::FinNeg:
532  {
533  pos -= 2;
534  auto m = (*this)[pos].mark;
535  auto om = other[pos].mark;
536  if (m < om)
537  return true;
538  if (m > om)
539  return false;
540  break;
541  }
542  }
543  }
544  return false;
545  }
546 
548  bool operator>(const acc_code& other) const
549  {
550  return other < *this;
551  }
552 
554  bool operator<=(const acc_code& other) const
555  {
556  return !(other < *this);
557  }
558 
560  bool operator>=(const acc_code& other) const
561  {
562  return !(*this < other);
563  }
564 
566  bool operator!=(const acc_code& other) const
567  {
568  return !(*this == other);
569  }
570 
575  bool is_t() const
576  {
577  // We store "t" as an empty condition, or as Inf({}).
578  unsigned s = size();
579  return s == 0 || ((*this)[s - 1].sub.op == acc_op::Inf
580  && !((*this)[s - 2].mark));
581  }
582 
589  bool is_f() const
590  {
591  // We store "f" as Fin({}).
592  unsigned s = size();
593  return s > 1
594  && (*this)[s - 1].sub.op == acc_op::Fin && !((*this)[s - 2].mark);
595  }
596 
597  private:
602  static constexpr size_t max_acc_formula_size_ = (1U << 24) - 1;
603 
604 #ifndef SWIG
606  [[noreturn]] static void report_too_large_acceptance_formula_()
607  {
608  throw std::runtime_error("acceptance formula is too large");
609  }
610 #endif
611 
612  public:
619  static acc_code f()
620  {
621  acc_code res;
622  res.resize(2);
623  res[0].mark = {};
624  res[1].sub.op = acc_op::Fin;
625  res[1].sub.size = 1;
626  return res;
627  }
628 
633  static acc_code t()
634  {
635  return {};
636  }
637 
645  static acc_code fin(mark_t m)
646  {
647  acc_code res;
648  res.resize(2);
649  res[0].mark = m;
650  res[1].sub.op = acc_op::Fin;
651  res[1].sub.size = 1;
652  return res;
653  }
654 
655  static acc_code fin(std::initializer_list<unsigned> vals)
656  {
657  return fin(mark_t(vals));
658  }
660 
678  {
679  acc_code res;
680  res.resize(2);
681  res[0].mark = m;
682  res[1].sub.op = acc_op::FinNeg;
683  res[1].sub.size = 1;
684  return res;
685  }
686 
687  static acc_code fin_neg(std::initializer_list<unsigned> vals)
688  {
689  return fin_neg(mark_t(vals));
690  }
692 
701  static acc_code inf(mark_t m)
702  {
703  acc_code res;
704  res.resize(2);
705  res[0].mark = m;
706  res[1].sub.op = acc_op::Inf;
707  res[1].sub.size = 1;
708  return res;
709  }
710 
711  static acc_code inf(std::initializer_list<unsigned> vals)
712  {
713  return inf(mark_t(vals));
714  }
716 
734  {
735  acc_code res;
736  res.resize(2);
737  res[0].mark = m;
738  res[1].sub.op = acc_op::InfNeg;
739  res[1].sub.size = 1;
740  return res;
741  }
742 
743  static acc_code inf_neg(std::initializer_list<unsigned> vals)
744  {
745  return inf_neg(mark_t(vals));
746  }
748 
752  static acc_code buchi()
753  {
754  return inf({0});
755  }
756 
760  static acc_code cobuchi()
761  {
762  return fin({0});
763  }
764 
770  static acc_code generalized_buchi(unsigned n)
771  {
772  if (n == 0)
773  return inf({});
774  acc_cond::mark_t m = mark_t::all();
775  m >>= mark_t::max_accsets() - n;
776  return inf(m);
777  }
778 
784  static acc_code generalized_co_buchi(unsigned n)
785  {
786  if (n == 0)
787  return fin({});
788  acc_cond::mark_t m = mark_t::all();
789  m >>= mark_t::max_accsets() - n;
790  return fin(m);
791  }
792 
797  static acc_code rabin(unsigned n)
798  {
799  acc_cond::acc_code res = f();
800  while (n > 0)
801  {
802  res |= inf({2*n - 1}) & fin({2*n - 2});
803  --n;
804  }
805  return res;
806  }
807 
812  static acc_code streett(unsigned n)
813  {
814  acc_cond::acc_code res = t();
815  while (n > 0)
816  {
817  res &= inf({2*n - 1}) | fin({2*n - 2});
818  --n;
819  }
820  return res;
821  }
822 
835  template<class Iterator>
836  static acc_code generalized_rabin(Iterator begin, Iterator end)
837  {
838  acc_cond::acc_code res = f();
839  unsigned n = 0;
840  for (Iterator i = begin; i != end; ++i)
841  {
842  unsigned f = n++;
843  acc_cond::mark_t m = {};
844  for (unsigned ni = *i; ni > 0; --ni)
845  m.set(n++);
846  auto pair = inf(m) & fin({f});
847  std::swap(pair, res);
848  res |= std::move(pair);
849  }
850  return res;
851  }
852 
860  static acc_code parity(bool is_max, bool is_odd, unsigned sets);
861  static acc_code parity_max(bool is_odd, unsigned sets)
862  {
863  return parity(true, is_odd, sets);
864  }
865  static acc_code parity_max_odd(unsigned sets)
866  {
867  return parity_max(true, sets);
868  }
869  static acc_code parity_max_even(unsigned sets)
870  {
871  return parity_max(false, sets);
872  }
873  static acc_code parity_min(bool is_odd, unsigned sets)
874  {
875  return parity(false, is_odd, sets);
876  }
877  static acc_code parity_min_odd(unsigned sets)
878  {
879  return parity_min(true, sets);
880  }
881  static acc_code parity_min_even(unsigned sets)
882  {
883  return parity_min(false, sets);
884  }
886 
903  static acc_code random(unsigned n, double reuse = 0.0);
904 
907  {
908  if (is_t() || r.is_f())
909  {
910  *this = r;
911  return *this;
912  }
913  if (is_f() || r.is_t())
914  return *this;
915  unsigned s = size() - 1;
916  unsigned rs = r.size() - 1;
917  // We want to group all Inf(x) operators:
918  // Inf(a) & Inf(b) = Inf(a & b)
919  if (((*this)[s].sub.op == acc_op::Inf
920  && r[rs].sub.op == acc_op::Inf)
921  || ((*this)[s].sub.op == acc_op::InfNeg
922  && r[rs].sub.op == acc_op::InfNeg))
923  {
924  (*this)[s - 1].mark |= r[rs - 1].mark;
925  return *this;
926  }
927 
928  // In the more complex scenarios, left and right may both
929  // be conjunctions, and Inf(x) might be a member of each
930  // side. Find it if it exists.
931  // left_inf points to the left Inf mark if any.
932  // right_inf points to the right Inf mark if any.
933  acc_word* left_inf = nullptr;
934  if ((*this)[s].sub.op == acc_op::And)
935  {
936  auto start = &(*this)[s] - (*this)[s].sub.size;
937  auto pos = &(*this)[s] - 1;
938  pop_back();
939  while (pos > start)
940  {
941  if (pos->sub.op == acc_op::Inf)
942  {
943  left_inf = pos - 1;
944  break;
945  }
946  pos -= pos->sub.size + 1;
947  }
948  }
949  else if ((*this)[s].sub.op == acc_op::Inf)
950  {
951  left_inf = &(*this)[s - 1];
952  }
953 
954  const acc_word* right_inf = nullptr;
955  auto right_end = &r.back();
956  if (right_end->sub.op == acc_op::And)
957  {
958  auto start = &r[0];
959  auto pos = --right_end;
960  while (pos > start)
961  {
962  if (pos->sub.op == acc_op::Inf)
963  {
964  right_inf = pos - 1;
965  break;
966  }
967  pos -= pos->sub.size + 1;
968  }
969  }
970  else if (right_end->sub.op == acc_op::Inf)
971  {
972  right_inf = right_end - 1;
973  }
974 
975  acc_cond::mark_t carry = {};
976  if (left_inf && right_inf)
977  {
978  carry = left_inf->mark;
979  auto pos = left_inf - &(*this)[0];
980  erase(begin() + pos, begin() + pos + 2);
981  }
982  auto sz = size();
983  insert(end(), &r[0], right_end + 1);
984  if (carry)
985  (*this)[sz + (right_inf - &r[0])].mark |= carry;
986 
987  acc_word w = {};
988  w.sub.op = acc_op::And;
989  auto new_size = size();
990  if (SPOT_UNLIKELY(new_size > max_acc_formula_size_))
991  report_too_large_acceptance_formula_();
992  w.sub.size = new_size;
993  emplace_back(w);
994  return *this;
995  }
996 
998  acc_code operator&(const acc_code& r) const
999  {
1000  acc_code res = *this;
1001  res &= r;
1002  return res;
1003  }
1004 
1005 #ifndef SWIG
1008  {
1009  acc_code res = *this;
1010  res &= r;
1011  return res;
1012  }
1013 #endif // SWIG
1014 
1017  {
1018  if (is_t() || r.is_f())
1019  return *this;
1020  if (is_f() || r.is_t())
1021  {
1022  *this = r;
1023  return *this;
1024  }
1025  unsigned s = size() - 1;
1026  unsigned rs = r.size() - 1;
1027  // Fin(a) | Fin(b) = Fin(a | b)
1028  if (((*this)[s].sub.op == acc_op::Fin
1029  && r[rs].sub.op == acc_op::Fin)
1030  || ((*this)[s].sub.op == acc_op::FinNeg
1031  && r[rs].sub.op == acc_op::FinNeg))
1032  {
1033  (*this)[s - 1].mark |= r[rs - 1].mark;
1034  return *this;
1035  }
1036 
1037  // In the more complex scenarios, left and right may both
1038  // be disjunctions, and Fin(x) might be a member of each
1039  // side. Find it if it exists.
1040  // left_inf points to the left Inf mark if any.
1041  // right_inf points to the right Inf mark if any.
1042  acc_word* left_fin = nullptr;
1043  if ((*this)[s].sub.op == acc_op::Or)
1044  {
1045  auto start = &(*this)[s] - (*this)[s].sub.size;
1046  auto pos = &(*this)[s] - 1;
1047  pop_back();
1048  while (pos > start)
1049  {
1050  if (pos->sub.op == acc_op::Fin)
1051  {
1052  left_fin = pos - 1;
1053  break;
1054  }
1055  pos -= pos->sub.size + 1;
1056  }
1057  }
1058  else if ((*this)[s].sub.op == acc_op::Fin)
1059  {
1060  left_fin = &(*this)[s - 1];
1061  }
1062 
1063  const acc_word* right_fin = nullptr;
1064  auto right_end = &r.back();
1065  if (right_end->sub.op == acc_op::Or)
1066  {
1067  auto start = &r[0];
1068  auto pos = --right_end;
1069  while (pos > start)
1070  {
1071  if (pos->sub.op == acc_op::Fin)
1072  {
1073  right_fin = pos - 1;
1074  break;
1075  }
1076  pos -= pos->sub.size + 1;
1077  }
1078  }
1079  else if (right_end->sub.op == acc_op::Fin)
1080  {
1081  right_fin = right_end - 1;
1082  }
1083 
1084  acc_cond::mark_t carry = {};
1085  if (left_fin && right_fin)
1086  {
1087  carry = left_fin->mark;
1088  auto pos = (left_fin - &(*this)[0]);
1089  this->erase(begin() + pos, begin() + pos + 2);
1090  }
1091  auto sz = size();
1092  insert(end(), &r[0], right_end + 1);
1093  if (carry)
1094  (*this)[sz + (right_fin - &r[0])].mark |= carry;
1095  acc_word w = {};
1096  w.sub.op = acc_op::Or;
1097  auto new_size = size();
1098  if (SPOT_UNLIKELY(new_size > max_acc_formula_size_))
1099  report_too_large_acceptance_formula_();
1100  w.sub.size = new_size;
1101  emplace_back(w);
1102  return *this;
1103  }
1104 
1105 #ifndef SWIG
1108  {
1109  acc_code res = *this;
1110  res |= r;
1111  return res;
1112  }
1113 #endif // SWIG
1114 
1116  acc_code operator|(const acc_code& r) const
1117  {
1118  acc_code res = *this;
1119  res |= r;
1120  return res;
1121  }
1122 
1128  acc_code& operator<<=(unsigned sets)
1129  {
1130  if (SPOT_UNLIKELY(sets >= mark_t::max_accsets()))
1131  report_too_many_sets();
1132  if (empty())
1133  return *this;
1134  unsigned pos = size();
1135  do
1136  {
1137  switch ((*this)[pos - 1].sub.op)
1138  {
1139  case acc_cond::acc_op::And:
1140  case acc_cond::acc_op::Or:
1141  --pos;
1142  break;
1143  case acc_cond::acc_op::Inf:
1144  case acc_cond::acc_op::InfNeg:
1145  case acc_cond::acc_op::Fin:
1146  case acc_cond::acc_op::FinNeg:
1147  pos -= 2;
1148  (*this)[pos].mark <<= sets;
1149  break;
1150  }
1151  }
1152  while (pos > 0);
1153  return *this;
1154  }
1155 
1159  acc_code operator<<(unsigned sets) const
1160  {
1161  acc_code res = *this;
1162  res <<= sets;
1163  return res;
1164  }
1165 
1172  bool is_dnf() const;
1173 
1180  bool is_cnf() const;
1181 
1192  acc_code to_dnf() const;
1193 
1200  acc_code to_cnf() const;
1201 
1206  bdd to_bdd(const bdd* map) const;
1207 
1216  std::vector<acc_code> top_disjuncts() const;
1217 
1226  std::vector<acc_code> top_conjuncts() const;
1227 
1239 
1253  mark_t fin_unit() const;
1254 
1267  mark_t mafins() const;
1268 
1280  mark_t inf_unit() const;
1281 
1286  int fin_one() const;
1287 
1308  std::pair<int, acc_code> fin_one_extract() const;
1309 
1328  std::tuple<int, acc_cond::acc_code, acc_cond::acc_code>
1330  std::tuple<int, acc_cond::acc_code, acc_cond::acc_code>
1333 
1349  std::vector<std::pair<acc_cond::mark_t, acc_cond::acc_code>>
1350  mafins_split() const;
1351 
1364  std::vector<std::vector<int>>
1365  missing(mark_t inf, bool accepting) const;
1366 
1369  bool accepting(mark_t inf) const;
1370 
1377  bool inf_satisfiable(mark_t inf) const;
1378 
1390  trival maybe_accepting(mark_t infinitely_often,
1391  mark_t always_present) const;
1392 
1406  trival weakly_accepting(mark_t infinitely_often,
1407  mark_t always_present) const;
1408 
1419  std::vector<unsigned> symmetries() const;
1420 
1434  acc_code remove(acc_cond::mark_t rem, bool missing) const;
1435 
1440  acc_code strip(acc_cond::mark_t rem, bool missing) const;
1443 
1450 
1453 
1465  std::vector<std::pair<acc_cond::mark_t, acc_cond::mark_t>>
1467 
1475 
1477  std::pair<acc_cond::mark_t, acc_cond::mark_t> used_inf_fin_sets() const;
1478 
1483  std::ostream&
1484  to_html(std::ostream& os,
1485  std::function<void(std::ostream&, int)>
1486  set_printer = nullptr) const;
1487 
1492  std::ostream&
1493  to_text(std::ostream& os,
1494  std::function<void(std::ostream&, int)>
1495  set_printer = nullptr) const;
1496 
1501  std::ostream&
1502  to_latex(std::ostream& os,
1503  std::function<void(std::ostream&, int)>
1504  set_printer = nullptr) const;
1505 
1528  acc_code(const char* input);
1529 
1534  {
1535  }
1536 
1538  acc_code(const acc_word* other)
1539  : std::vector<acc_word>(other - other->sub.size, other + 1)
1540  {
1541  }
1542 
1543  };
1544 
1552  acc_cond(unsigned n_sets = 0, const acc_code& code = {})
1553  : num_(0U), all_({}), code_(code)
1554  {
1555  add_sets(n_sets);
1556  uses_fin_acceptance_ = check_fin_acceptance();
1557  }
1558 
1563  acc_cond(const acc_code& code)
1564  : num_(0U), all_({}), code_(code)
1565  {
1566  add_sets(code.used_sets().max_set());
1567  uses_fin_acceptance_ = check_fin_acceptance();
1568  }
1569 
1571  acc_cond(const acc_cond& o)
1572  : num_(o.num_), all_(o.all_), code_(o.code_),
1573  uses_fin_acceptance_(o.uses_fin_acceptance_)
1574  {
1575  }
1576 
1579  {
1580  num_ = o.num_;
1581  all_ = o.all_;
1582  code_ = o.code_;
1583  uses_fin_acceptance_ = o.uses_fin_acceptance_;
1584  return *this;
1585  }
1586 
1587  ~acc_cond()
1588  {
1589  }
1590 
1594  void set_acceptance(const acc_code& code)
1595  {
1596  code_ = code;
1597  uses_fin_acceptance_ = check_fin_acceptance();
1598  }
1599 
1601  const acc_code& get_acceptance() const
1602  {
1603  return code_;
1604  }
1605 
1608  {
1609  return code_;
1610  }
1611 
1613  bool operator==(const acc_cond& other) const
1614  {
1615  if (other.num_sets() != num_)
1616  return false;
1617  const acc_code& ocode = other.get_acceptance();
1618  // We have two ways to represent t, unfortunately.
1619  return (ocode == code_ || (ocode.is_t() && code_.is_t()));
1620  }
1621 
1623  bool operator!=(const acc_cond& other) const
1624  {
1625  return !(*this == other);
1626  }
1627 
1629  bool uses_fin_acceptance() const
1630  {
1631  return uses_fin_acceptance_;
1632  }
1633 
1635  bool is_t() const
1636  {
1637  return code_.is_t();
1638  }
1639 
1644  bool is_all() const
1645  {
1646  return num_ == 0 && is_t();
1647  }
1648 
1650  bool is_f() const
1651  {
1652  return code_.is_f();
1653  }
1654 
1659  bool is_none() const
1660  {
1661  return num_ == 0 && is_f();
1662  }
1663 
1668  bool is_buchi() const
1669  {
1670  unsigned s = code_.size();
1671  return num_ == 1 &&
1672  s == 2 && code_[1].sub.op == acc_op::Inf && code_[0].mark == all_sets();
1673  }
1674 
1679  bool is_co_buchi() const
1680  {
1681  return num_ == 1 && is_generalized_co_buchi();
1682  }
1683 
1687  {
1688  set_acceptance(inf(all_sets()));
1689  }
1690 
1694  {
1695  set_acceptance(fin(all_sets()));
1696  }
1697 
1703  {
1704  unsigned s = code_.size();
1705  return (s == 0 && num_ == 0) || (s == 2 && code_[1].sub.op == acc_op::Inf
1706  && code_[0].mark == all_sets());
1707  }
1708 
1714  {
1715  unsigned s = code_.size();
1716  return (s == 2 &&
1717  code_[1].sub.op == acc_op::Fin && code_[0].mark == all_sets());
1718  }
1719 
1731  int is_rabin() const;
1732 
1744  int is_streett() const;
1745 
1755  struct SPOT_API rs_pair
1756  {
1757 #ifndef SWIG
1758  rs_pair() = default;
1760  rs_pair(const rs_pair&) = default;
1762  rs_pair& operator=(const rs_pair&) = default;
1763 #endif
1764 
1767  fin(fin),
1768  inf(inf)
1769  {}
1772 
1774  bool operator==(rs_pair o) const
1775  {
1776  return fin == o.fin && inf == o.inf;
1777  }
1779  bool operator!=(rs_pair o) const
1780  {
1781  return fin != o.fin || inf != o.inf;
1782  }
1784  bool operator<(rs_pair o) const
1785  {
1786  return fin < o.fin || (!(o.fin < fin) && inf < o.inf);
1787  }
1789  bool operator<=(rs_pair o) const
1790  {
1791  return !(o < *this);
1792  }
1794  bool operator>(rs_pair o) const
1795  {
1796  return o < *this;
1797  }
1799  bool operator>=(rs_pair o) const
1800  {
1801  return !(*this < o);
1802  }
1803  };
1814  bool is_streett_like(std::vector<rs_pair>& pairs) const;
1815 
1826  bool is_rabin_like(std::vector<rs_pair>& pairs) const;
1827 
1837  bool is_generalized_rabin(std::vector<unsigned>& pairs) const;
1838 
1851  bool is_generalized_streett(std::vector<unsigned>& pairs) const;
1852 
1862  bool is_parity(bool& max, bool& odd, bool equiv = false) const;
1863 
1864 
1867  bool is_parity() const
1868  {
1869  bool max;
1870  bool odd;
1871  return is_parity(max, odd);
1872  }
1873 
1882  {
1883  return acc_cond(num_, code_.unit_propagation());
1884  }
1885 
1890  std::pair<bool, acc_cond::mark_t> unsat_mark() const
1891  {
1892  return sat_unsat_mark(false);
1893  }
1898  std::pair<bool, acc_cond::mark_t> sat_mark() const
1899  {
1900  return sat_unsat_mark(true);
1901  }
1902 
1903  protected:
1905  bool check_fin_acceptance() const;
1907  std::pair<bool, acc_cond::mark_t> sat_unsat_mark(bool) const;
1908 
1909  public:
1918  static acc_code inf(mark_t mark)
1919  {
1920  return acc_code::inf(mark);
1921  }
1922 
1923  static acc_code inf(std::initializer_list<unsigned> vals)
1924  {
1925  return inf(mark_t(vals.begin(), vals.end()));
1926  }
1928 
1945  static acc_code inf_neg(mark_t mark)
1946  {
1947  return acc_code::inf_neg(mark);
1948  }
1949 
1950  static acc_code inf_neg(std::initializer_list<unsigned> vals)
1951  {
1952  return inf_neg(mark_t(vals.begin(), vals.end()));
1953  }
1955 
1963  static acc_code fin(mark_t mark)
1964  {
1965  return acc_code::fin(mark);
1966  }
1967 
1968  static acc_code fin(std::initializer_list<unsigned> vals)
1969  {
1970  return fin(mark_t(vals.begin(), vals.end()));
1971  }
1973 
1990  static acc_code fin_neg(mark_t mark)
1991  {
1992  return acc_code::fin_neg(mark);
1993  }
1994 
1995  static acc_code fin_neg(std::initializer_list<unsigned> vals)
1996  {
1997  return fin_neg(mark_t(vals.begin(), vals.end()));
1998  }
2000 
2005  unsigned add_sets(unsigned num)
2006  {
2007  if (num == 0)
2008  return -1U;
2009  unsigned j = num_;
2010  num += j;
2011  if (num > mark_t::max_accsets())
2012  report_too_many_sets();
2013  // Make sure we do not update if we raised an exception.
2014  num_ = num;
2015  all_ = all_sets_();
2016  return j;
2017  }
2018 
2023  unsigned add_set()
2024  {
2025  return add_sets(1);
2026  }
2027 
2029  mark_t mark(unsigned u) const
2030  {
2031  SPOT_ASSERT(u < num_sets());
2032  return mark_t({u});
2033  }
2034 
2039  mark_t comp(const mark_t& l) const
2040  {
2041  return all_ ^ l;
2042  }
2043 
2046  {
2047  return all_;
2048  }
2049 
2052  bool accepting(mark_t inf) const
2053  {
2054  return code_.accepting(inf);
2055  }
2056 
2062  bool inf_satisfiable(mark_t inf) const
2063  {
2064  return code_.inf_satisfiable(inf);
2065  }
2066 
2073  {
2074  return {num_sets(), code_.keep_one_inf_per_branch()};
2075  }
2076 
2088  trival maybe_accepting(mark_t infinitely_often, mark_t always_present) const
2089  {
2090  return code_.maybe_accepting(infinitely_often, always_present);
2091  }
2092 
2106  trival
2107  weakly_accepting(mark_t infinitely_often, mark_t always_present) const
2108  {
2109  return code_.weakly_accepting(infinitely_often, always_present);
2110  }
2111 
2126 
2128  unsigned num_sets() const
2129  {
2130  return num_;
2131  }
2132 
2140  template<class iterator>
2141  mark_t useless(iterator begin, iterator end) const
2142  {
2143  mark_t u = {}; // The set of useless sets
2144  for (unsigned x = 0; x < num_; ++x)
2145  {
2146  // Skip sets that are already known to be useless.
2147  if (u.has(x))
2148  continue;
2149  auto all = comp(u | mark_t({x}));
2150  // Iterate over all mark_t, and keep track of
2151  // set numbers that always appear with x.
2152  for (iterator y = begin; y != end; ++y)
2153  {
2154  const mark_t& v = *y;
2155  if (v.has(x))
2156  {
2157  all &= v;
2158  if (!all)
2159  break;
2160  }
2161  }
2162  u |= all;
2163  }
2164  return u;
2165  }
2166 
2180  acc_cond remove(mark_t rem, bool missing) const
2181  {
2182  return {num_sets(), code_.remove(rem, missing)};
2183  }
2184 
2189  acc_cond strip(mark_t rem, bool missing) const
2190  {
2191  return
2192  { num_sets() - (all_sets() & rem).count(), code_.strip(rem, missing) };
2193  }
2194 
2197  {
2198  return {num_sets(), code_.force_inf(m)};
2199  }
2200 
2204  {
2205  return {num_sets(), code_.remove(all_sets() - rem, true)};
2206  }
2207 
2219  std::string name(const char* fmt = "alo") const;
2220 
2235  {
2236  return code_.fin_unit();
2237  }
2238 
2251  mark_t mafins() const
2252  {
2253  return code_.mafins();
2254  }
2255 
2260  std::vector<std::pair<mark_t, acc_cond>> mafins_split() const
2261  {
2262  auto v = code_.mafins_split();
2263  std::vector<std::pair<mark_t, acc_cond>> result;
2264  result.reserve(v.size());
2265  for (auto& [m, c] : v)
2266  result.emplace_back(m, acc_cond(num_, c));
2267  return result;
2268  }
2269 
2282  {
2283  return code_.inf_unit();
2284  }
2285 
2290  int fin_one() const
2291  {
2292  return code_.fin_one();
2293  }
2294 
2315  std::pair<int, acc_cond> fin_one_extract() const
2316  {
2317  auto [f, c] = code_.fin_one_extract();
2318  return {f, {num_sets(), std::move(c)}};
2319  }
2320 
2339  std::tuple<int, acc_cond, acc_cond>
2341  {
2342  auto [f, l, r] = code_.fin_unit_one_split();
2343  return {f, {num_sets(), std::move(l)}, {num_sets(), std::move(r)}};
2344  }
2345  std::tuple<int, acc_cond, acc_cond>
2347  {
2348  auto [f, l, r] = code_.fin_unit_one_split_improved();
2349  return {f, {num_sets(), std::move(l)}, {num_sets(), std::move(r)}};
2350  }
2352 
2361  std::vector<acc_cond> top_disjuncts() const;
2362 
2371  std::vector<acc_cond> top_conjuncts() const;
2372 
2373  protected:
2376  {
2377  return mark_t::all() >> (spot::acc_cond::mark_t::max_accsets() - num_);
2378  }
2379 
2380  unsigned num_;
2384  bool uses_fin_acceptance_ = false;
2385 
2386  };
2387 
2390  struct rs_pairs_view {
2392  typedef std::vector<acc_cond::rs_pair> rs_pairs;
2393 
2395  explicit rs_pairs_view(const rs_pairs& p, const acc_cond::mark_t& m)
2396  : pairs_(p), view_marks_(m) {}
2397 
2399  explicit rs_pairs_view(const rs_pairs& p)
2400  : rs_pairs_view(p, acc_cond::mark_t::all()) {}
2401 
2404  {
2405  return do_view([&](const acc_cond::rs_pair& p)
2406  {
2407  return visible(p.inf) ? p.inf : acc_cond::mark_t({});
2408  });
2409  }
2410 
2413  {
2414  return do_view([&](const acc_cond::rs_pair& p)
2415  {
2416  return visible(p.fin) ? p.fin : acc_cond::mark_t({});
2417  });
2418  }
2419 
2422  {
2423  return do_view([&](const acc_cond::rs_pair& p)
2424  {
2425  return !visible(p.inf) && visible(p.fin) ? p.fin
2426  : acc_cond::mark_t({});
2427  });
2428  }
2429 
2432  {
2433  return do_view([&](const acc_cond::rs_pair& p)
2434  {
2435  return !visible(p.fin) && visible(p.inf) ? p.inf
2436  : acc_cond::mark_t({});
2437  });
2438  }
2439 
2443  acc_cond::mark_t paired_with_fin(unsigned mark) const
2444  {
2445  acc_cond::mark_t res = {};
2446  for (const auto& p: pairs_)
2447  if (p.fin.has(mark) && visible(p.fin) && visible(p.inf))
2448  res |= p.inf;
2449  return res;
2450  }
2451 
2453  const rs_pairs& pairs() const
2454  {
2455  return pairs_;
2456  }
2457 
2458  private:
2459  template<typename filter>
2460  acc_cond::mark_t do_view(const filter& filt) const
2461  {
2462  acc_cond::mark_t res = {};
2463  for (const auto& p: pairs_)
2464  res |= filt(p);
2465  return res;
2466  }
2467 
2468  bool visible(const acc_cond::mark_t& v) const
2469  {
2470  return !!(view_marks_ & v);
2471  }
2472 
2473  const rs_pairs& pairs_;
2474  acc_cond::mark_t view_marks_;
2475  };
2476 
2477 
2478  SPOT_API
2479  std::ostream& operator<<(std::ostream& os, const acc_cond& acc);
2480 
2481  // The next two operators used to be declared as friend inside the
2482  // acc_cond::mark_t and acc_cond::acc_code, but Swig 4.2.1
2483  // introduced a bug with friend operators. See
2484  // https://github.com/swig/swig/issues/2845
2485 
2486  SPOT_API
2487  std::ostream& operator<<(std::ostream& os, acc_cond::mark_t m);
2488 
2490  SPOT_API
2491  std::ostream& operator<<(std::ostream& os,
2492  const acc_cond::acc_code& code);
2493 
2495 
2496  namespace internal
2497  {
2498  class SPOT_API mark_iterator
2499  {
2500  public:
2501  typedef unsigned value_type;
2502  typedef const value_type& reference;
2503  typedef const value_type* pointer;
2504  typedef std::ptrdiff_t difference_type;
2505  typedef std::forward_iterator_tag iterator_category;
2506 
2507  mark_iterator() noexcept
2508  : m_({})
2509  {
2510  }
2511 
2512  mark_iterator(acc_cond::mark_t m) noexcept
2513  : m_(m)
2514  {
2515  }
2516 
2517  bool operator==(mark_iterator m) const
2518  {
2519  return m_ == m.m_;
2520  }
2521 
2522  bool operator!=(mark_iterator m) const
2523  {
2524  return m_ != m.m_;
2525  }
2526 
2527  value_type operator*() const
2528  {
2529  SPOT_ASSERT(m_);
2530  return m_.min_set() - 1;
2531  }
2532 
2533  mark_iterator& operator++()
2534  {
2535  m_.clear(this->operator*());
2536  return *this;
2537  }
2538 
2539  mark_iterator operator++(int)
2540  {
2541  mark_iterator it = *this;
2542  ++(*this);
2543  return it;
2544  }
2545  private:
2546  acc_cond::mark_t m_;
2547  };
2548 
2549  class SPOT_API mark_container
2550  {
2551  public:
2552  mark_container(spot::acc_cond::mark_t m) noexcept
2553  : m_(m)
2554  {
2555  }
2556 
2557  mark_iterator begin() const
2558  {
2559  return {m_};
2560  }
2561  mark_iterator end() const
2562  {
2563  return {};
2564  }
2565  private:
2567  };
2568  }
2569 
2570  inline spot::internal::mark_container acc_cond::mark_t::sets() const
2571  {
2572  return {*this};
2573  }
2574 
2575  template<class iterator>
2576  void acc_cond::mark_t::fill(iterator here) const
2577  {
2578  for (unsigned s : sets())
2579  *here++ = s;
2580  }
2581 }
2582 
2583 namespace std
2584 {
2587  template<>
2588  struct hash<spot::acc_cond::mark_t>
2589  {
2591  size_t operator()(spot::acc_cond::mark_t m) const noexcept
2592  {
2593  return m.hash();
2594  }
2595  };
2596 }
An acceptance condition.
Definition: acc.hh:54
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:2062
mark_t all_sets() const
Construct a mark_t with all declared sets.
Definition: acc.hh:2045
static acc_code fin_neg(mark_t mark)
Construct a generalized co-Büchi acceptance for complemented sets.
Definition: acc.hh:1990
mark_t mafins() const
Find a Fin(i) that is mandatory.
Definition: acc.hh:2251
static acc_code inf_neg(mark_t mark)
Construct a generalized Büchi acceptance for complemented sets.
Definition: acc.hh:1945
std::pair< bool, acc_cond::mark_t > sat_unsat_mark(bool) const
Shared implementation for sat_mark() and unsat_mark().
acc_cond unit_propagation()
Remove superfluous Fin and Inf by unit propagation.
Definition: acc.hh:1881
void set_generalized_co_buchi()
Change the acceptance condition to generalized-co-Büchi, over all declared sets.
Definition: acc.hh:1693
std::pair< bool, acc_cond::mark_t > unsat_mark() const
Return an unsatisfying mark if one exists.
Definition: acc.hh:1890
const acc_code & get_acceptance() const
Retrieve the acceptance formula.
Definition: acc.hh:1601
bool operator==(const acc_cond &other) const
Equality: same number of sets and equivalent formula.
Definition: acc.hh:1613
static acc_code fin(mark_t mark)
Construct a generalized co-Büchi acceptance.
Definition: acc.hh:1963
bool is_co_buchi() const
Whether the acceptance condition is "co-Büchi".
Definition: acc.hh:1679
bool accepting(mark_t inf) const
Check whether visiting exactly all sets inf infinitely often satisfies the acceptance condition.
Definition: acc.hh:2052
static acc_code inf(mark_t mark)
Construct a generalized Büchi acceptance.
Definition: acc.hh:1918
unsigned num_
Number of declared acceptance sets.
Definition: acc.hh:2380
bool is_generalized_buchi() const
Whether the acceptance condition is "generalized-Büchi".
Definition: acc.hh:1702
static acc_code fin_neg(std::initializer_list< unsigned > vals)
Construct a generalized co-Büchi acceptance for complemented sets.
Definition: acc.hh:1995
static acc_code inf(std::initializer_list< unsigned > vals)
Construct a generalized Büchi acceptance.
Definition: acc.hh:1923
unsigned add_set()
Add a single set to the acceptance condition.
Definition: acc.hh:2023
bool check_fin_acceptance() const
Recompute whether the formula uses Fin acceptance.
bool is_parity(bool &max, bool &odd, bool equiv=false) const
Check if the acceptance condition matches one of the four type of parity acceptance defined in the HO...
mark_t mark(unsigned u) const
Build a mark_t with a single set.
Definition: acc.hh:2029
void set_generalized_buchi()
Change the acceptance condition to generalized-Büchi, over all declared sets.
Definition: acc.hh:1686
acc_cond force_inf(mark_t m) const
For all x in m, replaces Fin(x) by false.
Definition: acc.hh:2196
acc_cond remove(mark_t rem, bool missing) const
Remove all the acceptance sets in rem.
Definition: acc.hh:2180
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:2340
acc_cond(unsigned n_sets=0, const acc_code &code={})
Build an acceptance condition.
Definition: acc.hh:1552
unsigned add_sets(unsigned num)
Add more sets to the acceptance condition.
Definition: acc.hh:2005
bool is_parity() const
Check if the acceptance condition matches one of the four type of parity acceptance defined in the HO...
Definition: acc.hh:1867
bool is_t() const
Whether the acceptance formula is "t" (true)
Definition: acc.hh:1635
trival weakly_accepting(mark_t infinitely_often, mark_t always_present) const
Check if cycles in a SCC are all accepting, all rejecting, or mixed.
Definition: acc.hh:2107
bool is_generalized_rabin(std::vector< unsigned > &pairs) const
Is the acceptance condition generalized-Rabin?
acc_op
Operators for acceptance formulas.
Definition: acc.hh:419
mark_t comp(const mark_t &l) const
Complement a mark_t.
Definition: acc.hh:2039
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:2072
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:2346
std::vector< acc_cond > top_conjuncts() const
Return the top-level conjuncts.
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:2315
static acc_code fin(std::initializer_list< unsigned > vals)
Construct a generalized co-Büchi acceptance.
Definition: acc.hh:1968
bool is_generalized_co_buchi() const
Whether the acceptance condition is "generalized-co-Büchi".
Definition: acc.hh:1713
std::vector< std::pair< mark_t, acc_cond > > mafins_split() const
Split an acceptance condition into disjuncts according to mandatory fins.
Definition: acc.hh:2260
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:2203
trival maybe_accepting(mark_t infinitely_often, mark_t always_present) const
Check potential acceptance of an SCC.
Definition: acc.hh:2088
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:1659
void set_acceptance(const acc_code &code)
Change the acceptance formula.
Definition: acc.hh:1594
int is_rabin() const
Check if the acceptance condition matches the Rabin acceptance of the HOA format.
bool uses_fin_acceptance_
Whether the formula contains any Fin term.
Definition: acc.hh:2384
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:1644
acc_cond strip(mark_t rem, bool missing) const
Remove acceptance sets, and shift set numbers.
Definition: acc.hh:2189
int fin_one() const
Return one acceptance set i that appear as Fin(i) in the condition.
Definition: acc.hh:2290
mark_t all_sets_() const
Returns a mark with one bit set per declared acceptance set.
Definition: acc.hh:2375
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:2141
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:2234
acc_code & get_acceptance()
Retrieve the acceptance formula.
Definition: acc.hh:1607
mark_t all_
Precomputed all_sets_() value.
Definition: acc.hh:2381
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:1563
acc_cond(const acc_cond &o)
Copy an acceptance condition.
Definition: acc.hh:1571
std::pair< bool, acc_cond::mark_t > sat_mark() const
Return a satisfying mark if one exists.
Definition: acc.hh:1898
acc_code code_
Definition: acc.hh:2382
acc_cond & operator=(const acc_cond &o)
Copy an acceptance condition.
Definition: acc.hh:1578
bool operator!=(const acc_cond &other) const
Inequality comparison.
Definition: acc.hh:1623
static acc_code inf_neg(std::initializer_list< unsigned > vals)
Construct a generalized Büchi acceptance for complemented sets.
Definition: acc.hh:1950
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:1668
mark_t inf_unit() const
Find a Inf(i) that is a unit clause.
Definition: acc.hh:2281
bool uses_fin_acceptance() const
Whether the acceptance condition uses Fin terms.
Definition: acc.hh:1629
bool is_f() const
Whether the acceptance formula is "f" (false)
Definition: acc.hh:1650
unsigned num_sets() const
The number of sets used in the acceptance condition.
Definition: acc.hh:2128
std::vector< acc_cond > top_disjuncts() const
Return the top-level disjuncts.
A fixed-size bitset backed by N unsigned words.
Definition: bitset.hh:40
A class implementing Kleene's three-valued logic.
Definition: trival.hh:33
op
Operator types.
Definition: formula.hh:85
@ Or
(omega-Rational) Or
@ U
until
@ And
(omega-Rational) And
scc_info_options operator&(scc_info_options left, scc_info_options right)
Bitwise AND of two scc_info_options values.
Definition: sccinfo.hh:427
Definition: automata.hh:26
std::ostream & operator<<(std::ostream &os, const mc_algorithm &ma)
Print an mc_algorithm value to a stream.
Definition: mc.hh:74
constexpr bool operator==(trival a, trival b)
Equality comparison of two trival values.
Definition: trival.hh:134
constexpr bool operator!=(trival a, trival b)
Inequality comparison of two trival values.
Definition: trival.hh:140
An acceptance formula.
Definition: acc.hh:456
std::vector< std::pair< acc_cond::mark_t, acc_cond::mark_t > > useless_colors_patterns() const
Find patterns of useless colors.
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.
static acc_code parity_max(bool is_odd, unsigned sets)
Build a parity acceptance condition.
Definition: acc.hh:861
bool operator!=(const acc_code &other) const
Inequality comparison of acceptance formulas.
Definition: acc.hh:566
mark_t mafins() const
Find a Fin(i) that is mandatory.
static acc_code inf(mark_t m)
Construct a generalized Büchi acceptance.
Definition: acc.hh:701
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:1007
acc_code force_inf(mark_t m) const
For all x in m, replaces Fin(x) by false.
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_neg(std::initializer_list< unsigned > vals)
Construct a generalized Büchi acceptance for complemented sets.
Definition: acc.hh:743
std::vector< std::pair< acc_cond::mark_t, acc_cond::acc_code > > mafins_split() const
Split an acceptance conditions into disjuncts according to mandatory fins.
std::vector< acc_code > top_disjuncts() const
Return the top-level disjuncts.
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.
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:1116
std::vector< std::vector< int > > missing(mark_t inf, bool accepting) const
Help closing accepting or rejecting cycle.
acc_code operator|(acc_code &&r) const
Disjunct the current condition with r.
Definition: acc.hh:1107
static acc_code fin(std::initializer_list< unsigned > vals)
Construct a generalized co-Büchi acceptance.
Definition: acc.hh:655
bool is_dnf() const
Whether the acceptance formula is in disjunctive normal form.
acc_code operator&(const acc_code &r) const
Conjunct the current condition with r.
Definition: acc.hh:998
static acc_code inf(std::initializer_list< unsigned > vals)
Construct a generalized Büchi acceptance.
Definition: acc.hh:711
static acc_code parity_min_even(unsigned sets)
Build a parity acceptance condition.
Definition: acc.hh:881
static acc_code parity(bool is_max, bool is_odd, unsigned sets)
Build a parity acceptance 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.
mark_t used_once_sets() const
Return the sets that appears only once in the acceptance.
bool is_f() const
Is this the "false" acceptance condition?
Definition: acc.hh:589
std::ostream & to_text(std::ostream &os, std::function< void(std::ostream &, int)> set_printer=nullptr) const
Print the acceptance formula as text.
static acc_code generalized_buchi(unsigned n)
Build a generalized-Büchi acceptance condition with n sets.
Definition: acc.hh:770
bool operator>(const acc_code &other) const
Greater-than comparison of acceptance formulas.
Definition: acc.hh:548
static acc_code parity_min_odd(unsigned sets)
Build a parity acceptance condition.
Definition: acc.hh:877
acc_code(const acc_word *other)
Copy a part of another acceptance formula.
Definition: acc.hh:1538
mark_t fin_unit() const
Find a Fin(i) that is a unit clause.
trival weakly_accepting(mark_t infinitely_often, mark_t always_present) const
Check if cycles in a SCC are all accepting, all rejecting, or mixed.
static acc_code parity_max_even(unsigned sets)
Build a parity acceptance condition.
Definition: acc.hh:869
static acc_code f()
Construct the "false" acceptance condition.
Definition: acc.hh:619
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:865
bool is_t() const
Is this the "true" acceptance condition?
Definition: acc.hh:575
acc_code operator<<(unsigned sets) const
Apply a left shift to all mark_t that appear in the condition.
Definition: acc.hh:1159
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:797
acc_code()
Build an empty acceptance formula.
Definition: acc.hh:1533
acc_code keep_one_inf_per_branch() const
Rewrite an acceptance condition by keeping at most one Inf(x) on each disjunctive branch.
bool operator==(const acc_code &other) const
Equality comparison of acceptance formulas.
Definition: acc.hh:462
static acc_code cobuchi()
Build a co-Büchi acceptance condition.
Definition: acc.hh:760
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:733
bdd to_bdd(const bdd *map) const
Convert the acceptance formula into a BDD.
int fin_one() const
Return one acceptance set i that appears as Fin(i) in the condition.
bool operator<=(const acc_code &other) const
Less-or-equal comparison of acceptance formulas.
Definition: acc.hh:554
acc_cond::mark_t used_sets() const
Return the set of sets appearing in the condition.
bool operator>=(const acc_code &other) const
Greater-or-equal comparison of acceptance formulas.
Definition: acc.hh:560
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:687
acc_code & operator<<=(unsigned sets)
Apply a left shift to all mark_t that appear in the condition.
Definition: acc.hh:1128
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:812
acc_code unit_propagation()
Apply unit propagation to simplify the formula.
std::vector< acc_code > top_conjuncts() const
Return the top-level conjuncts.
static acc_code t()
Construct the "true" acceptance condition.
Definition: acc.hh:633
static acc_code fin_neg(mark_t m)
Construct a generalized co-Büchi acceptance for complemented sets.
Definition: acc.hh:677
bool operator<(const acc_code &other) const
Lexicographic less-than comparison on acceptance formulas.
Definition: acc.hh:497
static acc_code parity_min(bool is_odd, unsigned sets)
Build a parity acceptance condition.
Definition: acc.hh:873
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 ...
static acc_code fin(mark_t m)
Construct a generalized co-Büchi acceptance.
Definition: acc.hh:645
bool inf_satisfiable(mark_t inf) const
Assuming that we will visit infinitely often at least all sets in inf, is there any chance that we wi...
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:752
static acc_code generalized_co_buchi(unsigned n)
Build a generalized-co-Büchi acceptance condition with n sets.
Definition: acc.hh:784
std::vector< unsigned > symmetries() const
compute the symmetry class of the acceptance sets.
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:836
acc_code & operator|=(const acc_code &r)
Disjunct the current condition in place with r.
Definition: acc.hh:1016
acc_code & operator&=(const acc_code &r)
Conjunct the current condition in place with r.
Definition: acc.hh:906
std::ostream & to_latex(std::ostream &os, std::function< void(std::ostream &, int)> set_printer=nullptr) const
Print the acceptance formula as LaTeX.
An acceptance mark.
Definition: acc.hh:76
std::string as_string() const
Returns a string representation of this mark.
mark_t operator~() const
Bitwise complement.
Definition: acc.hh:245
bool is_singleton() const
Whether the mark contains only one bit set.
Definition: acc.hh:375
mark_t lowest() const
A mark_t where all bits have been removed except the lowest one.
Definition: acc.hh:369
unsigned max_set() const
The number of the highest set used plus one.
Definition: acc.hh:345
mark_t & remove_some(unsigned n)
Remove n bits that were set.
Definition: acc.hh:399
constexpr static unsigned max_accsets()
The maximum number of acceptance sets supported by this implementation.
Definition: acc.hh:116
size_t hash() const noexcept
Returns a hash value for this mark.
Definition: acc.hh:132
bool operator<=(mark_t o) const
Less-or-equal comparison.
Definition: acc.hh:157
static mark_t all()
A mark_t with all bits set to one.
Definition: acc.hh:126
spot::internal::mark_container sets() const
Returns some iterable object that contains the used sets.
Definition: acc.hh:2570
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:330
mark_t & operator-=(mark_t r)
Difference-assignment (removes bits set in r).
Definition: acc.hh:213
mark_t strip(mark_t y) const
Remove bits indexed by y and compact the remaining bits.
Definition: acc.hh:298
mark_t(const iterator &begin, const iterator &end)
Create a mark_t from a range of set numbers.
Definition: acc.hh:94
mark_t & operator<<=(unsigned i)
Left-shift-assignment.
Definition: acc.hh:276
unsigned count() const
Number of bits set.
Definition: acc.hh:336
mark_t operator>>(unsigned i) const
Right-shift all acceptance set indices by i.
Definition: acc.hh:282
mark_t & operator>>=(unsigned i)
Right-shift-assignment.
Definition: acc.hh:288
mark_t & operator|=(mark_t r)
Union-assignment.
Definition: acc.hh:206
mark_t operator^(mark_t r) const
Symmetric difference.
Definition: acc.hh:251
mark_t operator-(mark_t r) const
Difference (bits in this mark but not in r).
Definition: acc.hh:239
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:105
bool operator!=(mark_t o) const
Inequality comparison.
Definition: acc.hh:145
mark_t operator<<(unsigned i) const
Left-shift all acceptance set indices by i.
Definition: acc.hh:270
bool operator>=(mark_t o) const
Greater-or-equal comparison.
Definition: acc.hh:169
bool has_many() const
Whether the mark contains at least two bits set.
Definition: acc.hh:386
mark_t & operator^=(mark_t r)
Symmetric-difference-assignment.
Definition: acc.hh:220
void clear(unsigned u)
Remove acceptance set u from this mark.
Definition: acc.hh:193
mark_t & operator&=(mark_t r)
Intersection-assignment.
Definition: acc.hh:199
unsigned min_set() const
The number of the lowest set used plus one.
Definition: acc.hh:357
mark_t operator&(mark_t r) const
Intersection.
Definition: acc.hh:227
bool has(unsigned u) const
Returns true iff acceptance set u is in this mark.
Definition: acc.hh:181
bool operator<(mark_t o) const
Less-than comparison.
Definition: acc.hh:151
bool operator>(mark_t o) const
Greater-than comparison.
Definition: acc.hh:163
mark_t operator|(mark_t r) const
Union.
Definition: acc.hh:233
bool operator==(mark_t o) const
Equality comparison.
Definition: acc.hh:139
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:323
void fill(iterator here) const
Fill a container with the indices of the bits that are set.
Definition: acc.hh:2576
void set(unsigned u)
Add acceptance set u to this mark.
Definition: acc.hh:187
Rabin/streett pairs used by is_rabin_like and is_streett_like.
Definition: acc.hh:1756
rs_pair(acc_cond::mark_t fin, acc_cond::mark_t inf) noexcept
Construct a pair with Fin mark fin and Inf mark inf.
Definition: acc.hh:1766
rs_pair(const rs_pair &)=default
Copy constructor.
bool operator<=(rs_pair o) const
Less-or-equal comparison.
Definition: acc.hh:1789
rs_pair & operator=(const rs_pair &)=default
Copy-assignment operator.
acc_cond::mark_t fin
The Fin acceptance mark of this pair.
Definition: acc.hh:1770
bool operator>=(rs_pair o) const
Greater-or-equal comparison.
Definition: acc.hh:1799
bool operator>(rs_pair o) const
Greater-than comparison.
Definition: acc.hh:1794
bool operator<(rs_pair o) const
Less-than comparison (lexicographic on fin then inf).
Definition: acc.hh:1784
bool operator==(rs_pair o) const
Equality comparison.
Definition: acc.hh:1774
bool operator!=(rs_pair o) const
Inequality comparison.
Definition: acc.hh:1779
acc_cond::mark_t inf
The Inf acceptance mark of this pair.
Definition: acc.hh:1771
A view over Rabin-Streett pairs restricted to a subset of acceptance marks.
Definition: acc.hh:2390
std::vector< acc_cond::rs_pair > rs_pairs
Type alias for a vector of Rabin-Streett pairs.
Definition: acc.hh:2392
acc_cond::mark_t fins() const
Returns the union of all visible Fin marks across all pairs.
Definition: acc.hh:2412
rs_pairs_view(const rs_pairs &p, const acc_cond::mark_t &m)
Create a view of pairs p restricted to marks visible in m.
Definition: acc.hh:2395
rs_pairs_view(const rs_pairs &p)
Create an unrestricted view of all pairs in p.
Definition: acc.hh:2399
acc_cond::mark_t paired_with_fin(unsigned mark) const
Returns all Inf marks paired with a Fin containing mark.
Definition: acc.hh:2443
acc_cond::mark_t fins_alone() const
Returns Fin marks from pairs whose Inf part is not visible.
Definition: acc.hh:2421
acc_cond::mark_t infs_alone() const
Returns Inf marks from pairs whose Fin part is not visible.
Definition: acc.hh:2431
const rs_pairs & pairs() const
Returns a reference to the underlying vector of pairs.
Definition: acc.hh:2453
acc_cond::mark_t infs() const
Returns the union of all visible Inf marks across all pairs.
Definition: acc.hh:2403
size_t operator()(spot::acc_cond::mark_t m) const noexcept
Returns the hash of acceptance mark m.
Definition: acc.hh:2591
A "node" in an acceptance formulas.
Definition: acc.hh:429
mark_t mark
A set of acceptance marks.
Definition: acc.hh:430
acc_op op
Operator (6 possible values, stored in 8 bits)
Definition: acc.hh:433
unsigned size
Size of the subtree.
Definition: acc.hh:439
struct spot::acc_cond::acc_word::@5 sub
An operator node with its subtree size.

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