Lattice Land Core Library
pre_b.hpp
Go to the documentation of this file.
1 // Copyright 2022 Pierre Talbot
2 
3 #ifndef LALA_CORE_PRE_B_HPP
4 #define LALA_CORE_PRE_B_HPP
5 
6 #include "../logic/logic.hpp"
7 
8 namespace lala {
9 
10 struct PreBD;
11 
12 /** `PreB` is a domain abstracting the Boolean universe of discourse \f$ \mathbb{B}=\{true,false\} \f$.
13  We overload the symbols \f$ \mathit{true} \f$ and \f$ \mathit{false} \f$ to be used in both `PreB` and the concrete domain (\f$ \bot, \top \f$ can be used to specifically refer to PreB elements).
14  We have \f$ PreB \triangleq \langle \{\mathit{false}, \mathit{true}\}, \implies, \land, \lor, \mathit{false}, \mathit{true} \rangle \f$ with the usual logical connectors (in particular, \f$ \mathit{false} \implies \mathit{true} \f$, \f$ \bot = \mathit{false} \f$ and \f$ \top = \mathit{true} \f$).
15 
16  We have a Galois connection between the concrete domain of values \f$ \mathcal{P}(\mathbb{B}) \f$ and PreB:
17  * Concretization: \f$ \gamma(b) \triangleq b = \top ? \{\mathit{true}, \mathit{false}\} : \{\mathit{false}\} \f$.
18  * Abstraction: \f$ \alpha(S) \triangleq \mathit{true} \in S ? \top : \bot \f$.
19 
20  Beware that, as suggested by the concretization function, \f$ \top \f$ represents both the true and false values in the concrete domain, and should be interpreted as "I don't know yet the value".
21 
22  Further, note that this lattice is unable to represent exactly Dunn/Belnap logic which requires four states (which is necessary when working in the abstract): unknown, true, false and failed.
23  To obtain Dunn/Belnap logic with a knowledge ordering, you can use `Interval<Bound<PreB>>`.
24 */
25 struct PreB {
26  using this_type = PreB;
27  using dual_type = PreBD;
28  using value_type = bool;
29 
30  constexpr static const bool is_natural = true; /** We consider \f$ \top = \mathit{true} \f$ is the natural order on Boolean. */
32 
33  constexpr static const bool is_totally_ordered = true;
34  constexpr static const bool preserve_bot = false; /** \f$ \gamma(\mathit{false}) = \{\mathit{false}\} \f$, therefore the empty set cannot be represented in this domain. */
35  constexpr static const bool preserve_top = true; /** \f$ \gamma(\mathit{unknown}) = \{false, true\} \f$ */
36  constexpr static const bool preserve_join = true; /** \f$ \gamma(x \sqcup y) = \gamma(x) \cup \gamma(y) \f$ */
37  constexpr static const bool preserve_meet = true; /** \f$ \gamma(x \sqcap y) = \gamma(x) \cap \gamma(y) \f$ */
38  constexpr static const bool injective_concretization = true; /** Each element of PreB maps to a different concrete value. */
39  constexpr static const bool preserve_concrete_covers = true; /** \f$ x \lessdot y \Leftrightarrow \gamma(x) \lessdot \gamma(y) \f$ */
40  constexpr static const char* name = "B";
41  constexpr static const bool is_arithmetic = true;
42  CUDA constexpr static value_type zero() { return false; }
43  CUDA constexpr static value_type one() { return true; }
44 
45  /** @sequential
46  * Interpret a formula into the PreB lattice.
47  * \return `true` if an overapproximation of a Boolean constant `b` could be placed in `tell`. Otherwise it returns `false` with a diagnostic. */
48  template<bool diagnose, class F, bool dualize=false>
49  CUDA static bool interpret_tell(const F& f, value_type& tell, IDiagnostics& diagnostics) {
50  if(f.is(F::B)) {
51  if(f.b() == dualize) {
52  if constexpr(dualize) {
53  INTERPRETATION_WARNING("Overapproximating the constant `false` by the top element (which concretization gives {true, false}) in the `PreBD` domain.");
54  }
55  else {
56  INTERPRETATION_WARNING("Overapproximating the constant `true` by the top element (which concretization gives {true, false}) in the `PreB` domain.");
57  }
58  }
59  tell = f.b();
60  return true;
61  }
62  RETURN_INTERPRETATION_ERROR("Only constant of types `Bool` can be interpreted in a Boolean domain.");
63  }
64 
65  /** @sequential
66  * We can only ask if an element of this lattice is `false`, because it cannot exactly represent `true`.
67  * This operation can be dualized.
68  */
69  template<bool diagnose, class F, bool dualize=false>
70  CUDA static bool interpret_ask(const F& f, value_type& ask, IDiagnostics& diagnostics) {
71  if(f.is(F::B)) {
72  if(f.b() == dualize) { /** In the dual, we can only ask for `true` elements. */
73  tell = f.b();
74  return true;
75  }
76  else {
77  if constexpr(dualize) {
78  RETURN_INTERPRETATION_ERROR("This Boolean domain can only represent two values: `true` or 'false'.");
79  }
80  else {
81  RETURN_INTERPRETATION_ERROR("This Boolean domain can only represent two values: `false` or 'I don't know'.");
82  }
83  }
84  }
85  RETURN_INTERPRETATION_ERROR("Only constant of types `Bool` can be interpreted in Boolean domains.");
86  }
87 
88  /** @sequential
89  * Verify if the type of a variable, introduced by an existential quantifier, is compatible with the current abstract universe.
90  * \return `bot()` if the type of the existentially quantified variable is `Bool`. Otherwise it returns an explanation of the error.
91  * This operation can be dualized.
92  */
93  template<bool diagnose, class F, bool dualize = false>
94  CUDA NI static bool interpret_type(const F& f, value_type& k, IDiagnostics& diagnostics) {
95  assert(f.is(F::E));
96  const auto& cty = battery::get<1>(f.exists());
97  if(cty.is_bool()) {
98  k = dualize ? top() : bot();
99  return true;
100  }
101  else {
102  const auto& vname = battery::get<0>(f.exists());
103  RETURN_INTERPRETATION_ERROR("The type of `" + vname + "` can only be `Bool` when interpreted in Boolean domains.");
104  }
105  }
106 
107  /** @parallel
108  * Given a Boolean value, create a logical constant representing that value.
109  * Note that the lattice order has no influence here.
110  */
111  // template<class F>
112  // CUDA static F deinterpret(const value_type& v) {
113  // return F::make_bool(v);
114  // }
115 
116  /** The logical predicate symbol corresponding to the order of this pre-universe.
117  We have \f$ a \leq_\mathit{BInc} b \Leftrightarrow a \leq b \f$.
118  \return The logical symbol `LEQ`. */
119  CUDA static constexpr Sig sig_order() { return LEQ; }
120 
121  /** Converse nonimplication: we have a < b only when `a` is `false` and `b` is `true`. */
122  CUDA static constexpr Sig sig_strict_order() { return LT; }
123 
124  /** \f$ \bot \f$ is represented by `false`. */
125  CUDA static constexpr value_type bot() { return false; }
126 
127  /** \f$ \top \f$ is represented by `true`. */
128  CUDA static constexpr value_type top() { return true; }
129 
130  /** \return \f$ x \sqcup y \f$ defined as \f$ x \lor y \f$. */
131  CUDA static constexpr value_type join(value_type x, value_type y) { return x || y; }
132 
133  /** \return \f$ x \sqcap y \f$ defined as \f$ x \land y \f$. */
134  CUDA static constexpr value_type meet(value_type x, value_type y) { return x && y; }
135 
136  /** \return \f$ \mathit{true} \f$ if \f$ x \leq_\mathit{BInc} y \f$ where the order \f$ \mathit{false} \leq_\mathit{BInc} \mathit{true} \f$, otherwise returns \f$ \mathit{false} \f$.
137  Note that the order is the Boolean implication, \f$ x \leq y \Rightleftarrow x \Rightarrow y \f$. */
138  CUDA static constexpr bool order(value_type x, value_type y) { return !x || y; }
139 
140 /** \return \f$ \mathit{true} \f$ if \f$ x \leq_\mathit{BInc} y \f$ where the order \f$ \mathit{false} \leq_\mathit{BInc} \mathit{true} \f$, otherwise returns \f$ \mathit{false} \f$.
141  Note that the strict order is the Boolean converse nonimplication, \f$ x \leq y \Rightleftarrow x \not\Leftarrow y \f$. */
142  CUDA static constexpr bool strict_order(value_type x, value_type y) { return !x && y; }
143 
144  /** From a lattice perspective, this function returns an element \f$ y \f$ such that \f$ y \f$ is a cover of \f$ x \f$.
145 
146  \return `true`. */
147  CUDA static constexpr value_type next(value_type x) { return true; }
148 
149  /** From a lattice perspective, this function returns an element \f$ y \f$ such that \f$ x \f$ is a cover of \f$ y \f$.
150 
151  \return `false`. */
152  CUDA static constexpr value_type prev(value_type x) { return false; }
153 
154  CUDA NI static constexpr bool is_supported_fun(Sig sig) {
155  switch(sig) {
156  case AND:
157  case OR:
158  case IMPLY:
159  case EQUIV:
160  case XOR:
161  case NOT:
162  case EQ:
163  case NEQ:
164  return true;
165  default:
166  return false;
167  }
168  }
169 
170  template<Sig sig>
171  CUDA static constexpr value_type fun(value_type x) {
172  static_assert(sig == NOT, "Unsupported unary function.");
173  switch(sig) {
174  case NOT: return !x;
175  default: assert(0); return x;
176  }
177  }
178 
179  template<Sig sig>
180  CUDA NI static constexpr value_type fun(value_type x, value_type y) {
181  static_assert(sig == AND || sig == OR || sig == IMPLY || sig == EQUIV || sig == XOR,
182  "Unsupported binary function.");
183  switch(sig) {
184  case AND: return x && y;
185  case OR: return x || y;
186  case IMPLY: return !x || y;
187  case EQUIV:
188  case EQ: return x == y;
189  case XOR:
190  case NEQ: return x != y;
191  default: assert(0); return x;
192  }
193  }
194 };
195 
196 } // namespace lala
197 
198 #endif
Definition: diagnostics.hpp:19
#define INTERPRETATION_WARNING(MSG)
Definition: diagnostics.hpp:150
#define RETURN_INTERPRETATION_ERROR(MSG)
Definition: diagnostics.hpp:155
::lala::B<::battery::local_memory > B
Definition: b.hpp:12
Definition: abstract_deps.hpp:14
Sig
Definition: ast.hpp:94
@ XOR
Logical connector.
Definition: ast.hpp:114
@ 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
@ OR
Unary arithmetic function symbols.
Definition: ast.hpp:114
@ EQ
Unary arithmetic function symbols.
Definition: ast.hpp:112
@ LT
Unary arithmetic function symbols.
Definition: ast.hpp:113
@ AND
Unary arithmetic function symbols.
Definition: ast.hpp:114
@ EQUIV
Unary arithmetic function symbols.
Definition: ast.hpp:114
Definition: pre_b.hpp:25
CUDA static constexpr NI bool is_supported_fun(Sig sig)
Definition: pre_b.hpp:154
constexpr static CUDA value_type one()
Definition: pre_b.hpp:43
constexpr static const bool is_totally_ordered
Definition: pre_b.hpp:33
constexpr static const char * name
Definition: pre_b.hpp:40
constexpr static const bool injective_concretization
Definition: pre_b.hpp:38
static constexpr CUDA bool strict_order(value_type x, value_type y)
Definition: pre_b.hpp:142
bool value_type
Definition: pre_b.hpp:28
constexpr static const bool preserve_bot
Definition: pre_b.hpp:34
static constexpr CUDA value_type top()
Definition: pre_b.hpp:128
constexpr static const bool preserve_join
Definition: pre_b.hpp:36
static constexpr CUDA value_type prev(value_type x)
Definition: pre_b.hpp:152
constexpr static const bool preserve_concrete_covers
Definition: pre_b.hpp:39
CUDA static constexpr NI value_type fun(value_type x, value_type y)
Definition: pre_b.hpp:180
constexpr static const bool preserve_meet
Definition: pre_b.hpp:37
static CUDA bool interpret_ask(const F &f, value_type &ask, IDiagnostics &diagnostics)
Definition: pre_b.hpp:70
constexpr static const bool preserve_top
Definition: pre_b.hpp:35
constexpr static const bool is_arithmetic
Definition: pre_b.hpp:41
static constexpr CUDA value_type meet(value_type x, value_type y)
Definition: pre_b.hpp:134
CUDA static NI bool interpret_type(const F &f, value_type &k, IDiagnostics &diagnostics)
Definition: pre_b.hpp:94
static CUDA bool interpret_tell(const F &f, value_type &tell, IDiagnostics &diagnostics)
Definition: pre_b.hpp:49
static constexpr CUDA Sig sig_order()
Definition: pre_b.hpp:119
PreBD dual_type
Definition: pre_b.hpp:27
static constexpr CUDA value_type join(value_type x, value_type y)
Definition: pre_b.hpp:131
constexpr static const bool is_natural
Definition: pre_b.hpp:30
static constexpr CUDA Sig sig_strict_order()
Definition: pre_b.hpp:122
static constexpr CUDA value_type fun(value_type x)
Definition: pre_b.hpp:171
static constexpr CUDA value_type bot()
Definition: pre_b.hpp:125
static constexpr CUDA bool order(value_type x, value_type y)
Definition: pre_b.hpp:138
static constexpr CUDA value_type next(value_type x)
Definition: pre_b.hpp:147
constexpr static CUDA value_type zero()
Definition: pre_b.hpp:42