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

Please direct any question, comment, or bug report to the Spot mailing list at spot@lrde.epita.fr.
Generated on Wed Aug 26 2015 08:42:37 for spot by doxygen 1.8.8