aGrUM 3.1.1
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-2026 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-2026 *
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
41#pragma once
42
43
51
52// Help IDE parsers
54
55namespace gum {
56
57 // Class constructor
58 template < typename GUM_ELEMENT >
60 GUM_ELEMENT high,
61 GUM_ELEMENT eps) :
62 ApproximationPolicy< GUM_ELEMENT >(), lowLimit_(low), highLimit_(high), epsilon_(eps) {
63 if (eps <= 0) { GUM_ERROR(OutOfBounds, "Epsilon must be >0") }
64
66 }
67
68 // Copy constructor.
69 template < typename GUM_ELEMENT >
74
75 // @brief Convert value to his approximation.
76 template < typename GUM_ELEMENT >
77 GUM_ELEMENT LinearApproximationPolicy< GUM_ELEMENT >::fromExact(const GUM_ELEMENT& value) const {
78 return _decode_(GUM_ELEMENT(encode(value)));
79 }
80
81 // @brief Combine using addition with the given gum::ApproximationPolicy.
82 template < typename GUM_ELEMENT >
85 try {
87 = dynamic_cast< const LinearApproximationPolicy< GUM_ELEMENT >* >(ap);
88
89 GUM_ELEMENT newHighLimit = lowLimit_ + lap->lowLimit();
90 GUM_ELEMENT newLowLimit = lowLimit_ + lap->lowLimit();
91
92 GUM_ELEMENT newVal = lowLimit_ + lap->highLimit();
93
94 if (newHighLimit < newVal) newHighLimit = newVal;
95
96 if (newLowLimit > newVal) newLowLimit = newVal;
97
98 newVal = highLimit_ + lap->lowLimit();
99
100 if (newHighLimit < newVal) newHighLimit = newVal;
101
102 if (newLowLimit > newVal) newLowLimit = newVal;
103
104 newVal = highLimit_ + lap->highLimit();
105
106 if (newHighLimit < newVal) newHighLimit = newVal;
107
108 if (newLowLimit > newVal) newLowLimit = newVal;
109
110 this->lowLimit_ = newLowLimit;
111 this->highLimit_ = newHighLimit;
113 } catch (const std::bad_cast&) {}
114 }
115
116 template < typename GUM_ELEMENT >
119 try {
121 = dynamic_cast< const LinearApproximationPolicy< GUM_ELEMENT >* >(ap);
122
123 GUM_ELEMENT newHighLimit = lowLimit_ - lap->lowLimit();
124 GUM_ELEMENT newLowLimit = lowLimit_ - lap->lowLimit();
125
126 GUM_ELEMENT newVal = lowLimit_ - lap->highLimit();
127
128 if (newHighLimit < newVal) newHighLimit = newVal;
129
130 if (newLowLimit > newVal) newLowLimit = newVal;
131
132 newVal = highLimit_ - lap->lowLimit();
133
134 if (newHighLimit < newVal) newHighLimit = newVal;
135
136 if (newLowLimit > newVal) newLowLimit = newVal;
137
138 newVal = highLimit_ - lap->highLimit();
139
140 if (newHighLimit < newVal) newHighLimit = newVal;
141
142 if (newLowLimit > newVal) newLowLimit = newVal;
143
144 this->lowLimit_ = newLowLimit;
145 this->highLimit_ = newHighLimit;
147 } catch (const std::bad_cast&) {}
148 }
149
150 template < typename GUM_ELEMENT >
153 try {
155 = dynamic_cast< const LinearApproximationPolicy< GUM_ELEMENT >* >(ap);
156
157 GUM_ELEMENT newHighLimit = lowLimit_ * lap->lowLimit();
158 GUM_ELEMENT newLowLimit = lowLimit_ * lap->lowLimit();
159
160 GUM_ELEMENT newVal = lowLimit_ * lap->highLimit();
161
162 if (newHighLimit < newVal) newHighLimit = newVal;
163
164 if (newLowLimit > newVal) newLowLimit = newVal;
165
166 newVal = highLimit_ * lap->lowLimit();
167
168 if (newHighLimit < newVal) newHighLimit = newVal;
169
170 if (newLowLimit > newVal) newLowLimit = newVal;
171
172 newVal = highLimit_ * lap->highLimit();
173
174 if (newHighLimit < newVal) newHighLimit = newVal;
175
176 if (newLowLimit > newVal) newLowLimit = newVal;
177
178 this->lowLimit_ = newLowLimit;
179 this->highLimit_ = newHighLimit;
181 } catch (const std::bad_cast&) {}
182 }
183
184 template < typename GUM_ELEMENT >
187 try {
189 = dynamic_cast< const LinearApproximationPolicy< GUM_ELEMENT >* >(ap);
190
191 GUM_ELEMENT newHighLimit = lowLimit_ / lap->lowLimit();
192 GUM_ELEMENT newLowLimit = lowLimit_ / lap->lowLimit();
193
194 GUM_ELEMENT newVal = lowLimit_ / lap->highLimit();
195
196 if (newHighLimit < newVal) newHighLimit = newVal;
197
198 if (newLowLimit > newVal) newLowLimit = newVal;
199
200 newVal = highLimit_ / lap->lowLimit();
201
202 if (newHighLimit < newVal) newHighLimit = newVal;
203
204 if (newLowLimit > newVal) newLowLimit = newVal;
205
206 newVal = highLimit_ / lap->highLimit();
207
208 if (newHighLimit < newVal) newHighLimit = newVal;
209
210 if (newLowLimit > newVal) newLowLimit = newVal;
211
212 this->lowLimit_ = newLowLimit;
213 this->highLimit_ = newHighLimit;
215 } catch (const std::bad_cast&) {}
216 }
217
218 template < typename GUM_ELEMENT >
221 try {
223 = dynamic_cast< const LinearApproximationPolicy< GUM_ELEMENT >* >(ap);
224
225 GUM_ELEMENT newHighLimit = lowLimit_ > lap->lowLimit() ? lowLimit_ : lap->lowLimit();
226 GUM_ELEMENT newLowLimit = lowLimit_ > lap->lowLimit() ? lowLimit_ : lap->lowLimit();
227
228 GUM_ELEMENT newVal = lowLimit_ > lap->highLimit() ? lowLimit_ : lap->highLimit();
229
230 if (newHighLimit < newVal) newHighLimit = newVal;
231
232 if (newLowLimit > newVal) newLowLimit = newVal;
233
234 newVal = highLimit_ > lap->lowLimit() ? highLimit_ : lap->lowLimit();
235
236 if (newHighLimit < newVal) newHighLimit = newVal;
237
238 if (newLowLimit > newVal) newLowLimit = newVal;
239
240 newVal = highLimit_ > lap->highLimit() ? highLimit_ : lap->highLimit();
241
242 if (newHighLimit < newVal) newHighLimit = newVal;
243
244 if (newLowLimit > newVal) newLowLimit = newVal;
245
246 this->lowLimit_ = newLowLimit;
247 this->highLimit_ = newHighLimit;
249 } catch (const std::bad_cast&) {}
250 }
251
252 template < typename GUM_ELEMENT >
255 try {
257 = dynamic_cast< const LinearApproximationPolicy< GUM_ELEMENT >* >(ap);
258
259 GUM_ELEMENT newHighLimit = lowLimit_ < lap->lowLimit() ? lowLimit_ : lap->lowLimit();
260 GUM_ELEMENT newLowLimit = lowLimit_ < lap->lowLimit() ? lowLimit_ : lap->lowLimit();
261
262 GUM_ELEMENT newVal = lowLimit_ < lap->highLimit() ? lowLimit_ : lap->highLimit();
263
264 if (newHighLimit < newVal) newHighLimit = newVal;
265
266 if (newLowLimit > newVal) newLowLimit = newVal;
267
268 newVal = highLimit_ < lap->lowLimit() ? highLimit_ : lap->lowLimit();
269
270 if (newHighLimit < newVal) newHighLimit = newVal;
271
272 if (newLowLimit > newVal) newLowLimit = newVal;
273
274 newVal = highLimit_ < lap->highLimit() ? highLimit_ : lap->highLimit();
275
276 if (newHighLimit < newVal) newHighLimit = newVal;
277
278 if (newLowLimit > newVal) newLowLimit = newVal;
279
280 this->lowLimit_ = newLowLimit;
281 this->highLimit_ = newHighLimit;
283 } catch (const std::bad_cast&) {}
284 }
285
286 // Convert value to his approximation. This method is slower than @ref
287 // fromExact since it verifies the bounds
288 template < typename GUM_ELEMENT >
289 GUM_ELEMENT LinearApproximationPolicy< GUM_ELEMENT >::safeFromExact(const GUM_ELEMENT& value) {
290 if (value > this->highLimit_) {
291 GUM_ERROR(OutOfBounds, "Value asked is higher than high limit")
292 }
293
294 if (value < this->lowLimit_) { GUM_ERROR(OutOfBounds, "Value asked is lower than low limit") }
295
296 return fromExact(value);
297 }
298
299 // Convert value to approximation representation
300 template < typename GUM_ELEMENT >
302// we keep the bounds checked in debug mode
303#ifdef GUM_DEBUG_MODE
304 if (value > this->highLimit_) {
306 "Value asked is higher than High limit : not in (" << this->lowLimit_ << "-"
307 << this->highLimit_ << ")")
308 }
309
310 if (value < this->lowLimit_) {
312 "Value asked is lower than low limit : not in (" << this->lowLimit_ << "-"
313 << this->highLimit_ << ")")
314 }
315
316#endif // GUM_DEBUG_MODE
317 return _encode_(value);
318 }
319
320 // Convert approximation representation to value
321 template < typename GUM_ELEMENT >
322 GUM_ELEMENT LinearApproximationPolicy< GUM_ELEMENT >::decode(Idx representation) const {
323 if (representation > nbInterval_) {
324 GUM_ERROR(OutOfBounds, "Interval Number asked is higher than total number of interval")
325 }
326
327 return _decode_(GUM_ELEMENT(representation));
328 }
329
330 // Sets approximation factor
331 template < typename GUM_ELEMENT >
333 if (e <= 0) { GUM_ERROR(OutOfBounds, "Epsilon must be >0") }
334 epsilon_ = e;
336 }
337
338 // set bounds in a whole
339 template < typename GUM_ELEMENT >
340 void LinearApproximationPolicy< GUM_ELEMENT >::setLimits(const GUM_ELEMENT& newLowLimit,
341 const GUM_ELEMENT& newHighLimit) {
342 if (newLowLimit > newHighLimit) {
343 GUM_ERROR(OutOfBounds, "Asked low value is higher than asked high value")
344 }
345
346 lowLimit_ = newLowLimit;
347 highLimit_ = newHighLimit;
349 }
350
351 // Sets lowest possible value
352 template < typename GUM_ELEMENT >
353 void LinearApproximationPolicy< GUM_ELEMENT >::setLowLimit(const GUM_ELEMENT& newLowLimit) {
354 if (newLowLimit > this->highLimit_) {
355 GUM_ERROR(OutOfBounds, "Value asked is higher than High limit")
356 }
357
358 lowLimit_ = newLowLimit;
359
361 }
362
363 // Gets lowest possible value
364 template < typename GUM_ELEMENT >
366 return lowLimit_;
367 }
368
369 // Sets Highest possible value
370 template < typename GUM_ELEMENT >
371 void LinearApproximationPolicy< GUM_ELEMENT >::setHighLimit(const GUM_ELEMENT& newHighLimit) {
372 if (newHighLimit < this->lowLimit_) {
373 GUM_ERROR(OutOfBounds, "Value asked is lower than low limit")
374 }
375
376 highLimit_ = newHighLimit;
377
379 }
380
381 // Gets Highest possible value
382 template < typename GUM_ELEMENT >
384 return highLimit_;
385 }
386
387 // Concretely computes the approximate representation
388 template < typename GUM_ELEMENT >
390 if (value <= this->lowLimit_) return 0;
391
392 if (value >= this->highLimit_) return nbInterval_;
393
394 return 1 + Idx(((value - this->lowLimit_) / this->epsilon_));
395 }
396
397 // Concretely computes the approximate value from representation
398 template < typename GUM_ELEMENT >
399 GUM_ELEMENT
400 LinearApproximationPolicy< GUM_ELEMENT >::_decode_(const GUM_ELEMENT& representation) const {
401 if (representation == 0) return this->lowLimit_;
402
403 if (representation == nbInterval_) return this->highLimit_;
404
405 return (GUM_ELEMENT)(((representation * this->epsilon_) - (this->epsilon_ / 2))
406 + this->lowLimit_);
407 }
408
409 // get the number of interval
410 template < typename GUM_ELEMENT >
414} // namespace gum
void combineMin(const ApproximationPolicy< GUM_ELEMENT > *ap) override
Combine using min with the given gum::ApproximationPolicy.
GUM_ELEMENT fromExact(const GUM_ELEMENT &value) const override
Convert value to his approximation.
GUM_ELEMENT _decode_(const GUM_ELEMENT &representation) const
Concretely computes the approximate value from representation.
void combineAdd(const ApproximationPolicy< GUM_ELEMENT > *ap) override
Combine using addition with the given gum::ApproximationPolicy.
void combineMax(const ApproximationPolicy< GUM_ELEMENT > *ap) override
Combine using max with the given gum::ApproximationPolicy.
virtual void setLowLimit(const GUM_ELEMENT &newLowLimit)
Sets lowest possible value.
void combineDiv(const ApproximationPolicy< GUM_ELEMENT > *ap) override
Combine using division with the given gum::ApproximationPolicy.
GUM_ELEMENT safeFromExact(const GUM_ELEMENT &value)
Convert value to his approximation.
Idx encode(const GUM_ELEMENT &value) const
Encode a given value into its approximation representation.
void computeNbInterval_()
Get the number of interval.
virtual void setLimits(const GUM_ELEMENT &newLowLimit, const GUM_ELEMENT &newHighLimit)
Set bounds in a whole.
void combineMult(const ApproximationPolicy< GUM_ELEMENT > *ap) override
Combine using multiplication with the given gum::ApproximationPolicy.
Idx _encode_(const GUM_ELEMENT &value) const
Concretely computes the approximate representation.
virtual void setEpsilon(const GUM_ELEMENT &e)
Sets approximation factor.
LinearApproximationPolicy(GUM_ELEMENT low=(GUM_ELEMENT) 0.0, GUM_ELEMENT high=(GUM_ELEMENT) 1.0, GUM_ELEMENT eps=(GUM_ELEMENT) 0.1)
Default constructor.
GUM_ELEMENT decode(Idx representation) const
Convert approximation representation to value.
const GUM_ELEMENT & highLimit() const
Gets Highest possible value.
GUM_ELEMENT lowLimit_
Lowest value possible.
virtual void setHighLimit(const GUM_ELEMENT &newHighLimit)
Sets Highest possible value.
const GUM_ELEMENT & lowLimit() const
Gets lowest possible value.
GUM_ELEMENT epsilon_
Approximation factor.
GUM_ELEMENT highLimit_
Highest value possible.
void combineSub(const ApproximationPolicy< GUM_ELEMENT > *ap) override
Combine using subtraction with the given gum::ApproximationPolicy.
Exception : out of bound.
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
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