aGrUM  0.14.2
kNML_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  ***************************************************************************/
27 #ifndef DOXYGEN_SHOULD_SKIP_THIS
28 
29 namespace gum {
30 
31  namespace learning {
32 
34  template < template < typename > class ALLOC >
35  INLINE KNML< ALLOC >::KNML(
36  const DBRowGeneratorParser< ALLOC >& parser,
37  const Apriori< ALLOC >& apriori,
38  const std::vector< std::pair< std::size_t, std::size_t >,
39  ALLOC< std::pair< std::size_t, std::size_t > > >& ranges,
40  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
41  nodeId2columns,
42  const typename KNML< ALLOC >::allocator_type& alloc) :
43  IndependenceTest< ALLOC >(parser, apriori, ranges, nodeId2columns, alloc),
44  __param_complexity(alloc) {
45  GUM_CONSTRUCTOR(KNML);
46  }
47 
48 
50  template < template < typename > class ALLOC >
51  INLINE KNML< ALLOC >::KNML(
52  const DBRowGeneratorParser< ALLOC >& parser,
53  const Apriori< ALLOC >& apriori,
54  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
55  nodeId2columns,
56  const typename KNML< ALLOC >::allocator_type& alloc) :
57  IndependenceTest< ALLOC >(parser, apriori, nodeId2columns, alloc),
58  __param_complexity(alloc) {
59  GUM_CONSTRUCTOR(KNML);
60  }
61 
62 
64  template < template < typename > class ALLOC >
65  INLINE
66  KNML< ALLOC >::KNML(const KNML< ALLOC >& from,
67  const typename KNML< ALLOC >::allocator_type& alloc) :
68  IndependenceTest< ALLOC >(from, alloc),
69  __param_complexity(from.__param_complexity, alloc) {
70  GUM_CONS_CPY(KNML);
71  }
72 
73 
75  template < template < typename > class ALLOC >
76  INLINE KNML< ALLOC >::KNML(const KNML< ALLOC >& from) :
77  KNML< ALLOC >(from, from.getAllocator()) {}
78 
79 
81  template < template < typename > class ALLOC >
82  INLINE
83  KNML< ALLOC >::KNML(KNML< ALLOC >&& from,
84  const typename KNML< ALLOC >::allocator_type& alloc) :
85  IndependenceTest< ALLOC >(std::move(from), alloc),
86  __param_complexity(std::move(from.__param_complexity), alloc) {
87  GUM_CONS_MOV(KNML);
88  }
89 
90 
92  template < template < typename > class ALLOC >
93  INLINE KNML< ALLOC >::KNML(KNML< ALLOC >&& from) :
94  KNML< ALLOC >(std::move(from), from.getAllocator()) {}
95 
96 
98  template < template < typename > class ALLOC >
99  KNML< ALLOC >* KNML< ALLOC >::clone(
100  const typename KNML< ALLOC >::allocator_type& alloc) const {
101  ALLOC< KNML< ALLOC > > allocator(alloc);
102  KNML< ALLOC >* new_score = allocator.allocate(1);
103  try {
104  allocator.construct(new_score, *this, alloc);
105  } catch (...) {
106  allocator.deallocate(new_score, 1);
107  throw;
108  }
109 
110  return new_score;
111  }
112 
113 
115  template < template < typename > class ALLOC >
116  KNML< ALLOC >* KNML< ALLOC >::clone() const {
117  return clone(this->getAllocator());
118  }
119 
120 
122  template < template < typename > class ALLOC >
124  GUM_DESTRUCTOR(KNML);
125  }
126 
127 
129  template < template < typename > class ALLOC >
130  KNML< ALLOC >& KNML< ALLOC >::operator=(const KNML< ALLOC >& from) {
131  if (this != &from) {
133  __param_complexity = from.__param_complexity;
134  }
135  return *this;
136  }
137 
138 
140  template < template < typename > class ALLOC >
141  KNML< ALLOC >& KNML< ALLOC >::operator=(KNML< ALLOC >&& from) {
142  if (this != &from) {
143  IndependenceTest< ALLOC >::operator=(std::move(from));
144  __param_complexity = std::move(from.__param_complexity);
145  }
146  return *this;
147  }
148 
149 
151  template < template < typename > class ALLOC >
152  void KNML< ALLOC >::clear() {
154  __param_complexity.clearCache();
155  }
156 
157 
159  template < template < typename > class ALLOC >
162  __param_complexity.clearCache();
163  }
164 
165 
167  template < template < typename > class ALLOC >
168  void KNML< ALLOC >::useCache(const bool on_off) {
170  __param_complexity.useCache(on_off);
171  }
172 
173 
175  template < template < typename > class ALLOC >
176  double KNML< ALLOC >::_score(const IdSet< ALLOC >& idset) {
177  // perform the countings on the database for all the nodes in the idset
178  // This will help optimizing the computations of the Nxui, Nyui and Nui
179  // that we will be needed subsequently
180  this->_counter.counts(idset, true);
181 
182  const bool informative_external_apriori = this->_apriori->isInformative();
183 
184  // get the domain sizes of X and Y
185  const auto& db = this->database();
186  const auto& node2cols = this->nodeId2Columns();
187  std::size_t r_x, r_y;
188  if (!node2cols.empty()) {
189  r_x = db.domainSize(node2cols.second(idset[0]));
190  r_y = db.domainSize(node2cols.second(idset[1]));
191  } else {
192  r_x = db.domainSize(idset[0]);
193  r_y = db.domainSize(idset[1]);
194  }
195 
196 
197  // here, we distinguish idsets with conditioning nodes from those
198  // without conditioning nodes
199  if (idset.hasConditioningSet()) {
200  // now get the Nxui, Nyui and Nui
201  IdSet< ALLOC > idset_xui = idset;
202  idset_xui.erase(idset[1]);
203  IdSet< ALLOC > idset_yui = idset;
204  idset_yui.erase(idset[0]);
205 
206  std::vector< double, ALLOC< double > > N_ui =
207  this->_counter.counts(idset.conditionalIdSet(), false);
208  std::vector< double, ALLOC< double > > N_xui =
209  this->_counter.counts(idset_xui, false);
210  std::vector< double, ALLOC< double > > N_yui =
211  this->_counter.counts(idset_yui, false);
212 
213  if (informative_external_apriori) {
214  this->_apriori->addConditioningApriori(idset, N_ui);
215  this->_apriori->addAllApriori(idset, N_xui);
216  this->_apriori->addAllApriori(idset, N_yui);
217  }
218 
219 
220  // the value of kNML is equal to:
221  // 0.5 * sum_Z ( sum_X( log( C^(r_y)_#ZX ) ) - log( C^(r_y)_#Z ) +
222  // sum_Y( log( C^(r_x)_#ZY ) ) - log( C^(r_x)_#Z ) )
223  double score = 0.0;
224  for (auto n_xui : N_xui)
225  score += __param_complexity.log2Cnr(r_y, n_xui);
226  for (auto n_yui : N_yui)
227  score += __param_complexity.log2Cnr(r_x, n_yui);
228  for (auto n_ui : N_ui) {
229  score -= __param_complexity.log2Cnr(r_y, n_ui);
230  score -= __param_complexity.log2Cnr(r_x, n_ui);
231  }
232 
233  score *= 0.5;
234 
235  return score;
236  } else {
237  // here, there is no conditioning set
238  // now get the Nxui, Nyui and Nui
239  IdSet< ALLOC > idset_xui(idset[0], this->_empty_ids, true);
240  IdSet< ALLOC > idset_yui(idset[1], this->_empty_ids, true);
241 
242  std::vector< double, ALLOC< double > > N_xui =
243  this->_counter.counts(idset_xui, false);
244  std::vector< double, ALLOC< double > > N_yui =
245  this->_counter.counts(idset_yui, false);
246 
247  if (informative_external_apriori) {
248  this->_apriori->addAllApriori(idset, N_xui);
249  this->_apriori->addAllApriori(idset, N_yui);
250  }
251 
252 
253  // so, the formula for kNML is:
254  // 0.5 * ( sum_X( log( C^(r_y)_#X ) ) - log( C^(r_y)_N ) +
255  // sum_Y( log( C^(r_x)_#Y ) ) - log( C^(r_x)_N ) )
256  double N = 0.0;
257  double score = 0.0;
258  for (auto n_xui : N_xui) {
259  score += __param_complexity.log2Cnr(r_y, n_xui);
260  N += n_xui;
261  }
262  for (auto n_yui : N_yui)
263  score += __param_complexity.log2Cnr(r_x, n_yui);
264  score -= __param_complexity.log2Cnr(r_y, N);
265  score -= __param_complexity.log2Cnr(r_x, N);
266 
267  score *= 0.5;
268 
269  return score;
270  }
271  }
272 
273  } /* namespace learning */
274 
275 } /* namespace gum */
276 
277 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
RecordCounter< ALLOC > _counter
the record counter used for the countings over discrete variables
ALLOC< NodeId > allocator_type
type for the allocators passed in arguments of methods
Definition: kNML.h:50
STL namespace.
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
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
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
virtual void clear()
clears all the data structures from memory, including the C_n^r cache
virtual ~KNML()
destructor
IndependenceTest< ALLOC > & operator=(const IndependenceTest< ALLOC > &from)
copy operator
virtual double _score(const IdSet< ALLOC > &idset) final
returns the score for a given IdSet
double score(const NodeId var1, const NodeId var2)
returns the score of a pair of nodes
virtual void clearCache()
clears the current C_n^r cache
KNML< ALLOC > & operator=(const KNML< ALLOC > &from)
copy operator
virtual void useCache(const bool on_off)
turn on/off the use of a cache of the previously computed score
virtual void useCache(const bool on_off)
turn on/off the use of the C_n^r cache
virtual KNML< ALLOC > * clone() const
virtual copy constructor
Size NodeId
Type for node ids.
Definition: graphElements.h:97
virtual void clear()
clears all the data structures from memory, including the cache
KNML(const DBRowGeneratorParser< ALLOC > &parser, const Apriori< ALLOC > &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
Apriori< ALLOC > * _apriori
the expert knowledge a priori we add to the contongency tables