aGrUM  0.16.0
scoreBDeu_tpl.h
Go to the documentation of this file.
1 
29 #ifndef DOXYGEN_SHOULD_SKIP_THIS
30 
32 # include <sstream>
33 
34 namespace gum {
35 
36  namespace learning {
37 
39  template < template < typename > class ALLOC >
41  const DBRowGeneratorParser< ALLOC >& parser,
42  const Apriori< ALLOC >& apriori,
43  const std::vector< std::pair< std::size_t, std::size_t >,
44  ALLOC< std::pair< std::size_t, std::size_t > > >& ranges,
45  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
46  nodeId2columns,
47  const typename ScoreBDeu< ALLOC >::allocator_type& alloc) :
48  Score< ALLOC >(parser, apriori, ranges, nodeId2columns, alloc),
49  __internal_apriori(parser.database(), nodeId2columns) {
50  GUM_CONSTRUCTOR(ScoreBDeu);
51  }
52 
53 
55  template < template < typename > class ALLOC >
57  const DBRowGeneratorParser< ALLOC >& parser,
58  const Apriori< ALLOC >& apriori,
59  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
60  nodeId2columns,
61  const typename ScoreBDeu< ALLOC >::allocator_type& alloc) :
62  Score< ALLOC >(parser, apriori, nodeId2columns, alloc),
63  __internal_apriori(parser.database(), nodeId2columns) {
64  GUM_CONSTRUCTOR(ScoreBDeu);
65  }
66 
67 
69  template < template < typename > class ALLOC >
71  const ScoreBDeu< ALLOC >& from,
72  const typename ScoreBDeu< ALLOC >::allocator_type& alloc) :
73  Score< ALLOC >(from, alloc),
74  __internal_apriori(from.__internal_apriori, alloc),
75  __gammalog2(from.__gammalog2) {
76  GUM_CONS_CPY(ScoreBDeu);
77  }
78 
79 
81  template < template < typename > class ALLOC >
82  INLINE ScoreBDeu< ALLOC >::ScoreBDeu(const ScoreBDeu< ALLOC >& from) :
83  ScoreBDeu< ALLOC >(from, from.getAllocator()) {}
84 
85 
87  template < template < typename > class ALLOC >
89  ScoreBDeu< ALLOC >&& from,
90  const typename ScoreBDeu< ALLOC >::allocator_type& alloc) :
91  Score< ALLOC >(std::move(from), alloc),
92  __internal_apriori(std::move(from.__internal_apriori), alloc),
93  __gammalog2(std::move(from.__gammalog2)) {
94  GUM_CONS_MOV(ScoreBDeu);
95  }
96 
97 
99  template < template < typename > class ALLOC >
100  INLINE ScoreBDeu< ALLOC >::ScoreBDeu(ScoreBDeu< ALLOC >&& from) :
101  ScoreBDeu< ALLOC >(std::move(from), from.getAllocator()) {}
102 
103 
105  template < template < typename > class ALLOC >
106  ScoreBDeu< ALLOC >* ScoreBDeu< ALLOC >::clone(
107  const typename ScoreBDeu< ALLOC >::allocator_type& alloc) const {
108  ALLOC< ScoreBDeu< ALLOC > > allocator(alloc);
109  ScoreBDeu< ALLOC >* new_score = allocator.allocate(1);
110  try {
111  allocator.construct(new_score, *this, alloc);
112  } catch (...) {
113  allocator.deallocate(new_score, 1);
114  throw;
115  }
116 
117  return new_score;
118  }
119 
120 
122  template < template < typename > class ALLOC >
123  ScoreBDeu< ALLOC >* ScoreBDeu< ALLOC >::clone() const {
124  return clone(this->getAllocator());
125  }
126 
127 
129  template < template < typename > class ALLOC >
131  GUM_DESTRUCTOR(ScoreBDeu);
132  }
133 
134 
136  template < template < typename > class ALLOC >
137  ScoreBDeu< ALLOC >& ScoreBDeu< ALLOC >::
138  operator=(const ScoreBDeu< ALLOC >& from) {
139  if (this != &from) {
141  __internal_apriori = from.__internal_apriori;
142  }
143  return *this;
144  }
145 
146 
148  template < template < typename > class ALLOC >
149  ScoreBDeu< ALLOC >& ScoreBDeu< ALLOC >::operator=(ScoreBDeu< ALLOC >&& from) {
150  if (this != &from) {
151  Score< ALLOC >::operator=(std::move(from));
152  __internal_apriori = std::move(from.__internal_apriori);
153  }
154  return *this;
155  }
156 
157 
159  template < template < typename > class ALLOC >
160  std::string
161  ScoreBDeu< ALLOC >::isAprioriCompatible(const std::string& apriori_type,
162  double weight) {
163  // check that the apriori is compatible with the score
164  if (apriori_type == AprioriNoAprioriType::type) { return ""; }
165 
166  if (weight == 0.0) {
167  return "The apriori is currently compatible with the BDeu score but "
168  "if you change the weight, it will become incompatible.";
169  }
170 
171  // known incompatible aprioris
172  if ((apriori_type == AprioriDirichletType::type)
173  || (apriori_type == AprioriSmoothingType::type)) {
174  return "The BDeu score already contains a different 'implicit' apriori. "
175  "Therefore, the learning will probably be biased.";
176  }
177 
178  // apriori types unsupported by the type checker
179  std::stringstream msg;
180  msg << "The apriori '" << apriori_type
181  << "' is not yet supported by method isAprioriCompatible os Score BDeu";
182  return msg.str();
183  }
184 
185 
187  template < template < typename > class ALLOC >
188  INLINE std::string
189  ScoreBDeu< ALLOC >::isAprioriCompatible(const Apriori< ALLOC >& apriori) {
190  return isAprioriCompatible(apriori.getType(), apriori.weight());
191  }
192 
193 
195  template < template < typename > class ALLOC >
196  INLINE std::string ScoreBDeu< ALLOC >::isAprioriCompatible() const {
197  return isAprioriCompatible(*(this->_apriori));
198  }
199 
200 
202  template < template < typename > class ALLOC >
203  INLINE const Apriori< ALLOC >& ScoreBDeu< ALLOC >::internalApriori() const {
204  return __internal_apriori;
205  }
206 
207 
209  template < template < typename > class ALLOC >
210  INLINE void ScoreBDeu< ALLOC >::setEffectiveSampleSize(double ess) {
211  if (ess < 0) {
212  GUM_ERROR(OutOfBounds,
213  "The effective sample size of the BDeu's "
214  "internal apriori must be positive");
215  } else {
216  __internal_apriori.setEffectiveSampleSize(ess);
217  }
218  }
219 
220 
222  template < template < typename > class ALLOC >
223  double ScoreBDeu< ALLOC >::_score(const IdSet< ALLOC >& idset) {
224  // get the counts for all the nodes in the idset and add the apriori
225  std::vector< double, ALLOC< double > > N_ijk(
226  this->_counter.counts(idset, true));
227  const std::size_t all_size = N_ijk.size();
228 
229  double score = 0.0;
230  const double ess = __internal_apriori.weight();
231  const bool informative_external_apriori = this->_apriori->isInformative();
232 
233 
234  // here, we distinguish idsets with conditioning nodes from those
235  // without conditioning nodes
236  if (idset.hasConditioningSet()) {
237  // get the counts for the conditioning nodes
238  std::vector< double, ALLOC< double > > N_ij(
239  this->_marginalize(idset[0], N_ijk));
240  const std::size_t conditioning_size = N_ij.size();
241  const double ess_qi = ess / conditioning_size;
242  const double ess_riqi = ess / all_size;
243 
244  if (informative_external_apriori) {
245  // the score to compute is that of BD with aprioris
246  // N'_ijk + ESS / (r_i * q_i )
247  // (the + ESS / (r_i * q_i ) is here to take into account the
248  // internal apriori of BDeu)
249  std::vector< double, ALLOC< double > > N_prime_ijk(all_size, 0.0);
250  this->_apriori->addAllApriori(idset, N_prime_ijk);
251  std::vector< double, ALLOC< double > > N_prime_ij(N_ij.size(), 0.0);
252  this->_apriori->addConditioningApriori(idset, N_prime_ij);
253 
254  // the BDeu score can be computed as follows:
255  // sum_j=1^qi [ gammalog2 ( N'_ij + ESS / q_i ) -
256  // gammalog2 ( N_ij + N'_ij + ESS / q_i )
257  // + sum_k=1^ri { gammlog2 ( N_ijk + N'_ijk + ESS / (r_i * q_i ) )
258  // - gammalog2 ( N'_ijk + ESS / (r_i * q_i ) ) } ]
259  for (std::size_t j = std::size_t(0); j < conditioning_size; ++j) {
260  score += __gammalog2(N_prime_ij[j] + ess_qi)
261  - __gammalog2(N_ij[j] + N_prime_ij[j] + ess_qi);
262  }
263  for (std::size_t k = std::size_t(0); k < all_size; ++k) {
264  score += __gammalog2(N_ijk[k] + N_prime_ijk[k] + ess_riqi)
265  - __gammalog2(N_prime_ijk[k] + ess_riqi);
266  }
267  } else {
268  // the BDeu score can be computed as follows:
269  // qi * gammalog2 (ess / qi) - ri * qi * gammalog2 (ess / (ri * qi) )
270  // - sum_j=1^qi [ gammalog2 ( N_ij + ess / qi ) ]
271  // + sum_j=1^qi sum_k=1^ri log [ gammalog2 ( N_ijk + ess / (ri * qi) )
272  // ]
273  score = conditioning_size * __gammalog2(ess_qi)
274  - all_size * __gammalog2(ess_riqi);
275 
276  for (const auto n_ij : N_ij) {
277  score -= __gammalog2(n_ij + ess_qi);
278  }
279  for (const auto n_ijk : N_ijk) {
280  score += __gammalog2(n_ijk + ess_riqi);
281  }
282  }
283  } else {
284  // here, there are no conditioning nodes
285  const double ess_ri = ess / all_size;
286 
287  if (informative_external_apriori) {
288  // the score to compute is that of BD with aprioris
289  // N'_ijk + ESS / ( ri * qi )
290  // (the + ESS / ( ri * qi ) is here to take into account the
291  // internal apriori of K2)
292  std::vector< double, ALLOC< double > > N_prime_ijk(all_size, 0.0);
293  this->_apriori->addAllApriori(idset, N_prime_ijk);
294 
295  // the BDeu score can be computed as follows:
296  // gammalog2 ( N' + ess ) - gammalog2 ( N + N' + ess )
297  // + sum_k=1^ri { gammlog2 ( N_i + N'_i + ESS / ri)
298  // - gammalog2 ( N'_i + ESS / ri ) }
299  double N = 0.0;
300  double N_prime = 0.0;
301  for (std::size_t k = std::size_t(0); k < all_size; ++k) {
302  score += __gammalog2(N_ijk[k] + N_prime_ijk[k] + ess_ri)
303  - __gammalog2(N_prime_ijk[k] + ess_ri);
304  N += N_ijk[k];
305  N_prime += N_prime_ijk[k];
306  }
307  score += __gammalog2(N_prime + ess) - __gammalog2(N + N_prime + ess);
308  } else {
309  // the BDeu score can be computed as follows:
310  // gammalog2 ( ess ) - ri * gammalog2 ( ess / ri )
311  // - gammalog2 ( N + ess )
312  // + sum_k=1^ri log [ gammalog2 ( N_ijk + ess / ri ) ]
313 
314  score = __gammalog2(ess) - all_size * __gammalog2(ess_ri);
315  double N = 0;
316  for (const auto n_ijk : N_ijk) {
317  score += __gammalog2(n_ijk + ess_ri);
318  N += n_ijk;
319  }
320  score -= __gammalog2(N + ess);
321  }
322  }
323 
324  return score;
325  }
326 
327  } /* namespace learning */
328 
329 } /* namespace gum */
330 
331 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
virtual ScoreBDeu< ALLOC > * clone() const
virtual copy constructor
const DatabaseTable< ALLOC > & database() const
return the database used by the score
double score(const NodeId var)
returns the score of a single node
virtual const Apriori< ALLOC > & internalApriori() const final
returns the internal apriori of the score
static const std::string type
Definition: aprioriTypes.h:43
Score(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
static const std::string type
Definition: aprioriTypes.h:48
ALLOC< NodeId > allocator_type
type for the allocators passed in arguments of methods
Definition: scoreBDeu.h:62
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
STL namespace.
virtual ~ScoreBDeu()
destructor
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
std::vector< double, ALLOC< double > > _marginalize(const NodeId X_id, const std::vector< double, ALLOC< double > > &N_xyz) const
returns a counting vector where variables are marginalized from N_xyz
void setEffectiveSampleSize(double ess)
sets the effective sample size of the internal apriori
virtual double _score(const IdSet< ALLOC > &idset) final
returns the score for a given IdSet
Score< ALLOC > & operator=(const Score< ALLOC > &from)
copy operator
virtual std::string isAprioriCompatible() const final
indicates whether the apriori is compatible (meaningful) with the score
allocator_type getAllocator() const
returns the allocator used by the score
ScoreBDeu< ALLOC > & operator=(const ScoreBDeu< ALLOC > &from)
copy operator
Apriori< ALLOC > * _apriori
the expert knowledge a priori we add to the score
Definition: score.h:242
static const std::string type
Definition: aprioriTypes.h:38
ScoreBDeu(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
RecordCounter< ALLOC > _counter
the record counter used for the countings over discrete variables
Definition: score.h:245
Size NodeId
Type for node ids.
Definition: graphElements.h:98
#define GUM_ERROR(type, msg)
Definition: exceptions.h:55