aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
discretizedVariable_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 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_(
30  const DiscretizedVariable< T_TICKS >& aDRV) {
31  eraseTicks();
32  IDiscretizedVariable::copy_(aDRV);
33 
34  for (Idx i = 0; i < aDRV.ticks_size__; ++i) {
35  addTick((T_TICKS)aDRV.ticks__[i]);
36  }
37  }
38 
39  template < typename T_TICKS >
40  Idx DiscretizedVariable< T_TICKS >::dichotomy_(const T_TICKS& target,
41  Idx min,
42  Idx max) const {
43  Idx res;
44  Idx mid = 0;
45 
46  if (max - min < 2)
47  res = min;
48  else {
49  mid = (max + min) / 2;
50  T_TICKS val = ticks__[mid];
51 
52  if (target == val)
53  res = mid;
54  else if (target < val)
55  res = dichotomy_(target, min, mid);
56  else if (target > val)
57  res = dichotomy_(target, mid, max);
58  else
59  res = mid;
60  }
61 
62  return res;
63  }
64 
65  template < typename T_TICKS >
66  INLINE Idx DiscretizedVariable< T_TICKS >::pos_(const T_TICKS& target) const {
67  if (ticks_size__ < 2) { GUM_ERROR(OutOfBounds, "not enough ticks"); }
68 
69  if (target < ticks__[0]) {
70  GUM_ERROR(OutOfLowerBound, "less than first range");
71  }
72 
73  if (target > ticks__[ticks_size__ - 1]) {
74  GUM_ERROR(OutOfUpperBound, "more than last range");
75  }
76 
77  if (target == ticks__[ticks_size__ - 1]) // special case for upper limit
78  // (which belongs to class ticks_size__-2
79  return ticks_size__ - 2;
80 
81  return dichotomy_(target, 0, ticks_size__ - 1);
82  }
83 
84  template < typename T_TICKS >
85  INLINE DiscretizedVariable< T_TICKS >::DiscretizedVariable(
86  const std::string& aName,
87  const std::string& aDesc) :
88  IDiscretizedVariable(aName, aDesc),
89  ticks_size__((Size)0) {
90  GUM_CONSTRUCTOR(DiscretizedVariable);
91  ticks__.reserve(1);
92  }
93 
94  template < typename T_TICKS >
95  INLINE DiscretizedVariable< T_TICKS >::DiscretizedVariable(
96  const std::string& aName,
97  const std::string& aDesc,
98  const std::vector< T_TICKS >& ticks) :
99  IDiscretizedVariable(aName, aDesc),
100  ticks_size__((Size)0) {
101  GUM_CONSTRUCTOR(DiscretizedVariable);
102  ticks__.reserve(ticks.size());
103  for (const auto t: ticks)
104  addTick(t);
105  }
106 
107  template < typename T_TICKS >
108  DiscretizedVariable< T_TICKS >::DiscretizedVariable(
109  const DiscretizedVariable< T_TICKS >& aDRV) :
110  IDiscretizedVariable(aDRV) {
111  GUM_CONS_CPY(DiscretizedVariable);
112  ticks__.reserve(1);
113  copy_(aDRV);
114  }
115 
116  template < typename T_TICKS >
117  DiscretizedVariable< T_TICKS >::~DiscretizedVariable() {
118  GUM_DESTRUCTOR(DiscretizedVariable);
119  }
120 
121  template < typename T_TICKS >
122  DiscretizedVariable< T_TICKS >* DiscretizedVariable< T_TICKS >::clone() const {
123  return new DiscretizedVariable< T_TICKS >(*this);
124  }
125 
126  template < typename T_TICKS >
127  INLINE DiscretizedVariable< T_TICKS >& DiscretizedVariable< T_TICKS >::operator=(
128  const DiscretizedVariable< T_TICKS >& aDRV) {
129  copy_(aDRV);
130  return *this;
131  }
132 
133  template < typename T_TICKS >
134  INLINE bool DiscretizedVariable< T_TICKS >::isTick(const T_TICKS& aTick) const {
135  if (ticks_size__ == 0) return false;
136 
137  if (ticks_size__ == 1) return (ticks__[0] == aTick);
138 
139  try {
140  Idx zeIdx = pos_(aTick);
141 
142  if (zeIdx != ticks_size__ - 2)
143  return (ticks__[zeIdx] == aTick);
144  else // special case for upper limit
145  return ((ticks__[zeIdx] == aTick) || (ticks__[zeIdx + 1] == aTick));
146  } catch (OutOfBounds&) { return false; }
147  }
148 
149  template < typename T_TICKS >
150  DiscretizedVariable< T_TICKS >&
151  DiscretizedVariable< T_TICKS >::addTick(const T_TICKS& aTick) {
152  if (isTick(aTick)) {
153  GUM_ERROR(DefaultInLabel,
154  "Tick '" << aTick << "' already used for variable " << name());
155  }
156 
157  if (ticks_size__ == ticks__.size()) { // streching ticks__ if necessary
158  ticks__.resize(ticks_size__ + 1);
159  }
160 
161  if (ticks_size__ == 0) { // special case for first tick
162  ticks__[0] = aTick;
163  } else if (ticks_size__ == 1) { // special case for second tick
164  if (ticks__[0] < aTick) {
165  ticks__[1] = aTick;
166  } else {
167  ticks__[1] = ticks__[0];
168  ticks__[0] = aTick;
169  }
170  } else {
171  try {
172  Idx zeIdx
173  = pos_(aTick); // aTick is in [ ticks__[zeIdx],__ticks[zeIdx+1] [
174 
175  for (Idx i = ticks_size__ - 1; i > zeIdx; --i) {
176  ticks__[i + 1] = ticks__[i];
177  }
178 
179  ticks__[zeIdx + 1] = aTick;
180  } catch (OutOfUpperBound&) { // new upper bound
181  ticks__[ticks_size__] = aTick;
182  } catch (OutOfLowerBound&) { // new lower bound
183  for (Idx i = ticks_size__; i >= 1; --i) {
184  ticks__[i] = ticks__[i - 1];
185  }
186 
187  ticks__[0] = aTick;
188  }
189  }
190 
191  ticks_size__++;
192 
193  return *this;
194  }
195 
196  template < typename T_TICKS >
197  INLINE void DiscretizedVariable< T_TICKS >::eraseTicks() {
198  if (ticks_size__ != 0) { ticks_size__ = 0; }
199  }
200 
201  template < typename T_TICKS >
202  INLINE std::string DiscretizedVariable< T_TICKS >::label(Idx i) const {
203  std::stringstream ss;
204 
205  if (i >= ticks_size__ - 1) {
206  GUM_ERROR(OutOfBounds, "inexisting label index");
207  }
208 
209  ss << "[" << ticks__[i] << ";" << ticks__[i + 1];
210 
211  ss << ((i == ticks_size__ - 2) ? "]" : "[");
212 
213  return ss.str();
214  }
215 
216  /// get a numerical representation of he indice-the value.
217  template < typename T_TICKS >
218  INLINE double DiscretizedVariable< T_TICKS >::numerical(Idx indice) const {
219  if (indice >= ticks_size__ - 1) {
220  GUM_ERROR(OutOfBounds, "inexisting label index");
221  }
222 
223  return double((ticks__[indice + 1] + ticks__[indice]) / 2);
224  }
225 
226  template < typename T_TICKS >
227  INLINE Idx
228  DiscretizedVariable< T_TICKS >::index(const std::string& label) const {
229  if (empty()) { GUM_ERROR(OutOfBounds, "empty variable : " + toString()); }
230 
231  std::istringstream i(label);
232  T_TICKS target;
233 
234  if (!(i >> target)) {
235  GUM_ERROR(NotFound, "Bad label : " << label << " for " << *this);
236  }
237 
238  return pos_(target);
239  }
240 
241  /**
242  *
243  * @return the size of the random discrete variable domain
244  */
245  template < typename T_TICKS >
246  INLINE Size DiscretizedVariable< T_TICKS >::domainSize() const {
247  return (ticks_size__ < 2) ? Size(0) : Size(ticks_size__ - 1);
248  }
249 
250  template < typename T_TICKS >
251  INLINE VarType DiscretizedVariable< T_TICKS >::varType() const {
252  return VarType::Discretized;
253  }
254 
255  template < typename T_TICKS >
256  INLINE const T_TICKS& DiscretizedVariable< T_TICKS >::tick(Idx i) const {
257  if (i >= ticks_size__) { GUM_ERROR(OutOfBounds, "There is no such tick"); }
258 
259  return ticks__[i];
260  }
261 
262  template < typename T_TICKS >
263  const std::string DiscretizedVariable< T_TICKS >::domain() const {
264  std::stringstream s;
265  s << "<";
266 
267  if (domainSize() > 0) {
268  s << label(0);
269 
270  for (Idx i = 1; i < domainSize(); ++i) {
271  s << ",";
272  s << label(i);
273  }
274  }
275 
276  s << ">";
277 
278  return s.str();
279  }
280 
281  template < typename T_TICKS >
282  INLINE const std::vector< T_TICKS >&
283  DiscretizedVariable< T_TICKS >::ticks() const {
284  return this->ticks__;
285  }
286 
287  template < typename T_TICKS >
288  INLINE std::vector< double >
289  DiscretizedVariable< T_TICKS >::ticksAsDoubles() const {
290  const std::size_t size = ticks__.size();
291  std::vector< double > ticks(size);
292  for (std::size_t i = std::size_t(0); i < size; ++i)
293  ticks[i] = (double)ticks__[i];
294  return ticks;
295  }
296 
297 } /* namespace gum */
298 
299 #endif /* DOXYGEN_SHOULD_SKIP_THIS */