Lattice Land Core Library
Loading...
Searching...
No Matches
pre_fub.hpp
Go to the documentation of this file.
1// Copyright 2022 Pierre Talbot
2
3#ifndef LALA_CORE_PRE_FUB_HPP
4#define LALA_CORE_PRE_FUB_HPP
5
6#include "../logic/logic.hpp"
7
8namespace lala {
9
10template <class VT>
11struct PreFLB;
12
13/** `PreFUB` is a pre-abstract universe \f$ \langle \mathbb{F}\setminus\{NaN\}, \leq \rangle \f$ totally ordered by the floating-point arithmetic comparison operator.
14 We work on a subset of floating-point numbers without NaN.
15 It is used to represent (and possibly approximate) constraints of the form \f$ x \leq k \f$ where \f$ k \f$ is a real number.
16*/
17template<class VT>
18struct PreFUB {
21 using value_type = VT;
24
25 constexpr static const bool is_totally_ordered = true;
26 constexpr static const bool preserve_bot = true;
27 constexpr static const bool preserve_top = true;
28 constexpr static const bool preserve_join = true;
29 constexpr static const bool preserve_meet = true;
30 /** Note that -0 and +0 are treated as the same element. */
31 constexpr static const bool injective_concretization = true;
32 constexpr static const bool preserve_concrete_covers = false;
33 constexpr static const bool is_lower_bound = false;
34 constexpr static const bool is_upper_bound = true;
35 constexpr static const char* name = "FUB";
36 constexpr static const bool is_arithmetic = true;
37 CUDA constexpr static value_type zero() { return 0.0; }
38 CUDA constexpr static value_type one() { return 1.0; }
39
40private:
41 template<bool diagnose, bool is_tell, class F>
42 CUDA NI static bool interpret(const F& f, value_type& k, IDiagnostics& diagnostics) {
43 if(f.is(F::Z)) {
44 auto z = f.z();
45 // We do not consider the min and max values of integers to be infinities when they are part of the logical formula.
46 if constexpr(is_tell) {
47 k = battery::ru_cast<value_type, decltype(z), false>(z);
48 }
49 else {
50 k = battery::rd_cast<value_type, decltype(z), false>(z);
51 }
52 return true;
53 }
54 else if(f.is(F::R)) {
55 if constexpr(is_tell) {
56 k = battery::ru_cast<value_type>(battery::get<1>(f.r()));
57 }
58 else {
59 k = battery::rd_cast<value_type>(battery::get<0>(f.r()));
60 }
61 return true;
62 }
63 RETURN_INTERPRETATION_ERROR("Only a constant of sort `Int` or `Real` can be interpreted by a floating-point abstract universe.")
64 }
65
66public:
67 /** Interpret a constant in the lattice of increasing floating-point numbers `FInc` according to the downset semantics.
68 Interpretations:
69 * Formulas of kind `F::Z` might be over-approximated (if the integer cannot be represented in a floating-point number because it is too large).
70 * Formulas of kind `F::R` might be over-approximated to the upper bound of the interval (if the real number is represented by an interval [lb..ub] where lb != ub).
71 * Other kind of formulas are not supported. */
72 template<bool diagnose, class F>
73 CUDA static bool interpret_tell(const F& f, value_type& k, IDiagnostics& diagnostics) {
74 return interpret<diagnose, true>(f, k, diagnostics);
75 }
76
77 /** Same as `interpret_tell` but the constant is under-approximated instead. */
78 template<bool diagnose, class F>
79 CUDA static bool interpret_ask(const F& f, value_type& k, IDiagnostics& diagnostics) {
80 return interpret<diagnose, false>(f, k, diagnostics);
81 }
82
83 /** Verify if the type of a variable, introduced by an existential quantifier, is compatible with the current abstract universe.
84 Interpretations:
85 * Variables of type `Int` are always over-approximated (\f$ \mathbb{Z} \subseteq \gamma(\top) \f$).
86 * Variables of type `Real` are represented exactly (only initially because \f$ \mathbb{R} = \gamma(\top) \f$). */
87 template<bool diagnose, class F, bool dualize = false>
88 CUDA NI static bool interpret_type(const F& f, value_type& k, IDiagnostics& diagnostics) {
89 assert(f.is(F::E));
90 const auto& vname = battery::get<0>(f.exists());
91 const auto& cty = battery::get<1>(f.exists());
92 if(cty.is_int()) {
93 k = dualize ? bot() : top();
94 RETURN_INTERPRETATION_WARNING("Variable `" + vname + "` of sort `Int` is over-approximated in a floating-point abstract universe.");
95 }
96 else if(cty.is_real()) {
97 k = dualize ? bot() : top();
98 return true;
99 }
100 else {
101 RETURN_INTERPRETATION_ERROR("Variable `" + vname + "` can only be of sort `Real`, or be over-approximated if the sort is `Bool` or `Int`.");
102 }
103 }
104
105 /** Given a floating-point value, create a logical constant representing that value.
106 * The constant is represented by a singleton interval of `double` [v..v].
107 * Note that the lattice order has no influence here.
108 * \pre `v != bot()` and `v != top()`.
109 */
110 template<class F>
111 CUDA static F deinterpret(const value_type& v) {
112 return F::make_real(v, v);
113 }
114
115 /** The logical predicate symbol corresponding to the order of this pre-universe.
116 We have \f$ a \leq_\mathit{FInc} b \Leftrightarrow a \leq b \f$.
117 \return The logical symbol `LEQ`. */
118 CUDA static constexpr Sig sig_order() { return LEQ; }
119
120 /** The logical predicate symbol corresponding to the strict order of this pre-universe.
121 We have \f$ a <_\mathit{FInc} b \Leftrightarrow a < b \f$.
122 \return The logical symbol `LT`. */
123 CUDA static constexpr Sig sig_strict_order() { return LT; }
124
125 /** \f$ \bot \f$ is represented by the floating-point negative infinity value. */
126 CUDA static constexpr value_type bot() {
127 return battery::limits<value_type>::neg_inf();
128 }
129
130 /** \f$ \top \f$ is represented by the floating-point positive infinity value. */
131 CUDA static constexpr value_type top() {
132 return battery::limits<value_type>::inf();
133 }
134
135 /** \return \f$ x \sqcup y \f$ defined as \f$ \mathit{max}(x, y) \f$. */
136 CUDA static constexpr value_type join(value_type x, value_type y) { return battery::max(x, y); }
137
138 /** \return \f$ x \sqcap y \f$ defined as \f$ \mathit{min}(x, y) \f$. */
139 CUDA static constexpr value_type meet(value_type x, value_type y) { return battery::min(x, y); }
140
141 /** \return \f$ \mathit{true} \f$ if \f$ x \leq_\mathit{FInc} y \f$ where the order \f$ \leq_\mathit{FInc} \f$ is the natural arithmetic ordering, otherwise returns \f$ \mathit{false} \f$. */
142 CUDA static constexpr bool order(value_type x, value_type y) { return x <= y; }
143
144 /** \return \f$ \mathit{true} \f$ if \f$ x <_\mathit{FInc} y \f$ where the order \f$ <_\mathit{ZInc} \f$ is the natural arithmetic ordering, otherwise returns \f$ \mathit{false} \f$. */
145 CUDA static constexpr bool strict_order(value_type x, value_type y) { return x < y; }
146
147 /** From a lattice perspective, this function returns an element \f$ y \f$ such that \f$ y \f$ is a cover of \f$ x \f$.
148
149 \return The next value of \f$ x \f$ in the floating-point increasing chain \f$ -\infty, \ldots, prev(-2.0), -2.0, next(-2.0), \ldots, \infty \f$ is the next representable value of \f$ x \f$ when \f$ x \not\in \{\infty, -\infty\} \f$ and \f$ x \f$ otherwise.
150 Note that \f$ 0 \f$ is considered to be represented by a single value. */
151 CUDA static constexpr value_type next(value_type x) {
152 if(x == bot() || x == top()) {
153 return x;
154 }
155 if(x == value_type{-0.0}) {
156 return battery::nextafter(value_type{+0.0}, top());
157 }
158 return battery::nextafter(x, top());
159 }
160
161 /** From a lattice perspective, this function returns an element \f$ y \f$ such that \f$ x \f$ is a cover of \f$ y \f$.
162
163 \return The previous value of \f$ x \f$ in the floating-point increasing chain \f$ -\infty, \ldots, prev(-2.0), -2.0, next(-2.0), \ldots, \infty \f$ is the previous representable value of \f$ x \f$ when \f$ x \not\in \{\infty, -\infty\} \f$ and \f$ x \f$ otherwise.
164 \f$ 0 \f$ is considered to be represented by a single value. */
165 CUDA static constexpr value_type prev(value_type x) {
166 if(x == bot() || x == top()) {
167 return x;
168 }
169 if(x == value_type{+0.0}) {
170 return battery::nextafter(value_type{-0.0}, bot());
171 }
172 return battery::nextafter(x, bot());
173 }
174
175 CUDA static constexpr value_type project(Sig fun, value_type x) {
176 switch(fun) {
177 case NEG: return -x;
178 default: return top();
179 }
180 }
181
182 CUDA static constexpr value_type project(Sig fun, value_type x, value_type y) {
183 switch(fun) {
184 case ADD: return battery::add_up(x, y);
185 case SUB: return battery::sub_up(x, y);
186 case MUL: return battery::mul_up(x, y);
187 case DIV: return battery::div_up(x, y);
188 case MIN: return battery::min(x, y);
189 case MAX: return battery::max(x, y);
190 case EQ: return x == y;
191 case NEQ: return x != y;
192 case LEQ: return x <= y;
193 case GEQ: return x >= y;
194 case LT: return x < y;
195 case GT: return x >= y;
196 default: return top();
197 }
198 }
199};
200
201} // namespace lala
202
203#endif
Definition diagnostics.hpp:19
#define RETURN_INTERPRETATION_WARNING(MSG)
Definition diagnostics.hpp:159
#define RETURN_INTERPRETATION_ERROR(MSG)
Definition diagnostics.hpp:155
Definition abstract_deps.hpp:14
Sig
Definition ast.hpp:94
@ NEQ
Equality relations.
Definition ast.hpp:112
@ LEQ
Unary arithmetic function symbols.
Definition ast.hpp:113
@ 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
@ MIN
Unary arithmetic function symbols.
Definition ast.hpp:97
@ DIV
Unary arithmetic function symbols.
Definition ast.hpp:101
@ GT
Arithmetic comparison predicates. When applied to set, it corresponds to the lexicographic ordering o...
Definition ast.hpp:113
@ MAX
Binary arithmetic function symbols.
Definition ast.hpp:97
@ LT
Unary arithmetic function symbols.
Definition ast.hpp:113
@ SUB
Unary arithmetic function symbols.
Definition ast.hpp:97
@ MUL
Unary arithmetic function symbols.
Definition ast.hpp:97
@ NEG
Unary arithmetic function symbols.
Definition ast.hpp:96
Definition pre_fub.hpp:11
Definition pre_fub.hpp:18
static CUDA constexpr value_type project(Sig fun, value_type x)
Definition pre_fub.hpp:175
static constexpr const bool is_lower_bound
Definition pre_fub.hpp:33
static constexpr const bool preserve_top
Definition pre_fub.hpp:27
static CUDA constexpr value_type next(value_type x)
Definition pre_fub.hpp:151
static CUDA constexpr value_type join(value_type x, value_type y)
Definition pre_fub.hpp:136
static CUDA constexpr value_type prev(value_type x)
Definition pre_fub.hpp:165
static CUDA constexpr value_type project(Sig fun, value_type x, value_type y)
Definition pre_fub.hpp:182
VT value_type
Definition pre_fub.hpp:21
static constexpr const bool injective_concretization
Definition pre_fub.hpp:31
static CUDA bool interpret_ask(const F &f, value_type &k, IDiagnostics &diagnostics)
Definition pre_fub.hpp:79
static constexpr const bool preserve_concrete_covers
Definition pre_fub.hpp:32
static constexpr const bool preserve_bot
Definition pre_fub.hpp:26
static CUDA F deinterpret(const value_type &v)
Definition pre_fub.hpp:111
CUDA static constexpr value_type zero()
Definition pre_fub.hpp:37
static CUDA constexpr bool order(value_type x, value_type y)
Definition pre_fub.hpp:142
static CUDA constexpr value_type top()
Definition pre_fub.hpp:131
PreFLB< VT > dual_type
Definition pre_fub.hpp:20
static constexpr const bool preserve_join
Definition pre_fub.hpp:28
CUDA static constexpr value_type one()
Definition pre_fub.hpp:38
static CUDA bool interpret_tell(const F &f, value_type &k, IDiagnostics &diagnostics)
Definition pre_fub.hpp:73
static constexpr const bool preserve_meet
Definition pre_fub.hpp:29
static constexpr const char * name
Definition pre_fub.hpp:35
static constexpr const bool is_arithmetic
Definition pre_fub.hpp:36
CUDA static NI bool interpret_type(const F &f, value_type &k, IDiagnostics &diagnostics)
Definition pre_fub.hpp:88
static constexpr const bool is_upper_bound
Definition pre_fub.hpp:34
static CUDA constexpr Sig sig_order()
Definition pre_fub.hpp:118
static constexpr const bool is_totally_ordered
Definition pre_fub.hpp:25
static CUDA constexpr value_type bot()
Definition pre_fub.hpp:126
static CUDA constexpr bool strict_order(value_type x, value_type y)
Definition pre_fub.hpp:145
static CUDA constexpr value_type meet(value_type x, value_type y)
Definition pre_fub.hpp:139
static CUDA constexpr Sig sig_strict_order()
Definition pre_fub.hpp:123
PreFUB< VT > this_type
Definition pre_fub.hpp:19