Lattice Land Core Library
Loading...
Searching...
No Matches
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
8namespace lala {
9
10struct 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*/
25struct 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:151
#define RETURN_INTERPRETATION_ERROR(MSG)
Definition diagnostics.hpp:156
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
static constexpr const bool is_totally_ordered
Definition pre_b.hpp:33
CUDA static NI constexpr value_type fun(value_type x, value_type y)
Definition pre_b.hpp:180
static CUDA constexpr value_type bot()
Definition pre_b.hpp:125
static CUDA constexpr value_type next(value_type x)
Definition pre_b.hpp:147
static CUDA constexpr value_type join(value_type x, value_type y)
Definition pre_b.hpp:131
static constexpr const bool injective_concretization
Definition pre_b.hpp:38
static constexpr const bool preserve_join
Definition pre_b.hpp:36
static CUDA constexpr value_type fun(value_type x)
Definition pre_b.hpp:171
static constexpr const bool preserve_bot
Definition pre_b.hpp:34
bool value_type
Definition pre_b.hpp:28
static CUDA constexpr bool strict_order(value_type x, value_type y)
Definition pre_b.hpp:142
static CUDA constexpr value_type prev(value_type x)
Definition pre_b.hpp:152
static CUDA constexpr Sig sig_strict_order()
Definition pre_b.hpp:122
static CUDA constexpr value_type meet(value_type x, value_type y)
Definition pre_b.hpp:134
static CUDA bool interpret_ask(const F &f, value_type &ask, IDiagnostics &diagnostics)
Definition pre_b.hpp:70
CUDA static constexpr value_type zero()
Definition pre_b.hpp:42
CUDA static NI constexpr bool is_supported_fun(Sig sig)
Definition pre_b.hpp:154
CUDA static constexpr value_type one()
Definition pre_b.hpp:43
CUDA static NI bool interpret_type(const F &f, value_type &k, IDiagnostics &diagnostics)
Definition pre_b.hpp:94
static constexpr const bool is_natural
Definition pre_b.hpp:30
static constexpr const bool is_arithmetic
Definition pre_b.hpp:41
static constexpr const bool preserve_concrete_covers
Definition pre_b.hpp:39
static CUDA bool interpret_tell(const F &f, value_type &tell, IDiagnostics &diagnostics)
Definition pre_b.hpp:49
static CUDA constexpr value_type top()
Definition pre_b.hpp:128
PreBD dual_type
Definition pre_b.hpp:27
static constexpr const bool preserve_meet
Definition pre_b.hpp:37
static CUDA constexpr bool order(value_type x, value_type y)
Definition pre_b.hpp:138
static constexpr const bool preserve_top
Definition pre_b.hpp:35
static CUDA constexpr Sig sig_order()
Definition pre_b.hpp:119
static constexpr const char * name
Definition pre_b.hpp:40