3#ifndef LALA_CORE_NBITSET_HPP
4#define LALA_CORE_NBITSET_HPP
7#include "battery/bitset.hpp"
17template <
size_t N,
class Mem,
class T =
unsigned long long>
31 template <
size_t N2,
class Mem2,
class T2>
35 constexpr static const bool sequential = Mem::sequential;
44 constexpr static const char*
name =
"NBitset";
49 struct top_constructor_tag {};
50 CUDA
constexpr NBitset(top_constructor_tag) {}
60 for(
int i = 0; i < values.size(); ++i) {
61 b.bits.set(battery::min(
static_cast<int>(N)-1, battery::max(values[i]+1,0)),
true);
71 bits.set(battery::min(
static_cast<int>(N)-1, battery::max(0, x+1)));
86 CUDA
constexpr NBitset(
const battery::bitset<N, M, T>& bits): bits(bits) {}
113 template<
bool diagnose,
class F,
class Env,
class M>
114 CUDA NI
static bool interpret_existential(
const F& f,
const Env& env, this_type2<M>& k,
IDiagnostics& diagnostics) {
115 const auto& sort = battery::get<1>(f.exists());
119 else if(sort.is_bool()) {
124 const auto& vname = battery::get<0>(f.exists());
129 template<
bool diagnose,
bool negated,
class F,
class M>
130 CUDA NI
static bool interpret_tell_set(
const F& f,
const F& k, this_type2<M>&
tell, IDiagnostics& diagnostics) {
131 using sort_type = Sort<typename F::allocator_type>;
132 thrust::optional<sort_type> sort = k.sort();
133 if(sort.has_value() &&
134 (sort.value() == sort_type(sort_type::Set, sort_type(sort_type::Int))
135 || sort.value() == sort_type(sort_type::Set, sort_type(sort_type::Bool))))
137 const auto& set = k.s();
139 bool over_appx =
false;
140 for(
int i = 0; i < set.size(); ++i) {
141 int l = battery::get<0>(set[i]).to_z();
142 int u = battery::get<1>(set[i]).to_z();
144 if(l < 0 || u >= meet_s.bits.size() - 2) {
148 if constexpr(negated) {
149 meet_s = meet_s.complement();
151 meet_s.bits.set(0,
true);
152 meet_s.bits.set(meet_s.bits.size()-1,
true);
165 template<
bool diagnose,
class F,
class M>
166 CUDA NI
static bool interpret_tell_x_op_k(
const F& f,
logic_int k,
Sig sig, this_type2<M>&
tell, IDiagnostics& diagnostics) {
168 return interpret_tell_x_op_k<diagnose>(f, k-1,
LEQ,
tell, diagnostics);
171 return interpret_tell_x_op_k<diagnose>(f, k+1,
GEQ,
tell, diagnostics);
173 else if(k < 0 || k >=
tell.bits.size() - 2) {
174 if((k == -1 && sig ==
LEQ) || (k ==
tell.bits.size() - 2 && sig ==
GEQ)) {
178 INTERPRETATION_WARNING(
"Constraint `x <op> k` is over-approximated because `k` is not representable in the bitset. Note that for a bitset of size `n`, the only values representable exactly are in the interval `[0, n-3]` because two bits are used to represent all negative values and all values exceeding the size of the bitset.");
195 template<
bool diagnose,
bool negated,
class F,
class Env,
class M>
196 CUDA NI
static bool interpret_binary(
const F& f,
const Env& env, this_type2<M>&
tell, IDiagnostics& diagnostics) {
197 int idx_constant = f.seq(0).is_constant() ? 0 : (f.seq(1).is_constant() ? 1 : 100);
198 int idx_variable = f.seq(0).is_variable() ? 0 : (f.seq(1).is_variable() ? 1 : 100);
199 if(idx_constant + idx_variable != 1) {
200 RETURN_INTERPRETATION_ERROR(
"Only binary formulas of the form `t1 <sig> t2` where if t1 is a constant and t2 is a variable (or conversely) are supported.");
202 const auto& k = f.seq(idx_constant);
204 if(idx_constant == 0) {
208 return interpret_tell_set<diagnose, negated>(f, k,
tell, diagnostics);
214 if(f.seq(idx_constant).is(F::Z) || f.seq(idx_constant).is(F::B)) {
215 return interpret_tell_x_op_k<diagnose>(f, k.to_z(), sig,
tell, diagnostics);
233 template<
bool diagnose = false,
class F,
class Env,
class M>
237 return interpret_existential<diagnose>(f, env,
tell, diagnostics);
239 else if(f.is_unary() && f.sig() ==
NOT && f.seq(0).is_binary()) {
240 return interpret_binary<diagnose, true>(f.seq(0), env,
tell, diagnostics);
242 else if(f.is_binary()) {
243 return interpret_binary<diagnose, false>(f, env,
tell, diagnostics);
251 template<
bool diagnose = false,
class F,
class Env,
class M>
255 if(!nf.has_value()) {
261 if(interpret_tell<diagnose>(nf.value(), env, b, diagnostics)) {
270 template<IKind kind,
bool diagnose = false,
class F,
class Env,
class M>
273 return interpret_ask<diagnose>(f, env, k, diagnostics);
276 return interpret_tell<diagnose>(f, env, k, diagnostics);
303 template<
class A,
class M>
308 template<
class A,
class M>
313 template<
class M1,
class M2>
315 if(!bits.is_subset_of(other.bits)) {
324 if(!bits.is_subset_of(other.bits)) {
335 template<
class M1,
class M2>
337 if(!other.bits.is_subset_of(bits)) {
346 if(!other.bits.is_subset_of(bits)) {
362 return F::make_true();
365 return F::make_false();
368 typename F::Sequence seq{env.get_allocator()};
370 seq.push_back(F::make_binary(F::make_avar(x),
LEQ, F::make_z(-1),
UNTYPED, env.get_allocator()));
372 if(bits.test(bits.size()-1)) {
373 seq.push_back(F::make_binary(F::make_avar(x),
GEQ, F::make_z(bits.size()-2),
UNTYPED, env.get_allocator()));
376 for(
int i = 1; i < bits.size()-1; ++i) {
379 for(i = i + 1; i < bits.size()-1 && bits.test(i); ++i) {}
381 logical_set.push_back(battery::make_tuple(F::make_z(l), F::make_z(u)));
384 if(logical_set.size() > 0) {
385 seq.push_back(F::make_binary(F::make_avar(x),
IN, F::make_set(std::move(logical_set)),
UNTYPED, env.get_allocator()));
387 if(seq.size() == 1) {
388 return std::move(seq[0]);
391 return F::make_nary(
OR, std::move(seq));
401 return lb().template deinterpret<F>();
406 bool comma_needed =
false;
411 for(
int i = 1; i < bits.size() - 1; ++i) {
413 if(comma_needed) { printf(
", "); }
418 if(bits.test(bits.size()-1)) {
419 if(comma_needed) { printf(
", "); }
420 printf(
"%d, ..",
static_cast<int>(bits.size())-2);
428 case NEG:
return true;
429 default:
return false;
446 return x.bits.test(0) ?
local_type(0, x.bits.size()) : x;
449 template<Sig sig,
class M>
451 static_assert(sig ==
NEG || sig ==
ABS,
"Unsupported unary function.");
462 printf(
"%% additive_inverse is unsupported\n");
468 template<Sig sig,
class M1,
class M2>
470 printf(
"%% binary functions %s are unsupported\n",
string_of_sig(sig));
477 if(bits.test(0) || bits.test(bits.size() - 1)) {
return bot(); }
484 int total = bits.count();
486 for(
int i = 0; i < bits.size(); ++i) {
489 if(current == total/2) {
500template<
size_t N,
class M1,
class M2,
class T>
506template<
size_t N,
class M1,
class M2,
class T>
512template<
size_t N,
class M1,
class M2,
class T>
513CUDA
constexpr bool operator<=(
const NBitset<N, M1, T>& a,
const NBitset<N, M2, T>& b)
515 return b.value().is_subset_of(a.value());
518template<
size_t N,
class M1,
class M2,
class T>
521 return b.
value().is_proper_subset_of(a.
value());
524template<
size_t N,
class M1,
class M2,
class T>
525CUDA
constexpr bool operator>=(
const NBitset<N, M1, T>& a,
const NBitset<N, M2, T>& b)
530template<
size_t N,
class M1,
class M2,
class T>
536template<
size_t N,
class M1,
class M2,
class T>
542template<
size_t N,
class M1,
class M2,
class T>
543CUDA
constexpr bool operator!=(
const NBitset<N, M1, T>& a,
const NBitset<N, M2, T>& b)
545 return a.value() != b.value();
548template<
size_t N,
class M,
class T>
551 bool comma_needed =
false;
552 if(a.
value().test(0)) {
556 for(
int i = 1; i < a.
value().size() - 1; ++i) {
557 if(a.
value().test(i)) {
558 if(comma_needed) { s <<
", "; }
564 if(comma_needed) { s <<
", "; }
565 s << a.
value().size()-2 <<
", ..";
Definition diagnostics.hpp:19
Definition nbitset.hpp:19
CUDA static constexpr local_type neg(const this_type2< M > &x)
Definition nbitset.hpp:435
CUDA static NI bool interpret(const F &f, const Env &env, this_type2< M > &k, IDiagnostics &diagnostics)
Definition nbitset.hpp:271
CUDA constexpr this_type & tell(const this_type2< M1 > &other, BInc< M2 > &has_changed)
Definition nbitset.hpp:314
static constexpr const bool complemented
Definition nbitset.hpp:43
static constexpr const char * name
Definition nbitset.hpp:44
CUDA constexpr this_type & tell_top()
Definition nbitset.hpp:298
battery::bitset< N, Mem, T > bitset_type
Definition nbitset.hpp:22
CUDA static NI bool interpret_tell(const F &f, const Env &env, this_type2< M > &tell, IDiagnostics &diagnostics)
Definition nbitset.hpp:234
friend class NBitset
Definition nbitset.hpp:32
static constexpr const bool preserve_join
Definition nbitset.hpp:39
static constexpr const bool is_abstract_universe
Definition nbitset.hpp:34
CUDA static constexpr local_type eq_zero()
Definition nbitset.hpp:102
CUDA constexpr this_type & tell_lb(const A &lb, BInc< M > &has_changed)
Definition nbitset.hpp:304
CUDA constexpr NBitset(value_type x)
Definition nbitset.hpp:70
static constexpr const bool preserve_concrete_covers
Definition nbitset.hpp:42
static constexpr const bool preserve_top
Definition nbitset.hpp:38
CUDA constexpr local::BDec is_bot() const
Definition nbitset.hpp:109
CUDA static constexpr local_type top()
Definition nbitset.hpp:107
CUDA constexpr local::BInc is_top() const
Definition nbitset.hpp:108
CUDA constexpr this_type & dtell(const this_type2< M > &other)
Definition nbitset.hpp:345
CUDA NI static constexpr bool is_supported_fun(Sig sig)
Definition nbitset.hpp:425
static constexpr const bool injective_concretization
Definition nbitset.hpp:41
CUDA constexpr this_type & dtell(const this_type2< M1 > &other, BInc< M2 > &has_changed)
Definition nbitset.hpp:336
CUDA constexpr NBitset(const battery::bitset< N, M, T > &bits)
Definition nbitset.hpp:86
CUDA constexpr LB lb() const
Definition nbitset.hpp:280
CUDA static constexpr local_type bot()
Definition nbitset.hpp:106
CUDA constexpr this_type & operator=(const this_type2< M > &other)
Definition nbitset.hpp:91
CUDA static constexpr local_type abs(const this_type2< M > &x)
Definition nbitset.hpp:445
constexpr NBitset(this_type &&)=default
CUDA constexpr bool extract(this_type2< M > &ua) const
Definition nbitset.hpp:353
static constexpr const bool is_totally_ordered
Definition nbitset.hpp:36
CUDA NI void print() const
Definition nbitset.hpp:404
CUDA NI F deinterpret() const
Definition nbitset.hpp:400
CUDA constexpr this_type & tell_ub(const A &ub, BInc< M > &has_changed)
Definition nbitset.hpp:309
CUDA constexpr NBitset(value_type lb, value_type ub)
Definition nbitset.hpp:74
CUDA constexpr NBitset(this_type2< M > &&other)
Definition nbitset.hpp:83
CUDA static constexpr local_type eq_one()
Definition nbitset.hpp:104
CUDA TFormula< typename Env::allocator_type > deinterpret(AVar x, const Env &env) const
Definition nbitset.hpp:359
CUDA constexpr this_type & dtell_bot()
Definition nbitset.hpp:330
CUDA static constexpr local_type additive_inverse(const this_type2< M > &x)
Definition nbitset.hpp:461
CUDA static constexpr local_type fun(const this_type2< M1 > &x, const this_type2< M2 > &y)
Definition nbitset.hpp:469
CUDA static NI bool interpret_ask(const F &f, const Env &env, this_type2< M > &k, IDiagnostics &diagnostics)
Definition nbitset.hpp:252
static constexpr const bool preserve_bot
Definition nbitset.hpp:37
static constexpr const bool preserve_meet
Definition nbitset.hpp:40
CUDA constexpr UB ub() const
Definition nbitset.hpp:286
Mem memory_type
Definition nbitset.hpp:21
this_type2< battery::local_memory > local_type
Definition nbitset.hpp:25
CUDA constexpr local_type median() const
Definition nbitset.hpp:482
CUDA static constexpr this_type from_set(const battery::vector< int > &values)
Definition nbitset.hpp:58
CUDA constexpr NBitset(const this_type &other)
Definition nbitset.hpp:66
typename LB::value_type value_type
Definition nbitset.hpp:29
CUDA constexpr local_type complement() const
Definition nbitset.hpp:292
CUDA constexpr local_type width() const
Definition nbitset.hpp:476
CUDA constexpr this_type & operator=(const this_type &other)
Definition nbitset.hpp:96
static constexpr const bool sequential
Definition nbitset.hpp:35
CUDA constexpr NBitset()
Definition nbitset.hpp:54
CUDA constexpr NBitset(const this_type2< M > &other)
Definition nbitset.hpp:80
CUDA static constexpr local_type fun(const this_type2< M > &x)
Definition nbitset.hpp:450
CUDA constexpr this_type & tell(const this_type2< M > &other)
Definition nbitset.hpp:323
CUDA constexpr const bitset_type & value() const
Definition nbitset.hpp:110
Definition primitive_upset.hpp:118
CUDA constexpr value_type value() const
Definition primitive_upset.hpp:219
static CUDA constexpr this_type geq_k(value_type k)
Definition primitive_upset.hpp:154
static CUDA constexpr local_type bot()
Definition primitive_upset.hpp:182
static CUDA constexpr this_type leq_k(value_type k)
Definition primitive_upset.hpp:165
typename pre_universe::value_type value_type
Definition primitive_upset.hpp:122
static CUDA constexpr local_type top()
Definition primitive_upset.hpp:185
CUDA constexpr this_type & tell_top()
Definition primitive_upset.hpp:233
#define INTERPRETATION_WARNING(MSG)
Definition diagnostics.hpp:150
#define RETURN_INTERPRETATION_WARNING(MSG)
Definition diagnostics.hpp:159
#define RETURN_INTERPRETATION_ERROR(MSG)
Definition diagnostics.hpp:155
::lala::ZDec< int, battery::local_memory > ZDec
Definition primitive_upset.hpp:82
::lala::ZInc< int, battery::local_memory > ZInc
Definition primitive_upset.hpp:81
Definition abstract_deps.hpp:14
std::ostream & operator<<(std::ostream &s, const CartesianProduct< A, As... > &cp)
Definition cartesian_product.hpp:597
battery::vector< battery::tuple< F, F >, typename F::allocator_type > logic_set
Definition sort.hpp:127
CUDA NI Sig converse_comparison(Sig sig)
Definition algorithm.hpp:377
CUDA constexpr bool operator==(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:572
CUDA NI bool is_arithmetic_comparison(const F &f)
Definition algorithm.hpp:320
@ 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
@ 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
@ IN
Set membership predicate.
Definition ast.hpp:108
@ GT
Arithmetic comparison predicates. When applied to set, it corresponds to the lexicographic ordering o...
Definition ast.hpp:113
@ LT
Unary arithmetic function symbols.
Definition ast.hpp:113
@ ABS
Unary arithmetic function symbols.
Definition ast.hpp:96
@ NEG
Unary arithmetic function symbols.
Definition ast.hpp:96
CUDA constexpr auto join(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:534
long long int logic_int
Definition sort.hpp:114
CUDA constexpr auto meet(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:541
CUDA constexpr bool operator<(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:554
CUDA NI const char * string_of_sig(Sig sig)
Definition ast.hpp:121
CUDA constexpr bool operator>(const CartesianProduct< As... > &a, const CartesianProduct< Bs... > &b)
Definition cartesian_product.hpp:566
CUDA NI thrust::optional< F > negate(const F &f)
Definition algorithm.hpp:266
CUDA Sig negate_arithmetic_comparison(Sig sig)
Definition algorithm.hpp:306
#define UNTYPED
Definition sort.hpp:21