Lattice land propagators completion library
formula.hpp
Go to the documentation of this file.
1 // Copyright 2021 Pierre Talbot
2 
3 #ifndef LALA_PC_FORMULA_HPP
4 #define LALA_PC_FORMULA_HPP
5 
6 #include "lala/universes/arith_bound.hpp"
7 
8 namespace lala {
9 namespace pc {
10 
11 template <class AD, class Allocator>
12 class Formula;
13 
14 template <class AD, class Allocator>
16 public:
17  using A = AD;
18  using U = typename A::local_universe;
19  using allocator_type = Allocator;
20 
21  using tell_type = typename A::template tell_type<allocator_type>;
22  using ask_type = typename A::template ask_type<allocator_type>;
24 
25  template <class A2, class Alloc>
26  friend class AbstractElement;
27 
28 private:
29  tell_type tellv;
30  tell_type not_tellv;
31  ask_type askv;
32  ask_type not_askv;
33 
34 public:
35  CUDA AbstractElement() {}
36 
38  tell_type&& tellv, tell_type&& not_tellv,
39  ask_type&& askv, ask_type&& not_askv)
40  : tellv(std::move(tellv)), not_tellv(std::move(not_tellv)), askv(std::move(askv)), not_askv(std::move(not_askv)) {}
41 
42  AbstractElement(this_type&& other) = default;
43  this_type& operator=(this_type&& other) = default;
44 
45  template <class A2, class Alloc2>
47  : tellv(other.tellv, alloc), not_tellv(other.not_tellv, alloc)
48  , askv(other.askv, alloc), not_askv(other.not_askv, alloc) {}
49 
50 public:
51  CUDA local::B ask(const A& a) const {
52  return a.ask(askv);
53  }
54 
55  CUDA local::B nask(const A& a) const {
56  return a.ask(not_askv);
57  }
58 
59  CUDA bool deduce(A& a) const {
60  return a.deduce(tellv);
61  }
62 
63  CUDA bool contradeduce(A& a) const {
64  return a.deduce(not_tellv);
65  }
66 
67  CUDA NI void print(const A& a) const {
68  printf("<abstract element (%d)>", a.aty());
69  }
70 
71  template <class Env, class Allocator2 = typename Env::allocator_type>
72  CUDA NI TFormula<Allocator2> deinterpret(const A& a, const Env& env, AType, Allocator2 allocator = Allocator2()) const {
73  return a.deinterpret(tellv, env, allocator);
74  }
75 
76  CUDA size_t length() const { return 1; }
77 };
78 
79 /** A Boolean variable defined on a universe of discourse supporting `0` for false and `1` for true. */
80 template<class AD, bool neg>
82 public:
83  using A = AD;
84  using U = typename A::local_universe;
85 
86  template <class A2, bool neg2>
87  friend class VariableLiteral;
88 
89 private:
90  AVar avar;
91 
92 public:
93  VariableLiteral() = default;
94  CUDA VariableLiteral(AVar avar): avar(avar) {}
95 
96  template <class A2, class Alloc>
97  CUDA VariableLiteral(const VariableLiteral<A2, neg>& other, const Alloc&): avar(other.avar) {}
98 
99 private:
100  template<bool negate>
101  CUDA local::B ask_impl(const A& a) const {
102  U tmp{};
103  a.project(avar, tmp);
104  if constexpr(negate) {
105  return tmp <= U::eq_zero();
106  }
107  else {
108  return !(tmp >= U::eq_zero());
109  }
110  }
111 
112  template <bool negate>
113  CUDA bool deduce_impl(A& a) const {
114  if constexpr(negate) {
115  return a.embed(avar, U::eq_zero());
116  }
117  else {
118  return a.embed(avar, U::eq_one());
119  }
120  }
121 
122 public:
123  /** Given a variable `x` taking a value in a universe `U` denoted by \f$ a(x) \f$.
124  * - \f$ a \vDash x \f$ holds iff \f$ \lnot (a(x) \leq [\![x = 0]\!]_U) \f$.
125  * - \f$ a \vDash \lnot{x} \f$ holds iff \f$ a(x) \geq [\![x = 0]\!]_U \f$. */
126  CUDA local::B ask(const A& a) const {
127  return ask_impl<neg>(a);
128  }
129 
130  /** Given a variable `x` taking a value in a universe `U` denoted by \f$ a(x) \f$.
131  * - \f$ a \nvDash x \f$ holds iff \f$ a(x) \geq [\![x = 0]\!]_U \f$.
132  * - \f$ a \nvDash \lnot{x} \f$ holds iff \f$ \lnot (a(x) \leq [\![x = 0]\!]_U) \f$. */
133  CUDA local::B nask(const A& a) const {
134  return ask_impl<!neg>(a);
135  }
136 
137  /** Perform:
138  * * Positive literal: \f$ x = a(x) \sqcup [\![x = 1]\!]_U \f$
139  * * Negative literal: \f$ x = a(x) \sqcup [\![x = 0]\!]_U \f$. */
140  CUDA bool deduce(A& a) const {
141  return deduce_impl<neg>(a);
142  }
143 
144  /** Perform:
145  * * Positive literal: \f$ x = a(x) \sqcup [\![x = 0]\!]_U \f$
146  * * Negative literal: \f$ x = a(x) \sqcup [\![x = 1]\!]_U \f$. */
147  CUDA bool contradeduce(A& a) const {
148  return deduce_impl<!neg>(a);
149  }
150 
151  CUDA NI void print(const A& a) const {
152  if constexpr(neg) { printf("not "); }
153  printf("(%d,%d)", avar.aty(), avar.vid());
154  }
155 
156  template <class Env, class Allocator = typename Env::allocator_type>
157  CUDA NI TFormula<Allocator> deinterpret(const A&, const Env& env, AType apc, Allocator allocator = Allocator()) const {
158  using F = TFormula<Allocator>;
159  auto f = F::make_lvar(avar.aty(), LVar<Allocator>(env.name_of(avar), allocator));
160  if constexpr(neg) {
161  f = F::make_unary(NOT, f, apc);
162  }
163  return f;
164  }
165 
166  CUDA size_t length() const { return 1; }
167 };
168 
169 template<class AD>
170 class False {
171 public:
172  using A = AD;
173  using U = typename A::local_universe;
174 
175  template <class A2>
176  friend class False;
177 
178 public:
179  False() = default;
180 
181  template <class A2, class Alloc>
182  CUDA False(const False<A2>&, const Alloc&) {}
183 
184  CUDA local::B ask(const A& a) const { return a.is_bot(); }
185  CUDA local::B nask(const A&) const { return true; }
186 
187  CUDA bool deduce(A& a) const {
188  if(!a.is_bot()) {
189  a.meet_bot();
190  return true;
191  }
192  return false;
193  }
194 
195  CUDA bool contradeduce(A&) const { return false; }
196  CUDA NI void print(const A& a) const { printf("false"); }
197 
198  template <class Env, class Allocator = typename Env::allocator_type>
199  CUDA NI TFormula<Allocator> deinterpret(const A&, const Env&, AType, Allocator allocator = Allocator()) const {
200  return TFormula<Allocator>::make_false();
201  }
202 
203  CUDA size_t length() const { return 1; }
204 };
205 
206 template<class AD>
207 class True {
208 public:
209  using A = AD;
210  using U = typename A::local_universe;
211 
212  template <class A2>
213  friend class True;
214 
215 public:
216  True() = default;
217 
218  template <class A2, class Alloc>
219  CUDA True(const True<A2>&, const Alloc&) {}
220 
221  CUDA local::B ask(const A&) const { return true; }
222  CUDA local::B nask(const A& a) const { return a.is_bot(); }
223  CUDA bool deduce(A&) const { return false; }
224  CUDA bool contradeduce(A& a) const {
225  if(!a.is_bot()) {
226  a.meet_bot();
227  return true;
228  }
229  return false;
230  }
231  CUDA void print(const A& a) const { printf("true"); }
232 
233  template <class Env, class Allocator = typename Env::allocator_type>
234  CUDA TFormula<Allocator> deinterpret(const A&, const Env&, AType, Allocator allocator = Allocator()) const {
235  return TFormula<Allocator>::make_true();
236  }
237 
238  CUDA size_t length() const { return 1; }
239 };
240 
241 template<class AD, class Allocator>
242 class Conjunction {
243 public:
244  using A = AD;
245  using U = typename A::local_universe;
246  using allocator_type = Allocator;
249  using sub_ptr = battery::unique_ptr<sub_type, allocator_type>;
250 
251  template <class A2, class Alloc2>
252  friend class Conjunction;
253 
254 private:
255  sub_ptr f;
256  sub_ptr g;
257 
258 public:
259  CUDA Conjunction(sub_ptr&& f, sub_ptr&& g): f(std::move(f)), g(std::move(g)) {}
260  CUDA Conjunction(this_type&& other): Conjunction(std::move(other.f), std::move(other.g)) {}
261 
262  template <class A2, class Alloc2>
263  CUDA Conjunction(const Conjunction<A2, Alloc2>& other, const allocator_type& alloc)
264  : f(battery::allocate_unique<sub_type>(alloc, *other.f, alloc))
265  , g(battery::allocate_unique<sub_type>(alloc, *other.g, alloc))
266  {}
267 
268  CUDA local::B ask(const A& a) const {
269  return f->ask(a) && g->ask(a);
270  }
271 
272  CUDA local::B nask(const A& a) const {
273  return f->nask(a) || g->nask(a);
274  }
275 
276  CUDA bool deduce(A& a) const {
277  bool has_changed = f->deduce(a);
278  has_changed |= g->deduce(a);
279  return has_changed;
280  }
281 
282  CUDA bool contradeduce(A& a) const {
283  if(f->ask(a)) { return g->contradeduce(a); }
284  else if(g->ask(a)) { return f->contradeduce(a); }
285  return false;
286  }
287 
288  CUDA NI void print(const A& a) const {
289  f->print(a);
290  printf(" /\\ ");
291  g->print(a);
292  }
293 
294  template <class Env, class Allocator2 = typename Env::allocator_type>
295  CUDA NI TFormula<Allocator2> deinterpret(const A& a, const Env& env, AType apc, Allocator2 allocator = Allocator2()) const {
296  auto left = f->deinterpret(a, env, apc, allocator);
297  auto right = g->deinterpret(a, env, apc, allocator);
298  if(left.is_true()) { return right; }
299  else if(right.is_true()) { return left; }
300  else if(left.is_false()) { return left; }
301  else if(right.is_false()) { return right; }
302  else {
303  return TFormula<Allocator2>::make_binary(left, AND, right, apc, allocator);
304  }
305  }
306 
307  CUDA size_t length() const { return 1 + f->length() + g->length(); }
308 };
309 
310 template<class AD, class Allocator>
311 class Disjunction {
312 public:
313  using A = AD;
314  using U = typename A::local_universe;
315  using allocator_type = Allocator;
318  using sub_ptr = battery::unique_ptr<sub_type, allocator_type>;
319 
320  template <class A2, class Alloc2>
321  friend class Disjunction;
322 
323 private:
324  sub_ptr f;
325  sub_ptr g;
326 
327 public:
328  CUDA Disjunction(sub_ptr&& f, sub_ptr&& g): f(std::move(f)), g(std::move(g)) {}
330  std::move(other.f), std::move(other.g)) {}
331 
332  template <class A2, class Alloc2>
333  CUDA Disjunction(const Disjunction<A2, Alloc2>& other, const allocator_type& alloc)
334  : f(battery::allocate_unique<sub_type>(alloc, *other.f, alloc))
335  , g(battery::allocate_unique<sub_type>(alloc, *other.g, alloc))
336  {}
337 
338  CUDA local::B ask(const A& a) const {
339  return f->ask(a) || g->ask(a);
340  }
341 
342  CUDA local::B nask(const A& a) const {
343  return f->nask(a) && g->nask(a);
344  }
345 
346  CUDA bool deduce(A& a) const {
347  if(f->nask(a)) { return g->deduce(a); }
348  else if(g->nask(a)) { return f->deduce(a); }
349  return false;
350  }
351 
352  CUDA bool contradeduce(A& a) const {
353  bool has_changed = f->contradeduce(a);
354  has_changed |= g->contradeduce(a);
355  return has_changed;
356  }
357 
358  CUDA NI void print(const A& a) const {
359  f->print(a);
360  printf(" \\/ ");
361  g->print(a);
362  }
363 
364  template <class Env, class Allocator2 = typename Env::allocator_type>
365  CUDA NI TFormula<Allocator2> deinterpret(const A& a, const Env& env, AType apc, Allocator2 allocator = Allocator2()) const {
366  auto left = f->deinterpret(a, env, apc, allocator);
367  auto right = g->deinterpret(a, env, apc, allocator);
368  if(left.is_true()) { return left; }
369  else if(right.is_true()) { return right; }
370  else if(left.is_false()) { return right; }
371  else if(right.is_false()) { return left; }
372  else {
373  return TFormula<Allocator2>::make_binary(left, OR, right, apc, allocator);
374  }
375  }
376 
377  CUDA size_t length() const { return 1 + f->length() + g->length(); }
378 };
379 
380 template<class AD, class Allocator>
382 public:
383  using A = AD;
384  using U = typename A::local_universe;
385  using allocator_type = Allocator;
388  using sub_ptr = battery::unique_ptr<sub_type, allocator_type>;
389 
390  template <class A2, class Alloc2>
391  friend class Biconditional;
392 
393 private:
394  sub_ptr f;
395  sub_ptr g;
396 
397 public:
398  CUDA Biconditional(sub_ptr&& f, sub_ptr&& g): f(std::move(f)), g(std::move(g)) {}
400  std::move(other.f), std::move(other.g)) {}
401 
402  template <class A2, class Alloc2>
403  CUDA Biconditional(const Biconditional<A2, Alloc2>& other, const allocator_type& alloc)
404  : f(battery::allocate_unique<sub_type>(alloc, *other.f, alloc))
405  , g(battery::allocate_unique<sub_type>(alloc, *other.g, alloc))
406  {}
407 
408  CUDA local::B ask(const A& a) const {
409  return
410  (f->ask(a) && g->ask(a)) ||
411  (f->nask(a) && g->nask(a));
412  }
413 
414  // note that not(f <=> g) is equivalent to (f <=> not g)
415  CUDA local::B nask(const A& a) const {
416  return
417  (f->ask(a) && g->nask(a)) ||
418  (f->nask(a) && g->ask(a));
419  }
420 
421  CUDA bool deduce(A& a) const {
422  if(f->ask(a)) { return g->deduce(a); }
423  else if(f->nask(a)) { return g->contradeduce(a); }
424  else if(g->ask(a)) { return f->deduce(a); }
425  else if(g->nask(a)) { return f->contradeduce(a); }
426  return false;
427  }
428 
429  // note that not(f <=> g) is equivalent to (f <=> not g)
430  CUDA bool contradeduce(A& a) const {
431  if(f->ask(a)) { return g->contradeduce(a); }
432  else if(f->nask(a)) { return g->deduce(a); }
433  else if(g->ask(a)) { return f->contradeduce(a); }
434  else if(g->nask(a)) { return f->deduce(a); }
435  return false;
436  }
437 
438  CUDA NI void print(const A& a) const {
439  f->print(a);
440  printf(" <=> ");
441  g->print(a);
442  }
443 
444  template <class Env, class Allocator2 = typename Env::allocator_type>
445  CUDA NI TFormula<Allocator2> deinterpret(const A& a, const Env& env, AType apc, Allocator2 allocator = Allocator2()) const {
446  return TFormula<Allocator2>::make_binary(
447  f->deinterpret(a, env, apc, allocator), EQUIV, g->deinterpret(a, env, apc, allocator), apc, allocator);
448  }
449 
450  CUDA size_t length() const { return 1 + f->length() + g->length(); }
451 };
452 
453 template<class AD, class Allocator>
454 class Implication {
455 public:
456  using A = AD;
457  using U = typename A::local_universe;
458  using allocator_type = Allocator;
461  using sub_ptr = battery::unique_ptr<sub_type, allocator_type>;
462 
463  template <class A2, class Alloc2>
464  friend class Implication;
465 
466 private:
467  sub_ptr f;
468  sub_ptr g;
469 
470 public:
471  CUDA Implication(sub_ptr&& f, sub_ptr&& g): f(std::move(f)), g(std::move(g)) {}
473  std::move(other.f), std::move(other.g)) {}
474 
475  template <class A2, class Alloc2>
476  CUDA Implication(const Implication<A2, Alloc2>& other, const allocator_type& alloc)
477  : f(battery::allocate_unique<sub_type>(alloc, *other.f, alloc))
478  , g(battery::allocate_unique<sub_type>(alloc, *other.g, alloc))
479  {}
480 
481  // note that f => g is equivalent to (not f) or g.
482  CUDA local::B ask(const A& a) const {
483  return f->nask(a) || g->ask(a);
484  }
485 
486  // note that not(f => g) is equivalent to f and (not g)
487  CUDA local::B nask(const A& a) const {
488  return f->ask(a) && g->nask(a);
489  }
490 
491  CUDA bool deduce(A& a) const {
492  if(f->ask(a)) { return g->deduce(a); }
493  else if(g->nask(a)) { return f->contradeduce(a); }
494  return false;
495  }
496 
497  CUDA bool contradeduce(A& a) const {
498  if(f->ask(a)) { return g->contradeduce(a); }
499  else if(g->nask(a)) { return f->deduce(a); }
500  return false;
501  }
502 
503  CUDA NI void print(const A& a) const {
504  f->print(a);
505  printf(" => ");
506  g->print(a);
507  }
508 
509  template <class Env, class Allocator2 = typename Env::allocator_type>
510  CUDA NI TFormula<Allocator2> deinterpret(const A& a, const Env& env, AType apc, Allocator2 allocator = Allocator2()) const {
511  return TFormula<Allocator2>::make_binary(
512  f->deinterpret(a, env, apc, allocator), IMPLY, g->deinterpret(a, env, apc, allocator), apc, allocator);
513  }
514 
515  CUDA size_t length() const { return 1 + f->length() + g->length(); }
516 };
517 
518 template<class AD, class Allocator>
520 public:
521  using A = AD;
522  using U = typename A::local_universe;
523  using allocator_type = Allocator;
526  using sub_ptr = battery::unique_ptr<sub_type, allocator_type>;
527 
528  template <class A2, class Alloc2>
529  friend class ExclusiveDisjunction;
530 
531 private:
532  sub_ptr f;
533  sub_ptr g;
534 
535 public:
536  CUDA ExclusiveDisjunction(sub_ptr&& f, sub_ptr&& g): f(std::move(f)), g(std::move(g)) {}
538  std::move(other.f), std::move(other.g)) {}
539 
540  template <class A2, class Alloc2>
542  : f(battery::allocate_unique<sub_type>(alloc, *other.f, alloc))
543  , g(battery::allocate_unique<sub_type>(alloc, *other.g, alloc))
544  {}
545 
546  CUDA local::B ask(const A& a) const {
547  return
548  (f->ask(a) && g->nask(a)) ||
549  (f->nask(a) && g->ask(a));
550  }
551 
552  CUDA local::B nask(const A& a) const {
553  return
554  (f->ask(a) && g->ask(a)) ||
555  (f->ask(a) && g->nask(a));
556  }
557 
558  CUDA bool deduce(A& a) const {
559  if(f->ask(a)) { return g->contradeduce(a); }
560  else if(f->nask(a)) { return g->deduce(a); }
561  else if(g->ask(a)) { return f->contradeduce(a); }
562  else if(g->nask(a)) { return f->deduce(a); }
563  return false;
564  }
565 
566  CUDA bool contradeduce(A& a) const {
567  if(f->ask(a)) { return g->deduce(a); }
568  else if(f->nask(a)) { return g->contradeduce(a); }
569  else if(g->ask(a)) { return f->deduce(a); }
570  else if(g->nask(a)) { return f->contradeduce(a); }
571  return false;
572  }
573 
574  CUDA NI void print(const A& a) const {
575  f->print(a);
576  printf(" xor ");
577  g->print(a);
578  }
579 
580  template <class Env, class Allocator2 = typename Env::allocator_type>
581  CUDA NI TFormula<Allocator2> deinterpret(const A& a, const Env& env, AType apc, Allocator2 allocator = Allocator2()) const {
582  return TFormula<Allocator2>::make_binary(
583  f->deinterpret(a, env, apc, allocator), XOR, g->deinterpret(a, env, apc, allocator), apc, allocator);
584  }
585 
586  CUDA size_t length() const { return 1 + f->length() + g->length(); }
587 };
588 
589 template<class AD, class Allocator, bool neg = false>
590 class Equality {
591 public:
592  using A = AD;
593  using U = typename A::local_universe;
594  using allocator_type = Allocator;
597 
598  template <class A2, class Alloc2, bool neg2>
599  friend class Equality;
600 
601 private:
602  using LB = typename U::LB::local_type;
603  using UB = typename U::UB::local_type;
604 
605  sub_type left;
606  sub_type right;
607 
608 public:
609  CUDA Equality(sub_type&& left, sub_type&& right): left(std::move(left)), right(std::move(right)) {}
610  CUDA Equality(this_type&& other): Equality(std::move(other.left), std::move(other.right)) {}
611 
612  template <class A2, class Alloc2>
613  CUDA Equality(const Equality<A2, Alloc2, neg>& other, const allocator_type& alloc):
614  left(other.left, alloc),
615  right(other.right, alloc)
616  {}
617 
618 private:
619  template <bool negate>
620  CUDA local::B ask_impl(const A& a) const {
621  U l{};
622  U r{};
623  left.project(a, l);
624  right.project(a, r);
625  if constexpr(negate) {
626  return fmeet(l, r).is_bot();
627  }
628  else {
629  return l == r && l.lb().value() == l.ub().value();
630  }
631  }
632 
633  template <bool negate>
634  CUDA bool deduce_impl(A& a) const {
635  U l{};
636  U r{};
637  bool has_changed = false;
638  if constexpr(negate) {
639  if(!right.is(sub_type::IConstant)) {
640  left.project(a, l);
641  if(l.lb().value() == l.ub().value()) {
642  if constexpr(U::complemented) {
643  return right.embed(a, l.complement());
644  }
645  else if (U::preserve_concrete_covers && U::is_arithmetic) {
646  right.project(a, r);
647  U lb{r};
648  U ub{r};
649  lb.meet_lb(LB::prev(l.lb()));
650  ub.meet_ub(UB::prev(l.ub()));
651  return right.embed(a, fjoin(lb, ub));
652  }
653  }
654  }
655  if(!left.is(sub_type::IConstant)) {
656  right.project(a, r);
657  if(r.lb().value() == r.ub().value()) {
658  if constexpr(U::complemented) {
659  return left.embed(a, r.complement());
660  }
661  else if (U::preserve_concrete_covers && U::is_arithmetic) {
662  left.project(a, l);
663  U lb{l};
664  U ub{l};
665  lb.meet_lb(LB::prev(r.lb()));
666  ub.meet_ub(UB::prev(r.ub()));
667  return left.embed(a, fjoin(lb, ub));
668  }
669  }
670  }
671  }
672  else {
673  if(!right.is(sub_type::IConstant)) {
674  left.project(a, l);
675  has_changed = right.embed(a, l);
676  }
677  if(!left.is(sub_type::IConstant)) {
678  right.project(a, r);
679  has_changed |= left.embed(a, r);
680  }
681  }
682  return has_changed;
683  }
684 
685 public:
686  CUDA local::B ask(const A& a) const {
687  return ask_impl<neg>(a);
688  }
689 
690  CUDA local::B nask(const A& a) const {
691  return ask_impl<!neg>(a);
692  }
693 
694  CUDA bool deduce(A& a) const {
695  return deduce_impl<neg>(a);
696  }
697 
698  CUDA bool contradeduce(A& a) const {
699  return deduce_impl<!neg>(a);
700  }
701 
702  CUDA NI void print(const A& a) const {
703  left.print(a);
704  if constexpr(neg) {
705  printf(" != ");
706  }
707  else {
708  printf(" == ");
709  }
710  right.print(a);
711  }
712 
713  template <class Env, class Allocator2 = typename Env::allocator_type>
714  CUDA NI TFormula<Allocator2> deinterpret(const A& a, const Env& env, AType apc, Allocator2 allocator = Allocator2()) const {
715  auto lf = left.deinterpret(a, env, apc, allocator);
716  auto rf = right.deinterpret(a, env, apc, allocator);
717  return TFormula<Allocator2>::make_binary(std::move(lf), neg ? NEQ : EQ, std::move(rf), apc, allocator);
718  }
719 
720  CUDA size_t length() const { return 1 + left.length() + right.length(); }
721 };
722 
723 template<class AD, class Allocator>
725 
726 /** Implement the constraint `t1 <= t2` or `t1 > t2` if `neg` is `true`. */
727 template<class AD, class Allocator, bool neg>
728 class Inequality {
729 public:
730  using A = AD;
731  using U = typename A::local_universe;
732  using allocator_type = Allocator;
735 
736  template <class A2, class Alloc2, bool neg2>
737  friend class Inequality;
738 
739 private:
740  using LB = typename U::LB::local_type;
741  using UB = typename U::UB::local_type;
742 
743  sub_type left;
744  sub_type right;
745 
746 public:
747  CUDA Inequality(sub_type&& left, sub_type&& right): left(std::move(left)), right(std::move(right)) {}
748  CUDA Inequality(this_type&& other): Inequality(std::move(other.left), std::move(other.right)) {}
749 
750  template <class A2, class Alloc2>
751  CUDA Inequality(const Inequality<A2, Alloc2, neg>& other, const allocator_type& alloc):
752  left(other.left, alloc),
753  right(other.right, alloc)
754  {}
755 
756 private:
757  template <bool negate>
758  CUDA local::B ask_impl(const A& a) const {
759  U l{};
760  U r{};
761  left.project(a, l);
762  right.project(a, r);
763  /** Note: we need the arithmetic order to compare both values.
764  * Using the lattice order is harder to work with due to infinities and incomparable bounds. */
765  if constexpr(negate) {
766  return l.lb().value() > r.ub().value();
767  }
768  else {
769  return l.ub().value() <= r.lb().value();
770  }
771  }
772 
773  template <bool negate>
774  CUDA bool deduce_impl(A& a) const {
775  U l{};
776  U r{};
777  bool has_changed = false;
778  // l > r
779  if constexpr(negate) {
780  if(!left.is(sub_type::IConstant)) {
781  right.project(a, r);
782  if constexpr(U::preserve_concrete_covers && U::is_arithmetic) {
783  r.meet_lb(LB::prev(r.lb()));
784  }
785  has_changed = left.embed(a, U(r.lb(), UB::top()));
786  }
787  if(!right.is(sub_type::IConstant)) {
788  left.project(a, l);
789  if constexpr(U::preserve_concrete_covers && U::is_arithmetic) {
790  l.meet_ub(UB::prev(l.ub()));
791  }
792  has_changed |= right.embed(a, U(LB::top(), l.ub()));
793  }
794  }
795  // l <= r
796  else {
797  if(!left.is(sub_type::IConstant)) {
798  right.project(a, r);
799  has_changed |= left.embed(a, U(LB::top(), r.ub()));
800  }
801  if(!right.is(sub_type::IConstant)) {
802  left.project(a, l);
803  has_changed = right.embed(a, U(l.lb(), UB::top()));
804  }
805  }
806  return has_changed;
807  }
808 
809 public:
810  CUDA local::B ask(const A& a) const {
811  return ask_impl<neg>(a);
812  }
813 
814  CUDA local::B nask(const A& a) const {
815  return ask_impl<!neg>(a);
816  }
817 
818  CUDA bool deduce(A& a) const {
819  return deduce_impl<neg>(a);
820  }
821 
822  CUDA bool contradeduce(A& a) const {
823  return deduce_impl<!neg>(a);
824  }
825 
826  CUDA NI void print(const A& a) const {
827  left.print(a);
828  if constexpr(neg) {
829  printf(" > ");
830  }
831  else {
832  printf(" <= ");
833  }
834  right.print(a);
835  }
836 
837  template <class Env, class Allocator2 = typename Env::allocator_type>
838  CUDA NI TFormula<Allocator2> deinterpret(const A& a, const Env& env, AType apc, Allocator2 allocator = Allocator2()) const {
839  auto lf = left.deinterpret(a, env, apc, allocator);
840  auto rf = right.deinterpret(a, env, apc, allocator);
841  return TFormula<Allocator2>::make_binary(std::move(lf), neg ? GT : LEQ, std::move(rf), apc, allocator);
842  }
843 
844  CUDA size_t length() const { return 1 + left.length() + right.length(); }
845 };
846 
847 template<class AD, class Allocator>
849 
850 template<class AD, class Allocator>
852 
853 /**
854  * A formula can occur in a term, e.g., `(x = 2) + (y = 2) + (z = 2) >= 2`
855  * In that case, the entailment of the formula is mapped onto a sublattice of `U` supporting initialization from `0` and `1`.
856  * A term can occur in a formula, as it is usually done.
857  * Therefore, a formula is both a formula and a term.
858  *
859  * A logical formula is turned into a term by mapping their satisfiability to and from a sublattice of `U` representing Boolean values:
860  * - Consists of four distinct values \f$\{[\![x = 0]\!]_U \sqcap [\![x = 1]\!]_U, [\![x = 0]\!]_U, [\![x = 1]\!]_U, \top_U \}\f$.
861  * - With \f$\{[\![x = 0]\!]_U \sqcap [\![x = 1]\!]_U \f$ meaning neither true or false yet (e.g., unknown), \f$\{[\![x = 0]\!]_U \f$ modelling falsity, \f$ [\![x = 1]\!]_U \f$ modelling truth, and \f$ \top_U \f$ a logical statement both true and false (i.e., one of the variable is top).
862 */
863 template <class AD, class Allocator>
864 class Formula {
865 public:
866  using A = AD;
867  using allocator_type = Allocator;
869  using U = typename A::local_universe;
871  using this_ptr = battery::unique_ptr<this_type, allocator_type>;
872 
885 
886  static constexpr size_t IPVarLit = 0;
887  static constexpr size_t INVarLit = IPVarLit + 1;
888  static constexpr size_t ITrue = INVarLit + 1;
889  static constexpr size_t IFalse = ITrue + 1;
890  static constexpr size_t ILeq = IFalse + 1;
891  static constexpr size_t IGt = ILeq + 1;
892  static constexpr size_t IEq = IGt + 1;
893  static constexpr size_t INeq = IEq + 1;
894  static constexpr size_t IConj = INeq + 1;
895  static constexpr size_t IDisj = IConj + 1;
896  static constexpr size_t IBicond = IDisj + 1;
897  static constexpr size_t IImply = IBicond + 1;
898  static constexpr size_t IXor = IImply + 1;
899  static constexpr size_t IAE = IXor + 1;
900 
901  template <class A2, class Alloc2>
902  friend class Formula;
903 
904 private:
905  using VFormula = battery::variant<
906  PVarLit,
907  NVarLit,
908  True<A>,
909  False<A>,
910  Leq,
911  Gt,
912  Eq,
913  Neq,
914  Conj,
915  Disj,
916  Bicond,
917  Imply,
918  Xor,
919  AE
920  >;
921 
922  VFormula formula;
923 
924  template <size_t I, class FormulaType, class A2, class Alloc2>
925  CUDA static VFormula create_one(const Formula<A2, Alloc2>& other, const allocator_type& allocator) {
926  return VFormula::template create<I>(FormulaType(battery::get<I>(other.formula), allocator));
927  }
928 
929  template <class A2, class Alloc2>
930  CUDA NI static VFormula create(const Formula<A2, Alloc2>& other, const allocator_type& allocator) {
931  switch(other.formula.index()) {
932  case IPVarLit: return create_one<IPVarLit, PVarLit>(other, allocator);
933  case INVarLit: return create_one<INVarLit, NVarLit>(other, allocator);
934  case ITrue: return create_one<ITrue, True<A>>(other, allocator);
935  case IFalse: return create_one<IFalse, False<A>>(other, allocator);
936  case ILeq: return create_one<ILeq, Leq>(other, allocator);
937  case IGt: return create_one<IGt, Gt>(other, allocator);
938  case IEq: return create_one<IEq, Eq>(other, allocator);
939  case INeq: return create_one<INeq, Neq>(other, allocator);
940  case IConj: return create_one<IConj, Conj>(other, allocator);
941  case IDisj: return create_one<IDisj, Disj>(other, allocator);
942  case IBicond: return create_one<IBicond, Bicond>(other, allocator);
943  case IImply: return create_one<IImply, Imply>(other, allocator);
944  case IXor: return create_one<IXor, Xor>(other, allocator);
945  case IAE: return create_one<IAE, AE>(other, allocator);
946  default:
947  printf("BUG: formula not handled.\n");
948  assert(false);
949  return VFormula::template create<IFalse>(False<A>());
950  }
951  }
952 
953  CUDA Formula(VFormula&& formula): formula(std::move(formula)) {}
954 
955  template <class F>
956  CUDA NI auto forward(F&& f) const {
957  switch(formula.index()) {
958  case IPVarLit: return f(battery::get<IPVarLit>(formula));
959  case INVarLit: return f(battery::get<INVarLit>(formula));
960  case ITrue: return f(battery::get<ITrue>(formula));
961  case IFalse: return f(battery::get<IFalse>(formula));
962  case ILeq: return f(battery::get<ILeq>(formula));
963  case IGt: return f(battery::get<IGt>(formula));
964  case IEq: return f(battery::get<IEq>(formula));
965  case INeq: return f(battery::get<INeq>(formula));
966  case IConj: return f(battery::get<IConj>(formula));
967  case IDisj: return f(battery::get<IDisj>(formula));
968  case IBicond: return f(battery::get<IBicond>(formula));
969  case IImply: return f(battery::get<IImply>(formula));
970  case IXor: return f(battery::get<IXor>(formula));
971  case IAE: return f(battery::get<IAE>(formula));
972  default:
973  printf("BUG: formula not handled.\n");
974  assert(false);
975  return f(False<A>());
976  }
977  }
978 
979  template <class F>
980  CUDA NI auto forward(F&& f) {
981  switch(formula.index()) {
982  case IPVarLit: return f(battery::get<IPVarLit>(formula));
983  case INVarLit: return f(battery::get<INVarLit>(formula));
984  case ITrue: return f(battery::get<ITrue>(formula));
985  case IFalse: return f(battery::get<IFalse>(formula));
986  case ILeq: return f(battery::get<ILeq>(formula));
987  case IGt: return f(battery::get<IGt>(formula));
988  case IEq: return f(battery::get<IEq>(formula));
989  case INeq: return f(battery::get<INeq>(formula));
990  case IConj: return f(battery::get<IConj>(formula));
991  case IDisj: return f(battery::get<IDisj>(formula));
992  case IBicond: return f(battery::get<IBicond>(formula));
993  case IImply: return f(battery::get<IImply>(formula));
994  case IXor: return f(battery::get<IXor>(formula));
995  case IAE: return f(battery::get<IAE>(formula));
996  default:
997  printf("BUG: formula not handled.\n");
998  assert(false);
999  False<A> false_{};
1000  return f(false_);
1001  }
1002  }
1003 
1004 public:
1005  Formula() = default;
1006  Formula(this_type&&) = default;
1008 
1009  template <class A2, class Alloc2>
1010  CUDA Formula(const Formula<A2, Alloc2>& other, const Allocator& allocator = Allocator())
1011  : formula(create(other, allocator))
1012  {}
1013 
1014  CUDA bool is(size_t kind) const {
1015  return formula.index() == kind;
1016  }
1017 
1018  CUDA size_t kind() const {
1019  return formula.index();
1020  }
1021 
1022  template <size_t I, class SubFormula>
1023  CUDA static this_type make(SubFormula&& sub_formula) {
1024  return Formula(VFormula::template create<I>(std::move(sub_formula)));
1025  }
1026 
1027  CUDA static this_type make_pvarlit(const AVar& avar) {
1028  return make<IPVarLit>(PVarLit(avar));
1029  }
1030 
1031  CUDA static this_type make_nvarlit(const AVar& avar) {
1032  return make<INVarLit>(NVarLit(avar));
1033  }
1034 
1035  CUDA static this_type make_true() {
1036  return make<ITrue>(True<A>{});
1037  }
1038 
1039  CUDA static this_type make_false() {
1040  return make<IFalse>(False<A>{});
1041  }
1042 
1043  CUDA static this_type make_leq(term_type&& left, term_type&& right) {
1044  return make<ILeq>(Leq(std::move(left), std::move(right)));
1045  }
1046 
1047  CUDA static this_type make_gt(term_type&& left, term_type&& right) {
1048  return make<IGt>(Gt(std::move(left), std::move(right)));
1049  }
1050 
1051  CUDA static this_type make_eq(term_type&& left, term_type&& right) {
1052  return make<IEq>(Eq(std::move(left), std::move(right)));
1053  }
1054 
1055  CUDA static this_type make_neq(term_type&& left, term_type&& right) {
1056  return make<INeq>(Neq(std::move(left), std::move(right)));
1057  }
1058 
1059  CUDA static this_type make_conj(this_ptr&& left, this_ptr&& right) {
1060  return make<IConj>(Conj(std::move(left), std::move(right)));
1061  }
1062 
1063  CUDA static this_type make_disj(this_ptr&& left, this_ptr&& right) {
1064  return make<IDisj>(Disj(std::move(left), std::move(right)));
1065  }
1066 
1067  CUDA static this_type make_bicond(this_ptr&& left, this_ptr&& right) {
1068  return make<IBicond>(Bicond(std::move(left), std::move(right)));
1069  }
1070 
1071  CUDA static this_type make_imply(this_ptr&& left, this_ptr&& right) {
1072  return make<IImply>(Imply(std::move(left), std::move(right)));
1073  }
1074 
1075  CUDA static this_type make_xor(this_ptr&& left, this_ptr&& right) {
1076  return make<IXor>(Xor(std::move(left), std::move(right)));
1077  }
1078 
1079  using tell_type = typename A::template tell_type<allocator_type>;
1080  using ask_type = typename A::template ask_type<allocator_type>;
1081 
1083  tell_type&& tellv, tell_type&& not_tellv,
1084  ask_type&& askv, ask_type&& not_askv)
1085  {
1086  return make<IAE>(AE(std::move(tellv), std::move(not_tellv), std::move(askv), std::move(not_askv)));
1087  }
1088 
1089  /** Call `deduce` iff \f$ u \leq [\![x = 1]\!]_U \f$ and `contradeduce` iff \f$ u \leq [\![x = 0]\!] \f$. */
1090  CUDA bool embed(A& a, const U& u) const {
1091  if(u <= U::eq_one()) { return deduce(a); }
1092  else if(u <= U::eq_zero()) { return contradeduce(a); }
1093  return false;
1094  }
1095 
1096  /** Maps the truth value of \f$ \varphi \f$ to the Boolean sublattice of `U` (see above). */
1097  CUDA void project(const A& a, U& r) const {
1098  if(a.is_bot()) { r.meet_bot(); }
1099  if(ask(a)) { r.meet(U::eq_one()); }
1100  if(nask(a)) { r.meet(U::eq_zero()); }
1101  r.meet(fjoin(U::eq_zero(), U::eq_one()));
1102  }
1103 
1104  CUDA void print(const A& a) const {
1105  forward([&](const auto& t) { t.print(a); });
1106  }
1107 
1108  template <class Env, class Allocator2 = typename Env::allocator_type>
1109  CUDA TFormula<Allocator2> deinterpret(const A& a, const Env& env, AType apc, Allocator2 allocator = Allocator2()) const {
1110  return forward([&](const auto& t) { return t.deinterpret(a, env, apc, allocator); });
1111  }
1112 
1113  /** Given a formula \f$ \varphi \f$, the ask operation \f$ a \vDash \varphi \f$ holds whenever we can deduce \f$ \varphi \f$ from \f$ a \f$.
1114  More precisely, if \f$ \gamma(a) \subseteq [\![\varphi]\!]^\flat \f$, which implies that \f$ \varphi \f$ cannot remove further deduce \f$ a \f$ since \f$ a \f$ is already more precise than \f$ \varphi \f$. */
1115  CUDA local::B ask(const A& a) const {
1116  return forward([&](const auto& t) { return t.ask(a); });
1117  }
1118 
1119  /** Similar to `ask` but for \f$ \lnot{\varphi} \f$. */
1120  CUDA local::B nask(const A& a) const {
1121  return forward([&](const auto& t) { return t.nask(a); });
1122  }
1123 
1124  /** Refine the formula by supposing it must be true. */
1125  CUDA bool deduce(A& a) const {
1126  return forward([&](const auto& t) { return t.deduce(a); });
1127  }
1128 
1129  /** Refine the negation of the formula, hence we suppose the original formula needs to be false. */
1130  CUDA bool contradeduce(A& a) const {
1131  return forward([&](const auto& t) { return t.contradeduce(a); });
1132  }
1133 
1134  CUDA size_t length() const {
1135  return forward([](const auto& t) { return t.length(); });
1136  }
1137 };
1138 
1139 } // namespace pc
1140 } // namespace lala
1141 
1142 #endif
Definition: formula.hpp:15
CUDA AbstractElement()
Definition: formula.hpp:35
typename A::local_universe U
Definition: formula.hpp:18
CUDA local::B nask(const A &a) const
Definition: formula.hpp:55
CUDA bool deduce(A &a) const
Definition: formula.hpp:59
CUDA NI void print(const A &a) const
Definition: formula.hpp:67
this_type & operator=(this_type &&other)=default
Allocator allocator_type
Definition: formula.hpp:19
AbstractElement(this_type &&other)=default
AD A
Definition: formula.hpp:17
CUDA AbstractElement(const AbstractElement< A2, Alloc2 > &other, const allocator_type &alloc)
Definition: formula.hpp:46
typename A::template tell_type< allocator_type > tell_type
Definition: formula.hpp:21
CUDA bool contradeduce(A &a) const
Definition: formula.hpp:63
typename A::template ask_type< allocator_type > ask_type
Definition: formula.hpp:22
CUDA local::B ask(const A &a) const
Definition: formula.hpp:51
CUDA AbstractElement(tell_type &&tellv, tell_type &&not_tellv, ask_type &&askv, ask_type &&not_askv)
Definition: formula.hpp:37
CUDA size_t length() const
Definition: formula.hpp:76
CUDA NI TFormula< Allocator2 > deinterpret(const A &a, const Env &env, AType, Allocator2 allocator=Allocator2()) const
Definition: formula.hpp:72
Definition: formula.hpp:381
Allocator allocator_type
Definition: formula.hpp:385
CUDA local::B ask(const A &a) const
Definition: formula.hpp:408
CUDA Biconditional(const Biconditional< A2, Alloc2 > &other, const allocator_type &alloc)
Definition: formula.hpp:403
CUDA NI void print(const A &a) const
Definition: formula.hpp:438
AD A
Definition: formula.hpp:383
CUDA NI TFormula< Allocator2 > deinterpret(const A &a, const Env &env, AType apc, Allocator2 allocator=Allocator2()) const
Definition: formula.hpp:445
CUDA size_t length() const
Definition: formula.hpp:450
typename A::local_universe U
Definition: formula.hpp:384
battery::unique_ptr< sub_type, allocator_type > sub_ptr
Definition: formula.hpp:388
CUDA Biconditional(sub_ptr &&f, sub_ptr &&g)
Definition: formula.hpp:398
CUDA Biconditional(this_type &&other)
Definition: formula.hpp:399
CUDA bool contradeduce(A &a) const
Definition: formula.hpp:430
CUDA local::B nask(const A &a) const
Definition: formula.hpp:415
CUDA bool deduce(A &a) const
Definition: formula.hpp:421
Definition: formula.hpp:242
battery::unique_ptr< sub_type, allocator_type > sub_ptr
Definition: formula.hpp:249
CUDA Conjunction(const Conjunction< A2, Alloc2 > &other, const allocator_type &alloc)
Definition: formula.hpp:263
CUDA NI TFormula< Allocator2 > deinterpret(const A &a, const Env &env, AType apc, Allocator2 allocator=Allocator2()) const
Definition: formula.hpp:295
CUDA bool contradeduce(A &a) const
Definition: formula.hpp:282
typename A::local_universe U
Definition: formula.hpp:245
Allocator allocator_type
Definition: formula.hpp:246
CUDA local::B ask(const A &a) const
Definition: formula.hpp:268
CUDA size_t length() const
Definition: formula.hpp:307
CUDA Conjunction(this_type &&other)
Definition: formula.hpp:260
CUDA Conjunction(sub_ptr &&f, sub_ptr &&g)
Definition: formula.hpp:259
CUDA NI void print(const A &a) const
Definition: formula.hpp:288
CUDA local::B nask(const A &a) const
Definition: formula.hpp:272
CUDA bool deduce(A &a) const
Definition: formula.hpp:276
AD A
Definition: formula.hpp:244
Definition: formula.hpp:311
CUDA NI TFormula< Allocator2 > deinterpret(const A &a, const Env &env, AType apc, Allocator2 allocator=Allocator2()) const
Definition: formula.hpp:365
CUDA bool contradeduce(A &a) const
Definition: formula.hpp:352
CUDA Disjunction(const Disjunction< A2, Alloc2 > &other, const allocator_type &alloc)
Definition: formula.hpp:333
typename A::local_universe U
Definition: formula.hpp:314
CUDA Disjunction(sub_ptr &&f, sub_ptr &&g)
Definition: formula.hpp:328
CUDA bool deduce(A &a) const
Definition: formula.hpp:346
CUDA Disjunction(this_type &&other)
Definition: formula.hpp:329
CUDA local::B ask(const A &a) const
Definition: formula.hpp:338
CUDA NI void print(const A &a) const
Definition: formula.hpp:358
battery::unique_ptr< sub_type, allocator_type > sub_ptr
Definition: formula.hpp:318
CUDA size_t length() const
Definition: formula.hpp:377
Allocator allocator_type
Definition: formula.hpp:315
AD A
Definition: formula.hpp:313
CUDA local::B nask(const A &a) const
Definition: formula.hpp:342
Definition: formula.hpp:590
CUDA bool deduce(A &a) const
Definition: formula.hpp:694
CUDA Equality(this_type &&other)
Definition: formula.hpp:610
CUDA size_t length() const
Definition: formula.hpp:720
CUDA NI void print(const A &a) const
Definition: formula.hpp:702
CUDA Equality(sub_type &&left, sub_type &&right)
Definition: formula.hpp:609
CUDA local::B nask(const A &a) const
Definition: formula.hpp:690
CUDA Equality(const Equality< A2, Alloc2, neg > &other, const allocator_type &alloc)
Definition: formula.hpp:613
CUDA local::B ask(const A &a) const
Definition: formula.hpp:686
AD A
Definition: formula.hpp:592
CUDA bool contradeduce(A &a) const
Definition: formula.hpp:698
CUDA NI TFormula< Allocator2 > deinterpret(const A &a, const Env &env, AType apc, Allocator2 allocator=Allocator2()) const
Definition: formula.hpp:714
Allocator allocator_type
Definition: formula.hpp:594
typename A::local_universe U
Definition: formula.hpp:593
Definition: formula.hpp:519
CUDA ExclusiveDisjunction(this_type &&other)
Definition: formula.hpp:537
CUDA ExclusiveDisjunction(sub_ptr &&f, sub_ptr &&g)
Definition: formula.hpp:536
CUDA local::B nask(const A &a) const
Definition: formula.hpp:552
CUDA ExclusiveDisjunction(const ExclusiveDisjunction< A2, Alloc2 > &other, const allocator_type &alloc)
Definition: formula.hpp:541
CUDA bool deduce(A &a) const
Definition: formula.hpp:558
typename A::local_universe U
Definition: formula.hpp:522
CUDA local::B ask(const A &a) const
Definition: formula.hpp:546
CUDA NI void print(const A &a) const
Definition: formula.hpp:574
CUDA NI TFormula< Allocator2 > deinterpret(const A &a, const Env &env, AType apc, Allocator2 allocator=Allocator2()) const
Definition: formula.hpp:581
battery::unique_ptr< sub_type, allocator_type > sub_ptr
Definition: formula.hpp:526
CUDA bool contradeduce(A &a) const
Definition: formula.hpp:566
Allocator allocator_type
Definition: formula.hpp:523
AD A
Definition: formula.hpp:521
CUDA size_t length() const
Definition: formula.hpp:586
Definition: formula.hpp:170
AD A
Definition: formula.hpp:172
CUDA NI TFormula< Allocator > deinterpret(const A &, const Env &, AType, Allocator allocator=Allocator()) const
Definition: formula.hpp:199
CUDA bool deduce(A &a) const
Definition: formula.hpp:187
CUDA local::B ask(const A &a) const
Definition: formula.hpp:184
CUDA NI void print(const A &a) const
Definition: formula.hpp:196
False()=default
CUDA False(const False< A2 > &, const Alloc &)
Definition: formula.hpp:182
CUDA bool contradeduce(A &) const
Definition: formula.hpp:195
typename A::local_universe U
Definition: formula.hpp:173
CUDA size_t length() const
Definition: formula.hpp:203
CUDA local::B nask(const A &) const
Definition: formula.hpp:185
Definition: formula.hpp:864
CUDA local::B ask(const A &a) const
Definition: formula.hpp:1115
Formula(this_type &&)=default
static constexpr size_t IGt
Definition: formula.hpp:891
static CUDA this_type make_true()
Definition: formula.hpp:1035
Implication< A, allocator_type > Imply
Definition: formula.hpp:882
Disjunction< A, allocator_type > Disj
Definition: formula.hpp:880
ExclusiveDisjunction< A, allocator_type > Xor
Definition: formula.hpp:883
this_type & operator=(this_type &&)=default
typename A::template tell_type< allocator_type > tell_type
Definition: formula.hpp:1079
static constexpr size_t IFalse
Definition: formula.hpp:889
static constexpr size_t INVarLit
Definition: formula.hpp:887
static constexpr size_t IDisj
Definition: formula.hpp:895
static constexpr size_t IAE
Definition: formula.hpp:899
static constexpr size_t IXor
Definition: formula.hpp:898
static CUDA this_type make_imply(this_ptr &&left, this_ptr &&right)
Definition: formula.hpp:1071
friend class Formula
Definition: formula.hpp:902
VariableLiteral< A, true > NVarLit
Definition: formula.hpp:874
static constexpr size_t IPVarLit
Definition: formula.hpp:886
static constexpr size_t INeq
Definition: formula.hpp:893
static CUDA this_type make_nvarlit(const AVar &avar)
Definition: formula.hpp:1031
static CUDA this_type make_false()
Definition: formula.hpp:1039
CUDA bool is(size_t kind) const
Definition: formula.hpp:1014
static CUDA this_type make_leq(term_type &&left, term_type &&right)
Definition: formula.hpp:1043
static CUDA this_type make_xor(this_ptr &&left, this_ptr &&right)
Definition: formula.hpp:1075
static constexpr size_t ILeq
Definition: formula.hpp:890
static CUDA this_type make_neq(term_type &&left, term_type &&right)
Definition: formula.hpp:1055
InequalityLEQ< A, allocator_type > Leq
Definition: formula.hpp:875
static CUDA this_type make_eq(term_type &&left, term_type &&right)
Definition: formula.hpp:1051
Allocator allocator_type
Definition: formula.hpp:867
battery::unique_ptr< this_type, allocator_type > this_ptr
Definition: formula.hpp:871
InequalityGT< A, allocator_type > Gt
Definition: formula.hpp:876
CUDA size_t kind() const
Definition: formula.hpp:1018
Equality< A, allocator_type > Eq
Definition: formula.hpp:877
CUDA void print(const A &a) const
Definition: formula.hpp:1104
CUDA bool embed(A &a, const U &u) const
Definition: formula.hpp:1090
static CUDA this_type make_abstract_element(tell_type &&tellv, tell_type &&not_tellv, ask_type &&askv, ask_type &&not_askv)
Definition: formula.hpp:1082
typename A::template ask_type< allocator_type > ask_type
Definition: formula.hpp:1080
CUDA local::B nask(const A &a) const
Definition: formula.hpp:1120
CUDA Formula(const Formula< A2, Alloc2 > &other, const Allocator &allocator=Allocator())
Definition: formula.hpp:1010
Conjunction< A, allocator_type > Conj
Definition: formula.hpp:879
static constexpr size_t IImply
Definition: formula.hpp:897
CUDA bool contradeduce(A &a) const
Definition: formula.hpp:1130
static CUDA this_type make(SubFormula &&sub_formula)
Definition: formula.hpp:1023
static constexpr size_t ITrue
Definition: formula.hpp:888
VariableLiteral< A, false > PVarLit
Definition: formula.hpp:873
AD A
Definition: formula.hpp:866
AbstractElement< A, allocator_type > AE
Definition: formula.hpp:884
static CUDA this_type make_conj(this_ptr &&left, this_ptr &&right)
Definition: formula.hpp:1059
CUDA bool deduce(A &a) const
Definition: formula.hpp:1125
CUDA TFormula< Allocator2 > deinterpret(const A &a, const Env &env, AType apc, Allocator2 allocator=Allocator2()) const
Definition: formula.hpp:1109
static CUDA this_type make_pvarlit(const AVar &avar)
Definition: formula.hpp:1027
static constexpr size_t IEq
Definition: formula.hpp:892
static CUDA this_type make_disj(this_ptr &&left, this_ptr &&right)
Definition: formula.hpp:1063
static constexpr size_t IBicond
Definition: formula.hpp:896
Biconditional< A, allocator_type > Bicond
Definition: formula.hpp:881
static CUDA this_type make_gt(term_type &&left, term_type &&right)
Definition: formula.hpp:1047
CUDA void project(const A &a, U &r) const
Definition: formula.hpp:1097
static CUDA this_type make_bicond(this_ptr &&left, this_ptr &&right)
Definition: formula.hpp:1067
typename A::local_universe U
Definition: formula.hpp:869
Disequality< A, allocator_type > Neq
Definition: formula.hpp:878
static constexpr size_t IConj
Definition: formula.hpp:894
CUDA size_t length() const
Definition: formula.hpp:1134
Definition: formula.hpp:454
CUDA bool deduce(A &a) const
Definition: formula.hpp:491
CUDA Implication(const Implication< A2, Alloc2 > &other, const allocator_type &alloc)
Definition: formula.hpp:476
CUDA bool contradeduce(A &a) const
Definition: formula.hpp:497
CUDA Implication(sub_ptr &&f, sub_ptr &&g)
Definition: formula.hpp:471
CUDA Implication(this_type &&other)
Definition: formula.hpp:472
Allocator allocator_type
Definition: formula.hpp:458
CUDA NI void print(const A &a) const
Definition: formula.hpp:503
CUDA size_t length() const
Definition: formula.hpp:515
typename A::local_universe U
Definition: formula.hpp:457
CUDA local::B nask(const A &a) const
Definition: formula.hpp:487
CUDA local::B ask(const A &a) const
Definition: formula.hpp:482
battery::unique_ptr< sub_type, allocator_type > sub_ptr
Definition: formula.hpp:461
CUDA NI TFormula< Allocator2 > deinterpret(const A &a, const Env &env, AType apc, Allocator2 allocator=Allocator2()) const
Definition: formula.hpp:510
AD A
Definition: formula.hpp:456
Definition: formula.hpp:728
typename A::local_universe U
Definition: formula.hpp:731
CUDA bool deduce(A &a) const
Definition: formula.hpp:818
CUDA Inequality(const Inequality< A2, Alloc2, neg > &other, const allocator_type &alloc)
Definition: formula.hpp:751
CUDA bool contradeduce(A &a) const
Definition: formula.hpp:822
CUDA Inequality(sub_type &&left, sub_type &&right)
Definition: formula.hpp:747
CUDA local::B nask(const A &a) const
Definition: formula.hpp:814
CUDA NI void print(const A &a) const
Definition: formula.hpp:826
Allocator allocator_type
Definition: formula.hpp:732
CUDA Inequality(this_type &&other)
Definition: formula.hpp:748
AD A
Definition: formula.hpp:730
CUDA local::B ask(const A &a) const
Definition: formula.hpp:810
CUDA NI TFormula< Allocator2 > deinterpret(const A &a, const Env &env, AType apc, Allocator2 allocator=Allocator2()) const
Definition: formula.hpp:838
CUDA size_t length() const
Definition: formula.hpp:844
CUDA void print(const A &a) const
Definition: terms.hpp:727
CUDA bool embed(A &a, const U &u) const
Definition: terms.hpp:719
CUDA TFormula< Allocator2 > deinterpret(const A &a, const Env &env, AType apc, Allocator2 allocator=Allocator2()) const
Definition: terms.hpp:732
CUDA void project(const A &a, U &r) const
Definition: terms.hpp:723
CUDA bool is(size_t kind) const
Definition: terms.hpp:646
CUDA size_t length() const
Definition: terms.hpp:736
static constexpr size_t IConstant
Definition: terms.hpp:534
Definition: formula.hpp:207
CUDA True(const True< A2 > &, const Alloc &)
Definition: formula.hpp:219
CUDA size_t length() const
Definition: formula.hpp:238
CUDA void print(const A &a) const
Definition: formula.hpp:231
CUDA local::B ask(const A &) const
Definition: formula.hpp:221
CUDA local::B nask(const A &a) const
Definition: formula.hpp:222
AD A
Definition: formula.hpp:209
CUDA bool deduce(A &) const
Definition: formula.hpp:223
True()=default
CUDA bool contradeduce(A &a) const
Definition: formula.hpp:224
typename A::local_universe U
Definition: formula.hpp:210
CUDA TFormula< Allocator > deinterpret(const A &, const Env &, AType, Allocator allocator=Allocator()) const
Definition: formula.hpp:234
Definition: formula.hpp:81
AD A
Definition: formula.hpp:83
CUDA VariableLiteral(AVar avar)
Definition: formula.hpp:94
CUDA NI TFormula< Allocator > deinterpret(const A &, const Env &env, AType apc, Allocator allocator=Allocator()) const
Definition: formula.hpp:157
CUDA bool contradeduce(A &a) const
Definition: formula.hpp:147
CUDA NI void print(const A &a) const
Definition: formula.hpp:151
typename A::local_universe U
Definition: formula.hpp:84
CUDA VariableLiteral(const VariableLiteral< A2, neg > &other, const Alloc &)
Definition: formula.hpp:97
CUDA local::B ask(const A &a) const
Definition: formula.hpp:126
CUDA size_t length() const
Definition: formula.hpp:166
CUDA bool deduce(A &a) const
Definition: formula.hpp:140
CUDA local::B nask(const A &a) const
Definition: formula.hpp:133
Definition: formula.hpp:8