aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
discretizedVariable_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 #ifndef DOXYGEN_SHOULD_SKIP_THIS
23 # include <sstream>
24 
25 # include <agrum/tools/variables/discretizedVariable.h>
26 
27 namespace gum {
28  template < typename T_TICKS >
29  INLINE void DiscretizedVariable< T_TICKS >::copy_(const DiscretizedVariable< T_TICKS >& aDRV) {
30  eraseTicks();
31  IDiscretizedVariable::copy_(aDRV);
32 
33  for (Idx i = 0; i < aDRV._ticks_size_; ++i) {
34  addTick((T_TICKS)aDRV._ticks_[i]);
35  }
36  }
37 
38  template < typename T_TICKS >
39  Idx DiscretizedVariable< T_TICKS >::dichotomy_(const T_TICKS& target, Idx min, Idx max) const {
40  Idx res;
41  Idx mid = 0;
42 
43  if (max - min < 2)
44  res = min;
45  else {
46  mid = (max + min) / 2;
47  T_TICKS val = _ticks_[mid];
48 
49  if (target == val)
50  res = mid;
51  else if (target < val)
52  res = dichotomy_(target, min, mid);
53  else if (target > val)
54  res = dichotomy_(target, mid, max);
55  else
56  res = mid;
57  }
58 
59  return res;
60  }
61 
62  template < typename T_TICKS >
63  INLINE Idx DiscretizedVariable< T_TICKS >::pos_(const T_TICKS& target) const {
64  if (_ticks_size_ < 2) { GUM_ERROR(OutOfBounds, "not enough ticks") }
65 
66  if (target < _ticks_[0]) { GUM_ERROR(OutOfLowerBound, "less than first range") }
67 
68  if (target > _ticks_[_ticks_size_ - 1]) { GUM_ERROR(OutOfUpperBound, "more than last range") }
69 
70  if (target == _ticks_[_ticks_size_ - 1]) // special case for upper limit
71  // (which belongs to class _ticks_size_-2
72  return _ticks_size_ - 2;
73 
74  return dichotomy_(target, 0, _ticks_size_ - 1);
75  }
76 
77  template < typename T_TICKS >
78  INLINE DiscretizedVariable< T_TICKS >::DiscretizedVariable(const std::string& aName,
79  const std::string& aDesc) :
80  IDiscretizedVariable(aName, aDesc),
81  _ticks_size_((Size)0) {
82  GUM_CONSTRUCTOR(DiscretizedVariable);
83  _ticks_.reserve(1);
84  }
85 
86  template < typename T_TICKS >
87  INLINE DiscretizedVariable< T_TICKS >::DiscretizedVariable(const std::string& aName,
88  const std::string& aDesc,
89  const std::vector< T_TICKS >& ticks) :
90  IDiscretizedVariable(aName, aDesc),
91  _ticks_size_((Size)0) {
92  GUM_CONSTRUCTOR(DiscretizedVariable);
93  _ticks_.reserve(ticks.size());
94  for (const auto t: ticks)
95  addTick(t);
96  }
97 
98  template < typename T_TICKS >
99  DiscretizedVariable< T_TICKS >::DiscretizedVariable(const DiscretizedVariable< T_TICKS >& aDRV) :
100  IDiscretizedVariable(aDRV) {
101  GUM_CONS_CPY(DiscretizedVariable);
102  _ticks_.reserve(1);
103  copy_(aDRV);
104  }
105 
106  template < typename T_TICKS >
107  DiscretizedVariable< T_TICKS >::~DiscretizedVariable() {
108  GUM_DESTRUCTOR(DiscretizedVariable);
109  }
110 
111  template < typename T_TICKS >
112  DiscretizedVariable< T_TICKS >* DiscretizedVariable< T_TICKS >::clone() const {
113  return new DiscretizedVariable< T_TICKS >(*this);
114  }
115 
116  template < typename T_TICKS >
117  INLINE DiscretizedVariable< T_TICKS >&
118  DiscretizedVariable< T_TICKS >::operator=(const DiscretizedVariable< T_TICKS >& aDRV) {
119  copy_(aDRV);
120  return *this;
121  }
122 
123  template < typename T_TICKS >
124  INLINE bool DiscretizedVariable< T_TICKS >::isTick(const T_TICKS& aTick) const {
125  if (_ticks_size_ == 0) return false;
126 
127  if (_ticks_size_ == 1) return (_ticks_[0] == aTick);
128 
129  try {
130  Idx zeIdx = pos_(aTick);
131 
132  if (zeIdx != _ticks_size_ - 2)
133  return (_ticks_[zeIdx] == aTick);
134  else // special case for upper limit
135  return ((_ticks_[zeIdx] == aTick) || (_ticks_[zeIdx + 1] == aTick));
136  } catch (OutOfBounds&) { return false; }
137  }
138 
139  template < typename T_TICKS >
140  DiscretizedVariable< T_TICKS >& DiscretizedVariable< T_TICKS >::addTick(const T_TICKS& aTick) {
141  if (isTick(aTick)) {
142  GUM_ERROR(DefaultInLabel, "Tick '" << aTick << "' already used for variable " << name())
143  }
144 
145  if (_ticks_size_ == _ticks_.size()) { // streching _ticks_ if necessary
146  _ticks_.resize(_ticks_size_ + 1);
147  }
148 
149  if (_ticks_size_ == 0) { // special case for first tick
150  _ticks_[0] = aTick;
151  } else if (_ticks_size_ == 1) { // special case for second tick
152  if (_ticks_[0] < aTick) {
153  _ticks_[1] = aTick;
154  } else {
155  _ticks_[1] = _ticks_[0];
156  _ticks_[0] = aTick;
157  }
158  } else {
159  try {
160  Idx zeIdx = pos_(aTick); // aTick is in [ _ticks_[zeIdx], __ticks[zeIdx+1] [
161 
162  for (Idx i = _ticks_size_ - 1; i > zeIdx; --i) {
163  _ticks_[i + 1] = _ticks_[i];
164  }
165 
166  _ticks_[zeIdx + 1] = aTick;
167  } catch (OutOfUpperBound&) { // new upper bound
168  _ticks_[_ticks_size_] = aTick;
169  } catch (OutOfLowerBound&) { // new lower bound
170  for (Idx i = _ticks_size_; i >= 1; --i) {
171  _ticks_[i] = _ticks_[i - 1];
172  }
173 
174  _ticks_[0] = aTick;
175  }
176  }
177 
178  _ticks_size_++;
179 
180  return *this;
181  }
182 
183  template < typename T_TICKS >
184  INLINE void DiscretizedVariable< T_TICKS >::eraseTicks() {
185  if (_ticks_size_ != 0) { _ticks_size_ = 0; }
186  }
187 
188  template < typename T_TICKS >
189  INLINE std::string DiscretizedVariable< T_TICKS >::label(Idx i) const {
190  std::stringstream ss;
191 
192  if (i >= _ticks_size_ - 1) { GUM_ERROR(OutOfBounds, "inexisting label index") }
193 
194  ss << "[" << _ticks_[i] << ";" << _ticks_[i + 1];
195 
196  ss << ((i == _ticks_size_ - 2) ? "]" : "[");
197 
198  return ss.str();
199  }
200 
201  /// get a numerical representation of he indice-the value.
202  template < typename T_TICKS >
203  INLINE double DiscretizedVariable< T_TICKS >::numerical(Idx indice) const {
204  if (indice >= _ticks_size_ - 1) { GUM_ERROR(OutOfBounds, "inexisting label index") }
205 
206  return double((_ticks_[indice + 1] + _ticks_[indice]) / 2);
207  }
208 
209  template < typename T_TICKS >
210  INLINE Idx DiscretizedVariable< T_TICKS >::index(const std::string& label) const {
211  if (empty()) { GUM_ERROR(OutOfBounds, "empty variable : " + toString()) }
212 
213  std::istringstream i(label);
214  T_TICKS target;
215 
216  if (!(i >> target)) { GUM_ERROR(NotFound, "Bad label : " << label << " for " << *this) }
217 
218  return pos_(target);
219  }
220 
221  /**
222  *
223  * @return the size of the random discrete variable domain
224  */
225  template < typename T_TICKS >
226  INLINE Size DiscretizedVariable< T_TICKS >::domainSize() const {
227  return (_ticks_size_ < 2) ? Size(0) : Size(_ticks_size_ - 1);
228  }
229 
230  template < typename T_TICKS >
231  INLINE VarType DiscretizedVariable< T_TICKS >::varType() const {
232  return VarType::Discretized;
233  }
234 
235  template < typename T_TICKS >
236  INLINE const T_TICKS& DiscretizedVariable< T_TICKS >::tick(Idx i) const {
237  if (i >= _ticks_size_) { GUM_ERROR(OutOfBounds, "There is no such tick") }
238 
239  return _ticks_[i];
240  }
241 
242  template < typename T_TICKS >
243  const std::string DiscretizedVariable< T_TICKS >::domain() const {
244  std::stringstream s;
245  s << "<";
246 
247  if (domainSize() > 0) {
248  s << label(0);
249 
250  for (Idx i = 1; i < domainSize(); ++i) {
251  s << ",";
252  s << label(i);
253  }
254  }
255 
256  s << ">";
257 
258  return s.str();
259  }
260 
261  template < typename T_TICKS >
262  INLINE const std::vector< T_TICKS >& DiscretizedVariable< T_TICKS >::ticks() const {
263  return this->_ticks_;
264  }
265 
266  template < typename T_TICKS >
267  INLINE std::vector< double > DiscretizedVariable< T_TICKS >::ticksAsDoubles() const {
268  const std::size_t size = _ticks_.size();
269  std::vector< double > ticks(size);
270  for (std::size_t i = std::size_t(0); i < size; ++i)
271  ticks[i] = (double)_ticks_[i];
272  return ticks;
273  }
274 
275 } /* namespace gum */
276 
277 #endif /* DOXYGEN_SHOULD_SKIP_THIS */