3 #ifndef LALA_CORE_ALGORITHM_HPP
4 #define LALA_CORE_ALGORITHM_HPP
11 template<
class Allocator,
class ExtendedSig>
16 && (f.
seq(0).is(F::LV) || f.
seq(0).is(F::V))
17 && f.
seq(1).is_constant();
21 template<
class Allocator,
class ExtendedSig>
26 && (f.
seq(0).is(F::LV) || f.
seq(0).is(F::V))
31 template<
class Allocator,
class ExtendedSig>
36 && (f.
seq(0).is(F::LV) || f.
seq(0).is(F::V))
37 && (f.
seq(1).is(F::LV) || f.
seq(1).is(F::V));
40 template<
class Allocator>
43 return F::make_binary(F::make_lvar(
UNTYPED, std::move(v)), sig, F::make_z(z), aty, allocator);
46 template<
class Allocator>
49 return F::make_binary(F::make_avar(v), sig, F::make_z(z), aty, allocator);
52 template <
class Allocator>
55 assert(f.
is(F::S) || f.
is(F::Z) || f.
is(F::R));
59 template <
class Allocator>
62 assert(f.
is(F::S) || f.
is(F::Z) || f.
is(F::R));
67 template<
class Allocator,
class ExtendedSig>
68 CUDA NI
const TFormula<Allocator, ExtendedSig>& var_in_impl(
const TFormula<Allocator, ExtendedSig>& f,
bool& found);
70 template<
size_t n,
class Allocator,
class ExtendedSig>
71 CUDA NI
const TFormula<Allocator, ExtendedSig>& find_var_in_seq(
const TFormula<Allocator, ExtendedSig>& f,
bool& found) {
72 const auto& children = battery::get<1>(battery::get<n>(f.data()));
73 for(
int i = 0; i < children.size(); ++i) {
74 const auto& subformula = var_in_impl(children[i], found);
82 template<
class Allocator,
class ExtendedSig>
83 CUDA NI
const TFormula<Allocator, ExtendedSig>& var_in_impl(
const TFormula<Allocator, ExtendedSig>& f,
bool& found)
85 using F = TFormula<Allocator, ExtendedSig>;
96 case F::Seq:
return find_var_in_seq<F::Seq>(f, found);
97 case F::ESeq:
return find_var_in_seq<F::ESeq>(f, found);
98 default: printf(
"var_in: formula not handled.\n"); assert(
false);
return f;
102 template<
size_t n,
class F>
103 CUDA NI
int num_vars_in_seq(
const F& f) {
104 const auto& children = battery::get<1>(battery::get<n>(f.data()));
106 for(
int i = 0; i < children.size(); ++i) {
113 CUDA NI
int num_qf_vars(
const F& f,
bool type_filter,
AType aty);
115 template<
size_t n,
class F>
116 CUDA NI
int num_qf_vars_in_seq(
const F& f,
bool type_filter,
AType aty) {
117 const auto& children = battery::get<1>(battery::get<n>(f.data()));
119 for(
int i = 0; i < children.size(); ++i) {
120 total += num_qf_vars(children[i], type_filter, aty);
126 CUDA NI
int num_qf_vars(
const F& f,
bool type_filter,
AType aty) {
130 return f.type() == aty ? 1 : 0;
135 case F::Seq:
return impl::num_qf_vars_in_seq<F::Seq>(f, type_filter, aty);
136 case F::ESeq:
return impl::num_qf_vars_in_seq<F::ESeq>(f, type_filter, aty);
144 template<
typename Allocator,
typename ExtendedSig>
147 return impl::var_in_impl(f, found);
160 case F::Seq:
return impl::num_vars_in_seq<F::Seq>(f);
161 case F::ESeq:
return impl::num_vars_in_seq<F::ESeq>(f);
169 return impl::num_qf_vars(f,
false,
UNTYPED);
175 return impl::num_qf_vars(f,
true, aty);
186 for(
int i = 0; i < f.seq().size(); ++i) {
199 for(
int i = 0; i < seq.size(); ++i) {
206 else if(ty != seq[i].type()) {
216 assert(f.is(F::Seq));
217 const auto& seq = f.seq();
218 typename F::Sequence fty;
219 typename F::Sequence other;
220 for(
int i = 0; i < seq.size(); ++i) {
222 if(seq[i].is(F::Seq) && seq[i].sig() ==
AND) {
224 auto& fty_ = battery::get<0>(r).seq();
225 auto& other_ = battery::get<1>(r).seq();
226 for(
int i = 0; i < fty_.size(); ++i) {
227 fty.push_back(std::move(fty_[i]));
229 for(
int i = 0; i < other_.size(); ++i) {
230 other.push_back(std::move(other_[i]));
233 else if(seq[i].type() == ty) {
234 fty.push_back(seq[i]);
237 other.push_back(seq[i]);
240 AType other_ty = type_of_conjunction<F>(other);
241 return battery::make_tuple(
242 F::make_nary(
AND, std::move(fty), ty),
243 F::make_nary(
AND, std::move(other), other_ty));
247 CUDA NI std::optional<F>
negate(
const F& f);
254 typename F::Sequence neg_seq(seq.size());
255 for(
int i = 0; i < f.seq().size(); ++i) {
256 auto neg_i =
negate(seq[i]);
257 if(neg_i.has_value()) {
264 return F::make_nary(sig_neg, neg_seq, f.type());
269 assert(f.is_binary() && f.sig() ==
EQ);
270 if(f.seq(0).is(
F::B)) {
273 return F::make_binary(b,
EQ, f.seq(1), f.type(), f.seq().get_allocator());
275 else if(f.seq(1).is(
F::B)) {
278 return F::make_binary(f.seq(0),
EQ, b, f.type(), f.seq().get_allocator());
280 return F::make_nary(
NEQ, f.seq(), f.type());
284 CUDA NI std::optional<F>
negate(
const F& f) {
286 return F::make_false();
288 else if(f.is_false()) {
289 return F::make_true();
291 else if(f.is_variable()) {
292 return F::make_unary(
NOT, f, f.type());
294 else if(f.is(F::Seq)) {
297 case NOT:
return f.seq(0);
300 case LEQ: neg_sig =
GT;
break;
301 case GEQ: neg_sig =
LT;
break;
302 case NEQ: neg_sig =
EQ;
break;
303 case LT: neg_sig =
GEQ;
break;
304 case GT: neg_sig =
LEQ;
break;
311 return F::make_unary(
NOT, f, f.type());
319 return F::make_nary(neg_sig, f.seq(), f.type());
332 default: assert(0);
return sig;
402 case NEQ:
return sig;
415 template <
class F,
class Env>
419 f = F::make_lvar(erase_type ?
UNTYPED : f.v().aty(), env.name_of(f.v()));
422 for(
int i = 0; i < f.seq().size(); ++i) {
427 for(
int i = 0; i < f.eseq().size(); ++i) {
437 CUDA
bool is_bz(
const F& f) {
438 return f.is(F::Z) || f.is(
F::B);
442 CUDA
bool is_binary_bz(
const typename F::Sequence& seq) {
443 return seq.size() == 2 && is_bz(seq[0]) && is_bz(seq[1]);
447 CUDA
bool is_binary_z(
const typename F::Sequence& seq) {
448 return seq.size() == 2 && seq[0].is(F::Z) && seq[1].is(F::Z);
455 CUDA F eval_seq(
Sig sig,
const typename F::Sequence& seq,
AType atype) {
458 typename F::Sequence residual;
459 for(
int i = 0; i < seq.size(); ++i) {
460 if(seq[i].is_false()) {
461 return F::make_false();
463 else if(!seq[i].is_true()) {
464 residual.push_back(seq[i]);
467 if(residual.size() == 0) {
468 return F::make_true();
470 else if(residual.size() == 1) {
474 return F::make_nary(
AND, std::move(residual), atype);
478 typename F::Sequence residual;
479 for(
int i = 0; i < seq.size(); ++i) {
480 if(seq[i].is_true()) {
481 return F::make_true();
483 else if(!seq[i].is_false()) {
484 residual.push_back(seq[i]);
487 if(residual.size() == 0) {
488 return F::make_false();
490 else if(residual.size() == 1) {
494 return F::make_nary(
OR, std::move(residual), atype);
498 if(is_binary_bz<F>(seq)) {
499 return seq[0].is_false() || seq[1].is_true() ? F::make_true() : F::make_false();
501 else if(seq.size() == 2) {
502 if(seq[0].is_true()) {
return seq[1]; }
503 else if(seq[0].is_false()) {
return F::make_true(); }
504 else if(seq[1].is_true()) {
return F::make_true(); }
505 else if(seq[1].is_false()) {
515 if(is_binary_bz<F>(seq)) {
516 return (seq[0].is_true() == seq[1].is_true()) ? F::make_true() : F::make_false();
518 else if(seq.size() == 2) {
519 if(seq[0].is_true()) {
return seq[1]; }
520 else if(seq[0].is_false()) {
return F::make_unary(
NOT, seq[1], atype); }
521 else if(seq[1].is_true()) {
return seq[0]; }
522 else if(seq[1].is_false()) {
return F::make_unary(
NOT, seq[0], atype); }
527 if(seq.size() == 1 && is_bz(seq[0])) {
528 return seq[0].is_true() ? F::make_false() : F::make_true();
530 if(seq.size() == 1 && seq[0].is_unary() && seq[0].sig() ==
NOT) {
531 return seq[0].seq(0);
536 if(is_binary_bz<F>(seq)) {
537 return (seq[0].is_true() != seq[1].is_true()) ? F::make_true() : F::make_false();
542 if(seq.size() == 3 && is_bz(seq[0])) {
543 return seq[0].is_true() ? seq[1] : seq[2];
548 if(seq.size() == 2 && seq[0].is_constant() && seq[1].is_constant()) {
549 return seq[0] == seq[1] ? F::make_true() : F::make_false();
552 if(seq.size() == 2 && seq[0].is_binary() &&
553 seq[1].is(F::Z) && seq[1].z() == 0 &&
554 seq[0].sig() ==
ADD &&
555 seq[0].seq(1).is_unary() && seq[0].seq(1).sig() ==
NEG && seq[0].seq(1).seq(0).is_variable() &&
556 seq[0].seq(0).is_variable())
558 return F::make_binary(seq[0].seq(0),
EQ, seq[0].seq(1).seq(0), atype);
563 if(seq.size() == 2 && seq[0].is_constant() && seq[1].is_constant()) {
564 return seq[0] != seq[1] ? F::make_true() : F::make_false();
567 if(seq.size() == 2 && seq[0].is_binary() &&
568 seq[1].is(F::Z) && seq[1].z() == 0 &&
569 seq[0].sig() ==
ADD &&
570 seq[0].seq(1).is_unary() && seq[0].seq(1).sig() ==
NEG && seq[0].seq(1).seq(0).is_variable() &&
571 seq[0].seq(0).is_variable())
573 return F::make_binary(seq[0].seq(0),
NEQ, seq[0].seq(1).seq(0), atype);
576 if(seq.size() == 2 && seq[0].is_binary() &&
578 seq[0].sig() ==
ADD &&
579 is_bz(seq[0].seq(1)))
581 return F::make_binary(seq[0].seq(0),
NEQ, F::make_z(seq[1].to_z() - seq[0].seq(1).to_z()), atype);
584 if(seq.size() == 2 && is_bz(seq[0]) && seq[1].is_unary() && seq[1].sig() ==
NEG && seq[1].seq(0).is_variable()) {
585 return F::make_binary(F::make_z(-seq[0].to_z()),
NEQ, seq[1].seq(0), atype);
588 if(seq.size() == 2 && is_bz(seq[1]) && seq[0].is_unary() && seq[0].sig() ==
NEG && seq[0].seq(0).is_variable()) {
589 return F::make_binary(seq[0].seq(0),
NEQ, F::make_z(-seq[1].to_z()), atype);
594 if(is_binary_z<F>(seq)) {
595 return seq[0].z() < seq[1].z() ? F::make_true() : F::make_false();
600 if(is_binary_z<F>(seq)) {
601 return seq[0].z() <= seq[1].z() ? F::make_true() : F::make_false();
606 if(is_binary_z<F>(seq)) {
607 return seq[0].z() > seq[1].z() ? F::make_true() : F::make_false();
612 if(is_binary_z<F>(seq)) {
613 return seq[0].z() >= seq[1].z() ? F::make_true() : F::make_false();
618 if(is_binary_z<F>(seq)) {
619 return F::make_z(battery::min(seq[0].z(), seq[1].z()));
624 if(is_binary_z<F>(seq)) {
625 return F::make_z(battery::max(seq[0].z(), seq[1].z()));
630 if(seq.size() == 1 && is_bz(seq[0])) {
631 return F::make_z(-seq[0].to_z());
633 if(seq.size() == 1 && seq[0].is_unary() && seq[0].sig() ==
NEG) {
634 return seq[0].seq(0);
639 if(seq.size() == 1 && is_bz(seq[0])) {
640 return F::make_z(abs(seq[0].to_z()));
645 typename F::Sequence residual;
647 for(
int i = 0; i < seq.size(); ++i) {
649 sum += seq[i].to_z();
652 residual.push_back(seq[i]);
655 if(residual.size() == 0) {
656 return F::make_z(sum);
660 residual.push_back(F::make_z(sum));
662 if(residual.size() == 1) {
666 return F::make_nary(
ADD, std::move(residual), atype);
671 typename F::Sequence residual;
673 for(
int i = 0; i < seq.size(); ++i) {
675 prod *= seq[i].to_z();
678 residual.push_back(seq[i]);
681 if(residual.size() == 0) {
682 return F::make_z(prod);
688 else if(prod == -1 && residual.size() > 0) {
689 residual[0] = F::make_unary(
NEG, std::move(residual[0]), atype);
692 residual.push_back(F::make_z(prod));
694 if(residual.size() == 1) {
698 return F::make_nary(
MUL, std::move(residual), atype);
703 if(is_binary_bz<F>(seq)) {
704 return F::make_z(seq[0].to_z() - seq[1].to_z());
706 else if(seq.size() == 2 && is_bz(seq[1]) && seq[1].to_z() == 0) {
709 else if(seq.size() == 2 && is_bz(seq[0]) && seq[0].to_z() == 0) {
710 return F::make_unary(
NEG, seq[1], atype);
718 if(is_binary_z<F>(seq)) {
720 case TDIV:
return F::make_z(battery::tdiv(seq[0].z(), seq[1].z()));
721 case FDIV:
return F::make_z(battery::fdiv(seq[0].z(), seq[1].z()));
722 case CDIV:
return F::make_z(battery::cdiv(seq[0].z(), seq[1].z()));
723 case EDIV:
return F::make_z(battery::ediv(seq[0].z(), seq[1].z()));
724 default: assert(0);
break;
727 else if(seq.size() == 2 && is_bz(seq[0]) && seq[0].to_z() == 0) {
730 else if(seq.size() == 2 && is_bz(seq[1]) && seq[1].to_z() == 1) {
736 if(is_binary_z<F>(seq)) {
737 return F::make_z(battery::tmod(seq[0].z(), seq[1].z()));
742 if(is_binary_z<F>(seq)) {
743 return F::make_z(battery::fmod(seq[0].z(), seq[1].z()));
748 if(is_binary_z<F>(seq)) {
749 return F::make_z(battery::cmod(seq[0].z(), seq[1].z()));
754 if(is_binary_z<F>(seq)) {
755 return F::make_z(battery::emod(seq[0].z(), seq[1].z()));
760 if(is_binary_bz<F>(seq)) {
761 return F::make_z(battery::ipow(seq[0].to_z(), seq[1].to_z()));
763 else if(seq.size() == 2 && is_bz(seq[1]) && seq[1].to_z() == 0) {
769 if(seq.size() == 2 && is_bz(seq[0]) && seq[1].is(F::S)) {
770 const auto& set = seq[1].s();
772 for(
int i = 0; i < set.size(); ++i) {
773 const auto& lb = battery::get<0>(set[i]);
774 const auto& ub = battery::get<1>(set[i]);
775 if(is_bz(lb) && is_bz(ub) && left >= lb.to_z() && left <= ub.to_z()) {
776 return F::make_true();
779 return F::make_false();
781 else if(seq.size() == 2 && seq[1].is(F::S) && seq[1].s().size() == 0) {
782 return F::make_false();
787 return F::make_nary(sig, seq, atype);
800 case F::LV:
return f;
802 const auto& seq = f.seq();
803 typename F::Sequence evaluated_seq(seq.get_allocator());
804 for(
int i = 0; i < seq.size(); ++i) {
805 evaluated_seq.push_back(
eval(seq[i]));
807 return impl::eval_seq<F>(f.sig(), evaluated_seq, f.type());
810 auto eseq = f.eseq();
811 typename F::Sequence evaluated_eseq(eseq.get_allocator());
812 for(
int i = 0; i < eseq.size(); ++i) {
813 evaluated_eseq.push_back(
eval(eseq[i]));
815 return F::make_nary(f.esig(), std::move(evaluated_eseq), f.type());
817 default: assert(
false);
return f;
840 case F::ESeq:
return f;
843 assert(f.seq().size() == 1);
844 if(f.seq(0).is_variable()) {
845 return F::make_binary(f.seq(0),
EQ, F::make_z(0), f.type());
849 if(not_f.has_value() && *not_f != f) {
853 return F::make_unary(
NOT, std::move(fi), f.type());
856 if(f.is_binary() &&
is_comparison(f) && f.seq(0).is_constant()) {
857 return F::make_binary(
859 f.type(), f.seq().get_allocator());
861 else if(f.is_binary() &&
is_comparison(f) && !f.seq(0).is_variable() && f.seq(1).is_variable()) {
862 return F::make_binary(
864 f.type(), f.seq().get_allocator());
867 else if(f.is_binary() && f.sig() ==
IN && f.seq(1).is(F::S) && f.seq(1).s().size() == 1 && battery::get<0>(f.seq(1).s()[0]) == battery::get<1>(f.seq(1).s()[0])) {
868 return F::make_binary(f.seq(0),
EQ, battery::get<0>(f.seq(1).s()[0]), f.type());
871 typename F::Sequence normalized_seq(f.seq().get_allocator());
872 for(
int i = 0; i < f.seq().size(); ++i) {
873 normalized_seq.push_back(
normalize(f.seq(i)));
875 return F::make_nary(f.sig(), std::move(normalized_seq), f.type(),
true);
878 default: assert(
false);
return f;
885 CUDA F itv_to_formula(
const F& f,
const battery::tuple<F, F>& itv,
const typename F::allocator_type& alloc =
typename F::allocator_type()) {
886 const auto& [l, u] = itv;
888 return F::make_binary(f,
EQ, l, f.type(), alloc);
895 F::make_binary(f, geq_sig, l, f.type(), alloc),
897 F::make_binary(f, leq_sig, u, f.type(), alloc),
907 if(f.is_binary() && f.sig() ==
IN && f.seq(1).is(F::S)) {
908 const auto& set = f.seq(1).s();
909 if(set.size() == 1) {
910 return impl::itv_to_formula(f.seq(0), set[0], alloc);
913 typename F::Sequence disjunction(alloc);
914 disjunction.reserve(set.size());
915 for(
size_t i = 0; i < set.size(); ++i) {
916 disjunction.push_back(impl::itv_to_formula(f.seq(0), set[i], alloc));
918 return F::make_nary(
OR, std::move(disjunction), f.type());
927 if(f.is_binary() && f.sig() ==
NEQ) {
928 return F::make_binary(
929 F::make_binary(f.seq(0),
LT, f.seq(1), f.type(), alloc),
931 F::make_binary(f.seq(0),
GT, f.seq(1), f.type(), alloc),
::lala::B<::battery::local_memory > B
Definition: b.hpp:12
Definition: abstract_deps.hpp:14
CUDA NI bool is_v_op_constant(const TFormula< Allocator, ExtendedSig > &f, Sig sig)
Definition: algorithm.hpp:12
CUDA const TFormula< Allocator, ExtendedSig > & var_in(const TFormula< Allocator, ExtendedSig > &f)
Definition: algorithm.hpp:145
CUDA NI void map_avar_to_lvar(F &f, const Env &env, bool erase_type=false)
Definition: algorithm.hpp:416
CUDA NI battery::tuple< F, F > extract_ty(const F &f, AType ty)
Definition: algorithm.hpp:215
long long int logic_int
Definition: sort.hpp:114
CUDA size_t num_constraints(const F &f)
Definition: algorithm.hpp:179
CUDA NI Sig converse_comparison(Sig sig)
Definition: algorithm.hpp:395
CUDA NI bool is_arithmetic_comparison(const F &f)
Definition: algorithm.hpp:338
Sig
Definition: ast.hpp:94
@ XOR
Logical connector.
Definition: ast.hpp:114
@ ITE
If-then-else.
Definition: ast.hpp:115
@ NEQ
Equality relations.
Definition: ast.hpp:112
@ LEQ
Unary arithmetic function symbols.
Definition: ast.hpp:113
@ NOT
Unary arithmetic function symbols.
Definition: ast.hpp:114
@ IMPLY
Unary arithmetic function symbols.
Definition: ast.hpp:114
@ TMOD
Truncated division, present in most programming languages, is defined as , i.e., it rounds towards ze...
Definition: ast.hpp:102
@ SUPSETEQ
Set inclusion predicates.
Definition: ast.hpp:107
@ OR
Unary arithmetic function symbols.
Definition: ast.hpp:114
@ EQ
Unary arithmetic function symbols.
Definition: ast.hpp:112
@ GEQ
Unary arithmetic function symbols.
Definition: ast.hpp:113
@ ADD
Unary arithmetic function symbols.
Definition: ast.hpp:97
@ IN
Set membership predicate.
Definition: ast.hpp:108
@ POW
Unary arithmetic function symbols.
Definition: ast.hpp:97
@ MIN
Unary arithmetic function symbols.
Definition: ast.hpp:97
@ EDIV
Unary arithmetic function symbols.
Definition: ast.hpp:105
@ GT
Arithmetic comparison predicates. When applied to set, it corresponds to the lexicographic ordering o...
Definition: ast.hpp:113
@ FMOD
Floor division (Knuth D. (1972). The Art of Computer Programming, Vol 1, Fundamental Algorithms),...
Definition: ast.hpp:103
@ MAX
Binary arithmetic function symbols.
Definition: ast.hpp:97
@ LT
Unary arithmetic function symbols.
Definition: ast.hpp:113
@ TDIV
Unary arithmetic function symbols.
Definition: ast.hpp:102
@ FDIV
Unary arithmetic function symbols.
Definition: ast.hpp:103
@ SUBSETEQ
Unary arithmetic function symbols.
Definition: ast.hpp:107
@ AND
Unary arithmetic function symbols.
Definition: ast.hpp:114
@ SUBSET
Unary arithmetic function symbols.
Definition: ast.hpp:107
@ EQUIV
Unary arithmetic function symbols.
Definition: ast.hpp:114
@ ABS
Unary arithmetic function symbols.
Definition: ast.hpp:96
@ SUB
Unary arithmetic function symbols.
Definition: ast.hpp:97
@ SUPSET
Unary arithmetic function symbols.
Definition: ast.hpp:107
@ MUL
Unary arithmetic function symbols.
Definition: ast.hpp:97
@ CMOD
Ceil division is defined as . Modulus is defined as .
Definition: ast.hpp:104
@ CDIV
Unary arithmetic function symbols.
Definition: ast.hpp:104
@ NEG
Unary arithmetic function symbols.
Definition: ast.hpp:96
@ EMOD
Euclidean division (Boute T. R. (1992). The Euclidean definition of the functions div and mod)....
Definition: ast.hpp:105
CUDA NI F normalize(const F &f)
Definition: algorithm.hpp:831
CUDA NI std::optional< F > negate(const F &f)
Definition: algorithm.hpp:284
CUDA size_t num_quantified_vars(const F &f)
Definition: algorithm.hpp:168
int AType
Definition: sort.hpp:18
CUDA NI bool is_var_equality(const TFormula< Allocator, ExtendedSig > &f)
Definition: algorithm.hpp:32
CUDA NI std::optional< F > de_morgan_law(Sig sig_neg, const F &f)
Definition: algorithm.hpp:252
CUDA NI bool is_v_op_z(const TFormula< Allocator, ExtendedSig > &f, Sig sig)
Definition: algorithm.hpp:22
CUDA NI TFormula< Allocator > make_v_op_z(LVar< Allocator > v, Sig sig, logic_int z, AType aty=UNTYPED, const Allocator &allocator=Allocator())
Definition: algorithm.hpp:41
CUDA NI AType type_of_conjunction(const typename F::Sequence &seq)
Definition: algorithm.hpp:197
CUDA Sig leq_of_constant(const TFormula< Allocator > &f)
Definition: algorithm.hpp:60
CUDA NI bool is_comparison(const F &f)
Definition: algorithm.hpp:374
CUDA F decompose_arith_neq_constraint(const F &f, const typename F::allocator_type &alloc=typename F::allocator_type())
Definition: algorithm.hpp:926
CUDA Sig geq_of_constant(const TFormula< Allocator > &f)
Definition: algorithm.hpp:53
CUDA NI int num_vars(const F &f)
Definition: algorithm.hpp:153
battery::string< Allocator > LVar
Definition: ast.hpp:25
CUDA Sig negate_arithmetic_comparison(Sig sig)
Definition: algorithm.hpp:324
CUDA NI F eval(const F &f)
Definition: algorithm.hpp:792
CUDA F decompose_in_constraint(const F &f, const typename F::allocator_type &alloc=typename F::allocator_type())
Definition: algorithm.hpp:906
CUDA NI std::optional< F > negate_eq(const F &f)
Definition: algorithm.hpp:268
CUDA NI bool is_set_comparison(const F &f)
Definition: algorithm.hpp:356
#define UNTYPED
Definition: sort.hpp:21