23 #include <unordered_map>
26 #include "tl/defaultenv.hh"
36 typedef unsigned value_t;
46 template<
class iterator>
47 mark_t(
const iterator& begin,
const iterator& end)
50 for (iterator i = begin; i != end; ++i)
54 mark_t(std::initializer_list<unsigned> vals)
55 :
mark_t(vals.begin(), vals.end())
59 bool operator==(
unsigned o)
const
65 bool operator!=(
unsigned o)
const
71 bool operator==(
mark_t o)
const
76 bool operator!=(
mark_t o)
const
81 bool operator<(
mark_t o)
const
86 bool operator<=(
mark_t o)
const
91 bool operator>(
mark_t o)
const
96 bool operator>=(
mark_t o)
const
101 operator bool()
const
106 bool has(
unsigned u)
const
108 return id & (1
U << u);
116 void clear(
unsigned u)
170 mark_t operator<<(
int i)
const
175 mark_t& operator<<=(
int i)
181 mark_t operator>>(
int i)
const
186 mark_t& operator>>=(
int i)
206 auto rm = (~yv) & (yv - 1);
208 auto lm = ~(yv ^ (yv - 1));
209 xv = ((xv & lm) >> 1) | (xv & rm);
216 unsigned count()
const
219 return __builtin_popcount(
id);
235 unsigned max_set()
const
254 mark_t& remove_some(
unsigned n)
261 template<
class iterator>
262 void fill(iterator here)
const
276 std::vector<unsigned> sets()
const
278 std::vector<unsigned> res;
279 fill(std::back_inserter(res));
284 friend std::ostream& operator<<(std::ostream& os,
mark_t m);
288 enum class acc_op : unsigned short
289 { Inf, Fin, InfNeg, FinNeg,
And,
Or };
300 struct SPOT_API
acc_code:
public std::vector<acc_word>
302 bool operator==(
const acc_code& other)
const
304 unsigned pos = size();
305 if (other.size() != pos)
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)
316 case acc_cond::acc_op::And:
317 case acc_cond::acc_op::Or:
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:
325 if (other[pos].mark != (*
this)[pos].mark)
333 bool operator<(
const acc_code& other)
const
335 unsigned pos = size();
336 auto osize = other.size();
343 auto op = (*this)[pos - 1].op;
344 auto oop = other[pos - 1].op;
349 auto sz = (*this)[pos - 1].size;
350 auto osz = other[pos - 1].size;
357 case acc_cond::acc_op::And:
358 case acc_cond::acc_op::Or:
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:
366 auto m = (*this)[pos].mark;
367 auto om = other[pos].mark;
378 bool operator>(
const acc_code& other)
const
380 return other < *
this;
383 bool operator<=(
const acc_code& other)
const
385 return !(other < *
this);
388 bool operator>=(
const acc_code& other)
const
390 return !(*
this < other);
393 bool operator!=(
const acc_code& other)
const
395 return !(*
this == other);
402 || ((*this)[s - 1].op == acc_op::Inf && (*this)[s - 2].mark == 0
U);
409 && (*this)[s - 1].op == acc_op::Fin && (*this)[s - 2].mark == 0
U;
417 res[1].op = acc_op::Fin;
432 res[1].op = acc_op::Fin;
437 static acc_code fin(std::initializer_list<unsigned> vals)
447 res[1].op = acc_op::FinNeg;
452 static acc_code fin_neg(std::initializer_list<unsigned> vals)
454 return fin_neg(
mark_t(vals));
462 res[1].op = acc_op::Inf;
467 static acc_code inf(std::initializer_list<unsigned> vals)
477 res[1].op = acc_op::InfNeg;
482 static acc_code inf_neg(std::initializer_list<unsigned> vals)
484 return inf_neg(
mark_t(vals));
497 static acc_code generalized_buchi(
unsigned n)
503 static acc_code generalized_co_buchi(
unsigned n)
516 pair.append_and(fin({2*n - 2}));
517 res.append_or(std::move(pair));
530 pair.append_or(fin({2*n - 2}));
531 res.append_and(std::move(pair));
537 template<
class Iterator>
538 static acc_code generalized_rabin(Iterator begin, Iterator end)
542 for (Iterator i = begin; i != end; ++i)
546 for (
unsigned ni = *i; ni > 0; --ni)
548 pair.append_and(inf(m));
549 std::swap(pair, res);
550 res.append_or(std::move(pair));
555 static acc_code parity(
bool max,
bool odd,
unsigned sets);
560 static acc_code random(
unsigned n,
double reuse = 0.0);
564 if (is_tt() || r.is_ff())
566 *
this = std::move(r);
569 if (is_ff() || r.is_tt())
571 unsigned s = size() - 1;
572 unsigned rs = r.size() - 1;
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))
578 (*this)[s - 1].mark |= r[rs - 1].mark;
590 auto start = &(*this)[s] - (*this)[s].size;
591 auto pos = &(*this)[s] - 1;
595 if (pos->op == acc_op::Inf)
600 pos -= pos->size + 1;
603 else if ((*
this)[s].
op == acc_op::Inf)
605 left_inf = &(*this)[s - 1];
609 auto right_end = &r.back();
613 auto pos = --right_end;
616 if (pos->op == acc_op::Inf)
621 pos -= pos->size + 1;
624 else if (right_end->op == acc_op::Inf)
626 right_inf = right_end - 1;
629 if (left_inf && right_inf)
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);
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);
644 insert(this->end(), &r[0], right_end + 1);
655 if (is_tt() || r.is_ff())
660 if (is_ff() || r.is_tt())
662 unsigned s = size() - 1;
663 unsigned rs = r.size() - 1;
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))
668 (*this)[s - 1].mark |= r[rs - 1].mark;
680 auto start = &(*this)[s] - (*this)[s].size;
681 auto pos = &(*this)[s] - 1;
685 if (pos->op == acc_op::Inf)
690 pos -= pos->size + 1;
693 else if ((*
this)[s].
op == acc_op::Inf)
695 left_inf = &(*this)[s - 1];
698 const acc_word* right_inf =
nullptr;
699 auto right_end = &r.back();
703 auto pos = --right_end;
706 if (pos->op == acc_op::Inf)
711 pos -= pos->size + 1;
714 else if (right_end->op == acc_op::Inf)
716 right_inf = right_end - 1;
719 if (left_inf && right_inf)
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);
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);
734 insert(this->end(), &r[0], right_end + 1);
745 if (is_tt() || r.is_ff())
747 if (is_ff() || r.is_tt())
749 *
this = std::move(r);
752 unsigned s = size() - 1;
753 unsigned rs = r.size() - 1;
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))
758 (*this)[s - 1].mark |= r[rs - 1].mark;
765 insert(this->end(), r.begin(), r.end());
772 void shift_left(
unsigned sets)
776 unsigned pos = size();
779 switch ((*
this)[pos - 1].
op)
781 case acc_cond::acc_op::And:
782 case acc_cond::acc_op::Or:
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:
790 (*this)[pos].mark.id <<= sets;
810 std::vector<std::vector<int>>
811 missing(
mark_t inf,
bool accepting)
const;
813 bool accepting(
mark_t inf)
const;
815 bool inf_satisfiable(
mark_t inf)
const;
837 std::pair<bool, acc_cond::mark_t> unsat_mark()
const;
840 std::pair<acc_cond::mark_t, acc_cond::mark_t> used_inf_fin_sets()
const;
845 to_html(std::ostream& os,
846 std::function<
void(std::ostream&,
int)>
847 set_printer =
nullptr)
const;
852 to_text(std::ostream& os,
853 std::function<
void(std::ostream&,
int)>
854 set_printer =
nullptr)
const;
858 friend std::ostream& operator<<(std::ostream& os,
const acc_code& code);
868 : num_(o.num_), all_(o.all_), code_(o.code_)
876 void set_acceptance(
const acc_code& code)
879 uses_fin_acceptance_ = check_fin_acceptance();
882 const acc_code& get_acceptance()
const
887 acc_code& get_acceptance()
892 bool uses_fin_acceptance()
const
894 return uses_fin_acceptance_;
899 return code_.is_tt();
904 return code_.is_ff();
907 bool is_buchi()
const
909 unsigned s = code_.size();
911 s == 2 && code_[1].op == acc_op::Inf && code_[0].mark == all_sets();
914 bool is_co_buchi()
const
916 return num_ == 1 && is_generalized_co_buchi();
919 void set_generalized_buchi()
921 set_acceptance(inf(all_sets()));
924 bool is_generalized_buchi()
const
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());
931 bool is_generalized_co_buchi()
const
933 unsigned s = code_.size();
935 code_[1].
op == acc_op::Fin && code_[0].mark == all_sets());
939 int is_rabin()
const;
941 int is_streett()
const;
944 bool is_generalized_rabin(std::vector<unsigned>& pairs)
const;
951 bool is_parity(
bool& max,
bool& odd,
bool equiv =
false)
const;
953 static acc_code generalized_buchi(
unsigned n)
955 mark_t m((1
U << n) - 1);
956 if (n == 8 *
sizeof(mark_t::value_t))
958 return acc_code::inf(m);
962 bool check_fin_acceptance()
const;
965 acc_code inf(mark_t mark)
const
967 return acc_code::inf(mark);
970 acc_code inf(std::initializer_list<unsigned> vals)
const
972 return inf(marks(vals.begin(), vals.end()));
975 acc_code inf_neg(mark_t mark)
const
977 return acc_code::inf_neg(mark);
980 acc_code inf_neg(std::initializer_list<unsigned> vals)
const
982 return inf_neg(marks(vals.begin(), vals.end()));
985 acc_code fin(mark_t mark)
const
987 return acc_code::fin(mark);
990 acc_code fin(std::initializer_list<unsigned> vals)
const
992 return fin(marks(vals.begin(), vals.end()));
995 acc_code fin_neg(mark_t mark)
const
997 return acc_code::fin_neg(mark);
1000 acc_code fin_neg(std::initializer_list<unsigned> vals)
const
1002 return fin_neg(marks(vals.begin(), vals.end()));
1005 unsigned add_sets(
unsigned num)
1011 if (num_ > 8 *
sizeof(mark_t::id))
1012 throw std::runtime_error(
"Too many acceptance sets used.");
1022 mark_t mark(
unsigned u)
const
1027 template<
class iterator>
1028 mark_t marks(
const iterator& begin,
const iterator& end)
const
1030 return mark_t(begin, end);
1033 mark_t marks(std::initializer_list<unsigned> vals)
const
1035 return marks(vals.begin(), vals.end());
1039 std::vector<unsigned> sets(mark_t m)
const
1045 bool has(mark_t m,
unsigned u)
const
1050 mark_t cup(mark_t l, mark_t r)
const
1055 mark_t cap(mark_t l, mark_t r)
const
1060 mark_t set_minus(mark_t l, mark_t r)
const
1065 mark_t join(
const acc_cond& la, mark_t lm,
1066 const acc_cond& ra, mark_t rm)
const
1068 assert(la.num_sets() + ra.num_sets() == num_sets());
1070 return lm.id | (rm.id << la.num_sets());
1073 mark_t comp(mark_t l)
const
1078 mark_t all_sets()
const
1083 bool accepting(mark_t inf)
const
1085 return code_.accepting(inf);
1088 bool inf_satisfiable(mark_t inf)
const
1090 return code_.inf_satisfiable(inf);
1093 mark_t accepting_sets(mark_t inf)
const;
1095 std::ostream& format(std::ostream& os, mark_t m)
const
1103 std::string format(mark_t m)
const
1105 std::ostringstream os;
1110 unsigned num_sets()
const
1115 template<
class iterator>
1116 mark_t useless(iterator begin, iterator end)
const
1118 mark_t::value_t u = 0
U;
1119 for (
unsigned x = 0; x < num_; ++x)
1124 unsigned all = all_ ^ (u | (1 << x));
1125 for (iterator y = begin; y != end; ++y)
1141 mark_t::value_t mark_(
unsigned u)
const
1143 assert(u < num_sets());
1147 mark_t::value_t all_sets_()
const
1151 return -1
U >> (8 *
sizeof(mark_t::value_t) - num_);
1155 mark_t::value_t all_;
1157 bool uses_fin_acceptance_ =
false;
1178 SPOT_API acc_cond::acc_code parse_acc_code(
const char* input);
1184 struct hash<
spot::acc_cond::mark_t>
1188 std::hash<decltype(m.id)> h;
Definition: formula.hh:1539
op
Operator types.
Definition: formula.hh:61