23 #include <unordered_map>
26 #include "ltlenv/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 & (1U << u);
116 void clear(
unsigned u)
179 auto rm = (~yv) & (yv - 1);
181 auto lm = ~(yv ^ (yv - 1));
182 xv = ((xv & lm) >> 1) | (xv & rm);
189 unsigned count()
const
192 return __builtin_popcount(
id);
208 unsigned max_set()
const
221 mark_t& remove_some(
unsigned n)
228 template<
class iterator>
229 void fill(iterator here)
const
243 std::vector<unsigned> sets()
const
245 std::vector<unsigned> res;
246 fill(std::back_inserter(res));
251 friend std::ostream& operator<<(std::ostream& os,
mark_t m);
255 enum class acc_op : unsigned short
256 { Inf, Fin, InfNeg, FinNeg, And, Or };
267 struct SPOT_API
acc_code:
public std::vector<acc_word>
269 bool operator==(
const acc_code& other)
const
271 unsigned pos = size();
272 if (other.size() != pos)
276 auto op = (*this)[pos - 1].op;
277 auto sz = (*this)[pos - 1].size;
278 if (other[pos - 1].op != op ||
279 other[pos - 1].size != sz)
283 case acc_cond::acc_op::And:
284 case acc_cond::acc_op::Or:
287 case acc_cond::acc_op::Inf:
288 case acc_cond::acc_op::InfNeg:
289 case acc_cond::acc_op::Fin:
290 case acc_cond::acc_op::FinNeg:
292 if (other[pos].mark != (*
this)[pos].mark)
300 bool operator<(
const acc_code& other)
const
302 unsigned pos = size();
303 auto osize = other.size();
310 auto op = (*this)[pos - 1].op;
311 auto oop = other[pos - 1].op;
316 auto sz = (*this)[pos - 1].size;
317 auto osz = other[pos - 1].size;
324 case acc_cond::acc_op::And:
325 case acc_cond::acc_op::Or:
328 case acc_cond::acc_op::Inf:
329 case acc_cond::acc_op::InfNeg:
330 case acc_cond::acc_op::Fin:
331 case acc_cond::acc_op::FinNeg:
333 auto m = (*this)[pos].mark;
334 auto om = other[pos].mark;
345 bool operator>(
const acc_code& other)
const
347 return other < *
this;
350 bool operator<=(
const acc_code& other)
const
352 return !(other < *
this);
355 bool operator>=(
const acc_code& other)
const
357 return !(*
this < other);
360 bool operator!=(
const acc_code& other)
const
362 return !(*
this == other);
369 || ((*this)[s - 1].op == acc_op::Inf && (*this)[s - 2].mark == 0U);
372 bool is_false()
const
376 && (*this)[s - 1].op == acc_op::Fin && (*this)[s - 2].mark == 0U;
384 res[1].op = acc_op::Fin;
399 res[1].op = acc_op::Fin;
404 static acc_code fin(std::initializer_list<unsigned> vals)
414 res[1].op = acc_op::FinNeg;
419 static acc_code fin_neg(std::initializer_list<unsigned> vals)
421 return fin_neg(
mark_t(vals));
429 res[1].op = acc_op::Inf;
434 static acc_code inf(std::initializer_list<unsigned> vals)
444 res[1].op = acc_op::InfNeg;
449 static acc_code inf_neg(std::initializer_list<unsigned> vals)
451 return inf_neg(
mark_t(vals));
464 static acc_code generalized_buchi(
unsigned n)
470 static acc_code generalized_co_buchi(
unsigned n)
483 pair.append_and(fin({2*n - 2}));
484 res.append_or(std::move(pair));
497 pair.append_or(fin({2*n - 2}));
498 res.append_and(std::move(pair));
504 template<
class Iterator>
505 static acc_code generalized_rabin(Iterator begin, Iterator end)
509 for (Iterator i = begin; i != end; ++i)
513 for (
unsigned ni = *i; ni > 0; --ni)
515 pair.append_and(inf(m));
516 std::swap(pair, res);
517 res.append_or(std::move(pair));
522 static acc_code parity(
bool max,
bool odd,
unsigned sets);
527 static acc_code random(
unsigned n,
double reuse = 0.0);
531 if (is_true() || r.is_false())
533 *
this = std::move(r);
536 if (is_false() || r.is_true())
538 unsigned s = size() - 1;
539 unsigned rs = r.size() - 1;
542 if (((*
this)[s].op == acc_op::Inf && r[rs].op == acc_op::Inf)
543 || ((*
this)[s].op == acc_op::InfNeg && r[rs].op == acc_op::InfNeg))
545 (*this)[s - 1].mark |= r[rs - 1].mark;
555 if ((*
this)[s].op == acc_op::And)
557 auto start = &(*this)[s] - (*this)[s].size;
558 auto pos = &(*this)[s] - 1;
562 if (pos->op == acc_op::Inf)
567 pos -= pos->size + 1;
570 else if ((*
this)[s].op == acc_op::Inf)
572 left_inf = &(*this)[s - 1];
576 auto right_end = &r.back();
577 if (right_end->op == acc_op::And)
580 auto pos = --right_end;
583 if (pos->op == acc_op::Inf)
588 pos -= pos->size + 1;
591 else if (right_end->op == acc_op::Inf)
593 right_inf = right_end - 1;
596 if (left_inf && right_inf)
598 left_inf->mark |= right_inf->mark;
599 insert(this->end(), &r[0], right_inf);
600 insert(this->end(), right_inf + 2, right_end + 1);
605 insert(this->begin(), right_inf, right_inf + 2);
606 insert(this->end(), &r[0], right_inf);
607 insert(this->end(), right_inf + 2, right_end + 1);
611 insert(this->end(), &r[0], right_end + 1);
622 if (is_true() || r.is_false())
627 if (is_false() || r.is_true())
629 unsigned s = size() - 1;
630 unsigned rs = r.size() - 1;
632 if (((*
this)[s].op == acc_op::Inf && r[rs].op == acc_op::Inf)
633 || ((*
this)[s].op == acc_op::InfNeg && r[rs].op == acc_op::InfNeg))
635 (*this)[s - 1].mark |= r[rs - 1].mark;
645 if ((*
this)[s].op == acc_op::And)
647 auto start = &(*this)[s] - (*this)[s].size;
648 auto pos = &(*this)[s] - 1;
652 if (pos->op == acc_op::Inf)
657 pos -= pos->size + 1;
660 else if ((*
this)[s].op == acc_op::Inf)
662 left_inf = &(*this)[s - 1];
665 const acc_word* right_inf =
nullptr;
666 auto right_end = &r.back();
667 if (right_end->op == acc_op::And)
670 auto pos = --right_end;
673 if (pos->op == acc_op::Inf)
678 pos -= pos->size + 1;
681 else if (right_end->op == acc_op::Inf)
683 right_inf = right_end - 1;
686 if (left_inf && right_inf)
688 left_inf->mark |= right_inf->mark;
689 insert(this->end(), &r[0], right_inf);
690 insert(this->end(), right_inf + 2, right_end + 1);
695 insert(this->begin(), right_inf, right_inf + 2);
696 insert(this->end(), &r[0], right_inf);
697 insert(this->end(), right_inf + 2, right_end + 1);
701 insert(this->end(), &r[0], right_end + 1);
712 if (is_true() || r.is_false())
714 if (is_false() || r.is_true())
716 *
this = std::move(r);
719 unsigned s = size() - 1;
720 unsigned rs = r.size() - 1;
722 if (((*
this)[s].op == acc_op::Fin && r[rs].op == acc_op::Fin)
723 || ((*
this)[s].op == acc_op::FinNeg && r[rs].op == acc_op::FinNeg))
725 (*this)[s - 1].mark |= r[rs - 1].mark;
728 if ((*
this)[s].op == acc_op::Or)
730 if (r.back().op == acc_op::Or)
732 insert(this->end(), r.begin(), r.end());
739 void shift_left(
unsigned sets)
743 unsigned pos = size();
746 switch ((*
this)[pos - 1].op)
748 case acc_cond::acc_op::And:
749 case acc_cond::acc_op::Or:
752 case acc_cond::acc_op::Inf:
753 case acc_cond::acc_op::InfNeg:
754 case acc_cond::acc_op::Fin:
755 case acc_cond::acc_op::FinNeg:
757 (*this)[pos].mark.id <<= sets;
777 std::vector<std::vector<int>>
778 missing(
mark_t inf,
bool accepting)
const;
780 bool accepting(
mark_t inf)
const;
782 bool inf_satisfiable(
mark_t inf)
const;
804 std::pair<bool, acc_cond::mark_t> unsat_mark()
const;
807 std::pair<acc_cond::mark_t, acc_cond::mark_t> used_inf_fin_sets()
const;
812 to_html(std::ostream& os,
813 std::function<
void(std::ostream&,
int)>
814 set_printer =
nullptr)
const;
819 to_text(std::ostream& os,
820 std::function<
void(std::ostream&,
int)>
821 set_printer =
nullptr)
const;
825 friend std::ostream& operator<<(std::ostream& os,
const acc_code& code);
835 : num_(o.num_), all_(o.all_), code_(o.code_)
843 void set_acceptance(
const acc_code& code)
846 uses_fin_acceptance_ = check_fin_acceptance();
849 const acc_code& get_acceptance()
const
854 acc_code& get_acceptance()
859 bool uses_fin_acceptance()
const
861 return uses_fin_acceptance_;
866 return code_.is_true();
869 bool is_false()
const
871 return code_.is_false();
874 bool is_buchi()
const
876 unsigned s = code_.size();
878 s == 2 && code_[1].op == acc_op::Inf && code_[0].mark == all_sets();
881 bool is_co_buchi()
const
883 return num_ == 1 && is_generalized_co_buchi();
886 void set_generalized_buchi()
888 set_acceptance(inf(all_sets()));
891 bool is_generalized_buchi()
const
893 unsigned s = code_.size();
894 return (s == 0 && num_ == 0) ||
895 (s == 2 && code_[1].op == acc_op::Inf && code_[0].mark == all_sets());
898 bool is_generalized_co_buchi()
const
900 unsigned s = code_.size();
902 code_[1].op == acc_op::Fin && code_[0].mark == all_sets());
906 int is_rabin()
const;
908 int is_streett()
const;
911 bool is_generalized_rabin(std::vector<unsigned>& pairs)
const;
918 bool is_parity(
bool& max,
bool& odd,
bool equiv =
false)
const;
920 static acc_code generalized_buchi(
unsigned n)
922 mark_t m((1U << n) - 1);
923 if (n == 8 *
sizeof(mark_t::value_t))
925 return acc_code::inf(m);
929 bool check_fin_acceptance()
const;
932 acc_code inf(mark_t mark)
const
934 return acc_code::inf(mark);
937 acc_code inf(std::initializer_list<unsigned> vals)
const
939 return inf(marks(vals.begin(), vals.end()));
942 acc_code inf_neg(mark_t mark)
const
944 return acc_code::inf_neg(mark);
947 acc_code inf_neg(std::initializer_list<unsigned> vals)
const
949 return inf_neg(marks(vals.begin(), vals.end()));
952 acc_code fin(mark_t mark)
const
954 return acc_code::fin(mark);
957 acc_code fin(std::initializer_list<unsigned> vals)
const
959 return fin(marks(vals.begin(), vals.end()));
962 acc_code fin_neg(mark_t mark)
const
964 return acc_code::fin_neg(mark);
967 acc_code fin_neg(std::initializer_list<unsigned> vals)
const
969 return fin_neg(marks(vals.begin(), vals.end()));
972 unsigned add_sets(
unsigned num)
978 if (num_ > 8 *
sizeof(mark_t::id))
979 throw std::runtime_error(
"Too many acceptance sets used.");
989 mark_t mark(
unsigned u)
const
994 template<
class iterator>
995 mark_t marks(
const iterator& begin,
const iterator& end)
const
997 return mark_t(begin, end);
1000 mark_t marks(std::initializer_list<unsigned> vals)
const
1002 return marks(vals.begin(), vals.end());
1006 std::vector<unsigned> sets(mark_t m)
const
1012 bool has(mark_t m,
unsigned u)
const
1017 mark_t cup(mark_t l, mark_t r)
const
1022 mark_t cap(mark_t l, mark_t r)
const
1027 mark_t set_minus(mark_t l, mark_t r)
const
1032 mark_t join(
const acc_cond& la, mark_t lm,
1033 const acc_cond& ra, mark_t rm)
const
1035 assert(la.num_sets() + ra.num_sets() == num_sets());
1037 return lm.id | (rm.id << la.num_sets());
1040 mark_t comp(mark_t l)
const
1045 mark_t all_sets()
const
1050 bool accepting(mark_t inf)
const
1052 return code_.accepting(inf);
1055 bool inf_satisfiable(mark_t inf)
const
1057 return code_.inf_satisfiable(inf);
1060 mark_t accepting_sets(mark_t inf)
const;
1062 std::ostream& format(std::ostream& os, mark_t m)
const
1070 std::string format(mark_t m)
const
1072 std::ostringstream os;
1077 unsigned num_sets()
const
1082 template<
class iterator>
1083 mark_t useless(iterator begin, iterator end)
const
1085 mark_t::value_t u = 0U;
1086 for (
unsigned x = 0; x < num_; ++x)
1091 unsigned all = all_ ^ (u | (1 << x));
1092 for (iterator y = begin; y != end; ++y)
1108 mark_t::value_t mark_(
unsigned u)
const
1110 assert(u < num_sets());
1114 mark_t::value_t all_sets_()
const
1118 return -1U >> (8 *
sizeof(mark_t::value_t) - num_);
1122 mark_t::value_t all_;
1124 bool uses_fin_acceptance_ =
false;
1145 SPOT_API acc_cond::acc_code parse_acc_code(
const char* input);
1151 struct hash<
spot::acc_cond::mark_t>
1155 std::hash<decltype(m.id)> h;
Definition: formula.hh:515