23 #include <unordered_map> 26 #include <spot/tl/defaultenv.hh> 36 typedef unsigned value_t;
41 mark_t(value_t
id) noexcept
46 template<
class iterator>
47 mark_t(
const iterator& begin,
const iterator& end) noexcept
50 for (iterator i = begin; i != end; ++i)
54 mark_t(std::initializer_list<unsigned> vals) noexcept
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 explicit operator bool()
const 106 bool has(
unsigned u)
const 108 return id & (1
U << u);
116 void clear(
unsigned u)
170 mark_t operator<<(
unsigned i)
const 175 mark_t& operator<<=(
unsigned i)
181 mark_t operator>>(
unsigned i)
const 186 mark_t& operator>>=(
unsigned 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 238 return (
id == 0) ? 0 : (
sizeof(unsigned) * 8 - __builtin_clz(
id));
254 unsigned min_set()
const 259 return __builtin_ctz(
id) + 1;
279 mark_t& remove_some(
unsigned n)
286 template<
class iterator>
287 void fill(iterator here)
const 301 std::vector<unsigned> sets()
const 303 std::vector<unsigned> res;
304 fill(std::back_inserter(res));
309 friend std::ostream& operator<<(std::ostream& os,
mark_t m);
313 enum class acc_op : unsigned short
314 { Inf, Fin, InfNeg, FinNeg,
And,
Or };
325 struct SPOT_API
acc_code:
public std::vector<acc_word>
327 bool operator==(
const acc_code& other)
const 329 unsigned pos = size();
330 if (other.size() != pos)
334 auto op = (*this)[pos - 1].sub.op;
335 auto sz = (*this)[pos - 1].sub.size;
336 if (other[pos - 1].sub.op !=
op ||
337 other[pos - 1].sub.size != sz)
341 case acc_cond::acc_op::And:
342 case acc_cond::acc_op::Or:
345 case acc_cond::acc_op::Inf:
346 case acc_cond::acc_op::InfNeg:
347 case acc_cond::acc_op::Fin:
348 case acc_cond::acc_op::FinNeg:
350 if (other[pos].mark != (*
this)[pos].mark)
358 bool operator<(
const acc_code& other)
const 360 unsigned pos = size();
361 auto osize = other.size();
368 auto op = (*this)[pos - 1].sub.op;
369 auto oop = other[pos - 1].sub.op;
374 auto sz = (*this)[pos - 1].sub.size;
375 auto osz = other[pos - 1].sub.size;
382 case acc_cond::acc_op::And:
383 case acc_cond::acc_op::Or:
386 case acc_cond::acc_op::Inf:
387 case acc_cond::acc_op::InfNeg:
388 case acc_cond::acc_op::Fin:
389 case acc_cond::acc_op::FinNeg:
391 auto m = (*this)[pos].mark;
392 auto om = other[pos].mark;
403 bool operator>(
const acc_code& other)
const 405 return other < *
this;
408 bool operator<=(
const acc_code& other)
const 410 return !(other < *
this);
413 bool operator>=(
const acc_code& other)
const 415 return !(*
this < other);
418 bool operator!=(
const acc_code& other)
const 420 return !(*
this == other);
426 return s == 0 || ((*this)[s - 1].sub.op == acc_op::Inf
427 && (*this)[s - 2].mark == 0
U);
434 && (*this)[s - 1].sub.op == acc_op::Fin && (*this)[s - 2].mark == 0
U;
442 res[1].sub.op = acc_op::Fin;
457 res[1].sub.op = acc_op::Fin;
462 static acc_code fin(std::initializer_list<unsigned> vals)
472 res[1].sub.op = acc_op::FinNeg;
477 static acc_code fin_neg(std::initializer_list<unsigned> vals)
479 return fin_neg(
mark_t(vals));
487 res[1].sub.op = acc_op::Inf;
492 static acc_code inf(std::initializer_list<unsigned> vals)
502 res[1].sub.op = acc_op::InfNeg;
507 static acc_code inf_neg(std::initializer_list<unsigned> vals)
509 return inf_neg(
mark_t(vals));
522 static acc_code generalized_buchi(
unsigned n)
525 if (n == 8 *
sizeof(mark_t::value_t))
530 static acc_code generalized_co_buchi(
unsigned n)
533 if (n == 8 *
sizeof(mark_t::value_t))
544 res |= inf({2*n - 1}) & fin({2*n - 2});
556 res &= inf({2*n - 1}) | fin({2*n - 2});
562 template<
class Iterator>
563 static acc_code generalized_rabin(Iterator begin, Iterator end)
567 for (Iterator i = begin; i != end; ++i)
571 for (
unsigned ni = *i; ni > 0; --ni)
574 std::swap(pair, res);
575 res |= std::move(pair);
580 static acc_code parity(
bool max,
bool odd,
unsigned sets);
585 static acc_code random(
unsigned n,
double reuse = 0.0);
589 if (is_t() || r.is_f())
591 *
this = std::move(r);
594 if (is_f() || r.is_t())
596 unsigned s = size() - 1;
597 unsigned rs = r.size() - 1;
600 if (((*
this)[s].sub.op == acc_op::Inf
601 && r[rs].sub.op == acc_op::Inf)
602 || ((*
this)[s].sub.op == acc_op::InfNeg
603 && r[rs].sub.op == acc_op::InfNeg))
605 (*this)[s - 1].mark |= r[rs - 1].mark;
617 auto start = &(*this)[s] - (*this)[s].sub.size;
618 auto pos = &(*this)[s] - 1;
622 if (pos->sub.op == acc_op::Inf)
627 pos -= pos->sub.size + 1;
630 else if ((*
this)[s].sub.op == acc_op::Inf)
632 left_inf = &(*this)[s - 1];
636 auto right_end = &r.back();
640 auto pos = --right_end;
643 if (pos->sub.op == acc_op::Inf)
648 pos -= pos->sub.size + 1;
651 else if (right_end->sub.op == acc_op::Inf)
653 right_inf = right_end - 1;
656 if (left_inf && right_inf)
658 left_inf->mark |= right_inf->mark;
659 insert(this->end(), &r[0], right_inf);
660 insert(this->end(), right_inf + 2, right_end + 1);
665 insert(this->begin(), right_inf, right_inf + 2);
666 insert(this->end(), &r[0], right_inf);
667 insert(this->end(), right_inf + 2, right_end + 1);
671 insert(this->end(), &r[0], right_end + 1);
683 if (is_t() || r.is_f())
688 if (is_f() || r.is_t())
690 unsigned s = size() - 1;
691 unsigned rs = r.size() - 1;
693 if (((*
this)[s].sub.op == acc_op::Inf
694 && r[rs].sub.op == acc_op::Inf)
695 || ((*
this)[s].sub.op == acc_op::InfNeg
696 && r[rs].sub.op == acc_op::InfNeg))
698 (*this)[s - 1].mark |= r[rs - 1].mark;
710 auto start = &(*this)[s] - (*this)[s].sub.size;
711 auto pos = &(*this)[s] - 1;
715 if (pos->sub.op == acc_op::Inf)
720 pos -= pos->sub.size + 1;
723 else if ((*
this)[s].sub.op == acc_op::Inf)
725 left_inf = &(*this)[s - 1];
728 const acc_word* right_inf =
nullptr;
729 auto right_end = &r.back();
733 auto pos = --right_end;
736 if (pos->sub.op == acc_op::Inf)
741 pos -= pos->sub.size + 1;
744 else if (right_end->sub.op == acc_op::Inf)
746 right_inf = right_end - 1;
749 if (left_inf && right_inf)
751 left_inf->mark |= right_inf->mark;
752 insert(this->end(), &r[0], right_inf);
753 insert(this->end(), right_inf + 2, right_end + 1);
758 insert(this->begin(), right_inf, right_inf + 2);
759 insert(this->end(), &r[0], right_inf);
760 insert(this->end(), right_inf + 2, right_end + 1);
764 insert(this->end(), &r[0], right_end + 1);
790 if (is_t() || r.is_f())
792 if (is_f() || r.is_t())
794 *
this = std::move(r);
797 unsigned s = size() - 1;
798 unsigned rs = r.size() - 1;
800 if (((*
this)[s].sub.op == acc_op::Fin
801 && r[rs].sub.op == acc_op::Fin)
802 || ((*
this)[s].sub.op == acc_op::FinNeg
803 && r[rs].sub.op == acc_op::FinNeg))
805 (*this)[s - 1].mark |= r[rs - 1].mark;
812 insert(this->end(), r.begin(), r.end());
839 acc_code& operator<<=(
unsigned sets)
843 unsigned pos = size();
846 switch ((*
this)[pos - 1].sub.op)
848 case acc_cond::acc_op::And:
849 case acc_cond::acc_op::Or:
852 case acc_cond::acc_op::Inf:
853 case acc_cond::acc_op::InfNeg:
854 case acc_cond::acc_op::Fin:
855 case acc_cond::acc_op::FinNeg:
857 (*this)[pos].mark.id <<= sets;
865 acc_code operator<<(
unsigned sets)
const 885 std::vector<std::vector<int>>
886 missing(
mark_t inf,
bool accepting)
const;
888 bool accepting(
mark_t inf)
const;
890 bool inf_satisfiable(
mark_t inf)
const;
911 std::pair<acc_cond::mark_t, acc_cond::mark_t> used_inf_fin_sets()
const;
916 to_html(std::ostream& os,
917 std::function<
void(std::ostream&,
int)>
918 set_printer =
nullptr)
const;
923 to_text(std::ostream& os,
924 std::function<
void(std::ostream&,
int)>
925 set_printer =
nullptr)
const;
961 friend std::ostream& operator<<(std::ostream& os,
const acc_code& code);
965 : num_(0
U), all_(0
U), code_(code)
968 uses_fin_acceptance_ = check_fin_acceptance();
972 : num_(0
U), all_(0
U), code_(code)
974 add_sets(code.used_sets().max_set());
975 uses_fin_acceptance_ = check_fin_acceptance();
979 : num_(o.num_), all_(o.all_), code_(o.code_),
980 uses_fin_acceptance_(o.uses_fin_acceptance_)
989 uses_fin_acceptance_ = o.uses_fin_acceptance_;
997 void set_acceptance(
const acc_code& code)
1000 uses_fin_acceptance_ = check_fin_acceptance();
1003 const acc_code& get_acceptance()
const 1013 bool uses_fin_acceptance()
const 1015 return uses_fin_acceptance_;
1020 return code_.is_t();
1025 return num_ == 0 && is_t();
1030 return code_.is_f();
1033 bool is_none()
const 1035 return num_ == 0 && is_f();
1038 bool is_buchi()
const 1040 unsigned s = code_.size();
1042 s == 2 && code_[1].sub.op == acc_op::Inf && code_[0].mark == all_sets();
1045 bool is_co_buchi()
const 1047 return num_ == 1 && is_generalized_co_buchi();
1050 void set_generalized_buchi()
1052 set_acceptance(inf(all_sets()));
1055 bool is_generalized_buchi()
const 1057 unsigned s = code_.size();
1058 return (s == 0 && num_ == 0) || (s == 2 && code_[1].sub.op == acc_op::Inf
1059 && code_[0].mark == all_sets());
1062 bool is_generalized_co_buchi()
const 1064 unsigned s = code_.size();
1066 code_[1].sub.op == acc_op::Fin && code_[0].mark == all_sets());
1070 int is_rabin()
const;
1072 int is_streett()
const;
1075 bool is_generalized_rabin(std::vector<unsigned>& pairs)
const;
1082 bool is_parity(
bool& max,
bool& odd,
bool equiv =
false)
const;
1083 bool is_parity()
const 1087 return is_parity(max, min);
1093 std::pair<bool, acc_cond::mark_t> unsat_mark()
const;
1096 bool check_fin_acceptance()
const;
1101 return acc_code::inf(mark);
1104 static acc_code inf(std::initializer_list<unsigned> vals)
1106 return inf(
mark_t(vals.begin(), vals.end()));
1111 return acc_code::inf_neg(mark);
1114 static acc_code inf_neg(std::initializer_list<unsigned> vals)
1116 return inf_neg(
mark_t(vals.begin(), vals.end()));
1121 return acc_code::fin(mark);
1124 static acc_code fin(std::initializer_list<unsigned> vals)
1126 return fin(
mark_t(vals.begin(), vals.end()));
1131 return acc_code::fin_neg(mark);
1134 static acc_code fin_neg(std::initializer_list<unsigned> vals)
1136 return fin_neg(
mark_t(vals.begin(), vals.end()));
1139 unsigned add_sets(
unsigned num)
1145 if (num_ > 8 *
sizeof(mark_t::id))
1146 throw std::runtime_error(
"Too many acceptance sets used.");
1156 mark_t mark(
unsigned u)
const 1158 SPOT_ASSERT(u < num_sets());
1172 bool accepting(
mark_t inf)
const 1174 return code_.accepting(inf);
1177 bool inf_satisfiable(
mark_t inf)
const 1179 return code_.inf_satisfiable(inf);
1184 std::ostream& format(std::ostream& os,
mark_t m)
const 1192 std::string format(
mark_t m)
const 1194 std::ostringstream os;
1199 unsigned num_sets()
const 1204 template<
class iterator>
1205 mark_t useless(iterator begin, iterator end)
const 1207 mark_t::value_t u = 0
U;
1208 for (
unsigned x = 0; x < num_; ++x)
1213 unsigned all = all_ ^ (u | (1 << x));
1214 for (iterator y = begin; y != end; ++y)
1230 mark_t::value_t all_sets_()
const 1234 return -1
U >> (8 *
sizeof(mark_t::value_t) - num_);
1238 mark_t::value_t all_;
1240 bool uses_fin_acceptance_ =
false;
1245 std::ostream& operator<<(std::ostream& os,
const acc_cond& acc);
1251 struct hash<
spot::acc_cond::mark_t>
1255 std::hash<decltype(m.id)> h;
Definition: formula.hh:1671
acc_code()
Build an empty acceptance condition.
Definition: acc.hh:955
op
Operator types.
Definition: formula.hh:62