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)
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
248 mark_t& remove_some(
unsigned n)
255 template<
class iterator>
256 void fill(iterator here)
const
270 std::vector<unsigned> sets()
const
272 std::vector<unsigned> res;
273 fill(std::back_inserter(res));
278 friend std::ostream& operator<<(std::ostream& os,
mark_t m);
282 enum class acc_op : unsigned short
283 { Inf, Fin, InfNeg, FinNeg, And, Or };
294 struct SPOT_API
acc_code:
public std::vector<acc_word>
296 bool operator==(
const acc_code& other)
const
298 unsigned pos = size();
299 if (other.size() != pos)
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)
310 case acc_cond::acc_op::And:
311 case acc_cond::acc_op::Or:
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:
319 if (other[pos].mark != (*
this)[pos].mark)
327 bool operator<(
const acc_code& other)
const
329 unsigned pos = size();
330 auto osize = other.size();
337 auto op = (*this)[pos - 1].op;
338 auto oop = other[pos - 1].op;
343 auto sz = (*this)[pos - 1].size;
344 auto osz = other[pos - 1].size;
351 case acc_cond::acc_op::And:
352 case acc_cond::acc_op::Or:
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:
360 auto m = (*this)[pos].mark;
361 auto om = other[pos].mark;
372 bool operator>(
const acc_code& other)
const
374 return other < *
this;
377 bool operator<=(
const acc_code& other)
const
379 return !(other < *
this);
382 bool operator>=(
const acc_code& other)
const
384 return !(*
this < other);
387 bool operator!=(
const acc_code& other)
const
389 return !(*
this == other);
396 || ((*this)[s - 1].op == acc_op::Inf && (*this)[s - 2].mark == 0U);
399 bool is_false()
const
403 && (*this)[s - 1].op == acc_op::Fin && (*this)[s - 2].mark == 0U;
411 res[1].op = acc_op::Fin;
426 res[1].op = acc_op::Fin;
431 static acc_code fin(std::initializer_list<unsigned> vals)
441 res[1].op = acc_op::FinNeg;
446 static acc_code fin_neg(std::initializer_list<unsigned> vals)
448 return fin_neg(
mark_t(vals));
456 res[1].op = acc_op::Inf;
461 static acc_code inf(std::initializer_list<unsigned> vals)
471 res[1].op = acc_op::InfNeg;
476 static acc_code inf_neg(std::initializer_list<unsigned> vals)
478 return inf_neg(
mark_t(vals));
491 static acc_code generalized_buchi(
unsigned n)
497 static acc_code generalized_co_buchi(
unsigned n)
510 pair.append_and(fin({2*n - 2}));
511 res.append_or(std::move(pair));
524 pair.append_or(fin({2*n - 2}));
525 res.append_and(std::move(pair));
531 template<
class Iterator>
532 static acc_code generalized_rabin(Iterator begin, Iterator end)
536 for (Iterator i = begin; i != end; ++i)
540 for (
unsigned ni = *i; ni > 0; --ni)
542 pair.append_and(inf(m));
543 std::swap(pair, res);
544 res.append_or(std::move(pair));
549 static acc_code parity(
bool max,
bool odd,
unsigned sets);
554 static acc_code random(
unsigned n,
double reuse = 0.0);
558 if (is_true() || r.is_false())
560 *
this = std::move(r);
563 if (is_false() || r.is_true())
565 unsigned s = size() - 1;
566 unsigned rs = r.size() - 1;
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))
572 (*this)[s - 1].mark |= r[rs - 1].mark;
582 if ((*
this)[s].op == acc_op::And)
584 auto start = &(*this)[s] - (*this)[s].size;
585 auto pos = &(*this)[s] - 1;
589 if (pos->op == acc_op::Inf)
594 pos -= pos->size + 1;
597 else if ((*
this)[s].op == acc_op::Inf)
599 left_inf = &(*this)[s - 1];
603 auto right_end = &r.back();
604 if (right_end->op == acc_op::And)
607 auto pos = --right_end;
610 if (pos->op == acc_op::Inf)
615 pos -= pos->size + 1;
618 else if (right_end->op == acc_op::Inf)
620 right_inf = right_end - 1;
623 if (left_inf && right_inf)
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);
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);
638 insert(this->end(), &r[0], right_end + 1);
649 if (is_true() || r.is_false())
654 if (is_false() || r.is_true())
656 unsigned s = size() - 1;
657 unsigned rs = r.size() - 1;
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))
662 (*this)[s - 1].mark |= r[rs - 1].mark;
672 if ((*
this)[s].op == acc_op::And)
674 auto start = &(*this)[s] - (*this)[s].size;
675 auto pos = &(*this)[s] - 1;
679 if (pos->op == acc_op::Inf)
684 pos -= pos->size + 1;
687 else if ((*
this)[s].op == acc_op::Inf)
689 left_inf = &(*this)[s - 1];
692 const acc_word* right_inf =
nullptr;
693 auto right_end = &r.back();
694 if (right_end->op == acc_op::And)
697 auto pos = --right_end;
700 if (pos->op == acc_op::Inf)
705 pos -= pos->size + 1;
708 else if (right_end->op == acc_op::Inf)
710 right_inf = right_end - 1;
713 if (left_inf && right_inf)
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);
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);
728 insert(this->end(), &r[0], right_end + 1);
739 if (is_true() || r.is_false())
741 if (is_false() || r.is_true())
743 *
this = std::move(r);
746 unsigned s = size() - 1;
747 unsigned rs = r.size() - 1;
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))
752 (*this)[s - 1].mark |= r[rs - 1].mark;
755 if ((*
this)[s].op == acc_op::Or)
757 if (r.back().op == acc_op::Or)
759 insert(this->end(), r.begin(), r.end());
766 void shift_left(
unsigned sets)
770 unsigned pos = size();
773 switch ((*
this)[pos - 1].op)
775 case acc_cond::acc_op::And:
776 case acc_cond::acc_op::Or:
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:
784 (*this)[pos].mark.id <<= sets;
804 std::vector<std::vector<int>>
805 missing(
mark_t inf,
bool accepting)
const;
807 bool accepting(
mark_t inf)
const;
809 bool inf_satisfiable(
mark_t inf)
const;
831 std::pair<bool, acc_cond::mark_t> unsat_mark()
const;
834 std::pair<acc_cond::mark_t, acc_cond::mark_t> used_inf_fin_sets()
const;
839 to_html(std::ostream& os,
840 std::function<
void(std::ostream&,
int)>
841 set_printer =
nullptr)
const;
846 to_text(std::ostream& os,
847 std::function<
void(std::ostream&,
int)>
848 set_printer =
nullptr)
const;
852 friend std::ostream& operator<<(std::ostream& os,
const acc_code& code);
862 : num_(o.num_), all_(o.all_), code_(o.code_)
870 void set_acceptance(
const acc_code& code)
873 uses_fin_acceptance_ = check_fin_acceptance();
876 const acc_code& get_acceptance()
const
881 acc_code& get_acceptance()
886 bool uses_fin_acceptance()
const
888 return uses_fin_acceptance_;
893 return code_.is_true();
896 bool is_false()
const
898 return code_.is_false();
901 bool is_buchi()
const
903 unsigned s = code_.size();
905 s == 2 && code_[1].op == acc_op::Inf && code_[0].mark == all_sets();
908 bool is_co_buchi()
const
910 return num_ == 1 && is_generalized_co_buchi();
913 void set_generalized_buchi()
915 set_acceptance(inf(all_sets()));
918 bool is_generalized_buchi()
const
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());
925 bool is_generalized_co_buchi()
const
927 unsigned s = code_.size();
929 code_[1].op == acc_op::Fin && code_[0].mark == all_sets());
933 int is_rabin()
const;
935 int is_streett()
const;
938 bool is_generalized_rabin(std::vector<unsigned>& pairs)
const;
945 bool is_parity(
bool& max,
bool& odd,
bool equiv =
false)
const;
947 static acc_code generalized_buchi(
unsigned n)
949 mark_t m((1U << n) - 1);
950 if (n == 8 *
sizeof(mark_t::value_t))
952 return acc_code::inf(m);
956 bool check_fin_acceptance()
const;
959 acc_code inf(mark_t mark)
const
961 return acc_code::inf(mark);
964 acc_code inf(std::initializer_list<unsigned> vals)
const
966 return inf(marks(vals.begin(), vals.end()));
969 acc_code inf_neg(mark_t mark)
const
971 return acc_code::inf_neg(mark);
974 acc_code inf_neg(std::initializer_list<unsigned> vals)
const
976 return inf_neg(marks(vals.begin(), vals.end()));
979 acc_code fin(mark_t mark)
const
981 return acc_code::fin(mark);
984 acc_code fin(std::initializer_list<unsigned> vals)
const
986 return fin(marks(vals.begin(), vals.end()));
989 acc_code fin_neg(mark_t mark)
const
991 return acc_code::fin_neg(mark);
994 acc_code fin_neg(std::initializer_list<unsigned> vals)
const
996 return fin_neg(marks(vals.begin(), vals.end()));
999 unsigned add_sets(
unsigned num)
1005 if (num_ > 8 *
sizeof(mark_t::id))
1006 throw std::runtime_error(
"Too many acceptance sets used.");
1016 mark_t mark(
unsigned u)
const
1021 template<
class iterator>
1022 mark_t marks(
const iterator& begin,
const iterator& end)
const
1024 return mark_t(begin, end);
1027 mark_t marks(std::initializer_list<unsigned> vals)
const
1029 return marks(vals.begin(), vals.end());
1033 std::vector<unsigned> sets(mark_t m)
const
1039 bool has(mark_t m,
unsigned u)
const
1044 mark_t cup(mark_t l, mark_t r)
const
1049 mark_t cap(mark_t l, mark_t r)
const
1054 mark_t set_minus(mark_t l, mark_t r)
const
1059 mark_t join(
const acc_cond& la, mark_t lm,
1060 const acc_cond& ra, mark_t rm)
const
1062 assert(la.num_sets() + ra.num_sets() == num_sets());
1064 return lm.id | (rm.id << la.num_sets());
1067 mark_t comp(mark_t l)
const
1072 mark_t all_sets()
const
1077 bool accepting(mark_t inf)
const
1079 return code_.accepting(inf);
1082 bool inf_satisfiable(mark_t inf)
const
1084 return code_.inf_satisfiable(inf);
1087 mark_t accepting_sets(mark_t inf)
const;
1089 std::ostream& format(std::ostream& os, mark_t m)
const
1097 std::string format(mark_t m)
const
1099 std::ostringstream os;
1104 unsigned num_sets()
const
1109 template<
class iterator>
1110 mark_t useless(iterator begin, iterator end)
const
1112 mark_t::value_t u = 0U;
1113 for (
unsigned x = 0; x < num_; ++x)
1118 unsigned all = all_ ^ (u | (1 << x));
1119 for (iterator y = begin; y != end; ++y)
1135 mark_t::value_t mark_(
unsigned u)
const
1137 assert(u < num_sets());
1141 mark_t::value_t all_sets_()
const
1145 return -1U >> (8 *
sizeof(mark_t::value_t) - num_);
1149 mark_t::value_t all_;
1151 bool uses_fin_acceptance_ =
false;
1172 SPOT_API acc_cond::acc_code parse_acc_code(
const char* input);
1178 struct hash<
spot::acc_cond::mark_t>
1182 std::hash<decltype(m.id)> h;
Definition: formula.hh:515