OpenStructure
multi_classifier.hh
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // This file is part of the OpenStructure project <www.openstructure.org>
3 //
4 // Copyright (C) 2008-2011 by the OpenStructure authors
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License as published by the Free
8 // Software Foundation; either version 3.0 of the License, or (at your option)
9 // any later version.
10 // This library is distributed in the hope that it will be useful, but WITHOUT
11 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 // details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with this library; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 //------------------------------------------------------------------------------
19 #ifndef OST_QA_MULTI_CLASSIFIER_HH
20 #define OST_QA_MULTI_CLASSIFIER_HH
21 
22 #include <ost/stdint.hh>
23 #include <vector>
24 #include <cassert>
25 #include <fstream>
26 #include <ost/message.hh>
27 #include <iostream>
28 
29 #include <boost/shared_ptr.hpp>
30 
31 #include "index.hh"
32 #include <ost/config.hh>
33 
34 namespace ost { namespace qa {
35 
36 namespace impl {
37  // Determine length of a typelist, i.e. the number of template arguments
38  // different from NullType. The length can be accessed over the Value
39  // member.
40  // usage example:
41  // int length=LengthOf<int, int>::Value;
42  struct NullType {
43  template <typename DS>
44  void Serialize(DS&) {}
45  };
46  template <typename T1,
47  typename T2,
48  typename T3,
49  typename T4,
50  typename T5,
51  typename T6,
52  typename T7>
53  struct LengthOf;
54 
55  template <typename T1,
56  typename T2,
57  typename T3,
58  typename T4,
59  typename T5,
60  typename T6,
61  typename T7>
62  struct LengthOf {
64  };
65  template <>
67  NullType>
68  {
69  enum { Value = 0 };
70  };
71 
73  // and set to F otherwise.
74  template <bool C,
75  typename T,
76  typename F>
77  struct If;
78 
79  template <typename T,
80  typename F>
81  struct If<true, T, F> {
82  typedef T Type;
83  };
84 
85  template <typename T,
86  typename F>
87  struct If<false, T, F> {
88  typedef F Type;
89  };
90 
92  // is true if T1 and T2 are identical, and false otherwise.
93  template <typename T1,
94  typename T2>
95  struct IsEqual;
96  template <typename T1,
97  typename T2>
98  struct IsEqual {
99  enum { Value = false };
100  };
101  template <typename T>
102  struct IsEqual<T,T> {
103  enum { Value = true };
104  };
105 
106  // Compile-time selector statement to execute conditional statement based
107  // on the identity of \c C. If C is identical to the NullType
108  // then IfNull<...>::Type is a typedef of T, otherwise, IfNull<...>::Type is a
109  // typedef for F.
110  template <typename C, typename T, typename F>
111  struct IfNull;
112 
113  template <typename C,
114  typename T,
115  typename F>
116  struct IfNull {
117  typedef typename If<IsEqual<NullType, C>::Value, T, F>::Type Type;
118  };
119 
120 }
121 
124 public:
125  ClassifierBase(uint32_t number_of_classes)
126  : number_of_classes_(number_of_classes) {
127  }
129  : number_of_classes_(0) {}
130  virtual ~ClassifierBase() {}
132  return number_of_classes_;
133  }
134 protected:
136 };
137 
140 public:
141  IntegralClassifier(uint32_t number_of_classes,
142  int lower_bound)
143  : ClassifierBase(number_of_classes),
144  lower_bound_(lower_bound) {
145  }
146  uint32_t GetIndexOf(int value) const {
147  uint32_t idx=(value-lower_bound_);
148  assert(this->GetNumberOfClasses()>idx);
149  return idx;
150  }
152  : ClassifierBase(0),
153  lower_bound_(0) {
154  }
155 
156  template <typename DS>
157  void Serialize(DS& ds)
158  {
159  ds & number_of_classes_;
160  ds & lower_bound_;
161  }
162 private:
163  int32_t lower_bound_;
164 };
165 
168 public:
169  ContinuousClassifier(uint32_t number_of_classes,
170  Real lower_bound,
171  Real upper_bound)
172  : ClassifierBase(number_of_classes),
173  lower_bound_(lower_bound),
174  upper_bound_(upper_bound) {
175  }
176  uint32_t GetIndexOf(Real value) const {
177  Real factor=(value-lower_bound_)/(upper_bound_-lower_bound_);
178  uint32_t idx=uint32_t(floor(this->GetNumberOfClasses()*factor));
179 // std::cout << value << " " << factor << std::endl;
180  assert(this->GetNumberOfClasses()>idx);
181  return idx;
182  }
184  : ClassifierBase(1),
185  lower_bound_(0), upper_bound_(1) {
186  }
187  template <typename DS>
188  void Serialize(DS& ds)
189  {
190  ds & number_of_classes_;
191  ds & lower_bound_;
192  ds & upper_bound_;
193  }
194 private:
195  Real lower_bound_;
196  Real upper_bound_;
197 };
198 
199 
200 template <typename T>
201 struct Classifier;
202 
203 template <>
204 struct DLLEXPORT_OST_QA Classifier<int> {
208 };
209 template <>
210 struct DLLEXPORT_OST_QA Classifier<Real> {
214 };
215 #if OST_DOUBLE_PRECISION
216 template <>
217 struct DLLEXPORT_OST_QA Classifier<float> {
218  typedef ContinuousClassifier Type;
219  typedef const ContinuousClassifier& ConstRefType;
220  typedef ContinuousClassifier& RefType;
221 };
222 #endif
223 template <>
224 struct DLLEXPORT_OST_QA Classifier<impl::NullType> {
226  typedef const impl::NullType& ConstRefType;
228 };
229 
230 template <typename I>
233 };
234 template <typename C, typename T, typename I>
235 struct IndexFind;
236 
237 template <typename C, typename I>
238 struct DLLEXPORT_OST_QA IndexFind<C,impl::NullType,I> {
239  IndexFind(const C&,
240  uint32_t,
241  const impl::NullType&, I&) {
242  }
243 };
244 
245 template <typename C, typename T, typename I>
247  IndexFind(const C& classifier, uint32_t i, const T& value, I& index) {
248  index[i]=classifier.GetIndexOf(value);
249  }
250 };
251 template <typename T>
252 struct NumberOfClasses;
253 
254 
255 template <>
256 struct DLLEXPORT_OST_QA NumberOfClasses<impl::NullType> {
257  uint32_t operator ()(const impl::NullType& t) {
258  return 1;
259  }
260 };
261 
262 template <typename T>
264  uint32_t operator ()(const T& t) {
265  return t.GetNumberOfClasses();
266  }
267 };
268 
270 template <typename V, typename T1,
271  typename T2=impl::NullType,
272  typename T3=impl::NullType,
273  typename T4=impl::NullType,
274  typename T5=impl::NullType,
275  typename T6=impl::NullType,
276  typename T7=impl::NullType>
278 public:
280  typedef V ValueType;
281  typedef Index<MultiClassifier::Dimension> IndexType;
283  typedef Classifier<T1> C1;
284  typedef Classifier<T2> C2;
285  typedef Classifier<T3> C3;
286  typedef Classifier<T4> C4;
287  typedef Classifier<T5> C5;
288  typedef Classifier<T6> C6;
289  typedef Classifier<T7> C7;
290 #if WIN32
291  MultiClassifier(const V& initial_value,
292  typename C1::ConstRefType c1,
293  typename C2::ConstRefType c2=C2::Type(),
294  typename C3::ConstRefType c3=C3::Type(),
295  typename C4::ConstRefType c4=C4::Type(),
296  typename C5::ConstRefType c5=C5::Type(),
297  typename C6::ConstRefType c6=C6::Type(),
298  typename C7::ConstRefType c7=C7::Type())
299 #else
300  MultiClassifier(const V& initial_value,
301  typename C1::ConstRefType c1,
302  typename C2::ConstRefType c2=typename C2::Type(),
303  typename C3::ConstRefType c3=typename C3::Type(),
304  typename C4::ConstRefType c4=typename C4::Type(),
305  typename C5::ConstRefType c5=typename C5::Type(),
306  typename C6::ConstRefType c6=typename C6::Type(),
307  typename C7::ConstRefType c7=typename C7::Type())
308 #endif
309  : classifier1_(c1), classifier2_(c2), classifier3_(c3),
310  classifier4_(c4), classifier5_(c5), classifier6_(c6),
311  classifier7_(c7) {
312  this->ExtractNumberOfClasses();
313  // allocate enough memory for all the buckets
314  uint32_t total=this->CalculateNumberOfBuckets();
315  buckets_.resize(total, initial_value);
316  }
317 
319  {
320  memset(number_of_classes_, 0, sizeof(number_of_classes_));
321  }
322 
323  template <typename DS>
324  void Serialize(DS& ds)
325  {
326  ds & classifier1_;
327  ds & classifier2_;
328  ds & classifier3_;
329  ds & classifier4_;
330  ds & classifier5_;
331  ds & classifier6_;
332  ds & classifier7_;
333  if (ds.IsSource()) {
334  this->ExtractNumberOfClasses();
335  }
336  ds & buckets_;
337  }
338 
340  : classifier1_(rhs.classifier1_), classifier2_(rhs.classifier2_),
341  classifier3_(rhs.classifier3_), classifier4_(rhs.classifier4_),
342  classifier5_(rhs.classifier5_), classifier6_(rhs.classifier6_),
343  classifier7_(rhs.classifier7_) {
344  this->ExtractNumberOfClasses();
345  uint32_t total=this->CalculateNumberOfBuckets();
346  buckets_.resize(total);
347  memcpy(&buckets_.front(), &rhs.buckets_.front(), sizeof(V)*total);
348  }
349 
351  return static_cast<uint32_t>(buckets_.size());
352  }
353 
354  void Add(const ValueType& value,
355  T1 x1=T1(), T2 x2=T2(),
356  T3 x3=T3(), T4 x4=T4(),
357  T5 x5=T5(), T6 x6=T6(),
358  T7 x7=T7()) {
359  IndexType index=this->FindBucket(x1, x2, x3, x4, x5, x6, x7);
360  uint32_t linear_index=this->LinearizeBucketIndex(index);
361  buckets_[linear_index]+=value;
362  }
363 
364  const ValueType& Get(T1 x1=T1(), T2 x2=T2(),
365  T3 x3=T3(), T4 x4=T4(),
366  T5 x5=T5(), T6 x6=T6(), T7 x7=T7()) const {
367  IndexType index=this->FindBucket(x1, x2, x3, x4, x5, x6, x7);
368  uint32_t linear_index=this->LinearizeBucketIndex(index);
369  return buckets_[linear_index];
370  }
371 
372  const ValueType& Get(const IndexType& index) const
373  {
374  return buckets_[this->LinearizeBucketIndex(index)];
375  }
376 
377  void Set(const IndexType& index, const ValueType& value)
378  {
379  buckets_[this->LinearizeBucketIndex(index)]=value;
380  }
381  //TODO Make sure that FindBucket is called with the correct number of
382  // arguments. Can be done over a wrapper type around T1..T6 that only
383  // provides a default c'tor when T is equal to NullType.
384  IndexType FindBucket(T1 x1=T1(), T2 x2=T2(), T3 x3=T3(),
385  T4 x4=T4(), T5 x5=T5(), T6 x6=T6(),
386  T7 x7=T7()) const {
387  // determine indices for parameters whose type is not equal to
388  // NullType
389  IndexType index;
390  IndexFind<typename C1::Type, T1,
391  IndexType> find_index_1(classifier1_, 0, x1, index);
392  IndexFind<typename C2::Type, T2,
393  IndexType> find_index_2(classifier2_, 1, x2, index);
394  IndexFind<typename C3::Type, T3,
395  IndexType> find_index_3(classifier3_, 2, x3, index);
396  IndexFind<typename C4::Type, T4,
397  IndexType> find_index_4(classifier4_, 3, x4, index);
398  IndexFind<typename C5::Type, T5,
399  IndexType> find_index_5(classifier5_, 4, x5, index);
400  IndexFind<typename C6::Type, T6,
401  IndexType> find_index_6(classifier6_, 5, x6, index);
402  IndexFind<typename C7::Type, T7,
403  IndexType> find_index_7(classifier7_, 6, x7, index);
404  return index;
405  }
406 
407  void Add(const ValueType& value, const IndexType& index)
408  {
409  buckets_[this->LinearizeBucketIndex(index)]+=value;
410  }
411 private:
412  void ExtractNumberOfClasses()
413  {
414  number_of_classes_[0]=NumberOfClasses<typename C1::Type>()(classifier1_);
415  number_of_classes_[1]=NumberOfClasses<typename C2::Type>()(classifier2_);
416  number_of_classes_[2]=NumberOfClasses<typename C3::Type>()(classifier3_);
417  number_of_classes_[3]=NumberOfClasses<typename C4::Type>()(classifier4_);
418  number_of_classes_[4]=NumberOfClasses<typename C5::Type>()(classifier5_);
419  number_of_classes_[5]=NumberOfClasses<typename C6::Type>()(classifier6_);
420  number_of_classes_[6]=NumberOfClasses<typename C7::Type>()(classifier7_);
421  }
422 
423  uint32_t LinearizeBucketIndex(const IndexType& index) const
424  {
425  uint32_t factor=1;
426  uint32_t linear_index=0;
427  for (uint32_t i=0; i<MultiClassifier::Dimension; ++i) {
428  linear_index+=factor*index[i];
429  factor*=number_of_classes_[i];
430  }
431  return linear_index;
432  }
433 
434  uint32_t CalculateNumberOfBuckets() const
435  {
436  uint32_t total=1;
437  for (uint32_t i=0; i<MultiClassifier::Dimension; ++i) {
438  total*=number_of_classes_[i];
439  }
440  return total;
441  }
442  typename C1::Type classifier1_;
443  typename C2::Type classifier2_;
444  typename C3::Type classifier3_;
445  typename C4::Type classifier4_;
446  typename C5::Type classifier5_;
447  typename C6::Type classifier6_;
448  typename C7::Type classifier7_;
449  uint32_t number_of_classes_[7];
450  std::vector<ValueType> buckets_;
451 };
452 
453 }}
454 
455 #endif