aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
linearApproximationPolicy_tpl.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2025 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2025 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40#pragma once
41
42
50
51// Help IDE parsers
53
54namespace gum {
55
56 // Class constructor
57 template < typename GUM_SCALAR >
59 GUM_SCALAR high,
60 GUM_SCALAR eps) :
61 ApproximationPolicy< GUM_SCALAR >(), lowLimit_(low), highLimit_(high), epsilon_(eps) {
62 if (eps <= 0) { GUM_ERROR(OutOfBounds, "Epsilon must be >0") }
63
65 }
66
67 // Copy constructor.
68 template < typename GUM_SCALAR >
72
73 // @brief Convert value to his approximation.
74 template < typename GUM_SCALAR >
75 INLINE GUM_SCALAR
77 return _decode_(GUM_SCALAR(encode(value)));
78 }
79
80 // @brief Combine using addition with the given gum::ApproximationPolicy.
81 template < typename GUM_SCALAR >
84 try {
86 = dynamic_cast< const LinearApproximationPolicy< GUM_SCALAR >* >(ap);
87
88 GUM_SCALAR newHighLimit = lowLimit_ + lap->lowLimit();
89 GUM_SCALAR newLowLimit = lowLimit_ + lap->lowLimit();
90
91 GUM_SCALAR newVal = lowLimit_ + lap->highLimit();
92
93 if (newHighLimit < newVal) newHighLimit = newVal;
94
95 if (newLowLimit > newVal) newLowLimit = newVal;
96
97 newVal = highLimit_ + lap->lowLimit();
98
99 if (newHighLimit < newVal) newHighLimit = newVal;
100
101 if (newLowLimit > newVal) newLowLimit = newVal;
102
103 newVal = highLimit_ + lap->highLimit();
104
105 if (newHighLimit < newVal) newHighLimit = newVal;
106
107 if (newLowLimit > newVal) newLowLimit = newVal;
108 } catch (const std::bad_cast&) {}
109 }
110
111 template < typename GUM_SCALAR >
114 try {
116 = dynamic_cast< const LinearApproximationPolicy< GUM_SCALAR >* >(ap);
117
118 GUM_SCALAR newHighLimit = lowLimit_ - lap->lowLimit();
119 GUM_SCALAR newLowLimit = lowLimit_ - lap->lowLimit();
120
121 GUM_SCALAR newVal = lowLimit_ - lap->highLimit();
122
123 if (newHighLimit < newVal) newHighLimit = newVal;
124
125 if (newLowLimit > newVal) newLowLimit = newVal;
126
127 newVal = highLimit_ - lap->lowLimit();
128
129 if (newHighLimit < newVal) newHighLimit = newVal;
130
131 if (newLowLimit > newVal) newLowLimit = newVal;
132
133 newVal = highLimit_ - lap->highLimit();
134
135 if (newHighLimit < newVal) newHighLimit = newVal;
136
137 if (newLowLimit > newVal) newLowLimit = newVal;
138 } catch (const std::bad_cast&) {}
139 }
140
141 template < typename GUM_SCALAR >
144 try {
146 = dynamic_cast< const LinearApproximationPolicy< GUM_SCALAR >* >(ap);
147
148 GUM_SCALAR newHighLimit = lowLimit_ * lap->lowLimit();
149 GUM_SCALAR newLowLimit = lowLimit_ * lap->lowLimit();
150
151 GUM_SCALAR newVal = lowLimit_ * lap->highLimit();
152
153 if (newHighLimit < newVal) newHighLimit = newVal;
154
155 if (newLowLimit > newVal) newLowLimit = newVal;
156
157 newVal = highLimit_ * lap->lowLimit();
158
159 if (newHighLimit < newVal) newHighLimit = newVal;
160
161 if (newLowLimit > newVal) newLowLimit = newVal;
162
163 newVal = highLimit_ * lap->highLimit();
164
165 if (newHighLimit < newVal) newHighLimit = newVal;
166
167 if (newLowLimit > newVal) newLowLimit = newVal;
168 } catch (const std::bad_cast&) {}
169 }
170
171 template < typename GUM_SCALAR >
174 try {
176 = dynamic_cast< const LinearApproximationPolicy< GUM_SCALAR >* >(ap);
177
178 GUM_SCALAR newHighLimit = lowLimit_ / lap->lowLimit();
179 GUM_SCALAR newLowLimit = lowLimit_ / lap->lowLimit();
180
181 GUM_SCALAR newVal = lowLimit_ / lap->highLimit();
182
183 if (newHighLimit < newVal) newHighLimit = newVal;
184
185 if (newLowLimit > newVal) newLowLimit = newVal;
186
187 newVal = highLimit_ / lap->lowLimit();
188
189 if (newHighLimit < newVal) newHighLimit = newVal;
190
191 if (newLowLimit > newVal) newLowLimit = newVal;
192
193 newVal = highLimit_ / lap->highLimit();
194
195 if (newHighLimit < newVal) newHighLimit = newVal;
196
197 if (newLowLimit > newVal) newLowLimit = newVal;
198 } catch (const std::bad_cast&) {}
199 }
200
201 template < typename GUM_SCALAR >
204 try {
206 = dynamic_cast< const LinearApproximationPolicy< GUM_SCALAR >* >(ap);
207
208 GUM_SCALAR newHighLimit = lowLimit_ > lap->lowLimit() ? lowLimit_ : lap->lowLimit();
209 GUM_SCALAR newLowLimit = lowLimit_ > lap->lowLimit() ? lowLimit_ : lap->lowLimit();
210
211 GUM_SCALAR newVal = lowLimit_ > lap->highLimit() ? lowLimit_ : lap->highLimit();
212
213 if (newHighLimit < newVal) newHighLimit = newVal;
214
215 if (newLowLimit > newVal) newLowLimit = newVal;
216
217 newVal = highLimit_ > lap->lowLimit() ? highLimit_ : lap->lowLimit();
218
219 if (newHighLimit < newVal) newHighLimit = newVal;
220
221 if (newLowLimit > newVal) newLowLimit = newVal;
222
223 newVal = highLimit_ > lap->highLimit() ? highLimit_ : lap->highLimit();
224
225 if (newHighLimit < newVal) newHighLimit = newVal;
226
227 if (newLowLimit > newVal) newLowLimit = newVal;
228 } catch (const std::bad_cast&) {}
229 }
230
231 template < typename GUM_SCALAR >
234 try {
236 = dynamic_cast< const LinearApproximationPolicy< GUM_SCALAR >* >(ap);
237
238 GUM_SCALAR newHighLimit = lowLimit_ < lap->lowLimit() ? lowLimit_ : lap->lowLimit();
239 GUM_SCALAR newLowLimit = lowLimit_ < lap->lowLimit() ? lowLimit_ : lap->lowLimit();
240
241 GUM_SCALAR newVal = lowLimit_ < lap->highLimit() ? lowLimit_ : lap->highLimit();
242
243 if (newHighLimit < newVal) newHighLimit = newVal;
244
245 if (newLowLimit > newVal) newLowLimit = newVal;
246
247 newVal = highLimit_ < lap->lowLimit() ? highLimit_ : lap->lowLimit();
248
249 if (newHighLimit < newVal) newHighLimit = newVal;
250
251 if (newLowLimit > newVal) newLowLimit = newVal;
252
253 newVal = highLimit_ < lap->highLimit() ? highLimit_ : lap->highLimit();
254
255 if (newHighLimit < newVal) newHighLimit = newVal;
256
257 if (newLowLimit > newVal) newLowLimit = newVal;
258 } catch (const std::bad_cast&) {}
259 }
260
261 // Convert value to his approximation. This method is slower than @ref
262 // fromExact since it verifies the bounds
263 template < typename GUM_SCALAR >
264 INLINE GUM_SCALAR
266 if (value > this->highLimit_) {
267 GUM_ERROR(OutOfBounds, "Value asked is higher than high limit")
268 }
269
270 if (value < this->lowLimit_) { GUM_ERROR(OutOfBounds, "Value asked is lower than low limit") }
271
272 return fromExact(value);
273 }
274
275 // Convert value to approximation representation
276 template < typename GUM_SCALAR >
277 INLINE Idx LinearApproximationPolicy< GUM_SCALAR >::encode(const GUM_SCALAR& value) const {
278// we keep the bounds checked in debug mode
279#ifdef GUM_DEBUG_MODE
280 if (value > this->highLimit_) {
282 "Value asked is higher than High limit : not in (" << this->lowLimit_ << "-"
283 << this->highLimit_ << ")")
284 }
285
286 if (value < this->lowLimit_) {
288 "Value asked is lower than low limit : not in (" << this->lowLimit_ << "-"
289 << this->highLimit_ << ")")
290 }
291
292#endif // GUM_DEBUG_MODE
293 return _encode_(value);
294 }
295
296 // Convert approximation representation to value
297 template < typename GUM_SCALAR >
298 INLINE GUM_SCALAR LinearApproximationPolicy< GUM_SCALAR >::decode(Idx representation) const {
299 if (representation > nbInterval_) {
300 GUM_ERROR(OutOfBounds, "Interval Number asked is higher than total number of interval")
301 }
302
303 return _decode_(GUM_SCALAR(representation));
304 }
305
306 // Sets approximation factor
307 template < typename GUM_SCALAR >
309 epsilon_ = e;
311 }
312
313 // set bounds in a whole
314 template < typename GUM_SCALAR >
315 INLINE void LinearApproximationPolicy< GUM_SCALAR >::setLimits(const GUM_SCALAR& newLowLimit,
316 const GUM_SCALAR& newHighLimit) {
317 if (newLowLimit > newHighLimit) {
318 GUM_ERROR(OutOfBounds, "Asked low value is higher than asked high value")
319 }
320
321 lowLimit_ = newLowLimit;
322 highLimit_ = newHighLimit;
324 }
325
326 // Sets lowest possible value
327 template < typename GUM_SCALAR >
328 INLINE void LinearApproximationPolicy< GUM_SCALAR >::setLowLimit(const GUM_SCALAR& newLowLimit) {
329 if (newLowLimit > this->highLimit_) {
330 GUM_ERROR(OutOfBounds, "Value asked is higher than High limit")
331 }
332
333 lowLimit_ = newLowLimit;
334
336 }
337
338 // Gets lowest possible value
339 template < typename GUM_SCALAR >
340 INLINE const GUM_SCALAR& LinearApproximationPolicy< GUM_SCALAR >::lowLimit() const {
341 return lowLimit_;
342 }
343
344 // Sets Highest possible value
345 template < typename GUM_SCALAR >
346 INLINE void
348 if (newHighLimit < this->lowLimit_) {
349 GUM_ERROR(OutOfBounds, "Value asked is lower than low limit")
350 }
351
352 highLimit_ = newHighLimit;
353
355 }
356
357 // Gets Highest possible value
358 template < typename GUM_SCALAR >
359 INLINE const GUM_SCALAR& LinearApproximationPolicy< GUM_SCALAR >::highLimit() const {
360 return highLimit_;
361 }
362
363 // Concretely computes the approximate representation
364 template < typename GUM_SCALAR >
365 INLINE Idx LinearApproximationPolicy< GUM_SCALAR >::_encode_(const GUM_SCALAR& value) const {
366 if (value <= this->lowLimit_) return 0;
367
368 if (value >= this->highLimit_) return nbInterval_;
369
370 return 1 + Idx(((value - this->lowLimit_) / this->epsilon_));
371 }
372
373 // Concretely computes the approximate value from representation
374 template < typename GUM_SCALAR >
375 INLINE GUM_SCALAR
376 LinearApproximationPolicy< GUM_SCALAR >::_decode_(const GUM_SCALAR& representation) const {
377 if (representation == 0) return this->lowLimit_;
378
379 if (representation == nbInterval_) return this->highLimit_;
380
381 return (GUM_SCALAR)(((representation * this->epsilon_) - (this->epsilon_ / 2))
382 + this->lowLimit_);
383 }
384
385 // get the number of interval
386 template < typename GUM_SCALAR >
390} // namespace gum
ApproximationPolicy()
Default constructor.
GUM_SCALAR _decode_(const GUM_SCALAR &representation) const
Concretely computes the approximate value from representation.
GUM_SCALAR highLimit_
Highest value possible.
void computeNbInterval_()
Get the number of interval.
virtual void setLowLimit(const GUM_SCALAR &newLowLimit)
Sets lowest possible value.
const GUM_SCALAR & highLimit() const
Gets Highest possible value.
void combineSub(const ApproximationPolicy< GUM_SCALAR > *ap)
Combine using substraction with the given gum::ApproximationPolicy.
GUM_SCALAR safeFromExact(const GUM_SCALAR &value)
Convert value to his approximation.
const GUM_SCALAR & lowLimit() const
Gets lowest possible value.
LinearApproximationPolicy(GUM_SCALAR low=(GUM_SCALAR) 0.0, GUM_SCALAR high=(GUM_SCALAR) 1.0, GUM_SCALAR eps=(GUM_SCALAR) 0.1)
Default constructor.
void combineDiv(const ApproximationPolicy< GUM_SCALAR > *ap)
Combine using division with the given gum::ApproximationPolicy.
Idx _encode_(const GUM_SCALAR &value) const
Concretely computes the approximate representation.
GUM_SCALAR fromExact(const GUM_SCALAR &value) const
Convert value to his approximation.
GUM_SCALAR decode(Idx representation) const
Convert approximation representation to value.
GUM_SCALAR lowLimit_
Lowest value possible.
virtual void setEpsilon(const GUM_SCALAR &e)
Sets approximation factor.
void combineAdd(const ApproximationPolicy< GUM_SCALAR > *ap)
Combine using addition with the given gum::ApproximationPolicy.
void combineMult(const ApproximationPolicy< GUM_SCALAR > *ap)
Combine using multiplication with the given gum::ApproximationPolicy.
virtual void setHighLimit(const GUM_SCALAR &newHighLimit)
Sets Highest possible value.
Idx encode(const GUM_SCALAR &value) const
Encode a given value into its approximation representation.
GUM_SCALAR epsilon_
Approximation factor.
void combineMin(const ApproximationPolicy< GUM_SCALAR > *ap)
Combine using min with the given gum::ApproximationPolicy.
void combineMax(const ApproximationPolicy< GUM_SCALAR > *ap)
Combine using max with the given gum::ApproximationPolicy.
virtual void setLimits(const GUM_SCALAR &newLowLimit, const GUM_SCALAR &newHighLimit)
Set bounds in a whole.
Exception : out of bound.
#define GUM_ERROR(type, msg)
Definition exceptions.h:72
Size Idx
Type for indexes.
Definition types.h:79
Classes used to practice approximation on value.
gum is the global namespace for all aGrUM entities
Definition agrum.h:46