45#include <spot/misc/common.hh>
48#include <initializer_list>
64# define SPOT_HAS_STRONG_X 1
68# define SPOT_WANT_STRONG_X 1
70# define SPOT_HAS_QUANTIFIERS 1
78 enum class op: uint8_t
177 if (SPOT_UNLIKELY(!refs_))
189 if (SPOT_LIKELY(refs_))
191 else if (SPOT_LIKELY(!saturated_))
203 static const fnode*
ap(
const std::string& name);
218 unsigned min,
unsigned max = unbounded());
222 unsigned max,
const fnode* f);
230 std::vector<const fnode*> aps,
251 return op_ == o1 || op_ == o2;
256 return op_ == o1 || op_ == o2 || op_ == o3;
261 return op_ == o1 || op_ == o2 || op_ == o3 || op_ == o4;
264 bool is(std::initializer_list<op> l)
const
266 const fnode* n =
this;
282 if (SPOT_UNLIKELY(size_ != 1))
283 report_get_child_of_expecting_single_child_node();
303 if (SPOT_UNLIKELY(op_ != op::FStar && op_ != op::Star))
304 report_min_invalid_arg();
311 if (SPOT_UNLIKELY(op_ != op::FStar && op_ != op::Star))
312 report_max_invalid_arg();
343 return children + size();
349 if (SPOT_UNLIKELY(i >= size()))
350 report_non_existing_child();
351 const fnode* c = children[i];
352 SPOT_ASSUME(c !=
nullptr);
365 return op_ == op::ff;
377 return op_ == op::tt;
389 return op_ == op::eword;
395 return op_ == op::ff || op_ == op::tt || op_ == op::eword;
403 return range_.min == 0 && range_.max == unbounded();
410 one_star_ =
new fnode(op::Star, tt_, 0, unbounded(),
true);
418 one_plus_ =
new fnode(op::Star, tt_, 1, unbounded(),
true);
428 if (SPOT_UNLIKELY(op_ != op::ap))
429 report_apid_on_nonap();
434 std::ostream&
dump(std::ostream& os)
const;
444 while (pos < s && children[pos]->is_boolean())
477 return is_.sugar_free_boolean;
483 return is_.in_nenoform;
489 return is_.syntactic_si;
495 return is_.sugar_free_ltl;
501 return is_.ltl_formula;
507 return is_.psl_formula;
513 return is_.sere_formula;
531 return is_.universal;
537 return is_.syntactic_safety;
543 return is_.syntactic_guarantee;
549 return is_.syntactic_obligation;
555 return is_.syntactic_recurrence;
561 return is_.syntactic_persistence;
567 return !is_.not_marked;
573 return is_.accepting_eword;
579 return is_.lbt_atomic_props;
585 return is_.spin_atomic_props;
615 return is_.quantified;
619 static size_t bump_next_id();
620 void setup_props(
op o);
621 void destroy_aux()
const;
623 [[noreturn]]
static void report_non_existing_child();
624 [[noreturn]]
static void report_too_many_children();
625 [[noreturn]]
static void
626 report_get_child_of_expecting_single_child_node();
627 [[noreturn]]
static void report_min_invalid_arg();
628 [[noreturn]]
static void report_max_invalid_arg();
629 [[noreturn]]
static void report_apid_on_nonap();
632 static const fnode* multop_sorted(
op o, std::vector<const fnode*>&& l);
643 fnode(
op o, iter begin, iter end,
bool saturated =
false)
656 saturated_(saturated), ap_id_(0)
658 saturated_(saturated)
661 size_t s = std::distance(begin, end);
662 if (SPOT_UNLIKELY(s > (
size_t) UINT16_MAX))
663 report_too_many_children();
666 for (
auto i = begin; i != end; ++i)
671 fnode(op o, std::initializer_list<const fnode*> l,
672 bool saturated =
false)
673 : fnode(o, l.begin(), l.end(), saturated)
677 fnode(op o,
const fnode* f, uint8_t min, uint8_t max,
678 bool saturated =
false)
679 : op_(o), saturated_(saturated), size_(1)
687 fnode(op o, uint16_t apid,
bool saturated =
false)
688 : op_(o), saturated_(saturated), size_(0)
694 static const fnode* ff_;
695 static const fnode* tt_;
696 static const fnode* ew_;
697 static const fnode* one_star_;
698 static const fnode* one_plus_;
701 mutable uint8_t saturated_;
713 mutable uint16_t refs_ = 0;
715 static size_t next_id_;
733 bool sugar_free_boolean:1;
736 bool sugar_free_ltl:1;
743 bool syntactic_safety:1;
744 bool syntactic_guarantee:1;
745 bool syntactic_obligation:1;
746 bool syntactic_recurrence:1;
747 bool syntactic_persistence:1;
749 bool accepting_eword:1;
750 bool lbt_atomic_props:1;
751 bool spin_atomic_props:1;
765 const fnode* children[1];
777 operator()(
const fnode* left,
const fnode* right)
const
797 auto get_literal = [](
const fnode* f) ->
const fnode*
806 const fnode* litl = get_literal(left);
807 const fnode* litr = get_literal(right);
820 size_t l = left->
id();
821 size_t r = right->
id();
834 std::ostringstream old;
836 std::ostringstream ord;
838 return old.str() < ord.str();
923 const formula& operator=(formula&& f)
noexcept
925 std::swap(f.ptr_, ptr_);
929 bool operator<(
const formula& other)
const noexcept
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_;
946 bool operator<=(
const formula& other)
const noexcept
948 return *
this == other || *
this < other;
951 bool operator>(
const formula& other)
const noexcept
953 return !(*
this <= other);
956 bool operator>=(
const formula& other)
const noexcept
958 return !(*
this < other);
961 bool operator==(
const formula& other)
const noexcept
963 return other.ptr_ == ptr_;
966 bool operator==(std::nullptr_t)
const noexcept
968 return ptr_ ==
nullptr;
971 bool operator!=(
const formula& other)
const noexcept
973 return other.ptr_ != ptr_;
976 bool operator!=(std::nullptr_t)
const noexcept
978 return ptr_ !=
nullptr;
981 explicit operator bool() const noexcept
983 return ptr_ !=
nullptr;
1006 static
bool is_valid_apid(
unsigned id) noexcept;
1009 static const std::
string& apname_from_apid(
unsigned id);
1023 void throw_if_quantified(const
char* message)
1025 if (SPOT_UNLIKELY(is_quantified()))
1026 report_message(message);
1036 return fnode::unbounded();
1042 return formula(fnode::ap(name));
1052 if (SPOT_UNLIKELY(a.
kind() != op::ap))
1053 report_ap_invalid_arg();
1075#define SPOT_DEF_UNOP(Name) \
1076 static formula Name(const formula& f) \
1078 return unop(op::Name, f); \
1081#define SPOT_DEF_UNOP(Name) \
1082 static formula Name(const formula& f) \
1084 return unop(op::Name, f); \
1086 static formula Name(formula&& f) \
1088 return unop(op::Name, std::move(f)); \
1106 return nested_unop_range(op::X, op::Or , level, level, f);
1111 SPOT_DEF_UNOP(strong_X);
1119 return nested_unop_range(op::strong_X, op::Or ,
1136 return nested_unop_range(op::X, op::Or, min_level, max_level, f);
1147 return nested_unop_range(op::X, op::And, min_level, max_level, f);
1157 SPOT_DEF_UNOP(Closure);
1162 SPOT_DEF_UNOP(NegClosure);
1167 SPOT_DEF_UNOP(NegClosureMarked);
1172 SPOT_DEF_UNOP(first_match);
1189 return formula(fnode::binop(o, f.ptr_->
clone(), g.to_node_()));
1206#define SPOT_DEF_BINOP(Name) \
1207 static formula Name(const formula& f, const formula& g) \
1209 return binop(op::Name, f, g); \
1212#define SPOT_DEF_BINOP(Name) \
1213 static formula Name(const formula& f, const formula& g) \
1215 return binop(op::Name, f, g); \
1217 static formula Name(const formula& f, formula&& g) \
1219 return binop(op::Name, f, std::move(g)); \
1221 static formula Name(formula&& f, const formula& g) \
1223 return binop(op::Name, std::move(f), g); \
1225 static formula Name(formula&& f, formula&& g) \
1227 return binop(op::Name, std::move(f), std::move(g)); \
1232 SPOT_DEF_BINOP(Xor);
1237 SPOT_DEF_BINOP(Implies);
1242 SPOT_DEF_BINOP(Equiv);
1267 SPOT_DEF_BINOP(EConcat);
1272 SPOT_DEF_BINOP(EConcatMarked);
1277 SPOT_DEF_BINOP(UConcat);
1279#undef SPOT_DEF_BINOP
1306 std::vector<const fnode*> tmp;
1307 tmp.reserve(l.size());
1310 tmp.emplace_back(f.ptr_->
clone());
1311 return formula(fnode::multop(o, std::move(tmp)));
1317 std::vector<const fnode*> tmp;
1318 tmp.reserve(l.size());
1322 return formula(fnode::multop(o, std::move(tmp)));
1334 return formula(fnode::multop(o, f.ptr_->
clone(), g.to_node_()));
1350#define SPOT_DEF_MULTOP(Name) \
1351 static formula Name(const std::vector<formula>& l) \
1353 return multop(op::Name, l); \
1356 static formula Name(const formula& left, const formula& right) \
1358 return multop(op::Name, left, right); \
1361#define SPOT_DEF_MULTOP(Name) \
1362 static formula Name(const std::vector<formula>& l) \
1364 return multop(op::Name, l); \
1367 static formula Name(std::vector<formula>&& l) \
1369 return multop(op::Name, std::move(l)); \
1372 static formula Name(const formula& left, const formula& right) \
1374 return multop(op::Name, left, right); \
1378#define SPOT_DEF_MULTOP2(Name) \
1379 static formula Name(const std::vector<formula>& l) \
1381 return multop(op::Name, l); \
1384 static formula Name(const formula& left, const formula& right) \
1386 return formula(fnode::multop_build_and_or<op::Name> \
1387 (left->ptr_->clone(), right->ptr_->clone()); \
1390#define SPOT_DEF_MULTOP2(Name) \
1391 static formula Name(const std::vector<formula>& l) \
1393 return multop(op::Name, l); \
1396 static formula Name(std::vector<formula>&& l) \
1398 return multop(op::Name, std::move(l)); \
1401 static formula Name(const formula& left, const formula& right) \
1403 return formula(fnode::multop_build_and_or<op::Name> \
1404 (left.ptr_->clone(), right.ptr_->clone())); \
1406 static formula Name(const formula& left, formula&& right) \
1408 return formula(fnode::multop_build_and_or<op::Name> \
1409 (left.ptr_->clone(), right.to_node_())); \
1411 static formula Name(formula&& left, const formula& right) \
1413 return formula(fnode::multop_build_and_or<op::Name> \
1414 (left.to_node_(), right.ptr_->clone())); \
1416 static formula Name(formula&& left, formula&& right) \
1418 return formula(fnode::multop_build_and_or<op::Name> \
1419 (left.to_node_(), right.to_node_())); \
1424 SPOT_DEF_MULTOP2(Or);
1429 SPOT_DEF_MULTOP(OrRat);
1434 SPOT_DEF_MULTOP2(And);
1439 SPOT_DEF_MULTOP(AndRat);
1444 SPOT_DEF_MULTOP(AndNLM);
1449 SPOT_DEF_MULTOP(Concat);
1454 SPOT_DEF_MULTOP(Fusion);
1456#undef SPOT_DEF_MULTOP
1464 unsigned max = unbounded())
1466 return formula(fnode::bunop(o, f.ptr_->
clone(), min, max));
1472 unsigned max = unbounded())
1480#define SPOT_DEF_BUNOP(Name) \
1481 static formula Name(const formula& f, \
1482 unsigned min = 0U, \
1483 unsigned max = unbounded()) \
1485 return bunop(op::Name, f, min, max); \
1488#define SPOT_DEF_BUNOP(Name) \
1489 static formula Name(const formula& f, \
1490 unsigned min = 0U, \
1491 unsigned max = unbounded()) \
1493 return bunop(op::Name, f, min, max); \
1495 static formula Name(formula&& f, \
1496 unsigned min = 0U, \
1497 unsigned max = unbounded()) \
1499 return bunop(op::Name, std::move(f), min, max); \
1504 SPOT_DEF_BUNOP(Star);
1512 SPOT_DEF_BUNOP(FStar);
1514#undef SPOT_DEF_BUNOP
1520 return formula(fnode::quantify(quantifier,
1529 return formula(fnode::quantify(quantifier,
1534 static formula quantify(op quantifier,
1535 const std::vector<formula>& aps,
1538 std::vector<const fnode*> tmp;
1539 tmp.reserve(aps.size() + 1);
1542 tmp.emplace_back(a.to_node_());
1543 return formula(fnode::quantify(quantifier, std::move(tmp),
1548 static formula quantify(op quantifier,
1549 std::vector<formula>&& aps,
1552 std::vector<const fnode*> tmp;
1553 tmp.reserve(aps.size() + 1);
1556 tmp.emplace_back(a.to_node_());
1557 return formula(fnode::quantify(quantifier, std::move(tmp),
1562#define SPOT_DEF_QUANTIFY(Name) \
1563 static formula Name(const std::vector<formula>& aps, const formula& f) \
1565 return quantify(op::Name, aps, f); \
1568 static formula Name(const formula& ap, const formula& f) \
1570 return quantify(op::Name, ap, f); \
1575 SPOT_DEF_QUANTIFY(exists);
1580 SPOT_DEF_QUANTIFY(forall);
1582#undef SPOT_DEF_QUANTIFY
1598 return formula(fnode::nested_unop_range(uo, bo, min, max,
1638 unsigned min,
unsigned max);
1640 unsigned min,
unsigned max);
1664 return ptr_->kind();
1670 return ptr_->kindstr();
1683 return ptr_->is(o1, o2);
1689 return ptr_->is(o1, o2, o3);
1696 return ptr_->is(o1, o2, o3, o4);
1700 bool is(std::initializer_list<op> l)
const
1752 return ptr_->size();
1761 return ptr_->is_leaf();
1781 const fnode*
const* ptr_;
1795 return ptr_ == o.ptr_;
1800 return ptr_ != o.ptr_;
1805 return formula((*ptr_)->clone());
1825 return ptr_->begin();
1837 return formula(ptr_->nth(i)->clone());
1850 return ptr_->is_ff();
1862 return ptr_->is_tt();
1868 return formula(fnode::eword());
1874 return ptr_->is_eword();
1880 return ptr_->is_constant();
1889 return ptr_->is_Kleene_star();
1896 return formula(fnode::one_star());
1903 return formula(fnode::one_plus());
1910 return (is(op::ap) ||
1914 (is(op::Not) && is_boolean() && is_in_nenoform()));
1922 return ptr_->ap_name();
1935 return ptr_->apid();
1942 std::ostream&
dump(std::ostream& os)
const
1944 return ptr_->dump(os);
1954 return formula(ptr_->all_but(i));
1968 return ptr_->boolean_count();
1986 return formula(ptr_->boolean_operands(width));
1989#define SPOT_DEF_PROP(Name) \
1992 return ptr_->Name(); \
1999 SPOT_DEF_PROP(is_boolean);
2001 SPOT_DEF_PROP(is_sugar_free_boolean);
2006 SPOT_DEF_PROP(is_in_nenoform);
2008 SPOT_DEF_PROP(is_syntactic_stutter_invariant);
2010 SPOT_DEF_PROP(is_sugar_free_ltl);
2012 SPOT_DEF_PROP(is_ltl_formula);
2014 SPOT_DEF_PROP(is_psl_formula);
2016 SPOT_DEF_PROP(is_sere_formula);
2019 SPOT_DEF_PROP(is_finite);
2027 SPOT_DEF_PROP(is_eventual);
2035 SPOT_DEF_PROP(is_universal);
2039 SPOT_DEF_PROP(is_syntactic_safety);
2043 SPOT_DEF_PROP(is_syntactic_guarantee);
2048 SPOT_DEF_PROP(is_delta1);
2053 SPOT_DEF_PROP(is_syntactic_obligation);
2055 SPOT_DEF_PROP(is_sigma2);
2057 SPOT_DEF_PROP(is_pi2);
2062 SPOT_DEF_PROP(is_syntactic_recurrence);
2067 SPOT_DEF_PROP(is_syntactic_persistence);
2072 SPOT_DEF_PROP(is_delta2);
2075 SPOT_DEF_PROP(is_marked);
2077 SPOT_DEF_PROP(accepts_eword);
2083 SPOT_DEF_PROP(has_lbt_atomic_props);
2092 SPOT_DEF_PROP(has_spin_atomic_props);
2094 SPOT_DEF_PROP(is_quantified);
2100 template<
typename Trans,
typename... Args>
2103 switch (
op o = kind())
2112#if SPOT_HAS_STRONG_X
2118 case op::NegClosure:
2119 case op::NegClosureMarked:
2120 case op::first_match:
2123 formula new_arg = trans(arg, std::forward<Args>(args)...);
2127 return unop(o, new_arg);
2137 case op::EConcatMarked:
2142 formula new_left = trans(left, std::forward<Args>(args)...);
2143 formula new_right = trans(right, std::forward<Args>(args)...);
2144 if (left == new_left && right == new_right)
2147 return binop(o, new_left, new_right);
2157 std::vector<formula> tmp;
2158 bool changed =
false;
2159 tmp.reserve(size());
2162 formula g = trans(f, std::forward<Args>(args)...);
2163 tmp.emplace_back(g);
2169 return multop(o, std::move(tmp));
2175 formula new_arg = trans(arg, std::forward<Args>(args)...);
2179 return bunop(o, new_arg, min(), max());
2184 std::vector<formula> tmp;
2185 unsigned sz = size();
2186 tmp.reserve(sz - 1);
2187 bool changed =
false;
2188 for (
unsigned i = 0; i < sz - 1; ++i)
2191 formula g = trans(c, std::forward<Args>(args)...);
2196 formula g = trans(c, std::forward<Args>(args)...);
2197 if (c == g && !changed)
2199 return quantify(o, std::move(tmp), g);
2213 template<
typename Func,
typename... Args>
2216 if (func(*
this, std::forward<Args>(args)...))
2219 f.traverse(func, std::forward<Args>(args)...);
2223 [[noreturn]]
static void report_message(
const char* message);
2225 [[noreturn]]
static void report_ap_invalid_arg();
2232 bool abbreviated =
false);
2240 std::ostream& operator<<(std::ostream& os,
const formula& f);
Actual storage for formula nodes.
Definition formula.hh:167
bool is_pi2() const
Definition formula.hh:595
std::string kindstr() const
const fnode * boolean_operands(unsigned *width=nullptr) const
bool is_boolean() const
Definition formula.hh:469
size_t id() const
Definition formula.hh:329
bool is_ff() const
Definition formula.hh:363
bool is_sugar_free_boolean() const
Definition formula.hh:475
bool is_Kleene_star() const
Definition formula.hh:399
static const fnode * nested_unop_range(op uo, op bo, unsigned min, unsigned max, const fnode *f)
const fnode *const * end() const
Definition formula.hh:341
unsigned min() const
Definition formula.hh:301
bool is_syntactic_safety() const
Definition formula.hh:535
bool is_syntactic_stutter_invariant() const
Definition formula.hh:487
static const fnode * quantify(op quantifier, const fnode *ap, const fnode *f)
static const fnode * binop(op o, const fnode *f, const fnode *g)
bool is_delta2() const
Definition formula.hh:607
unsigned size() const
Definition formula.hh:317
static constexpr uint8_t unbounded()
Definition formula.hh:197
const fnode * get_child_of(std::initializer_list< op > l) const
Definition formula.hh:288
unsigned max() const
Definition formula.hh:309
const fnode * get_child_of(op o) const
Definition formula.hh:278
const fnode * all_but(unsigned i) const
bool accepts_eword() const
Definition formula.hh:571
bool is_eventual() const
Definition formula.hh:523
bool is(op o1, op o2, op o3, op o4) const
Definition formula.hh:259
static bool instances_check()
safety check for the reference counters
bool is_leaf() const
Definition formula.hh:323
bool has_spin_atomic_props() const
Definition formula.hh:583
bool is_eword() const
Definition formula.hh:387
bool is(op o1, op o2, op o3) const
Definition formula.hh:254
op kind() const
Definition formula.hh:234
const fnode * clone() const
Clone an fnode.
Definition formula.hh:173
bool has_lbt_atomic_props() const
Definition formula.hh:577
unsigned apid() const
Definition formula.hh:426
bool is_sugar_free_ltl() const
Definition formula.hh:493
const std::string & ap_name() const
bool is_syntactic_persistence() const
Definition formula.hh:559
unsigned boolean_count() const
Definition formula.hh:440
static const fnode * tt()
Definition formula.hh:369
bool is_universal() const
Definition formula.hh:529
bool is_tt() const
Definition formula.hh:375
bool is_constant() const
Definition formula.hh:393
bool is_syntactic_recurrence() const
Definition formula.hh:553
bool is(std::initializer_list< op > l) const
Definition formula.hh:264
bool is_syntactic_obligation() const
Definition formula.hh:547
bool is_quantified() const
Definition formula.hh:613
static const fnode * unop(op o, const fnode *f)
const fnode * nth(unsigned i) const
Definition formula.hh:347
bool is_ltl_formula() const
Definition formula.hh:499
static const fnode * multop(op o, const fnode *f, const fnode *g)
static const fnode * quantify(op quantifier, std::vector< const fnode * > aps, const fnode *f)
static const fnode * ff()
Definition formula.hh:357
bool is_finite() const
Definition formula.hh:517
static const fnode * multop_build_and_or(const fnode *left, const fnode *right)
fast path for binary and/or
bool is_sigma2() const
Definition formula.hh:589
bool is_psl_formula() const
Definition formula.hh:505
bool is_delta1() const
Definition formula.hh:601
static const fnode * eword()
Definition formula.hh:381
bool is_marked() const
Definition formula.hh:565
std::ostream & dump(std::ostream &os) const
void destroy() const
Dereference an fnode.
Definition formula.hh:187
static const fnode * one_plus()
Definition formula.hh:415
static const fnode * ap(const std::string &name)
bool is(op o1, op o2) const
Definition formula.hh:249
bool is_in_nenoform() const
Definition formula.hh:481
static const fnode * bunop(op o, const fnode *f, unsigned min, unsigned max=unbounded())
bool is_syntactic_guarantee() const
Definition formula.hh:541
static const fnode * multop(op o, std::vector< const fnode * > l)
bool is_sere_formula() const
Definition formula.hh:511
static const fnode * one_star()
Definition formula.hh:407
const fnode *const * begin() const
Definition formula.hh:335
bool is(op o) const
Definition formula.hh:244
op
Operator types.
Definition formula.hh:79
@ 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)
Definition automata.hh:26
int atomic_prop_cmp(const fnode *f, const fnode *g)
Order two atomic propositions.
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.