aGrUM  0.16.0
kNML_tpl.h
Go to the documentation of this file.
1 
30 #ifndef DOXYGEN_SHOULD_SKIP_THIS
31 
32 namespace gum {
33 
34  namespace learning {
35 
37  template < template < typename > class ALLOC >
38  INLINE KNML< ALLOC >::KNML(
39  const DBRowGeneratorParser< ALLOC >& parser,
40  const Apriori< ALLOC >& apriori,
41  const std::vector< std::pair< std::size_t, std::size_t >,
42  ALLOC< std::pair< std::size_t, std::size_t > > >& ranges,
43  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
44  nodeId2columns,
45  const typename KNML< ALLOC >::allocator_type& alloc) :
46  IndependenceTest< ALLOC >(parser, apriori, ranges, nodeId2columns, alloc),
47  __param_complexity(alloc) {
48  GUM_CONSTRUCTOR(KNML);
49  }
50 
51 
53  template < template < typename > class ALLOC >
54  INLINE KNML< ALLOC >::KNML(
55  const DBRowGeneratorParser< ALLOC >& parser,
56  const Apriori< ALLOC >& apriori,
57  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
58  nodeId2columns,
59  const typename KNML< ALLOC >::allocator_type& alloc) :
60  IndependenceTest< ALLOC >(parser, apriori, nodeId2columns, alloc),
61  __param_complexity(alloc) {
62  GUM_CONSTRUCTOR(KNML);
63  }
64 
65 
67  template < template < typename > class ALLOC >
68  INLINE
69  KNML< ALLOC >::KNML(const KNML< ALLOC >& from,
70  const typename KNML< ALLOC >::allocator_type& alloc) :
71  IndependenceTest< ALLOC >(from, alloc),
72  __param_complexity(from.__param_complexity, alloc) {
73  GUM_CONS_CPY(KNML);
74  }
75 
76 
78  template < template < typename > class ALLOC >
79  INLINE KNML< ALLOC >::KNML(const KNML< ALLOC >& from) :
80  KNML< ALLOC >(from, from.getAllocator()) {}
81 
82 
84  template < template < typename > class ALLOC >
85  INLINE
86  KNML< ALLOC >::KNML(KNML< ALLOC >&& from,
87  const typename KNML< ALLOC >::allocator_type& alloc) :
88  IndependenceTest< ALLOC >(std::move(from), alloc),
89  __param_complexity(std::move(from.__param_complexity), alloc) {
90  GUM_CONS_MOV(KNML);
91  }
92 
93 
95  template < template < typename > class ALLOC >
96  INLINE KNML< ALLOC >::KNML(KNML< ALLOC >&& from) :
97  KNML< ALLOC >(std::move(from), from.getAllocator()) {}
98 
99 
101  template < template < typename > class ALLOC >
102  KNML< ALLOC >* KNML< ALLOC >::clone(
103  const typename KNML< ALLOC >::allocator_type& alloc) const {
104  ALLOC< KNML< ALLOC > > allocator(alloc);
105  KNML< ALLOC >* new_score = allocator.allocate(1);
106  try {
107  allocator.construct(new_score, *this, alloc);
108  } catch (...) {
109  allocator.deallocate(new_score, 1);
110  throw;
111  }
112 
113  return new_score;
114  }
115 
116 
118  template < template < typename > class ALLOC >
119  KNML< ALLOC >* KNML< ALLOC >::clone() const {
120  return clone(this->getAllocator());
121  }
122 
123 
125  template < template < typename > class ALLOC >
127  GUM_DESTRUCTOR(KNML);
128  }
129 
130 
132  template < template < typename > class ALLOC >
133  KNML< ALLOC >& KNML< ALLOC >::operator=(const KNML< ALLOC >& from) {
134  if (this != &from) {
136  __param_complexity = from.__param_complexity;
137  }
138  return *this;
139  }
140 
141 
143  template < template < typename > class ALLOC >
144  KNML< ALLOC >& KNML< ALLOC >::operator=(KNML< ALLOC >&& from) {
145  if (this != &from) {
146  IndependenceTest< ALLOC >::operator=(std::move(from));
147  __param_complexity = std::move(from.__param_complexity);
148  }
149  return *this;
150  }
151 
152 
154  template < template < typename > class ALLOC >
155  void KNML< ALLOC >::clear() {
157  __param_complexity.clearCache();
158  }
159 
160 
162  template < template < typename > class ALLOC >
165  __param_complexity.clearCache();
166  }
167 
168 
170  template < template < typename > class ALLOC >
171  void KNML< ALLOC >::useCache(const bool on_off) {
173  __param_complexity.useCache(on_off);
174  }
175 
176 
178  template < template < typename > class ALLOC >
179  double KNML< ALLOC >::_score(const IdSet< ALLOC >& idset) {
180  // perform the countings on the database for all the nodes in the idset
181  // This will help optimizing the computations of the Nxui, Nyui and Nui
182  // that we will be needed subsequently
183  this->_counter.counts(idset, true);
184 
185  const bool informative_external_apriori = this->_apriori->isInformative();
186 
187  // get the domain sizes of X and Y
188  const auto& db = this->database();
189  const auto& node2cols = this->nodeId2Columns();
190  std::size_t r_x, r_y;
191  if (!node2cols.empty()) {
192  r_x = db.domainSize(node2cols.second(idset[0]));
193  r_y = db.domainSize(node2cols.second(idset[1]));
194  } else {
195  r_x = db.domainSize(idset[0]);
196  r_y = db.domainSize(idset[1]);
197  }
198 
199 
200  // here, we distinguish idsets with conditioning nodes from those
201  // without conditioning nodes
202  if (idset.hasConditioningSet()) {
203  // now get the Nxui, Nyui and Nui
204  IdSet< ALLOC > idset_xui = idset;
205  idset_xui.erase(idset[1]);
206  IdSet< ALLOC > idset_yui = idset;
207  idset_yui.erase(idset[0]);
208 
209  std::vector< double, ALLOC< double > > N_ui =
210  this->_counter.counts(idset.conditionalIdSet(), false);
211  std::vector< double, ALLOC< double > > N_xui =
212  this->_counter.counts(idset_xui, false);
213  std::vector< double, ALLOC< double > > N_yui =
214  this->_counter.counts(idset_yui, false);
215 
216  if (informative_external_apriori) {
217  this->_apriori->addConditioningApriori(idset, N_ui);
218  this->_apriori->addAllApriori(idset, N_xui);
219  this->_apriori->addAllApriori(idset, N_yui);
220  }
221 
222 
223  // the value of kNML is equal to:
224  // 0.5 * sum_Z ( sum_X( log( C^(r_y)_#ZX ) ) - log( C^(r_y)_#Z ) +
225  // sum_Y( log( C^(r_x)_#ZY ) ) - log( C^(r_x)_#Z ) )
226  double score = 0.0;
227  for (auto n_xui : N_xui)
228  score += __param_complexity.log2Cnr(r_y, n_xui);
229  for (auto n_yui : N_yui)
230  score += __param_complexity.log2Cnr(r_x, n_yui);
231  for (auto n_ui : N_ui) {
232  score -= __param_complexity.log2Cnr(r_y, n_ui);
233  score -= __param_complexity.log2Cnr(r_x, n_ui);
234  }
235 
236  score *= 0.5;
237 
238  return score;
239  } else {
240  // here, there is no conditioning set
241  // now get the Nxui, Nyui and Nui
242  IdSet< ALLOC > idset_xui(idset[0], this->_empty_ids, true);
243  IdSet< ALLOC > idset_yui(idset[1], this->_empty_ids, true);
244 
245  std::vector< double, ALLOC< double > > N_xui =
246  this->_counter.counts(idset_xui, false);
247  std::vector< double, ALLOC< double > > N_yui =
248  this->_counter.counts(idset_yui, false);
249 
250  if (informative_external_apriori) {
251  this->_apriori->addAllApriori(idset, N_xui);
252  this->_apriori->addAllApriori(idset, N_yui);
253  }
254 
255 
256  // so, the formula for kNML is:
257  // 0.5 * ( sum_X( log( C^(r_y)_#X ) ) - log( C^(r_y)_N ) +
258  // sum_Y( log( C^(r_x)_#Y ) ) - log( C^(r_x)_N ) )
259  double N = 0.0;
260  double score = 0.0;
261  for (auto n_xui : N_xui) {
262  score += __param_complexity.log2Cnr(r_y, n_xui);
263  N += n_xui;
264  }
265  for (auto n_yui : N_yui)
266  score += __param_complexity.log2Cnr(r_x, n_yui);
267  score -= __param_complexity.log2Cnr(r_y, N);
268  score -= __param_complexity.log2Cnr(r_x, N);
269 
270  score *= 0.5;
271 
272  return score;
273  }
274  }
275 
276  } /* namespace learning */
277 
278 } /* namespace gum */
279 
280 #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:53
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
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
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:98
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