48 #include <spot/misc/common.hh>
51 #include <initializer_list>
68 # define SPOT_HAS_STRONG_X 1
72 # define SPOT_WANT_STRONG_X 1
75 # define SPOT_HAS_QUANTIFIERS 1
84 enum class op: uint8_t
183 if (SPOT_UNLIKELY(!refs_))
195 if (SPOT_LIKELY(refs_))
197 else if (SPOT_LIKELY(!saturated_))
209 static const fnode*
ap(
const std::string& name);
224 unsigned min,
unsigned max = unbounded());
228 unsigned max,
const fnode* f);
236 std::vector<const fnode*> aps,
257 return op_ == o1 || op_ == o2;
262 return op_ == o1 || op_ == o2 || op_ == o3;
267 return op_ == o1 || op_ == o2 || op_ == o3 || op_ == o4;
270 bool is(std::initializer_list<op> l)
const
272 const fnode* n =
this;
288 if (SPOT_UNLIKELY(size_ != 1))
289 report_get_child_of_expecting_single_child_node();
310 report_min_invalid_arg();
318 report_max_invalid_arg();
349 return children + size();
355 if (SPOT_UNLIKELY(i >= size()))
356 report_non_existing_child();
357 const fnode* c = children[i];
358 SPOT_ASSUME(c !=
nullptr);
409 return range_.min == 0 && range_.max == unbounded();
434 if (SPOT_UNLIKELY(op_ !=
op::ap))
435 report_apid_on_nonap();
440 std::ostream&
dump(std::ostream& os)
const;
450 while (pos < s && children[pos]->is_boolean())
483 return is_.sugar_free_boolean;
489 return is_.in_nenoform;
495 return is_.syntactic_si;
501 return is_.sugar_free_ltl;
507 return is_.ltl_formula;
513 return is_.psl_formula;
519 return is_.sere_formula;
537 return is_.universal;
543 return is_.syntactic_safety;
549 return is_.syntactic_guarantee;
555 return is_.syntactic_obligation;
561 return is_.syntactic_recurrence;
567 return is_.syntactic_persistence;
573 return !is_.not_marked;
579 return is_.accepting_eword;
585 return is_.lbt_atomic_props;
591 return is_.spin_atomic_props;
621 return is_.quantified;
625 static size_t bump_next_id();
626 void setup_props(
op o);
627 void destroy_aux()
const;
630 [[noreturn]]
static void report_non_existing_child();
631 [[noreturn]]
static void report_too_many_children();
632 [[noreturn]]
static void
633 report_get_child_of_expecting_single_child_node();
634 [[noreturn]]
static void report_min_invalid_arg();
635 [[noreturn]]
static void report_max_invalid_arg();
636 [[noreturn]]
static void report_apid_on_nonap();
640 static const fnode* multop_sorted(
op o, std::vector<const fnode*>&& l);
651 fnode(
op o, iter begin, iter end,
bool saturated =
false)
652 : op_(o), saturated_(saturated)
654 size_t s = std::distance(begin, end);
655 if (SPOT_UNLIKELY(s > (
size_t) UINT16_MAX))
656 report_too_many_children();
659 for (
auto i = begin; i != end; ++i)
664 fnode(
op o, std::initializer_list<const fnode*> l,
665 bool saturated =
false)
666 : fnode(o, l.begin(), l.end(), saturated)
670 fnode(
op o,
const fnode* f,
unsigned min,
unsigned max,
671 bool saturated =
false)
672 : op_(o), saturated_(saturated), size_(1)
680 fnode(
op o, uint16_t apid,
bool saturated =
false)
681 : op_(o), saturated_(saturated), size_(0)
687 static const fnode* ff_;
688 static const fnode* tt_;
689 static const fnode* ew_;
690 static const fnode* one_star_;
691 static const fnode* one_plus_;
694 mutable uint8_t saturated_;
695 mutable uint16_t refs_ = 0;
708 static size_t next_id_;
726 bool sugar_free_boolean:1;
729 bool sugar_free_ltl:1;
736 bool syntactic_safety:1;
737 bool syntactic_guarantee:1;
738 bool syntactic_obligation:1;
739 bool syntactic_recurrence:1;
740 bool syntactic_persistence:1;
742 bool accepting_eword:1;
743 bool lbt_atomic_props:1;
744 bool spin_atomic_props:1;
758 const fnode* children[1];
793 auto get_literal = [](
const fnode* f) ->
const fnode*
802 const fnode* litl = get_literal(left);
803 const fnode* litr = get_literal(right);
816 size_t l = left->
id();
817 size_t r = right->
id();
830 std::ostringstream old;
832 std::ostringstream ord;
834 return old.str() < ord.str();
924 std::swap(f.ptr_, ptr_);
931 if (SPOT_UNLIKELY(!other.ptr_))
933 if (SPOT_UNLIKELY(!ptr_))
935 if (
id() < other.id())
937 if (
id() > other.id())
943 return ptr_ < other.ptr_;
949 return *
this == other || *
this < other;
955 return !(*
this <= other);
961 return !(*
this < other);
968 return other.ptr_ == ptr_;
974 return ptr_ ==
nullptr;
980 return other.ptr_ != ptr_;
986 return ptr_ !=
nullptr;
990 explicit operator bool() const noexcept
992 return ptr_ !=
nullptr;
1015 static
bool is_valid_apid(
unsigned id) noexcept;
1018 static const std::
string& apname_from_apid(
unsigned id);
1032 void throw_if_quantified(const
char* message)
1034 if (SPOT_UNLIKELY(is_quantified()))
1035 report_message(message);
1062 report_ap_invalid_arg();
1085 #define SPOT_DEF_UNOP(Name) \
1086 static formula Name(const formula& f) \
1088 return unop(op::Name, f); \
1091 #define SPOT_DEF_UNOP(Name) \
1092 static formula Name(const formula& f) \
1094 return unop(op::Name, f); \
1096 static formula Name(formula&& f) \
1098 return unop(op::Name, std::move(f)); \
1117 return nested_unop_range(
op::X,
op::Or , level, level, f);
1147 return nested_unop_range(
op::X,
op::Or, min_level, max_level, f);
1158 return nested_unop_range(
op::X,
op::And, min_level, max_level, f);
1185 #undef SPOT_DEF_UNOP
1217 #define SPOT_DEF_BINOP(Name) \
1218 static formula Name(const formula& f, const formula& g) \
1220 return binop(op::Name, f, g); \
1223 #define SPOT_DEF_BINOP(Name) \
1224 static formula Name(const formula& f, const formula& g) \
1226 return binop(op::Name, f, g); \
1228 static formula Name(const formula& f, formula&& g) \
1230 return binop(op::Name, f, std::move(g)); \
1232 static formula Name(formula&& f, const formula& g) \
1234 return binop(op::Name, std::move(f), g); \
1236 static formula Name(formula&& f, formula&& g) \
1238 return binop(op::Name, std::move(f), std::move(g)); \
1244 SPOT_DEF_BINOP(Xor);
1291 #undef SPOT_DEF_BINOP
1318 std::vector<const fnode*> tmp;
1319 tmp.reserve(l.size());
1322 tmp.emplace_back(f.ptr_->
clone());
1329 std::vector<const fnode*> tmp;
1330 tmp.reserve(l.size());
1333 tmp.emplace_back(f.to_node_());
1363 #define SPOT_DEF_MULTOP(Name) \
1364 static formula Name(const std::vector<formula>& l) \
1366 return multop(op::Name, l); \
1369 static formula Name(const formula& left, const formula& right) \
1371 return multop(op::Name, left, right); \
1374 #define SPOT_DEF_MULTOP(Name) \
1375 static formula Name(const std::vector<formula>& l) \
1377 return multop(op::Name, l); \
1380 static formula Name(std::vector<formula>&& l) \
1382 return multop(op::Name, std::move(l)); \
1385 static formula Name(const formula& left, const formula& right) \
1387 return multop(op::Name, left, right); \
1391 #define SPOT_DEF_MULTOP2(Name) \
1392 static formula Name(const std::vector<formula>& l) \
1394 return multop(op::Name, l); \
1397 static formula Name(const formula& left, const formula& right) \
1399 return formula(fnode::multop_build_and_or<op::Name> \
1400 (left->ptr_->clone(), right->ptr_->clone()); \
1403 #define SPOT_DEF_MULTOP2(Name) \
1404 static formula Name(const std::vector<formula>& l) \
1406 return multop(op::Name, l); \
1409 static formula Name(std::vector<formula>&& l) \
1411 return multop(op::Name, std::move(l)); \
1414 static formula Name(const formula& left, const formula& right) \
1416 return formula(fnode::multop_build_and_or<op::Name> \
1417 (left.ptr_->clone(), right.ptr_->clone())); \
1419 static formula Name(const formula& left, formula&& right) \
1421 return formula(fnode::multop_build_and_or<op::Name> \
1422 (left.ptr_->clone(), right.to_node_())); \
1424 static formula Name(formula&& left, const formula& right) \
1426 return formula(fnode::multop_build_and_or<op::Name> \
1427 (left.to_node_(), right.ptr_->clone())); \
1429 static formula Name(formula&& left, formula&& right) \
1431 return formula(fnode::multop_build_and_or<op::Name> \
1432 (left.to_node_(), right.to_node_())); \
1438 SPOT_DEF_MULTOP2(Or);
1470 #undef SPOT_DEF_MULTOP
1478 unsigned max = unbounded())
1486 unsigned max = unbounded())
1495 #define SPOT_DEF_BUNOP(Name) \
1496 static formula Name(const formula& f, \
1497 unsigned min = 0U, \
1498 unsigned max = unbounded()) \
1500 return bunop(op::Name, f, min, max); \
1503 #define SPOT_DEF_BUNOP(Name) \
1504 static formula Name(const formula& f, \
1505 unsigned min = 0U, \
1506 unsigned max = unbounded()) \
1508 return bunop(op::Name, f, min, max); \
1510 static formula Name(formula&& f, \
1511 unsigned min = 0U, \
1512 unsigned max = unbounded()) \
1514 return bunop(op::Name, std::move(f), min, max); \
1530 #undef SPOT_DEF_BUNOP
1555 const std::vector<formula>& aps,
1558 std::vector<const fnode*> tmp;
1559 tmp.reserve(aps.size() + 1);
1562 tmp.emplace_back(a.to_node_());
1569 std::vector<formula>&& aps,
1572 std::vector<const fnode*> tmp;
1573 tmp.reserve(aps.size() + 1);
1576 tmp.emplace_back(a.to_node_());
1584 #define SPOT_DEF_QUANTIFY(Name) \
1585 static formula Name(const std::vector<formula>& aps, const formula& f) \
1587 return quantify(op::Name, aps, f); \
1590 static formula Name(const formula& ap, const formula& f) \
1592 return quantify(op::Name, ap, f); \
1605 #undef SPOT_DEF_QUANTIFY
1661 unsigned min,
unsigned max);
1663 unsigned min,
unsigned max);
1687 return ptr_->kind();
1693 return ptr_->kindstr();
1706 return ptr_->is(o1, o2);
1712 return ptr_->is(o1, o2, o3);
1719 return ptr_->is(o1, o2, o3, o4);
1723 bool is(std::initializer_list<op> l)
const
1775 return ptr_->size();
1784 return ptr_->is_leaf();
1804 const fnode*
const* ptr_;
1820 return ptr_ == o.ptr_;
1826 return ptr_ != o.ptr_;
1832 return formula((*ptr_)->clone());
1854 return ptr_->begin();
1866 return formula(ptr_->nth(i)->clone());
1879 return ptr_->is_ff();
1891 return ptr_->is_tt();
1903 return ptr_->is_eword();
1909 return ptr_->is_constant();
1918 return ptr_->is_Kleene_star();
1943 (is(
op::Not) && is_boolean() && is_in_nenoform()));
1951 return ptr_->ap_name();
1964 return ptr_->apid();
1971 std::ostream&
dump(std::ostream& os)
const
1973 return ptr_->dump(os);
1983 return formula(ptr_->all_but(i));
1997 return ptr_->boolean_count();
2015 return formula(ptr_->boolean_operands(width));
2019 #define SPOT_DEF_PROP(Name) \
2022 return ptr_->Name(); \
2126 #undef SPOT_DEF_PROP
2131 template<
typename Trans,
typename... Args>
2134 switch (
op o = kind())
2143 #if SPOT_HAS_STRONG_X
2154 formula new_arg = trans(arg, std::forward<Args>(args)...);
2158 return unop(o, new_arg);
2173 formula new_left = trans(left, std::forward<Args>(args)...);
2174 formula new_right = trans(right, std::forward<Args>(args)...);
2175 if (left == new_left && right == new_right)
2178 return binop(o, new_left, new_right);
2188 std::vector<formula> tmp;
2189 bool changed =
false;
2190 tmp.reserve(size());
2193 formula g = trans(f, std::forward<Args>(args)...);
2194 tmp.emplace_back(g);
2200 return multop(o, std::move(tmp));
2206 formula new_arg = trans(arg, std::forward<Args>(args)...);
2210 return bunop(o, new_arg, min(), max());
2215 std::vector<formula> tmp;
2216 unsigned sz = size();
2217 tmp.reserve(sz - 1);
2218 bool changed =
false;
2219 for (
unsigned i = 0; i < sz - 1; ++i)
2222 formula g = trans(c, std::forward<Args>(args)...);
2227 formula g = trans(c, std::forward<Args>(args)...);
2228 if (c == g && !changed)
2230 return quantify(o, std::move(tmp), g);
2244 template<
typename Func,
typename... Args>
2247 if (func(*
this, std::forward<Args>(args)...))
2250 f.
traverse(func, std::forward<Args>(args)...);
2257 [[noreturn]]
static void report_ap_invalid_arg();
2264 bool abbreviated =
false);
Actual storage for formula nodes.
Definition: formula.hh:173
bool is_pi2() const
Definition: formula.hh:601
const fnode *const * begin() const
Definition: formula.hh:341
const fnode *const * end() const
Definition: formula.hh:347
std::string kindstr() const
std::ostream & dump(std::ostream &os) const
bool is_boolean() const
Definition: formula.hh:475
size_t id() const
Definition: formula.hh:335
bool is_ff() const
Definition: formula.hh:369
static constexpr uint16_t unbounded()
Definition: formula.hh:203
bool is_sugar_free_boolean() const
Definition: formula.hh:481
bool is_Kleene_star() const
Definition: formula.hh:405
unsigned min() const
Definition: formula.hh:307
bool is_syntactic_safety() const
Definition: formula.hh:541
bool is_syntactic_stutter_invariant() const
Definition: formula.hh:493
bool is_delta2() const
Definition: formula.hh:613
unsigned size() const
Definition: formula.hh:323
static const fnode * eword()
Definition: formula.hh:387
const fnode * get_child_of(op o) const
Definition: formula.hh:284
static const fnode * multop_build_and_or(const fnode *left, const fnode *right)
fast path for binary and/or
unsigned max() const
Definition: formula.hh:315
static const fnode * ff()
Definition: formula.hh:363
const fnode * boolean_operands(unsigned *width=nullptr) const
bool accepts_eword() const
Definition: formula.hh:577
bool is_eventual() const
Definition: formula.hh:529
const std::string & ap_name() const
bool is(op o1, op o2, op o3, op o4) const
Definition: formula.hh:265
static bool instances_check()
safety check for the reference counters
bool is_leaf() const
Definition: formula.hh:329
bool has_spin_atomic_props() const
Definition: formula.hh:589
bool is_eword() const
Definition: formula.hh:393
static const fnode * tt()
Definition: formula.hh:375
bool is(op o1, op o2, op o3) const
Definition: formula.hh:260
op kind() const
Definition: formula.hh:240
bool has_lbt_atomic_props() const
Definition: formula.hh:583
unsigned apid() const
Definition: formula.hh:432
bool is_sugar_free_ltl() const
Definition: formula.hh:499
bool is_syntactic_persistence() const
Definition: formula.hh:565
static const fnode * nested_unop_range(op uo, op bo, unsigned min, unsigned max, const fnode *f)
unsigned boolean_count() const
Definition: formula.hh:446
bool is_universal() const
Definition: formula.hh:535
bool is_tt() const
Definition: formula.hh:381
const fnode * get_child_of(std::initializer_list< op > l) const
Definition: formula.hh:294
static const fnode * one_plus()
Definition: formula.hh:421
const fnode * nth(unsigned i) const
Definition: formula.hh:353
bool is_constant() const
Definition: formula.hh:399
static const fnode * binop(op o, const fnode *f, const fnode *g)
static const fnode * multop(op o, const fnode *f, const fnode *g)
static const fnode * quantify(op quantifier, const fnode *ap, const fnode *f)
static const fnode * one_star()
Definition: formula.hh:413
const fnode * all_but(unsigned i) const
bool is_syntactic_recurrence() const
Definition: formula.hh:559
bool is(std::initializer_list< op > l) const
Definition: formula.hh:270
bool is_syntactic_obligation() const
Definition: formula.hh:553
bool is_quantified() const
Definition: formula.hh:619
static const fnode * unop(op o, const fnode *f)
static const fnode * quantify(op quantifier, std::vector< const fnode * > aps, const fnode *f)
bool is_ltl_formula() const
Definition: formula.hh:505
bool is_finite() const
Definition: formula.hh:523
bool is_sigma2() const
Definition: formula.hh:595
bool is_psl_formula() const
Definition: formula.hh:511
bool is_delta1() const
Definition: formula.hh:607
static const fnode * multop(op o, std::vector< const fnode * > l)
bool is_marked() const
Definition: formula.hh:571
void destroy() const
Dereference an fnode.
Definition: formula.hh:193
static const fnode * bunop(op o, const fnode *f, unsigned min, unsigned max=unbounded())
bool is(op o1, op o2) const
Definition: formula.hh:255
bool is_in_nenoform() const
Definition: formula.hh:487
static const fnode * ap(const std::string &name)
bool is_syntactic_guarantee() const
Definition: formula.hh:547
bool is_sere_formula() const
Definition: formula.hh:517
const fnode * clone() const
Clone an fnode.
Definition: formula.hh:179
bool is(op o) const
Definition: formula.hh:250
op
Operator types.
Definition: formula.hh:85
@ first_match
first_match(sere)
@ EConcatMarked
Seq, Marked.
@ NegClosure
Negated PSL Closure.
@ M
strong release (dual of weak until)
@ NegClosureMarked
marked version of the Negated PSL Closure
@ forall
universal quantification of AP
@ And
(omega-Rational) And
@ AndNLM
Non-Length-Matching Rational-And.
@ exists
existential quantification of AP
@ R
release (dual of until)
bool is_universal(const const_twa_graph_ptr &aut)
Return true iff aut is universal.
Definition: automata.hh:26
int atomic_prop_cmp(const fnode *f, const fnode *g)
Order two atomic propositions.
std::ostream & operator<<(std::ostream &os, const mc_algorithm &ma)
Print an mc_algorithm value to a stream.
Definition: mc.hh:74
std::list< std::string > list_formula_props(const formula &f)
List the properties of formula f.
std::ostream & print_formula_props(std::ostream &out, const formula &f, bool abbreviated=false)
Print the properties of formula f on stream out.