aGrUM  0.14.2
independenceTest_tpl.h
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005 by Christophe GONZALES and Pierre-Henri WUILLEMIN *
3  * {prenom.nom}_at_lip6.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
25 #ifndef DOXYGEN_SHOULD_SKIP_THIS
26 
27 namespace gum {
28 
29  namespace learning {
30 
32  template < template < typename > class ALLOC >
35  return _counter.getAllocator();
36  }
37 
38 
40  template < template < typename > class ALLOC >
42  const DBRowGeneratorParser< ALLOC >& parser,
43  const Apriori< ALLOC >& apriori,
44  const std::vector< std::pair< std::size_t, std::size_t >,
45  ALLOC< std::pair< std::size_t, std::size_t > > >& ranges,
46  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
47  nodeId2columns,
48  const typename IndependenceTest< ALLOC >::allocator_type& alloc) :
49  _apriori(apriori.clone(alloc)),
50  _counter(parser, ranges, nodeId2columns, alloc), _cache(alloc) {
51  GUM_CONSTRUCTOR(IndependenceTest);
52  }
53 
54 
56  template < template < typename > class ALLOC >
58  const DBRowGeneratorParser< ALLOC >& parser,
59  const Apriori< ALLOC >& apriori,
60  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
61  nodeId2columns,
62  const typename IndependenceTest< ALLOC >::allocator_type& alloc) :
63  _apriori(apriori.clone(alloc)),
64  _counter(parser, nodeId2columns, alloc), _cache(alloc) {
65  GUM_CONSTRUCTOR(IndependenceTest);
66  }
67 
68 
70  template < template < typename > class ALLOC >
72  const IndependenceTest< ALLOC >& from,
73  const typename IndependenceTest< ALLOC >::allocator_type& alloc) :
74  _apriori(from._apriori->clone(alloc)),
75  _counter(from._counter, alloc), _cache(from._cache, alloc),
76  _use_cache(from._use_cache) {
77  GUM_CONS_CPY(IndependenceTest);
78  }
79 
80 
82  template < template < typename > class ALLOC >
84  const IndependenceTest< ALLOC >& from) :
85  IndependenceTest(from, from.getAllocator()) {}
86 
87 
89  template < template < typename > class ALLOC >
91  IndependenceTest< ALLOC >&& from,
92  const typename IndependenceTest< ALLOC >::allocator_type& alloc) :
93  _apriori(from._apriori),
94  _counter(std::move(from._counter), alloc),
95  _cache(std::move(from._cache), alloc), _use_cache(from._use_cache) {
96  from._apriori = nullptr;
97  GUM_CONS_MOV(IndependenceTest);
98  }
99 
100 
102  template < template < typename > class ALLOC >
104  IndependenceTest< ALLOC >&& from) :
105  IndependenceTest(std::move(from), from.getAllocator()) {}
106 
107 
109  template < template < typename > class ALLOC >
111  if (_apriori != nullptr) {
112  ALLOC< Apriori< ALLOC > > allocator(this->getAllocator());
113  allocator.destroy(_apriori);
114  allocator.deallocate(_apriori, 1);
115  }
116  GUM_DESTRUCTOR(IndependenceTest);
117  }
118 
119 
121  template < template < typename > class ALLOC >
122  IndependenceTest< ALLOC >& IndependenceTest< ALLOC >::
123  operator=(const IndependenceTest< ALLOC >& from) {
124  if (this != &from) {
125  Apriori< ALLOC >* new_apriori = from._apriori->clone();
126  RecordCounter< ALLOC > new_counter = from._counter;
127  ScoringCache< ALLOC > new_cache = from._cache;
128 
129  if (_apriori != nullptr) {
130  ALLOC< Apriori< ALLOC > > allocator(this->getAllocator());
131  allocator.destroy(_apriori);
132  allocator.deallocate(_apriori, 1);
133  }
134 
135  _apriori = new_apriori;
136  _counter = std::move(new_counter);
137  _cache = std::move(new_cache);
138 
139  _use_cache = from._use_cache;
140  }
141  return *this;
142  }
143 
144 
146  template < template < typename > class ALLOC >
147  IndependenceTest< ALLOC >& IndependenceTest< ALLOC >::
148  operator=(IndependenceTest< ALLOC >&& from) {
149  if (this != &from) {
150  std::swap(_apriori, from._apriori);
151 
152  _counter = std::move(from._counter);
153  _cache = std::move(from._cache);
154  _use_cache = from._use_cache;
155  }
156  return *this;
157  }
158 
159 
161  template < template < typename > class ALLOC >
162  INLINE void IndependenceTest< ALLOC >::setMaxNbThreads(std::size_t nb) const {
163  _counter.setMaxNbThreads(nb);
164  }
165 
166 
168  template < template < typename > class ALLOC >
169  INLINE std::size_t IndependenceTest< ALLOC >::nbThreads() const {
170  return _counter.nbThreads();
171  }
172 
173 
176  template < template < typename > class ALLOC >
178  const std::size_t nb) const {
179  _counter.setMinNbRowsPerThread(nb);
180  }
181 
182 
184  template < template < typename > class ALLOC >
185  INLINE std::size_t IndependenceTest< ALLOC >::minNbRowsPerThread() const {
186  return _counter.minNbRowsPerThread();
187  }
188 
189 
191 
197  template < template < typename > class ALLOC >
198  template < template < typename > class XALLOC >
200  const std::vector< std::pair< std::size_t, std::size_t >,
201  XALLOC< std::pair< std::size_t, std::size_t > > >&
202  new_ranges) {
203  std::vector< std::pair< std::size_t, std::size_t >,
204  ALLOC< std::pair< std::size_t, std::size_t > > >
205  old_ranges = ranges();
206  _counter.setRanges(new_ranges);
207  if (old_ranges != ranges()) clear();
208  }
209 
210 
212  template < template < typename > class ALLOC >
214  std::vector< std::pair< std::size_t, std::size_t >,
215  ALLOC< std::pair< std::size_t, std::size_t > > >
216  old_ranges = ranges();
217  _counter.clearRanges();
218  if (old_ranges != ranges()) clear();
219  }
220 
221 
223  template < template < typename > class ALLOC >
224  INLINE const std::vector< std::pair< std::size_t, std::size_t >,
225  ALLOC< std::pair< std::size_t, std::size_t > > >&
227  return _counter.ranges();
228  }
229 
230 
232  template < template < typename > class ALLOC >
233  INLINE double IndependenceTest< ALLOC >::score(const NodeId var1,
234  const NodeId var2) {
235  IdSet< ALLOC > idset(
236  var1, var2, _empty_ids, false, true, this->getAllocator());
237  if (_use_cache) {
238  try {
239  return _cache.score(idset);
240  } catch (NotFound&) {}
241  double the_score = _score(idset);
242  _cache.insert(std::move(idset), the_score);
243  return the_score;
244  } else {
245  return _score(std::move(idset));
246  }
247  }
248 
249 
251  template < template < typename > class ALLOC >
252  INLINE double IndependenceTest< ALLOC >::score(
253  const NodeId var1,
254  const NodeId var2,
255  const std::vector< NodeId, ALLOC< NodeId > >& rhs_ids) {
256  IdSet< ALLOC > idset(
257  var1, var2, rhs_ids, false, false, this->getAllocator());
258  if (_use_cache) {
259  try {
260  return _cache.score(idset);
261  } catch (NotFound&) {}
262  double the_score = _score(idset);
263  _cache.insert(std::move(idset), the_score);
264  return the_score;
265  } else {
266  return _score(idset);
267  }
268  }
269 
270 
272  template < template < typename > class ALLOC >
273  INLINE void IndependenceTest< ALLOC >::clear() {
274  _counter.clear();
275  _cache.clear();
276  }
277 
278 
280  template < template < typename > class ALLOC >
282  _cache.clear();
283  }
284 
285 
287  template < template < typename > class ALLOC >
288  INLINE void IndependenceTest< ALLOC >::useCache(const bool on_off) {
289  _use_cache = on_off;
290  }
291 
292 
294  template < template < typename > class ALLOC >
295  INLINE const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
297  return _counter.nodeId2Columns();
298  }
299 
300 
302  template < template < typename > class ALLOC >
303  INLINE const DatabaseTable< ALLOC >&
305  return _counter.database();
306  }
307 
308 
310 
315  template < template < typename > class ALLOC >
316  std::vector< double, ALLOC< double > > IndependenceTest< ALLOC >::_marginalize(
317  const std::size_t node_2_marginalize,
318  const std::size_t X_size,
319  const std::size_t Y_size,
320  const std::size_t Z_size,
321  const std::vector< double, ALLOC< double > >& N_xyz) const {
322  // determine the size of the output vector
323  std::size_t out_size = Z_size;
324  if (node_2_marginalize == std::size_t(0))
325  out_size *= Y_size;
326  else if (node_2_marginalize == std::size_t(1))
327  out_size *= X_size;
328 
329  // allocate the output vector
330  std::vector< double, ALLOC< double > > res(out_size, 0.0);
331 
332  // fill the vector:
333  if (node_2_marginalize == std::size_t(0)) { // marginalize X
334  for (std::size_t yz = std::size_t(0), xyz = std::size_t(0); yz < out_size;
335  ++yz) {
336  for (std::size_t x = std::size_t(0); x < X_size; ++x, ++xyz) {
337  res[yz] += N_xyz[xyz];
338  }
339  }
340  } else if (node_2_marginalize == std::size_t(1)) { // marginalize Y
341  for (std::size_t z = std::size_t(0),
342  xyz = std::size_t(0),
343  beg_xz = std::size_t(0);
344  z < Z_size;
345  ++z, beg_xz += X_size) {
346  for (std::size_t y = std::size_t(0); y < Y_size; ++y) {
347  for (std::size_t x = std::size_t(0), xz = beg_xz; x < X_size;
348  ++x, ++xz, ++xyz) {
349  res[xz] += N_xyz[xyz];
350  }
351  }
352  }
353  } else if (node_2_marginalize == std::size_t(2)) { // marginalize X and Y
354  const std::size_t XY_size = X_size * Y_size;
355  for (std::size_t z = std::size_t(0), xyz = std::size_t(0); z < out_size;
356  ++z) {
357  for (std::size_t xy = std::size_t(0); xy < XY_size; ++xy, ++xyz) {
358  res[z] += N_xyz[xyz];
359  }
360  }
361  } else {
362  GUM_ERROR(NotImplementedYet,
363  "_marginalize not implemented for nodeset "
364  << node_2_marginalize);
365  }
366 
367  return res;
368  }
369 
370  } /* namespace learning */
371 
372 } /* namespace gum */
373 
374 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
ScoringCache< ALLOC > _cache
the scoring cache
std::vector< double, ALLOC< double > > _marginalize(const std::size_t node_2_marginalize, const std::size_t X_size, const std::size_t Y_size, const std::size_t Z_size, const std::vector< double, ALLOC< double > > &N_xyz) const
returns a counting vector where variables are marginalized from N_xyz
ALLOC< NodeId > allocator_type
type for the allocators passed in arguments of methods
RecordCounter< ALLOC > _counter
the record counter used for the countings over discrete variables
virtual std::size_t minNbRowsPerThread() const
returns the minimum of rows that each thread should process
STL namespace.
const std::vector< std::pair< std::size_t, std::size_t >, ALLOC< std::pair< std::size_t, std::size_t > > > & ranges() const
returns the current ranges
void swap(HashTable< LpCol, double > *&a, HashTable< LpCol, double > *&b)
Swap the addresses of two pointers to hashTables.
virtual void clearCache()
clears the current cache
const DatabaseTable< ALLOC > & database() const
return the database used by the score
const Bijection< NodeId, std::size_t, ALLOC< std::size_t > > & nodeId2Columns() const
return the mapping between the columns of the database and the node ids
virtual void setMinNbRowsPerThread(const std::size_t nb) const
changes the number min of rows a thread should process in a multithreading context ...
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
virtual double _score(const IdSet< ALLOC > &idset)=0
returns the score for a given IdSet
const std::vector< NodeId, ALLOC< NodeId > > _empty_ids
an empty vector
IndependenceTest(const DBRowGeneratorParser< ALLOC > &parser, const Apriori< ALLOC > &external_apriori, const std::vector< std::pair< std::size_t, std::size_t >, ALLOC< std::pair< std::size_t, std::size_t > > > &ranges, const Bijection< NodeId, std::size_t, ALLOC< std::size_t > > &nodeId2columns=Bijection< NodeId, std::size_t, ALLOC< std::size_t > >(), const allocator_type &alloc=allocator_type())
default constructor
allocator_type getAllocator() const
returns the allocator used by the score
void clearRanges()
reset the ranges to the one range corresponding to the whole database
virtual IndependenceTest< ALLOC > * clone() const =0
virtual copy constructor
virtual void setMaxNbThreads(std::size_t nb) const
changes the max number of threads used to parse the database
IndependenceTest< ALLOC > & operator=(const IndependenceTest< ALLOC > &from)
copy operator
double score(const NodeId var1, const NodeId var2)
returns the score of a pair of nodes
virtual ~IndependenceTest()
destructor
bool _use_cache
a Boolean indicating whether we wish to use the cache
virtual void useCache(const bool on_off)
turn on/off the use of a cache of the previously computed score
virtual std::size_t nbThreads() const
returns the number of threads used to parse the database
Size NodeId
Type for node ids.
Definition: graphElements.h:97
virtual void clear()
clears all the data structures from memory, including the cache
#define GUM_ERROR(type, msg)
Definition: exceptions.h:52
void setRanges(const std::vector< std::pair< std::size_t, std::size_t >, XALLOC< std::pair< std::size_t, std::size_t > > > &new_ranges)
sets new ranges to perform the countings used by the independence test
Apriori< ALLOC > * _apriori
the expert knowledge a priori we add to the contongency tables