spot  2.11.6
acc.hh
1 // -*- coding: utf-8 -*-
2 // Copyright (C) 2014-2022 Laboratoire de Recherche et Développement
3 // de l'Epita.
4 //
5 // This file is part of Spot, a model checking library.
6 //
7 // Spot is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // Spot is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 // License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 
20 #pragma once
21 
22 #include <functional>
23 #include <sstream>
24 #include <vector>
25 #include <iostream>
26 #include <algorithm>
27 #include <numeric>
28 #include <bddx.h>
29 #include <tuple>
30 #include <spot/misc/_config.h>
31 #include <spot/misc/bitset.hh>
32 #include <spot/misc/trival.hh>
33 
34 namespace spot
35 {
36  namespace internal
37  {
38  class mark_container;
39 
40  template<bool>
41  struct _32acc {};
42  template<>
43  struct _32acc<true>
44  {
45  SPOT_DEPRECATED("mark_t no longer relies on unsigned, stop using value_t")
46  typedef unsigned value_t;
47  };
48  }
49 
52 
61  class SPOT_API acc_cond
62  {
63 #ifndef SWIG
64  private:
65  [[noreturn]] static void report_too_many_sets();
66 #endif
67  public:
68 
83  struct mark_t :
84  public internal::_32acc<SPOT_MAX_ACCSETS == 8*sizeof(unsigned)>
85  {
86  private:
87  // configure guarantees that SPOT_MAX_ACCSETS % (8*sizeof(unsigned)) == 0
88  typedef bitset<SPOT_MAX_ACCSETS / (8*sizeof(unsigned))> _value_t;
89  _value_t id;
90 
91  mark_t(_value_t id) noexcept
92  : id(id)
93  {
94  }
95 
96  public:
98  mark_t() = default;
99 
100 #ifndef SWIG
102  template<class iterator>
103  mark_t(const iterator& begin, const iterator& end)
104  : mark_t(_value_t::zero())
105  {
106  for (iterator i = begin; i != end; ++i)
107  if (SPOT_LIKELY(*i < SPOT_MAX_ACCSETS))
108  set(*i);
109  else
110  report_too_many_sets();
111  }
112 
114  mark_t(std::initializer_list<unsigned> vals)
115  : mark_t(vals.begin(), vals.end())
116  {
117  }
118 
119  SPOT_DEPRECATED("use brace initialization instead")
120  mark_t(unsigned i)
121  {
122  unsigned j = 0;
123  while (i)
124  {
125  if (i & 1U)
126  this->set(j);
127  ++j;
128  i >>= 1;
129  }
130  }
131 #endif
132 
138  constexpr static unsigned max_accsets()
139  {
140  return SPOT_MAX_ACCSETS;
141  }
142 
148  static mark_t all()
149  {
150  return mark_t(_value_t::mone());
151  }
152 
153  size_t hash() const noexcept
154  {
155  std::hash<decltype(id)> h;
156  return h(id);
157  }
158 
159  SPOT_DEPRECATED("compare mark_t to mark_t, not to unsigned")
160  bool operator==(unsigned o) const
161  {
162  SPOT_ASSERT(o == 0U);
163  (void)o;
164  return !id;
165  }
166 
167  SPOT_DEPRECATED("compare mark_t to mark_t, not to unsigned")
168  bool operator!=(unsigned o) const
169  {
170  SPOT_ASSERT(o == 0U);
171  (void)o;
172  return !!id;
173  }
174 
175  bool operator==(mark_t o) const
176  {
177  return id == o.id;
178  }
179 
180  bool operator!=(mark_t o) const
181  {
182  return id != o.id;
183  }
184 
185  bool operator<(mark_t o) const
186  {
187  return id < o.id;
188  }
189 
190  bool operator<=(mark_t o) const
191  {
192  return id <= o.id;
193  }
194 
195  bool operator>(mark_t o) const
196  {
197  return id > o.id;
198  }
199 
200  bool operator>=(mark_t o) const
201  {
202  return id >= o.id;
203  }
204 
205  explicit operator bool() const
206  {
207  return !!id;
208  }
209 
210  bool has(unsigned u) const
211  {
212  return !!this->operator&(mark_t({0}) << u);
213  }
214 
215  void set(unsigned u)
216  {
217  id.set(u);
218  }
219 
220  void clear(unsigned u)
221  {
222  id.clear(u);
223  }
224 
225  mark_t& operator&=(mark_t r)
226  {
227  id &= r.id;
228  return *this;
229  }
230 
231  mark_t& operator|=(mark_t r)
232  {
233  id |= r.id;
234  return *this;
235  }
236 
237  mark_t& operator-=(mark_t r)
238  {
239  id &= ~r.id;
240  return *this;
241  }
242 
243  mark_t& operator^=(mark_t r)
244  {
245  id ^= r.id;
246  return *this;
247  }
248 
249  mark_t operator&(mark_t r) const
250  {
251  return id & r.id;
252  }
253 
254  mark_t operator|(mark_t r) const
255  {
256  return id | r.id;
257  }
258 
259  mark_t operator-(mark_t r) const
260  {
261  return id & ~r.id;
262  }
263 
264  mark_t operator~() const
265  {
266  return ~id;
267  }
268 
269  mark_t operator^(mark_t r) const
270  {
271  return id ^ r.id;
272  }
273 
274 #if SPOT_DEBUG || defined(SWIGPYTHON)
275 # define SPOT_WRAP_OP(ins) \
276  try \
277  { \
278  ins; \
279  } \
280  catch (const std::runtime_error& e) \
281  { \
282  report_too_many_sets(); \
283  }
284 #else
285 # define SPOT_WRAP_OP(ins) ins;
286 #endif
287  mark_t operator<<(unsigned i) const
288  {
289  SPOT_WRAP_OP(return id << i);
290  }
291 
292  mark_t& operator<<=(unsigned i)
293  {
294  SPOT_WRAP_OP(id <<= i; return *this);
295  }
296 
297  mark_t operator>>(unsigned i) const
298  {
299  SPOT_WRAP_OP(return id >> i);
300  }
301 
302  mark_t& operator>>=(unsigned i)
303  {
304  SPOT_WRAP_OP(id >>= i; return *this);
305  }
306 #undef SPOT_WRAP_OP
307 
308  mark_t strip(mark_t y) const
309  {
310  // strip every bit of id that is marked in y
311  // 100101110100.strip(
312  // 001011001000)
313  // == 10 1 11 100
314  // == 10111100
315 
316  auto xv = id; // 100101110100
317  auto yv = y.id; // 001011001000
318 
319  while (yv && xv)
320  {
321  // Mask for everything after the last 1 in y
322  auto rm = (~yv) & (yv - 1); // 000000000111
323  // Mask for everything before the last 1 in y
324  auto lm = ~(yv ^ (yv - 1)); // 111111110000
325  xv = ((xv & lm) >> 1) | (xv & rm);
326  yv = (yv & lm) >> 1;
327  }
328  return xv;
329  }
330 
333  bool subset(mark_t m) const
334  {
335  return !((*this) - m);
336  }
337 
340  bool proper_subset(mark_t m) const
341  {
342  return *this != m && this->subset(m);
343  }
344 
346  unsigned count() const
347  {
348  return id.count();
349  }
350 
355  unsigned max_set() const
356  {
357  if (id)
358  return id.highest()+1;
359  else
360  return 0;
361  }
362 
367  unsigned min_set() const
368  {
369  if (id)
370  return id.lowest()+1;
371  else
372  return 0;
373  }
374 
379  mark_t lowest() const
380  {
381  return id & -id;
382  }
383 
385  bool is_singleton() const
386  {
387 #if __GNUC__
388  /* With GCC and Clang, count() is implemented using popcount. */
389  return count() == 1;
390 #else
391  return id && !(id & (id - 1));
392 #endif
393  }
394 
396  bool has_many() const
397  {
398 #if __GNUC__
399  /* With GCC and Clang, count() is implemented using popcount. */
400  return count() > 1;
401 #else
402  return !!(id & (id - 1));
403 #endif
404  }
405 
409  mark_t& remove_some(unsigned n)
410  {
411  while (n--)
412  id &= id - 1;
413  return *this;
414  }
415 
417  template<class iterator>
418  void fill(iterator here) const
419  {
420  auto a = *this;
421  unsigned level = 0;
422  while (a)
423  {
424  if (a.has(0))
425  *here++ = level;
426  ++level;
427  a >>= 1;
428  }
429  }
430 
432  spot::internal::mark_container sets() const;
433 
434  SPOT_API
435  friend std::ostream& operator<<(std::ostream& os, mark_t m);
436 
437  std::string as_string() const
438  {
439  std::ostringstream os;
440  os << *this;
441  return os.str();
442  }
443  };
444 
446  enum class acc_op : unsigned short
447  { Inf, Fin, InfNeg, FinNeg, And, Or };
448 
456  union acc_word
457  {
458  mark_t mark;
459  struct {
460  acc_op op; // Operator
461  unsigned short size; // Size of the subtree (number of acc_word),
462  // not counting this node.
463  } sub;
464  };
465 
478  struct SPOT_API acc_code: public std::vector<acc_word>
479  {
480  acc_code
481  unit_propagation();
482 
483  bool operator==(const acc_code& other) const
484  {
485  unsigned pos = size();
486  if (other.size() != pos)
487  return false;
488  while (pos > 0)
489  {
490  auto op = (*this)[pos - 1].sub.op;
491  auto sz = (*this)[pos - 1].sub.size;
492  if (other[pos - 1].sub.op != op ||
493  other[pos - 1].sub.size != sz)
494  return false;
495  switch (op)
496  {
497  case acc_cond::acc_op::And:
498  case acc_cond::acc_op::Or:
499  --pos;
500  break;
501  case acc_cond::acc_op::Inf:
502  case acc_cond::acc_op::InfNeg:
503  case acc_cond::acc_op::Fin:
504  case acc_cond::acc_op::FinNeg:
505  pos -= 2;
506  if (other[pos].mark != (*this)[pos].mark)
507  return false;
508  break;
509  }
510  }
511  return true;
512  };
513 
514  bool operator<(const acc_code& other) const
515  {
516  unsigned pos = size();
517  auto osize = other.size();
518  if (pos < osize)
519  return true;
520  if (pos > osize)
521  return false;
522  while (pos > 0)
523  {
524  auto op = (*this)[pos - 1].sub.op;
525  auto oop = other[pos - 1].sub.op;
526  if (op < oop)
527  return true;
528  if (op > oop)
529  return false;
530  auto sz = (*this)[pos - 1].sub.size;
531  auto osz = other[pos - 1].sub.size;
532  if (sz < osz)
533  return true;
534  if (sz > osz)
535  return false;
536  switch (op)
537  {
538  case acc_cond::acc_op::And:
539  case acc_cond::acc_op::Or:
540  --pos;
541  break;
542  case acc_cond::acc_op::Inf:
543  case acc_cond::acc_op::InfNeg:
544  case acc_cond::acc_op::Fin:
545  case acc_cond::acc_op::FinNeg:
546  {
547  pos -= 2;
548  auto m = (*this)[pos].mark;
549  auto om = other[pos].mark;
550  if (m < om)
551  return true;
552  if (m > om)
553  return false;
554  break;
555  }
556  }
557  }
558  return false;
559  }
560 
561  bool operator>(const acc_code& other) const
562  {
563  return other < *this;
564  }
565 
566  bool operator<=(const acc_code& other) const
567  {
568  return !(other < *this);
569  }
570 
571  bool operator>=(const acc_code& other) const
572  {
573  return !(*this < other);
574  }
575 
576  bool operator!=(const acc_code& other) const
577  {
578  return !(*this == other);
579  }
580 
585  bool is_t() const
586  {
587  // We store "t" as an empty condition, or as Inf({}).
588  unsigned s = size();
589  return s == 0 || ((*this)[s - 1].sub.op == acc_op::Inf
590  && !((*this)[s - 2].mark));
591  }
592 
599  bool is_f() const
600  {
601  // We store "f" as Fin({}).
602  unsigned s = size();
603  return s > 1
604  && (*this)[s - 1].sub.op == acc_op::Fin && !((*this)[s - 2].mark);
605  }
606 
613  static acc_code f()
614  {
615  acc_code res;
616  res.resize(2);
617  res[0].mark = {};
618  res[1].sub.op = acc_op::Fin;
619  res[1].sub.size = 1;
620  return res;
621  }
622 
627  static acc_code t()
628  {
629  return {};
630  }
631 
639  static acc_code fin(mark_t m)
640  {
641  acc_code res;
642  res.resize(2);
643  res[0].mark = m;
644  res[1].sub.op = acc_op::Fin;
645  res[1].sub.size = 1;
646  return res;
647  }
648 
649  static acc_code fin(std::initializer_list<unsigned> vals)
650  {
651  return fin(mark_t(vals));
652  }
654 
672  {
673  acc_code res;
674  res.resize(2);
675  res[0].mark = m;
676  res[1].sub.op = acc_op::FinNeg;
677  res[1].sub.size = 1;
678  return res;
679  }
680 
681  static acc_code fin_neg(std::initializer_list<unsigned> vals)
682  {
683  return fin_neg(mark_t(vals));
684  }
686 
695  static acc_code inf(mark_t m)
696  {
697  acc_code res;
698  res.resize(2);
699  res[0].mark = m;
700  res[1].sub.op = acc_op::Inf;
701  res[1].sub.size = 1;
702  return res;
703  }
704 
705  static acc_code inf(std::initializer_list<unsigned> vals)
706  {
707  return inf(mark_t(vals));
708  }
710 
728  {
729  acc_code res;
730  res.resize(2);
731  res[0].mark = m;
732  res[1].sub.op = acc_op::InfNeg;
733  res[1].sub.size = 1;
734  return res;
735  }
736 
737  static acc_code inf_neg(std::initializer_list<unsigned> vals)
738  {
739  return inf_neg(mark_t(vals));
740  }
742 
746  static acc_code buchi()
747  {
748  return inf({0});
749  }
750 
754  static acc_code cobuchi()
755  {
756  return fin({0});
757  }
758 
764  static acc_code generalized_buchi(unsigned n)
765  {
766  if (n == 0)
767  return inf({});
768  acc_cond::mark_t m = mark_t::all();
769  m >>= mark_t::max_accsets() - n;
770  return inf(m);
771  }
772 
778  static acc_code generalized_co_buchi(unsigned n)
779  {
780  if (n == 0)
781  return fin({});
782  acc_cond::mark_t m = mark_t::all();
783  m >>= mark_t::max_accsets() - n;
784  return fin(m);
785  }
786 
791  static acc_code rabin(unsigned n)
792  {
793  acc_cond::acc_code res = f();
794  while (n > 0)
795  {
796  res |= inf({2*n - 1}) & fin({2*n - 2});
797  --n;
798  }
799  return res;
800  }
801 
806  static acc_code streett(unsigned n)
807  {
808  acc_cond::acc_code res = t();
809  while (n > 0)
810  {
811  res &= inf({2*n - 1}) | fin({2*n - 2});
812  --n;
813  }
814  return res;
815  }
816 
829  template<class Iterator>
830  static acc_code generalized_rabin(Iterator begin, Iterator end)
831  {
832  acc_cond::acc_code res = f();
833  unsigned n = 0;
834  for (Iterator i = begin; i != end; ++i)
835  {
836  unsigned f = n++;
837  acc_cond::mark_t m = {};
838  for (unsigned ni = *i; ni > 0; --ni)
839  m.set(n++);
840  auto pair = inf(m) & fin({f});
841  std::swap(pair, res);
842  res |= std::move(pair);
843  }
844  return res;
845  }
846 
854  static acc_code parity(bool is_max, bool is_odd, unsigned sets);
855  static acc_code parity_max(bool is_odd, unsigned sets)
856  {
857  return parity(true, is_odd, sets);
858  }
859  static acc_code parity_max_odd(unsigned sets)
860  {
861  return parity_max(true, sets);
862  }
863  static acc_code parity_max_even(unsigned sets)
864  {
865  return parity_max(false, sets);
866  }
867  static acc_code parity_min(bool is_odd, unsigned sets)
868  {
869  return parity(false, is_odd, sets);
870  }
871  static acc_code parity_min_odd(unsigned sets)
872  {
873  return parity_min(true, sets);
874  }
875  static acc_code parity_min_even(unsigned sets)
876  {
877  return parity_min(false, sets);
878  }
880 
897  static acc_code random(unsigned n, double reuse = 0.0);
898 
901  {
902  if (is_t() || r.is_f())
903  {
904  *this = r;
905  return *this;
906  }
907  if (is_f() || r.is_t())
908  return *this;
909  unsigned s = size() - 1;
910  unsigned rs = r.size() - 1;
911  // We want to group all Inf(x) operators:
912  // Inf(a) & Inf(b) = Inf(a & b)
913  if (((*this)[s].sub.op == acc_op::Inf
914  && r[rs].sub.op == acc_op::Inf)
915  || ((*this)[s].sub.op == acc_op::InfNeg
916  && r[rs].sub.op == acc_op::InfNeg))
917  {
918  (*this)[s - 1].mark |= r[rs - 1].mark;
919  return *this;
920  }
921 
922  // In the more complex scenarios, left and right may both
923  // be conjunctions, and Inf(x) might be a member of each
924  // side. Find it if it exists.
925  // left_inf points to the left Inf mark if any.
926  // right_inf points to the right Inf mark if any.
927  acc_word* left_inf = nullptr;
928  if ((*this)[s].sub.op == acc_op::And)
929  {
930  auto start = &(*this)[s] - (*this)[s].sub.size;
931  auto pos = &(*this)[s] - 1;
932  pop_back();
933  while (pos > start)
934  {
935  if (pos->sub.op == acc_op::Inf)
936  {
937  left_inf = pos - 1;
938  break;
939  }
940  pos -= pos->sub.size + 1;
941  }
942  }
943  else if ((*this)[s].sub.op == acc_op::Inf)
944  {
945  left_inf = &(*this)[s - 1];
946  }
947 
948  const acc_word* right_inf = nullptr;
949  auto right_end = &r.back();
950  if (right_end->sub.op == acc_op::And)
951  {
952  auto start = &r[0];
953  auto pos = --right_end;
954  while (pos > start)
955  {
956  if (pos->sub.op == acc_op::Inf)
957  {
958  right_inf = pos - 1;
959  break;
960  }
961  pos -= pos->sub.size + 1;
962  }
963  }
964  else if (right_end->sub.op == acc_op::Inf)
965  {
966  right_inf = right_end - 1;
967  }
968 
969  acc_cond::mark_t carry = {};
970  if (left_inf && right_inf)
971  {
972  carry = left_inf->mark;
973  auto pos = left_inf - &(*this)[0];
974  erase(begin() + pos, begin() + pos + 2);
975  }
976  auto sz = size();
977  insert(end(), &r[0], right_end + 1);
978  if (carry)
979  (*this)[sz + (right_inf - &r[0])].mark |= carry;
980 
981  acc_word w;
982  w.sub.op = acc_op::And;
983  w.sub.size = size();
984  emplace_back(w);
985  return *this;
986  }
987 
989  acc_code operator&(const acc_code& r) const
990  {
991  acc_code res = *this;
992  res &= r;
993  return res;
994  }
995 
996 #ifndef SWIG
999  {
1000  acc_code res = *this;
1001  res &= r;
1002  return res;
1003  }
1004 #endif // SWIG
1005 
1008  {
1009  if (is_t() || r.is_f())
1010  return *this;
1011  if (is_f() || r.is_t())
1012  {
1013  *this = r;
1014  return *this;
1015  }
1016  unsigned s = size() - 1;
1017  unsigned rs = r.size() - 1;
1018  // Fin(a) | Fin(b) = Fin(a | b)
1019  if (((*this)[s].sub.op == acc_op::Fin
1020  && r[rs].sub.op == acc_op::Fin)
1021  || ((*this)[s].sub.op == acc_op::FinNeg
1022  && r[rs].sub.op == acc_op::FinNeg))
1023  {
1024  (*this)[s - 1].mark |= r[rs - 1].mark;
1025  return *this;
1026  }
1027 
1028  // In the more complex scenarios, left and right may both
1029  // be disjunctions, and Fin(x) might be a member of each
1030  // side. Find it if it exists.
1031  // left_inf points to the left Inf mark if any.
1032  // right_inf points to the right Inf mark if any.
1033  acc_word* left_fin = nullptr;
1034  if ((*this)[s].sub.op == acc_op::Or)
1035  {
1036  auto start = &(*this)[s] - (*this)[s].sub.size;
1037  auto pos = &(*this)[s] - 1;
1038  pop_back();
1039  while (pos > start)
1040  {
1041  if (pos->sub.op == acc_op::Fin)
1042  {
1043  left_fin = pos - 1;
1044  break;
1045  }
1046  pos -= pos->sub.size + 1;
1047  }
1048  }
1049  else if ((*this)[s].sub.op == acc_op::Fin)
1050  {
1051  left_fin = &(*this)[s - 1];
1052  }
1053 
1054  const acc_word* right_fin = nullptr;
1055  auto right_end = &r.back();
1056  if (right_end->sub.op == acc_op::Or)
1057  {
1058  auto start = &r[0];
1059  auto pos = --right_end;
1060  while (pos > start)
1061  {
1062  if (pos->sub.op == acc_op::Fin)
1063  {
1064  right_fin = pos - 1;
1065  break;
1066  }
1067  pos -= pos->sub.size + 1;
1068  }
1069  }
1070  else if (right_end->sub.op == acc_op::Fin)
1071  {
1072  right_fin = right_end - 1;
1073  }
1074 
1075  acc_cond::mark_t carry = {};
1076  if (left_fin && right_fin)
1077  {
1078  carry = left_fin->mark;
1079  auto pos = (left_fin - &(*this)[0]);
1080  this->erase(begin() + pos, begin() + pos + 2);
1081  }
1082  auto sz = size();
1083  insert(end(), &r[0], right_end + 1);
1084  if (carry)
1085  (*this)[sz + (right_fin - &r[0])].mark |= carry;
1086  acc_word w;
1087  w.sub.op = acc_op::Or;
1088  w.sub.size = size();
1089  emplace_back(w);
1090  return *this;
1091  }
1092 
1093 #ifndef SWIG
1096  {
1097  acc_code res = *this;
1098  res |= r;
1099  return res;
1100  }
1101 #endif // SWIG
1102 
1104  acc_code operator|(const acc_code& r) const
1105  {
1106  acc_code res = *this;
1107  res |= r;
1108  return res;
1109  }
1110 
1116  acc_code& operator<<=(unsigned sets)
1117  {
1118  if (SPOT_UNLIKELY(sets >= mark_t::max_accsets()))
1119  report_too_many_sets();
1120  if (empty())
1121  return *this;
1122  unsigned pos = size();
1123  do
1124  {
1125  switch ((*this)[pos - 1].sub.op)
1126  {
1127  case acc_cond::acc_op::And:
1128  case acc_cond::acc_op::Or:
1129  --pos;
1130  break;
1131  case acc_cond::acc_op::Inf:
1132  case acc_cond::acc_op::InfNeg:
1133  case acc_cond::acc_op::Fin:
1134  case acc_cond::acc_op::FinNeg:
1135  pos -= 2;
1136  (*this)[pos].mark <<= sets;
1137  break;
1138  }
1139  }
1140  while (pos > 0);
1141  return *this;
1142  }
1143 
1147  acc_code operator<<(unsigned sets) const
1148  {
1149  acc_code res = *this;
1150  res <<= sets;
1151  return res;
1152  }
1153 
1160  bool is_dnf() const;
1161 
1168  bool is_cnf() const;
1169 
1180  acc_code to_dnf() const;
1181 
1188  acc_code to_cnf() const;
1189 
1194  bdd to_bdd(const bdd* map) const;
1195 
1204  std::vector<acc_code> top_disjuncts() const;
1205 
1214  std::vector<acc_code> top_conjuncts() const;
1215 
1227 
1239  mark_t fin_unit() const;
1240 
1252  mark_t inf_unit() const;
1253 
1258  int fin_one() const;
1259 
1280  std::pair<int, acc_code> fin_one_extract() const;
1281 
1298  std::tuple<int, acc_cond::acc_code, acc_cond::acc_code>
1300 
1313  std::vector<std::vector<int>>
1314  missing(mark_t inf, bool accepting) const;
1315 
1318  bool accepting(mark_t inf) const;
1319 
1325  bool inf_satisfiable(mark_t inf) const;
1326 
1338  trival maybe_accepting(mark_t infinitely_often,
1339  mark_t always_present) const;
1340 
1351  std::vector<unsigned> symmetries() const;
1352 
1366  acc_code remove(acc_cond::mark_t rem, bool missing) const;
1367 
1372  acc_code strip(acc_cond::mark_t rem, bool missing) const;
1375 
1378 
1390  std::vector<std::pair<acc_cond::mark_t, acc_cond::mark_t>>
1392 
1400 
1402  std::pair<acc_cond::mark_t, acc_cond::mark_t> used_inf_fin_sets() const;
1403 
1408  std::ostream&
1409  to_html(std::ostream& os,
1410  std::function<void(std::ostream&, int)>
1411  set_printer = nullptr) const;
1412 
1417  std::ostream&
1418  to_text(std::ostream& os,
1419  std::function<void(std::ostream&, int)>
1420  set_printer = nullptr) const;
1421 
1426  std::ostream&
1427  to_latex(std::ostream& os,
1428  std::function<void(std::ostream&, int)>
1429  set_printer = nullptr) const;
1430 
1453  acc_code(const char* input);
1454 
1459  {
1460  }
1461 
1463  acc_code(const acc_word* other)
1464  : std::vector<acc_word>(other - other->sub.size, other + 1)
1465  {
1466  }
1467 
1469  SPOT_API
1470  friend std::ostream& operator<<(std::ostream& os, const acc_code& code);
1471  };
1472 
1480  acc_cond(unsigned n_sets = 0, const acc_code& code = {})
1481  : num_(0U), all_({}), code_(code)
1482  {
1483  add_sets(n_sets);
1484  uses_fin_acceptance_ = check_fin_acceptance();
1485  }
1486 
1491  acc_cond(const acc_code& code)
1492  : num_(0U), all_({}), code_(code)
1493  {
1494  add_sets(code.used_sets().max_set());
1495  uses_fin_acceptance_ = check_fin_acceptance();
1496  }
1497 
1499  acc_cond(const acc_cond& o)
1500  : num_(o.num_), all_(o.all_), code_(o.code_),
1501  uses_fin_acceptance_(o.uses_fin_acceptance_)
1502  {
1503  }
1504 
1507  {
1508  num_ = o.num_;
1509  all_ = o.all_;
1510  code_ = o.code_;
1511  uses_fin_acceptance_ = o.uses_fin_acceptance_;
1512  return *this;
1513  }
1514 
1515  ~acc_cond()
1516  {
1517  }
1518 
1522  void set_acceptance(const acc_code& code)
1523  {
1524  code_ = code;
1525  uses_fin_acceptance_ = check_fin_acceptance();
1526  }
1527 
1529  const acc_code& get_acceptance() const
1530  {
1531  return code_;
1532  }
1533 
1536  {
1537  return code_;
1538  }
1539 
1540  bool operator==(const acc_cond& other) const
1541  {
1542  return other.num_sets() == num_ && other.get_acceptance() == code_;
1543  }
1544 
1545  bool operator!=(const acc_cond& other) const
1546  {
1547  return !(*this == other);
1548  }
1549 
1551  bool uses_fin_acceptance() const
1552  {
1553  return uses_fin_acceptance_;
1554  }
1555 
1557  bool is_t() const
1558  {
1559  return code_.is_t();
1560  }
1561 
1566  bool is_all() const
1567  {
1568  return num_ == 0 && is_t();
1569  }
1570 
1572  bool is_f() const
1573  {
1574  return code_.is_f();
1575  }
1576 
1581  bool is_none() const
1582  {
1583  return num_ == 0 && is_f();
1584  }
1585 
1590  bool is_buchi() const
1591  {
1592  unsigned s = code_.size();
1593  return num_ == 1 &&
1594  s == 2 && code_[1].sub.op == acc_op::Inf && code_[0].mark == all_sets();
1595  }
1596 
1601  bool is_co_buchi() const
1602  {
1603  return num_ == 1 && is_generalized_co_buchi();
1604  }
1605 
1609  {
1610  set_acceptance(inf(all_sets()));
1611  }
1612 
1616  {
1617  set_acceptance(fin(all_sets()));
1618  }
1619 
1625  {
1626  unsigned s = code_.size();
1627  return (s == 0 && num_ == 0) || (s == 2 && code_[1].sub.op == acc_op::Inf
1628  && code_[0].mark == all_sets());
1629  }
1630 
1636  {
1637  unsigned s = code_.size();
1638  return (s == 2 &&
1639  code_[1].sub.op == acc_op::Fin && code_[0].mark == all_sets());
1640  }
1641 
1653  int is_rabin() const;
1654 
1666  int is_streett() const;
1667 
1677  struct SPOT_API rs_pair
1678  {
1679 #ifndef SWIG
1680  rs_pair() = default;
1681  rs_pair(const rs_pair&) = default;
1682  rs_pair& operator=(const rs_pair&) = default;
1683 #endif
1684 
1685  rs_pair(acc_cond::mark_t fin, acc_cond::mark_t inf) noexcept:
1686  fin(fin),
1687  inf(inf)
1688  {}
1689  acc_cond::mark_t fin;
1690  acc_cond::mark_t inf;
1691 
1692  bool operator==(rs_pair o) const
1693  {
1694  return fin == o.fin && inf == o.inf;
1695  }
1696  bool operator!=(rs_pair o) const
1697  {
1698  return fin != o.fin || inf != o.inf;
1699  }
1700  bool operator<(rs_pair o) const
1701  {
1702  return fin < o.fin || (!(o.fin < fin) && inf < o.inf);
1703  }
1704  bool operator<=(rs_pair o) const
1705  {
1706  return !(o < *this);
1707  }
1708  bool operator>(rs_pair o) const
1709  {
1710  return o < *this;
1711  }
1712  bool operator>=(rs_pair o) const
1713  {
1714  return !(*this < o);
1715  }
1716  };
1727  bool is_streett_like(std::vector<rs_pair>& pairs) const;
1728 
1739  bool is_rabin_like(std::vector<rs_pair>& pairs) const;
1740 
1750  bool is_generalized_rabin(std::vector<unsigned>& pairs) const;
1751 
1764  bool is_generalized_streett(std::vector<unsigned>& pairs) const;
1765 
1775  bool is_parity(bool& max, bool& odd, bool equiv = false) const;
1776 
1777 
1780  bool is_parity() const
1781  {
1782  bool max;
1783  bool odd;
1784  return is_parity(max, odd);
1785  }
1786 
1795  {
1796  return acc_cond(num_, code_.unit_propagation());
1797  }
1798 
1799  // Return (true, m) if there exist some acceptance mark m that
1800  // does not satisfy the acceptance condition. Return (false, 0U)
1801  // otherwise.
1802  std::pair<bool, acc_cond::mark_t> unsat_mark() const
1803  {
1804  return sat_unsat_mark(false);
1805  }
1806  // Return (true, m) if there exist some acceptance mark m that
1807  // does satisfy the acceptance condition. Return (false, 0U)
1808  // otherwise.
1809  std::pair<bool, acc_cond::mark_t> sat_mark() const
1810  {
1811  return sat_unsat_mark(true);
1812  }
1813 
1814  protected:
1815  bool check_fin_acceptance() const;
1816  std::pair<bool, acc_cond::mark_t> sat_unsat_mark(bool) const;
1817 
1818  public:
1827  static acc_code inf(mark_t mark)
1828  {
1829  return acc_code::inf(mark);
1830  }
1831 
1832  static acc_code inf(std::initializer_list<unsigned> vals)
1833  {
1834  return inf(mark_t(vals.begin(), vals.end()));
1835  }
1837 
1854  static acc_code inf_neg(mark_t mark)
1855  {
1856  return acc_code::inf_neg(mark);
1857  }
1858 
1859  static acc_code inf_neg(std::initializer_list<unsigned> vals)
1860  {
1861  return inf_neg(mark_t(vals.begin(), vals.end()));
1862  }
1864 
1872  static acc_code fin(mark_t mark)
1873  {
1874  return acc_code::fin(mark);
1875  }
1876 
1877  static acc_code fin(std::initializer_list<unsigned> vals)
1878  {
1879  return fin(mark_t(vals.begin(), vals.end()));
1880  }
1882 
1899  static acc_code fin_neg(mark_t mark)
1900  {
1901  return acc_code::fin_neg(mark);
1902  }
1903 
1904  static acc_code fin_neg(std::initializer_list<unsigned> vals)
1905  {
1906  return fin_neg(mark_t(vals.begin(), vals.end()));
1907  }
1909 
1914  unsigned add_sets(unsigned num)
1915  {
1916  if (num == 0)
1917  return -1U;
1918  unsigned j = num_;
1919  num += j;
1920  if (num > mark_t::max_accsets())
1921  report_too_many_sets();
1922  // Make sure we do not update if we raised an exception.
1923  num_ = num;
1924  all_ = all_sets_();
1925  return j;
1926  }
1927 
1932  unsigned add_set()
1933  {
1934  return add_sets(1);
1935  }
1936 
1938  mark_t mark(unsigned u) const
1939  {
1940  SPOT_ASSERT(u < num_sets());
1941  return mark_t({u});
1942  }
1943 
1948  mark_t comp(const mark_t& l) const
1949  {
1950  return all_ ^ l;
1951  }
1952 
1955  {
1956  return all_;
1957  }
1958 
1961  bool accepting(mark_t inf) const
1962  {
1963  return code_.accepting(inf);
1964  }
1965 
1971  bool inf_satisfiable(mark_t inf) const
1972  {
1973  return code_.inf_satisfiable(inf);
1974  }
1975 
1987  trival maybe_accepting(mark_t infinitely_often, mark_t always_present) const
1988  {
1989  return code_.maybe_accepting(infinitely_often, always_present);
1990  }
1991 
2006 
2007  // Deprecated since Spot 2.8
2008  SPOT_DEPRECATED("Use operator<< instead.")
2009  std::ostream& format(std::ostream& os, mark_t m) const
2010  {
2011  if (!m)
2012  return os;
2013  return os << m;
2014  }
2015 
2016  // Deprecated since Spot 2.8
2017  SPOT_DEPRECATED("Use operator<< or mark_t::as_string() instead.")
2018  std::string format(mark_t m) const
2019  {
2020  std::ostringstream os;
2021  if (m)
2022  os << m;
2023  return os.str();
2024  }
2025 
2027  unsigned num_sets() const
2028  {
2029  return num_;
2030  }
2031 
2039  template<class iterator>
2040  mark_t useless(iterator begin, iterator end) const
2041  {
2042  mark_t u = {}; // The set of useless sets
2043  for (unsigned x = 0; x < num_; ++x)
2044  {
2045  // Skip sets that are already known to be useless.
2046  if (u.has(x))
2047  continue;
2048  auto all = comp(u | mark_t({x}));
2049  // Iterate over all mark_t, and keep track of
2050  // set numbers that always appear with x.
2051  for (iterator y = begin; y != end; ++y)
2052  {
2053  const mark_t& v = *y;
2054  if (v.has(x))
2055  {
2056  all &= v;
2057  if (!all)
2058  break;
2059  }
2060  }
2061  u |= all;
2062  }
2063  return u;
2064  }
2065 
2079  acc_cond remove(mark_t rem, bool missing) const
2080  {
2081  return {num_sets(), code_.remove(rem, missing)};
2082  }
2083 
2088  acc_cond strip(mark_t rem, bool missing) const
2089  {
2090  return
2091  { num_sets() - (all_sets() & rem).count(), code_.strip(rem, missing) };
2092  }
2093 
2096  {
2097  return {num_sets(), code_.force_inf(m)};
2098  }
2099 
2103  {
2104  return {num_sets(), code_.remove(all_sets() - rem, true)};
2105  }
2106 
2118  std::string name(const char* fmt = "alo") const;
2119 
2132  {
2133  return code_.fin_unit();
2134  }
2135 
2148  {
2149  return code_.inf_unit();
2150  }
2151 
2156  int fin_one() const
2157  {
2158  return code_.fin_one();
2159  }
2160 
2181  std::pair<int, acc_cond> fin_one_extract() const
2182  {
2183  auto [f, c] = code_.fin_one_extract();
2184  return {f, {num_sets(), std::move(c)}};
2185  }
2186 
2203  std::tuple<int, acc_cond, acc_cond>
2205  {
2206  auto [f, l, r] = code_.fin_unit_one_split();
2207  return {f, {num_sets(), std::move(l)}, {num_sets(), std::move(r)}};
2208  }
2209 
2218  std::vector<acc_cond> top_disjuncts() const;
2219 
2228  std::vector<acc_cond> top_conjuncts() const;
2229 
2230  protected:
2231  mark_t all_sets_() const
2232  {
2233  return mark_t::all() >> (spot::acc_cond::mark_t::max_accsets() - num_);
2234  }
2235 
2236  unsigned num_;
2237  mark_t all_;
2238  acc_code code_;
2239  bool uses_fin_acceptance_ = false;
2240 
2241  };
2242 
2243  struct rs_pairs_view {
2244  typedef std::vector<acc_cond::rs_pair> rs_pairs;
2245 
2246  // Creates view of pairs 'p' with restriction only to marks in 'm'
2247  explicit rs_pairs_view(const rs_pairs& p, const acc_cond::mark_t& m)
2248  : pairs_(p), view_marks_(m) {}
2249 
2250  // Creates view of pairs without restriction to marks
2251  explicit rs_pairs_view(const rs_pairs& p)
2253 
2254  acc_cond::mark_t infs() const
2255  {
2256  return do_view([&](const acc_cond::rs_pair& p)
2257  {
2258  return visible(p.inf) ? p.inf : acc_cond::mark_t({});
2259  });
2260  }
2261 
2262  acc_cond::mark_t fins() const
2263  {
2264  return do_view([&](const acc_cond::rs_pair& p)
2265  {
2266  return visible(p.fin) ? p.fin : acc_cond::mark_t({});
2267  });
2268  }
2269 
2270  acc_cond::mark_t fins_alone() const
2271  {
2272  return do_view([&](const acc_cond::rs_pair& p)
2273  {
2274  return !visible(p.inf) && visible(p.fin) ? p.fin
2275  : acc_cond::mark_t({});
2276  });
2277  }
2278 
2279  acc_cond::mark_t infs_alone() const
2280  {
2281  return do_view([&](const acc_cond::rs_pair& p)
2282  {
2283  return !visible(p.fin) && visible(p.inf) ? p.inf
2284  : acc_cond::mark_t({});
2285  });
2286  }
2287 
2288  acc_cond::mark_t paired_with_fin(unsigned mark) const
2289  {
2290  acc_cond::mark_t res = {};
2291  for (const auto& p: pairs_)
2292  if (p.fin.has(mark) && visible(p.fin) && visible(p.inf))
2293  res |= p.inf;
2294  return res;
2295  }
2296 
2297  const rs_pairs& pairs() const
2298  {
2299  return pairs_;
2300  }
2301 
2302  private:
2303  template<typename filter>
2304  acc_cond::mark_t do_view(const filter& filt) const
2305  {
2306  acc_cond::mark_t res = {};
2307  for (const auto& p: pairs_)
2308  res |= filt(p);
2309  return res;
2310  }
2311 
2312  bool visible(const acc_cond::mark_t& v) const
2313  {
2314  return !!(view_marks_ & v);
2315  }
2316 
2317  const rs_pairs& pairs_;
2318  acc_cond::mark_t view_marks_;
2319  };
2320 
2321 
2322  SPOT_API
2323  std::ostream& operator<<(std::ostream& os, const acc_cond& acc);
2324 
2326 
2327  namespace internal
2328  {
2329  class SPOT_API mark_iterator
2330  {
2331  public:
2332  typedef unsigned value_type;
2333  typedef const value_type& reference;
2334  typedef const value_type* pointer;
2335  typedef std::ptrdiff_t difference_type;
2336  typedef std::forward_iterator_tag iterator_category;
2337 
2338  mark_iterator() noexcept
2339  : m_({})
2340  {
2341  }
2342 
2343  mark_iterator(acc_cond::mark_t m) noexcept
2344  : m_(m)
2345  {
2346  }
2347 
2348  bool operator==(mark_iterator m) const
2349  {
2350  return m_ == m.m_;
2351  }
2352 
2353  bool operator!=(mark_iterator m) const
2354  {
2355  return m_ != m.m_;
2356  }
2357 
2358  value_type operator*() const
2359  {
2360  SPOT_ASSERT(m_);
2361  return m_.min_set() - 1;
2362  }
2363 
2364  mark_iterator& operator++()
2365  {
2366  m_.clear(this->operator*());
2367  return *this;
2368  }
2369 
2370  mark_iterator operator++(int)
2371  {
2372  mark_iterator it = *this;
2373  ++(*this);
2374  return it;
2375  }
2376  private:
2377  acc_cond::mark_t m_;
2378  };
2379 
2380  class SPOT_API mark_container
2381  {
2382  public:
2384  : m_(m)
2385  {
2386  }
2387 
2388  mark_iterator begin() const
2389  {
2390  return {m_};
2391  }
2392  mark_iterator end() const
2393  {
2394  return {};
2395  }
2396  private:
2398  };
2399  }
2400 
2402  {
2403  return {*this};
2404  }
2405 }
2406 
2407 namespace std
2408 {
2409  template<>
2410  struct hash<spot::acc_cond::mark_t>
2411  {
2412  size_t operator()(spot::acc_cond::mark_t m) const noexcept
2413  {
2414  return m.hash();
2415  }
2416  };
2417 }
An acceptance condition.
Definition: acc.hh:62
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:1971
mark_t all_sets() const
Construct a mark_t with all declared sets.
Definition: acc.hh:1954
static acc_code fin_neg(mark_t mark)
Construct a generalized co-Büchi acceptance for complemented sets.
Definition: acc.hh:1899
static acc_code inf_neg(mark_t mark)
Construct a generalized Büchi acceptance for complemented sets.
Definition: acc.hh:1854
acc_cond unit_propagation()
Remove superfluous Fin and Inf by unit propagation.
Definition: acc.hh:1794
void set_generalized_co_buchi()
Change the acceptance condition to generalized-co-Büchi, over all declared sets.
Definition: acc.hh:1615
const acc_code & get_acceptance() const
Retrieve the acceptance formula.
Definition: acc.hh:1529
static acc_code fin(mark_t mark)
Construct a generalized co-Büchi acceptance.
Definition: acc.hh:1872
bool is_co_buchi() const
Whether the acceptance condition is "co-Büchi".
Definition: acc.hh:1601
bool accepting(mark_t inf) const
Check whether visiting exactly all sets inf infinitely often satisfies the acceptance condition.
Definition: acc.hh:1961
static acc_code inf(mark_t mark)
Construct a generalized Büchi acceptance.
Definition: acc.hh:1827
bool is_generalized_buchi() const
Whether the acceptance condition is "generalized-Büchi".
Definition: acc.hh:1624
static acc_code fin_neg(std::initializer_list< unsigned > vals)
Construct a generalized co-Büchi acceptance for complemented sets.
Definition: acc.hh:1904
static acc_code inf(std::initializer_list< unsigned > vals)
Construct a generalized Büchi acceptance.
Definition: acc.hh:1832
unsigned add_set()
Add a single set to the acceptance condition.
Definition: acc.hh:1932
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...
mark_t mark(unsigned u) const
Build a mark_t with a single set.
Definition: acc.hh:1938
void set_generalized_buchi()
Change the acceptance condition to generalized-Büchi, over all declared sets.
Definition: acc.hh:1608
acc_cond force_inf(mark_t m) const
For all x in m, replaces Fin(x) by false.
Definition: acc.hh:2095
acc_cond remove(mark_t rem, bool missing) const
Remove all the acceptance sets in rem.
Definition: acc.hh:2079
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:2204
acc_op
Operators for acceptance formulas.
Definition: acc.hh:447
acc_cond(unsigned n_sets=0, const acc_code &code={})
Build an acceptance condition.
Definition: acc.hh:1480
unsigned add_sets(unsigned num)
Add more sets to the acceptance condition.
Definition: acc.hh:1914
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:1780
bool is_t() const
Whether the acceptance formula is "t" (true)
Definition: acc.hh:1557
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:1948
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:2181
static acc_code fin(std::initializer_list< unsigned > vals)
Construct a generalized co-Büchi acceptance.
Definition: acc.hh:1877
bool is_generalized_co_buchi() const
Whether the acceptance condition is "generalized-co-Büchi".
Definition: acc.hh:1635
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:2102
trival maybe_accepting(mark_t infinitely_often, mark_t always_present) const
Check potential acceptance of an SCC.
Definition: acc.hh:1987
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:1581
void set_acceptance(const acc_code &code)
Change the acceptance formula.
Definition: acc.hh:1522
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:1566
acc_cond strip(mark_t rem, bool missing) const
Remove acceptance sets, and shift set numbers.
Definition: acc.hh:2088
int fin_one() const
Return one acceptance set i that appear as Fin(i) in the condition.
Definition: acc.hh:2156
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:2040
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:2131
acc_code & get_acceptance()
Retrieve the acceptance formula.
Definition: acc.hh:1535
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:1491
acc_cond(const acc_cond &o)
Copy an acceptance condition.
Definition: acc.hh:1499
acc_cond & operator=(const acc_cond &o)
Copy an acceptance condition.
Definition: acc.hh:1506
static acc_code inf_neg(std::initializer_list< unsigned > vals)
Construct a generalized Büchi acceptance for complemented sets.
Definition: acc.hh:1859
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:1590
mark_t inf_unit() const
Find a Inf(i) that is a unit clause.
Definition: acc.hh:2147
bool uses_fin_acceptance() const
Whether the acceptance condition uses Fin terms.
Definition: acc.hh:1551
bool is_f() const
Whether the acceptance formula is "f" (false)
Definition: acc.hh:1572
unsigned num_sets() const
The number of sets used in the acceptance condition.
Definition: acc.hh:2027
std::vector< acc_cond > top_disjuncts() const
Return the top-level disjuncts.
Definition: bitset.hh:39
Definition: acc.hh:2381
Definition: acc.hh:2330
A class implementing Kleene's three-valued logic.
Definition: trival.hh:34
op
Operator types.
Definition: formula.hh:79
@ Or
(omega-Rational) Or
@ U
until
@ And
(omega-Rational) And
SPOT_DEPRECATED("use to_parity() instead") twa_graph_ptr iar(const const_twa_graph_ptr &aut
Turn a Rabin-like or Streett-like automaton into a parity automaton based on the index appearence rec...
Definition: automata.hh:27
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:131
An acceptance formula.
Definition: acc.hh:479
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:855
static acc_code inf(mark_t m)
Construct a generalized Büchi acceptance.
Definition: acc.hh:695
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:998
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:737
std::vector< acc_code > top_disjuncts() const
Return the top-level disjuncts.
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:1104
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:1095
static acc_code fin(std::initializer_list< unsigned > vals)
Construct a generalized co-Büchi acceptance.
Definition: acc.hh:649
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:989
static acc_code inf(std::initializer_list< unsigned > vals)
Construct a generalized Büchi acceptance.
Definition: acc.hh:705
static acc_code parity_min_even(unsigned sets)
Build a parity acceptance condition.
Definition: acc.hh:875
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:599
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:764
static acc_code parity_min_odd(unsigned sets)
Build a parity acceptance condition.
Definition: acc.hh:871
acc_code(const acc_word *other)
Copy a part of another acceptance formula.
Definition: acc.hh:1463
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:863
static acc_code f()
Construct the "false" acceptance condition.
Definition: acc.hh:613
bool accepting(mark_t inf) const
Check whether visiting exactly all sets inf infinitely often satisfies the acceptance condition.
friend std::ostream & operator<<(std::ostream &os, const acc_code &code)
prints the acceptance formula as text
static acc_code parity_max_odd(unsigned sets)
Build a parity acceptance condition.
Definition: acc.hh:859
bool is_t() const
Is this the "true" acceptance condition?
Definition: acc.hh:585
acc_code operator<<(unsigned sets) const
Apply a left shift to all mark_t that appear in the condition.
Definition: acc.hh:1147
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:791
acc_code()
Build an empty acceptance formula.
Definition: acc.hh:1458
static acc_code cobuchi()
Build a co-Büchi acceptance condition.
Definition: acc.hh:754
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:727
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.
acc_cond::mark_t used_sets() const
Return the set of sets appearing in the 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:681
acc_code & operator<<=(unsigned sets)
Apply a left shift to all mark_t that appear in the condition.
Definition: acc.hh:1116
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:806
std::vector< acc_code > top_conjuncts() const
Return the top-level conjuncts.
static acc_code t()
Construct the "true" acceptance condition.
Definition: acc.hh:627
static acc_code fin_neg(mark_t m)
Construct a generalized co-Büchi acceptance for complemented sets.
Definition: acc.hh:671
static acc_code parity_min(bool is_odd, unsigned sets)
Build a parity acceptance condition.
Definition: acc.hh:867
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:639
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:746
static acc_code generalized_co_buchi(unsigned n)
Build a generalized-co-Büchi acceptance condition with n sets.
Definition: acc.hh:778
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:830
acc_code & operator|=(const acc_code &r)
Disjunct the current condition in place with r.
Definition: acc.hh:1007
acc_code & operator&=(const acc_code &r)
Conjunct the current condition in place with r.
Definition: acc.hh:900
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:85
bool is_singleton() const
Whether the mark contains only one bit set.
Definition: acc.hh:385
mark_t lowest() const
A mark_t where all bits have been removed except the lowest one.
Definition: acc.hh:379
unsigned max_set() const
The number of the highest set used plus one.
Definition: acc.hh:355
mark_t & remove_some(unsigned n)
Remove n bits that where set.
Definition: acc.hh:409
constexpr static unsigned max_accsets()
The maximum number of acceptance sets supported by this implementation.
Definition: acc.hh:138
static mark_t all()
A mark_t with all bits set to one.
Definition: acc.hh:148
spot::internal::mark_container sets() const
Returns some iterable object that contains the used sets.
Definition: acc.hh:2401
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:340
mark_t(const iterator &begin, const iterator &end)
Create a mark_t from a range of set numbers.
Definition: acc.hh:103
unsigned count() const
Number of bits sets.
Definition: acc.hh:346
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:114
bool has_many() const
Whether the mark contains at least two bits set.
Definition: acc.hh:396
unsigned min_set() const
The number of the lowest set used plus one.
Definition: acc.hh:367
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:333
void fill(iterator here) const
Fill a container with the indices of the bits that are set.
Definition: acc.hh:418
Rabin/streett pairs used by is_rabin_like and is_streett_like.
Definition: acc.hh:1678
Definition: acc.hh:41
Definition: acc.hh:2243
A "node" in an acceptance formulas.
Definition: acc.hh:457

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