spot  1.99.2
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
acc.hh
1 // -*- coding: utf-8 -*-
2 // Copyright (C) 2014, 2015 Laboratoire de Recherche et Développement de
3 // 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 <unordered_map>
24 #include <sstream>
25 #include <vector>
26 #include "ltlenv/defaultenv.hh"
27 #include <iostream>
28 
29 namespace spot
30 {
31  class SPOT_API acc_cond
32  {
33  public:
34  struct mark_t
35  {
36  typedef unsigned value_t;
37  value_t id;
38 
39  mark_t() = default;
40 
41  mark_t(value_t id)
42  : id(id)
43  {
44  }
45 
46  template<class iterator>
47  mark_t(const iterator& begin, const iterator& end)
48  {
49  id = 0U;
50  for (iterator i = begin; i != end; ++i)
51  set(*i);
52  }
53 
54  mark_t(std::initializer_list<unsigned> vals)
55  : mark_t(vals.begin(), vals.end())
56  {
57  }
58 
59  bool operator==(unsigned o) const
60  {
61  assert(o == 0U);
62  return id == o;
63  }
64 
65  bool operator!=(unsigned o) const
66  {
67  assert(o == 0U);
68  return id != o;
69  }
70 
71  bool operator==(mark_t o) const
72  {
73  return id == o.id;
74  }
75 
76  bool operator!=(mark_t o) const
77  {
78  return id != o.id;
79  }
80 
81  bool operator<(mark_t o) const
82  {
83  return id < o.id;
84  }
85 
86  bool operator<=(mark_t o) const
87  {
88  return id <= o.id;
89  }
90 
91  bool operator>(mark_t o) const
92  {
93  return id > o.id;
94  }
95 
96  bool operator>=(mark_t o) const
97  {
98  return id >= o.id;
99  }
100 
101  operator bool() const
102  {
103  return id != 0;
104  }
105 
106  bool has(unsigned u) const
107  {
108  return id & (1U << u);
109  }
110 
111  void set(unsigned u)
112  {
113  id |= (1U << u);
114  }
115 
116  void clear(unsigned u)
117  {
118  id &= ~(1U << u);
119  }
120 
121  mark_t& operator&=(mark_t r)
122  {
123  id &= r.id;
124  return *this;
125  }
126 
127  mark_t& operator|=(mark_t r)
128  {
129  id |= r.id;
130  return *this;
131  }
132 
133  mark_t& operator-=(mark_t r)
134  {
135  id &= ~r.id;
136  return *this;
137  }
138 
139  mark_t& operator^=(mark_t r)
140  {
141  id ^= r.id;
142  return *this;
143  }
144 
145  mark_t operator&(mark_t r) const
146  {
147  return id & r.id;
148  }
149 
150  mark_t operator|(mark_t r) const
151  {
152  return id | r.id;
153  }
154 
155  mark_t operator-(mark_t r) const
156  {
157  return id & ~r.id;
158  }
159 
160  mark_t operator~() const
161  {
162  return ~id;
163  }
164 
165  mark_t operator^(mark_t r) const
166  {
167  return id ^ r.id;
168  }
169 
170  mark_t operator<<(int i) const
171  {
172  return id << i;
173  }
174 
175  mark_t& operator<<=(int i)
176  {
177  id <<= i;
178  return *this;
179  }
180 
181  mark_t operator>>(int i) const
182  {
183  return id >> i;
184  }
185 
186  mark_t& operator>>=(int i)
187  {
188  id >>= i;
189  return *this;
190  }
191 
192  mark_t strip(mark_t y) const
193  {
194  // strip every bit of id that is marked in y
195  // 100101110100.strip(
196  // 001011001000)
197  // == 10 1 11 100
198  // == 10111100
199 
200  auto xv = id; // 100101110100
201  auto yv = y.id; // 001011001000
202 
203  while (yv && xv)
204  {
205  // Mask for everything after the last 1 in y
206  auto rm = (~yv) & (yv - 1); // 000000000111
207  // Mask for everything before the last 1 in y
208  auto lm = ~(yv ^ (yv - 1)); // 111111110000
209  xv = ((xv & lm) >> 1) | (xv & rm);
210  yv = (yv & lm) >> 1;
211  }
212  return xv;
213  }
214 
215  // Number of bits sets.
216  unsigned count() const
217  {
218 #ifdef __GNUC__
219  return __builtin_popcount(id);
220 #else
221  unsigned c = 0U;
222  auto v = id;
223  while (v)
224  {
225  ++c;
226  v &= v - 1;
227  }
228  return c;
229 #endif
230  }
231 
232  // Return the number of the highest set used plus one.
233  // So if no set is used, this returns 0,
234  // but if the sets {1,3,8} are used, this returns 9.
235  unsigned max_set() const
236  {
237  auto i = id;
238  int res = 0;
239  while (i)
240  {
241  ++res;
242  i >>= 1;
243  }
244  return res;
245  }
246 
247  // Remove n bits that where set
248  mark_t& remove_some(unsigned n)
249  {
250  while (n--)
251  id &= id - 1;
252  return *this;
253  }
254 
255  template<class iterator>
256  void fill(iterator here) const
257  {
258  auto a = id;
259  unsigned level = 0;
260  while (a)
261  {
262  if (a & 1)
263  *here++ = level;
264  ++level;
265  a >>= 1;
266  }
267  }
268 
269  // FIXME: Return some iterable object without building a vector.
270  std::vector<unsigned> sets() const
271  {
272  std::vector<unsigned> res;
273  fill(std::back_inserter(res));
274  return res;
275  }
276 
277  SPOT_API
278  friend std::ostream& operator<<(std::ostream& os, mark_t m);
279  };
280 
281  // This encodes either an operator or set of acceptance sets.
282  enum class acc_op : unsigned short
283  { Inf, Fin, InfNeg, FinNeg, And, Or };
284  union acc_word
285  {
286  mark_t mark;
287  struct {
288  acc_op op; // Operator
289  unsigned short size; // Size of the subtree (number of acc_word),
290  // not counting this node.
291  };
292  };
293 
294  struct SPOT_API acc_code: public std::vector<acc_word>
295  {
296  bool operator==(const acc_code& other) const
297  {
298  unsigned pos = size();
299  if (other.size() != pos)
300  return false;
301  while (pos > 0)
302  {
303  auto op = (*this)[pos - 1].op;
304  auto sz = (*this)[pos - 1].size;
305  if (other[pos - 1].op != op ||
306  other[pos - 1].size != sz)
307  return false;
308  switch (op)
309  {
310  case acc_cond::acc_op::And:
311  case acc_cond::acc_op::Or:
312  --pos;
313  break;
314  case acc_cond::acc_op::Inf:
315  case acc_cond::acc_op::InfNeg:
316  case acc_cond::acc_op::Fin:
317  case acc_cond::acc_op::FinNeg:
318  pos -= 2;
319  if (other[pos].mark != (*this)[pos].mark)
320  return false;
321  break;
322  }
323  }
324  return true;
325  };
326 
327  bool operator<(const acc_code& other) const
328  {
329  unsigned pos = size();
330  auto osize = other.size();
331  if (pos < osize)
332  return true;
333  if (pos > osize)
334  return false;
335  while (pos > 0)
336  {
337  auto op = (*this)[pos - 1].op;
338  auto oop = other[pos - 1].op;
339  if (op < oop)
340  return true;
341  if (op > oop)
342  return false;
343  auto sz = (*this)[pos - 1].size;
344  auto osz = other[pos - 1].size;
345  if (sz < osz)
346  return true;
347  if (sz > osz)
348  return false;
349  switch (op)
350  {
351  case acc_cond::acc_op::And:
352  case acc_cond::acc_op::Or:
353  --pos;
354  break;
355  case acc_cond::acc_op::Inf:
356  case acc_cond::acc_op::InfNeg:
357  case acc_cond::acc_op::Fin:
358  case acc_cond::acc_op::FinNeg:
359  pos -= 2;
360  auto m = (*this)[pos].mark;
361  auto om = other[pos].mark;
362  if (m < om)
363  return true;
364  if (m > om)
365  return false;
366  break;
367  }
368  }
369  return false;
370  }
371 
372  bool operator>(const acc_code& other) const
373  {
374  return other < *this;
375  }
376 
377  bool operator<=(const acc_code& other) const
378  {
379  return !(other < *this);
380  }
381 
382  bool operator>=(const acc_code& other) const
383  {
384  return !(*this < other);
385  }
386 
387  bool operator!=(const acc_code& other) const
388  {
389  return !(*this == other);
390  }
391 
392  bool is_true() const
393  {
394  unsigned s = size();
395  return s == 0
396  || ((*this)[s - 1].op == acc_op::Inf && (*this)[s - 2].mark == 0U);
397  }
398 
399  bool is_false() const
400  {
401  unsigned s = size();
402  return s > 1
403  && (*this)[s - 1].op == acc_op::Fin && (*this)[s - 2].mark == 0U;
404  }
405 
406  static acc_code f()
407  {
408  acc_code res;
409  res.resize(2);
410  res[0].mark = 0U;
411  res[1].op = acc_op::Fin;
412  res[1].size = 1;
413  return res;
414  }
415 
416  static acc_code t()
417  {
418  return {};
419  }
420 
421  static acc_code fin(mark_t m)
422  {
423  acc_code res;
424  res.resize(2);
425  res[0].mark = m;
426  res[1].op = acc_op::Fin;
427  res[1].size = 1;
428  return res;
429  }
430 
431  static acc_code fin(std::initializer_list<unsigned> vals)
432  {
433  return fin(mark_t(vals));
434  }
435 
436  static acc_code fin_neg(mark_t m)
437  {
438  acc_code res;
439  res.resize(2);
440  res[0].mark = m;
441  res[1].op = acc_op::FinNeg;
442  res[1].size = 1;
443  return res;
444  }
445 
446  static acc_code fin_neg(std::initializer_list<unsigned> vals)
447  {
448  return fin_neg(mark_t(vals));
449  }
450 
451  static acc_code inf(mark_t m)
452  {
453  acc_code res;
454  res.resize(2);
455  res[0].mark = m;
456  res[1].op = acc_op::Inf;
457  res[1].size = 1;
458  return res;
459  }
460 
461  static acc_code inf(std::initializer_list<unsigned> vals)
462  {
463  return inf(mark_t(vals));
464  }
465 
466  static acc_code inf_neg(mark_t m)
467  {
468  acc_code res;
469  res.resize(2);
470  res[0].mark = m;
471  res[1].op = acc_op::InfNeg;
472  res[1].size = 1;
473  return res;
474  }
475 
476  static acc_code inf_neg(std::initializer_list<unsigned> vals)
477  {
478  return inf_neg(mark_t(vals));
479  }
480 
481  static acc_code buchi()
482  {
483  return inf({0});
484  }
485 
486  static acc_code cobuchi()
487  {
488  return fin({0});
489  }
490 
491  static acc_code generalized_buchi(unsigned n)
492  {
493  acc_cond::mark_t m = (1U << n) - 1;
494  return inf(m);
495  }
496 
497  static acc_code generalized_co_buchi(unsigned n)
498  {
499  acc_cond::mark_t m = (1U << n) - 1;
500  return fin(m);
501  }
502 
503  // n is a number of pairs.
504  static acc_code rabin(unsigned n)
505  {
506  acc_cond::acc_code res = f();
507  while (n > 0)
508  {
509  acc_cond::acc_code pair = inf({2*n - 1});
510  pair.append_and(fin({2*n - 2}));
511  res.append_or(std::move(pair));
512  --n;
513  }
514  return res;
515  }
516 
517  // n is a number of pairs.
518  static acc_code streett(unsigned n)
519  {
520  acc_cond::acc_code res = t();
521  while (n > 0)
522  {
523  acc_cond::acc_code pair = inf({2*n - 1});
524  pair.append_or(fin({2*n - 2}));
525  res.append_and(std::move(pair));
526  --n;
527  }
528  return res;
529  }
530 
531  template<class Iterator>
532  static acc_code generalized_rabin(Iterator begin, Iterator end)
533  {
534  acc_cond::acc_code res = f();
535  unsigned n = 0;
536  for (Iterator i = begin; i != end; ++i)
537  {
538  acc_cond::acc_code pair = fin({n++});
539  acc_cond::mark_t m = 0U;
540  for (unsigned ni = *i; ni > 0; --ni)
541  m.set({n++});
542  pair.append_and(inf(m));
543  std::swap(pair, res);
544  res.append_or(std::move(pair));
545  }
546  return res;
547  }
548 
549  static acc_code parity(bool max, bool odd, unsigned sets);
550 
551  // Number of acceptance sets to use, and probability to reuse
552  // each set another time after it has been used in the
553  // acceptance formula.
554  static acc_code random(unsigned n, double reuse = 0.0);
555 
556  void append_and(acc_code&& r)
557  {
558  if (is_true() || r.is_false())
559  {
560  *this = std::move(r);
561  return;
562  }
563  if (is_false() || r.is_true())
564  return;
565  unsigned s = size() - 1;
566  unsigned rs = r.size() - 1;
567  // We want to group all Inf(x) operators:
568  // Inf(a) & Inf(b) = Inf(a & b)
569  if (((*this)[s].op == acc_op::Inf && r[rs].op == acc_op::Inf)
570  || ((*this)[s].op == acc_op::InfNeg && r[rs].op == acc_op::InfNeg))
571  {
572  (*this)[s - 1].mark |= r[rs - 1].mark;
573  return;
574  }
575 
576  // In the more complex scenarios, left and right may both
577  // be conjunctions, and Inf(x) might be a member of each
578  // side. Find it if it exists.
579  // left_inf points to the left Inf mark if any.
580  // right_inf points to the right Inf mark if any.
581  acc_word* left_inf = nullptr;
582  if ((*this)[s].op == acc_op::And)
583  {
584  auto start = &(*this)[s] - (*this)[s].size;
585  auto pos = &(*this)[s] - 1;
586  pop_back();
587  while (pos > start)
588  {
589  if (pos->op == acc_op::Inf)
590  {
591  left_inf = pos - 1;
592  break;
593  }
594  pos -= pos->size + 1;
595  }
596  }
597  else if ((*this)[s].op == acc_op::Inf)
598  {
599  left_inf = &(*this)[s - 1];
600  }
601 
602  acc_word* right_inf = nullptr;
603  auto right_end = &r.back();
604  if (right_end->op == acc_op::And)
605  {
606  auto start = &r[0];
607  auto pos = --right_end;
608  while (pos > start)
609  {
610  if (pos->op == acc_op::Inf)
611  {
612  right_inf = pos - 1;
613  break;
614  }
615  pos -= pos->size + 1;
616  }
617  }
618  else if (right_end->op == acc_op::Inf)
619  {
620  right_inf = right_end - 1;
621  }
622 
623  if (left_inf && right_inf)
624  {
625  left_inf->mark |= right_inf->mark;
626  insert(this->end(), &r[0], right_inf);
627  insert(this->end(), right_inf + 2, right_end + 1);
628  }
629  else if (right_inf)
630  {
631  // Always insert Inf() at the very first entry.
632  insert(this->begin(), right_inf, right_inf + 2);
633  insert(this->end(), &r[0], right_inf);
634  insert(this->end(), right_inf + 2, right_end + 1);
635  }
636  else
637  {
638  insert(this->end(), &r[0], right_end + 1);
639  }
640 
641  acc_word w;
642  w.op = acc_op::And;
643  w.size = size();
644  push_back(w);
645  }
646 
647  void append_and(const acc_code& r)
648  {
649  if (is_true() || r.is_false())
650  {
651  *this = r;
652  return;
653  }
654  if (is_false() || r.is_true())
655  return;
656  unsigned s = size() - 1;
657  unsigned rs = r.size() - 1;
658  // Inf(a) & Inf(b) = Inf(a & b)
659  if (((*this)[s].op == acc_op::Inf && r[rs].op == acc_op::Inf)
660  || ((*this)[s].op == acc_op::InfNeg && r[rs].op == acc_op::InfNeg))
661  {
662  (*this)[s - 1].mark |= r[rs - 1].mark;
663  return;
664  }
665 
666  // In the more complex scenarios, left and right may both
667  // be conjunctions, and Inf(x) might be a member of each
668  // side. Find it if it exists.
669  // left_inf points to the left Inf mark if any.
670  // right_inf points to the right Inf mark if any.
671  acc_word* left_inf = nullptr;
672  if ((*this)[s].op == acc_op::And)
673  {
674  auto start = &(*this)[s] - (*this)[s].size;
675  auto pos = &(*this)[s] - 1;
676  pop_back();
677  while (pos > start)
678  {
679  if (pos->op == acc_op::Inf)
680  {
681  left_inf = pos - 1;
682  break;
683  }
684  pos -= pos->size + 1;
685  }
686  }
687  else if ((*this)[s].op == acc_op::Inf)
688  {
689  left_inf = &(*this)[s - 1];
690  }
691 
692  const acc_word* right_inf = nullptr;
693  auto right_end = &r.back();
694  if (right_end->op == acc_op::And)
695  {
696  auto start = &r[0];
697  auto pos = --right_end;
698  while (pos > start)
699  {
700  if (pos->op == acc_op::Inf)
701  {
702  right_inf = pos - 1;
703  break;
704  }
705  pos -= pos->size + 1;
706  }
707  }
708  else if (right_end->op == acc_op::Inf)
709  {
710  right_inf = right_end - 1;
711  }
712 
713  if (left_inf && right_inf)
714  {
715  left_inf->mark |= right_inf->mark;
716  insert(this->end(), &r[0], right_inf);
717  insert(this->end(), right_inf + 2, right_end + 1);
718  }
719  else if (right_inf)
720  {
721  // Always insert Inf() at the very first entry.
722  insert(this->begin(), right_inf, right_inf + 2);
723  insert(this->end(), &r[0], right_inf);
724  insert(this->end(), right_inf + 2, right_end + 1);
725  }
726  else
727  {
728  insert(this->end(), &r[0], right_end + 1);
729  }
730 
731  acc_word w;
732  w.op = acc_op::And;
733  w.size = size();
734  push_back(w);
735  }
736 
737  void append_or(acc_code&& r)
738  {
739  if (is_true() || r.is_false())
740  return;
741  if (is_false() || r.is_true())
742  {
743  *this = std::move(r);
744  return;
745  }
746  unsigned s = size() - 1;
747  unsigned rs = r.size() - 1;
748  // Fin(a) | Fin(b) = Fin(a | b)
749  if (((*this)[s].op == acc_op::Fin && r[rs].op == acc_op::Fin)
750  || ((*this)[s].op == acc_op::FinNeg && r[rs].op == acc_op::FinNeg))
751  {
752  (*this)[s - 1].mark |= r[rs - 1].mark;
753  return;
754  }
755  if ((*this)[s].op == acc_op::Or)
756  pop_back();
757  if (r.back().op == acc_op::Or)
758  r.pop_back();
759  insert(this->end(), r.begin(), r.end());
760  acc_word w;
761  w.op = acc_op::Or;
762  w.size = size();
763  push_back(w);
764  }
765 
766  void shift_left(unsigned sets)
767  {
768  if (empty())
769  return;
770  unsigned pos = size();
771  do
772  {
773  switch ((*this)[pos - 1].op)
774  {
775  case acc_cond::acc_op::And:
776  case acc_cond::acc_op::Or:
777  --pos;
778  break;
779  case acc_cond::acc_op::Inf:
780  case acc_cond::acc_op::InfNeg:
781  case acc_cond::acc_op::Fin:
782  case acc_cond::acc_op::FinNeg:
783  pos -= 2;
784  (*this)[pos].mark.id <<= sets;
785  break;
786  }
787  }
788  while (pos > 0);
789  }
790 
791  bool is_dnf() const;
792  bool is_cnf() const;
793 
794  acc_code to_dnf() const;
795  acc_code to_cnf() const;
796 
797  acc_code complement() const;
798 
799  // Return a list of acceptance marks needed to close a cycle
800  // that already visit INF infinitely often, so that the cycle is
801  // accepting (ACCEPTING=true) or rejecting (ACCEPTING=false).
802  // Positive values describe positive set.
803  // A negative value x means the set -x-1 must be absent.
804  std::vector<std::vector<int>>
805  missing(mark_t inf, bool accepting) const;
806 
807  bool accepting(mark_t inf) const;
808 
809  bool inf_satisfiable(mark_t inf) const;
810 
811  // Remove all the acceptance sets in rem.
812  //
813  // If MISSING is set, the acceptance sets are assumed to be
814  // missing from the automaton, and the acceptance is updated to
815  // reflect this. For instance (Inf(1)&Inf(2))|Fin(3) will
816  // become Fin(3) if we remove 2 because it is missing from this
817  // automaton, because there is no way to fulfill Inf(1)&Inf(2)
818  // in this case. So essentially MISSING causes Inf(rem) to
819  // become f, and Fin(rem) to become t.
820  //
821  // If MISSING is unset, Inf(rem) become t while Fin(rem) become
822  // f. Removing 2 from (Inf(1)&Inf(2))|Fin(3) would then give
823  // Inf(1)|Fin(3).
824  acc_code strip(acc_cond::mark_t rem, bool missing) const;
825 
826  // Return the set of sets appearing in the condition.
827  acc_cond::mark_t used_sets() const;
828 
829  // Return (true, m) if there exist some m that does not satisfy
830  // the acceptance condition. Return (false, 0U) otherwise.
831  std::pair<bool, acc_cond::mark_t> unsat_mark() const;
832 
833  // Return the sets used as Inf or Fin in the acceptance condition
834  std::pair<acc_cond::mark_t, acc_cond::mark_t> used_inf_fin_sets() const;
835 
836  // Print the acceptance as HTML. The set_printer function can
837  // be used to implement customized output for set numbers.
838  std::ostream&
839  to_html(std::ostream& os,
840  std::function<void(std::ostream&, int)>
841  set_printer = nullptr) const;
842 
843  // Print the acceptance as text. The set_printer function can
844  // be used to implement customized output for set numbers.
845  std::ostream&
846  to_text(std::ostream& os,
847  std::function<void(std::ostream&, int)>
848  set_printer = nullptr) const;
849 
850  // Calls to_text
851  SPOT_API
852  friend std::ostream& operator<<(std::ostream& os, const acc_code& code);
853  };
854 
855  acc_cond(unsigned n_sets = 0)
856  : num_(0U), all_(0U)
857  {
858  add_sets(n_sets);
859  }
860 
861  acc_cond(const acc_cond& o)
862  : num_(o.num_), all_(o.all_), code_(o.code_)
863  {
864  }
865 
866  ~acc_cond()
867  {
868  }
869 
870  void set_acceptance(const acc_code& code)
871  {
872  code_ = code;
873  uses_fin_acceptance_ = check_fin_acceptance();
874  }
875 
876  const acc_code& get_acceptance() const
877  {
878  return code_;
879  }
880 
881  acc_code& get_acceptance()
882  {
883  return code_;
884  }
885 
886  bool uses_fin_acceptance() const
887  {
888  return uses_fin_acceptance_;
889  }
890 
891  bool is_true() const
892  {
893  return code_.is_true();
894  }
895 
896  bool is_false() const
897  {
898  return code_.is_false();
899  }
900 
901  bool is_buchi() const
902  {
903  unsigned s = code_.size();
904  return num_ == 1 &&
905  s == 2 && code_[1].op == acc_op::Inf && code_[0].mark == all_sets();
906  }
907 
908  bool is_co_buchi() const
909  {
910  return num_ == 1 && is_generalized_co_buchi();
911  }
912 
913  void set_generalized_buchi()
914  {
915  set_acceptance(inf(all_sets()));
916  }
917 
918  bool is_generalized_buchi() const
919  {
920  unsigned s = code_.size();
921  return (s == 0 && num_ == 0) ||
922  (s == 2 && code_[1].op == acc_op::Inf && code_[0].mark == all_sets());
923  }
924 
925  bool is_generalized_co_buchi() const
926  {
927  unsigned s = code_.size();
928  return (s == 2 &&
929  code_[1].op == acc_op::Fin && code_[0].mark == all_sets());
930  }
931 
932  // Returns a number of pairs (>=0) if Rabin, or -1 else.
933  int is_rabin() const;
934  // Returns a number of pairs (>=0) if Streett, or -1 else.
935  int is_streett() const;
936 
937  // Return the number of Inf in each pair.
938  bool is_generalized_rabin(std::vector<unsigned>& pairs) const;
939 
940  // If EQUIV is false, this return true iff the acceptance
941  // condition is a parity condition written in the canonical way
942  // given in the HOA specifications. If EQUIV is true, then we
943  // check whether the condition is logically equivalent to some
944  // parity acceptance condition.
945  bool is_parity(bool& max, bool& odd, bool equiv = false) const;
946 
947  static acc_code generalized_buchi(unsigned n)
948  {
949  mark_t m((1U << n) - 1);
950  if (n == 8 * sizeof(mark_t::value_t))
951  m = mark_t(-1U);
952  return acc_code::inf(m);
953  }
954 
955  protected:
956  bool check_fin_acceptance() const;
957 
958  public:
959  acc_code inf(mark_t mark) const
960  {
961  return acc_code::inf(mark);
962  }
963 
964  acc_code inf(std::initializer_list<unsigned> vals) const
965  {
966  return inf(marks(vals.begin(), vals.end()));
967  }
968 
969  acc_code inf_neg(mark_t mark) const
970  {
971  return acc_code::inf_neg(mark);
972  }
973 
974  acc_code inf_neg(std::initializer_list<unsigned> vals) const
975  {
976  return inf_neg(marks(vals.begin(), vals.end()));
977  }
978 
979  acc_code fin(mark_t mark) const
980  {
981  return acc_code::fin(mark);
982  }
983 
984  acc_code fin(std::initializer_list<unsigned> vals) const
985  {
986  return fin(marks(vals.begin(), vals.end()));
987  }
988 
989  acc_code fin_neg(mark_t mark) const
990  {
991  return acc_code::fin_neg(mark);
992  }
993 
994  acc_code fin_neg(std::initializer_list<unsigned> vals) const
995  {
996  return fin_neg(marks(vals.begin(), vals.end()));
997  }
998 
999  unsigned add_sets(unsigned num)
1000  {
1001  if (num == 0)
1002  return -1U;
1003  unsigned j = num_;
1004  num_ += num;
1005  if (num_ > 8 * sizeof(mark_t::id))
1006  throw std::runtime_error("Too many acceptance sets used.");
1007  all_ = all_sets_();
1008  return j;
1009  }
1010 
1011  unsigned add_set()
1012  {
1013  return add_sets(1);
1014  }
1015 
1016  mark_t mark(unsigned u) const
1017  {
1018  return mark_(u);
1019  }
1020 
1021  template<class iterator>
1022  mark_t marks(const iterator& begin, const iterator& end) const
1023  {
1024  return mark_t(begin, end);
1025  }
1026 
1027  mark_t marks(std::initializer_list<unsigned> vals) const
1028  {
1029  return marks(vals.begin(), vals.end());
1030  }
1031 
1032  // FIXME: Return some iterable object without building a vector.
1033  std::vector<unsigned> sets(mark_t m) const
1034  {
1035  return m.sets();
1036  }
1037 
1038  // whether m contains u
1039  bool has(mark_t m, unsigned u) const
1040  {
1041  return m.has(u);
1042  }
1043 
1044  mark_t cup(mark_t l, mark_t r) const
1045  {
1046  return l | r;
1047  }
1048 
1049  mark_t cap(mark_t l, mark_t r) const
1050  {
1051  return l & r;
1052  }
1053 
1054  mark_t set_minus(mark_t l, mark_t r) const
1055  {
1056  return l - r;
1057  }
1058 
1059  mark_t join(const acc_cond& la, mark_t lm,
1060  const acc_cond& ra, mark_t rm) const
1061  {
1062  assert(la.num_sets() + ra.num_sets() == num_sets());
1063  (void)ra;
1064  return lm.id | (rm.id << la.num_sets());
1065  }
1066 
1067  mark_t comp(mark_t l) const
1068  {
1069  return all_ ^ l.id;
1070  }
1071 
1072  mark_t all_sets() const
1073  {
1074  return all_;
1075  }
1076 
1077  bool accepting(mark_t inf) const
1078  {
1079  return code_.accepting(inf);
1080  }
1081 
1082  bool inf_satisfiable(mark_t inf) const
1083  {
1084  return code_.inf_satisfiable(inf);
1085  }
1086 
1087  mark_t accepting_sets(mark_t inf) const;
1088 
1089  std::ostream& format(std::ostream& os, mark_t m) const
1090  {
1091  auto a = m;
1092  if (a == 0U)
1093  return os;
1094  return os << m;
1095  }
1096 
1097  std::string format(mark_t m) const
1098  {
1099  std::ostringstream os;
1100  format(os, m);
1101  return os.str();
1102  }
1103 
1104  unsigned num_sets() const
1105  {
1106  return num_;
1107  }
1108 
1109  template<class iterator>
1110  mark_t useless(iterator begin, iterator end) const
1111  {
1112  mark_t::value_t u = 0U; // The set of useless marks.
1113  for (unsigned x = 0; x < num_; ++x)
1114  {
1115  // Skip marks that are already known to be useless.
1116  if (u & (1 << x))
1117  continue;
1118  unsigned all = all_ ^ (u | (1 << x));
1119  for (iterator y = begin; y != end; ++y)
1120  {
1121  auto v = y->id;
1122  if (v & (1 << x))
1123  {
1124  all &= v;
1125  if (!all)
1126  break;
1127  }
1128  }
1129  u |= all;
1130  }
1131  return u;
1132  }
1133 
1134  protected:
1135  mark_t::value_t mark_(unsigned u) const
1136  {
1137  assert(u < num_sets());
1138  return 1U << u;
1139  }
1140 
1141  mark_t::value_t all_sets_() const
1142  {
1143  if (num_ == 0)
1144  return 0;
1145  return -1U >> (8 * sizeof(mark_t::value_t) - num_);
1146  }
1147 
1148  unsigned num_;
1149  mark_t::value_t all_;
1150  acc_code code_;
1151  bool uses_fin_acceptance_ = false;
1152  };
1153 
1172  SPOT_API acc_cond::acc_code parse_acc_code(const char* input);
1173 }
1174 
1175 namespace std
1176 {
1177  template<>
1178  struct hash<spot::acc_cond::mark_t>
1179  {
1180  size_t operator()(spot::acc_cond::mark_t m) const
1181  {
1182  std::hash<decltype(m.id)> h;
1183  return h(m.id);
1184  }
1185  };
1186 }
Definition: public.hh:31
Definition: formula.hh:515
Definition: acc.hh:31
Definition: acc.hh:284
Definition: acc.hh:294
Definition: acc.hh:34

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on Fri Jul 17 2015 23:40:21 for spot by doxygen 1.8.8