aGrUM  0.14.2
scoreBIC_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  ***************************************************************************/
26 #ifndef DOXYGEN_SHOULD_SKIP_THIS
27 
29 # include <sstream>
30 
31 namespace gum {
32 
33  namespace learning {
34 
36  template < template < typename > class ALLOC >
38  const DBRowGeneratorParser< ALLOC >& parser,
39  const Apriori< ALLOC >& apriori,
40  const std::vector< std::pair< std::size_t, std::size_t >,
41  ALLOC< std::pair< std::size_t, std::size_t > > >& ranges,
42  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
43  nodeId2columns,
44  const typename ScoreBIC< ALLOC >::allocator_type& alloc) :
45  Score< ALLOC >(parser, apriori, ranges, nodeId2columns, alloc),
46  __internal_apriori(parser.database(), nodeId2columns) {
47  GUM_CONSTRUCTOR(ScoreBIC);
48  }
49 
50 
52  template < template < typename > class ALLOC >
54  const DBRowGeneratorParser< ALLOC >& parser,
55  const Apriori< ALLOC >& apriori,
56  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
57  nodeId2columns,
58  const typename ScoreBIC< ALLOC >::allocator_type& alloc) :
59  Score< ALLOC >(parser, apriori, nodeId2columns, alloc),
60  __internal_apriori(parser.database(), nodeId2columns) {
61  GUM_CONSTRUCTOR(ScoreBIC);
62  }
63 
64 
66  template < template < typename > class ALLOC >
68  const ScoreBIC< ALLOC >& from,
69  const typename ScoreBIC< ALLOC >::allocator_type& alloc) :
70  Score< ALLOC >(from, alloc),
71  __internal_apriori(from.__internal_apriori, alloc) {
72  GUM_CONS_CPY(ScoreBIC);
73  }
74 
75 
77  template < template < typename > class ALLOC >
78  INLINE ScoreBIC< ALLOC >::ScoreBIC(const ScoreBIC< ALLOC >& from) :
79  ScoreBIC< ALLOC >(from, from.getAllocator()) {}
80 
81 
83  template < template < typename > class ALLOC >
85  ScoreBIC< ALLOC >&& from,
86  const typename ScoreBIC< ALLOC >::allocator_type& alloc) :
87  Score< ALLOC >(std::move(from), alloc),
88  __internal_apriori(std::move(from.__internal_apriori), alloc) {
89  GUM_CONS_MOV(ScoreBIC);
90  }
91 
92 
94  template < template < typename > class ALLOC >
95  INLINE ScoreBIC< ALLOC >::ScoreBIC(ScoreBIC< ALLOC >&& from) :
96  ScoreBIC< ALLOC >(std::move(from), from.getAllocator()) {}
97 
98 
100  template < template < typename > class ALLOC >
101  ScoreBIC< ALLOC >* ScoreBIC< ALLOC >::clone(
102  const typename ScoreBIC< ALLOC >::allocator_type& alloc) const {
103  ALLOC< ScoreBIC< ALLOC > > allocator(alloc);
104  ScoreBIC< ALLOC >* new_score = allocator.allocate(1);
105  try {
106  allocator.construct(new_score, *this, alloc);
107  } catch (...) {
108  allocator.deallocate(new_score, 1);
109  throw;
110  }
111 
112  return new_score;
113  }
114 
115 
117  template < template < typename > class ALLOC >
118  ScoreBIC< ALLOC >* ScoreBIC< ALLOC >::clone() const {
119  return clone(this->getAllocator());
120  }
121 
122 
124  template < template < typename > class ALLOC >
126  GUM_DESTRUCTOR(ScoreBIC);
127  }
128 
129 
131  template < template < typename > class ALLOC >
132  ScoreBIC< ALLOC >& ScoreBIC< ALLOC >::
133  operator=(const ScoreBIC< ALLOC >& from) {
134  if (this != &from) {
136  __internal_apriori = from.__internal_apriori;
137  }
138  return *this;
139  }
140 
141 
143  template < template < typename > class ALLOC >
144  ScoreBIC< ALLOC >& ScoreBIC< ALLOC >::operator=(ScoreBIC< ALLOC >&& from) {
145  if (this != &from) {
146  Score< ALLOC >::operator=(std::move(from));
147  __internal_apriori = std::move(from.__internal_apriori);
148  }
149  return *this;
150  }
151 
152 
154  template < template < typename > class ALLOC >
155  std::string
156  ScoreBIC< ALLOC >::isAprioriCompatible(const std::string& apriori_type,
157  double weight) {
158  // check that the apriori is compatible with the score
159  if ((apriori_type == AprioriDirichletType::type)
160  || (apriori_type == AprioriSmoothingType::type)
161  || (apriori_type == AprioriNoAprioriType::type)) {
162  return "";
163  }
164 
165  // apriori types unsupported by the type checker
166  std::stringstream msg;
167  msg << "The apriori '" << apriori_type
168  << "' is not yet supported by method isAprioriCompatible os Score BIC";
169  return msg.str();
170  }
171 
172 
174  template < template < typename > class ALLOC >
175  INLINE std::string
176  ScoreBIC< ALLOC >::isAprioriCompatible(const Apriori< ALLOC >& apriori) {
177  return isAprioriCompatible(apriori.getType(), apriori.weight());
178  }
179 
180 
182  template < template < typename > class ALLOC >
183  INLINE std::string ScoreBIC< ALLOC >::isAprioriCompatible() const {
184  return isAprioriCompatible(*(this->_apriori));
185  }
186 
187 
189  template < template < typename > class ALLOC >
190  INLINE const Apriori< ALLOC >& ScoreBIC< ALLOC >::internalApriori() const {
191  return __internal_apriori;
192  }
193 
194 
196  template < template < typename > class ALLOC >
197  double ScoreBIC< ALLOC >::_score(const IdSet< ALLOC >& idset) {
198  // get the counts for all the nodes in the idset and add the apriori
199  std::vector< double, ALLOC< double > > N_ijk(
200  this->_counter.counts(idset, true));
201  const bool informative_external_apriori = this->_apriori->isInformative();
202  if (informative_external_apriori)
203  this->_apriori->addAllApriori(idset, N_ijk);
204  const std::size_t all_size = N_ijk.size();
205 
206  // here, we distinguish idsets with conditioning nodes from those
207  // without conditioning nodes
208  if (idset.hasConditioningSet()) {
209  // get the counts for the conditioning nodes
210  std::vector< double, ALLOC< double > > N_ij(
211  this->_marginalize(idset[0], N_ijk));
212  const std::size_t conditioning_size = N_ij.size();
213 
214  // initialize the score: this should be the penalty of the BIC score,
215  // i.e., -(ri-1 ) * qi * .5 * log ( N + N' )
216  const std::size_t target_domsize = all_size / conditioning_size;
217  const double penalty =
218  conditioning_size * double(target_domsize - std::size_t(1));
219 
220  // compute the score: it remains to compute the log likelihood, i.e.,
221  // sum_k=1^r_i sum_j=1^q_i N_ijk log (N_ijk / N_ij), which is also
222  // equivalent to:
223  // sum_j=1^q_i sum_k=1^r_i N_ijk log N_ijk - sum_j=1^q_i N_ij log N_ij
224  double score = 0.0;
225  for (const auto n_ijk : N_ijk) {
226  if (n_ijk) { score += n_ijk * std::log(n_ijk); }
227  }
228  double N = 0;
229  for (const auto n_ij : N_ij) {
230  if (n_ij) {
231  score -= n_ij * std::log(n_ij);
232  N += n_ij;
233  }
234  }
235 
236  // finally, remove the penalty
237  score -= penalty * std::log(N) * 0.5;
238 
239  // divide by log(2), since the log likelihood uses log_2
240  score *= this->_1log2;
241 
242  return score;
243  } else {
244  // here, there are no conditioning nodes
245 
246  // initialize the score: this should be the penalty of the BIC score,
247  // i.e., -(ri-1 )
248  const double penalty = double(all_size - std::size_t(1));
249 
250  // compute the score: it remains to compute the log likelihood, i.e.,
251  // sum_k=1^r_i N_ijk log (N_ijk / N), which is also
252  // equivalent to:
253  // sum_j=1^q_i sum_k=1^r_i N_ijk log N_ijk - N log N
254  double N = 0.0;
255  double score = 0.0;
256  for (const auto n_ijk : N_ijk) {
257  if (n_ijk) {
258  score += n_ijk * std::log(n_ijk);
259  N += n_ijk;
260  }
261  }
262  score -= N * std::log(N);
263 
264  // finally, remove the penalty
265  score -= penalty * std::log(N) * 0.5;
266 
267  // divide by log(2), since the log likelihood uses log_2
268  score *= this->_1log2;
269 
270  return score;
271  }
272  }
273 
274 
276  template < template < typename > class ALLOC >
277  double ScoreBIC< ALLOC >::N(const IdSet< ALLOC >& idset) {
278  // get the counts for all the nodes in the idset and add the apriori
279  std::vector< double, ALLOC< double > > N_ijk(
280  this->_counter.counts(idset, true));
281  if (this->_apriori->isInformative())
282  this->_apriori->addAllApriori(idset, N_ijk);
283 
284  double N = 0;
285  for (const auto n_ijk : N_ijk) {
286  N += n_ijk;
287  }
288 
289  return N;
290  }
291 
292  } /* namespace learning */
293 
294 } /* namespace gum */
295 
296 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
const DatabaseTable< ALLOC > & database() const
return the database used by the score
double score(const NodeId var)
returns the score of a single node
double N(const IdSet< ALLOC > &idset)
returns the size of the database w.r.t. a given idset
virtual ScoreBIC< ALLOC > * clone() const
virtual copy constructor
static const std::string type
Definition: aprioriTypes.h:40
ScoreBIC< ALLOC > & operator=(const ScoreBIC< ALLOC > &from)
copy operator
virtual ~ScoreBIC()
destructor
the class for computing BIC scores
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:45
STL namespace.
const double _1log2
1 / log(2)
Definition: score.h:236
virtual std::string isAprioriCompatible() const final
indicates whether the apriori is compatible (meaningful) with the score
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
virtual double _score(const IdSet< ALLOC > &idset) final
returns the score for a given IdSet
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
ScoreBIC(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
ALLOC< NodeId > allocator_type
type for the allocators passed in arguments of methods
Definition: scoreBIC.h:52
Score< ALLOC > & operator=(const Score< ALLOC > &from)
copy operator
virtual const Apriori< ALLOC > & internalApriori() const final
returns the internal apriori of the score
allocator_type getAllocator() const
returns the allocator used by the score
Apriori< ALLOC > * _apriori
the expert knowledge a priori we add to the score
Definition: score.h:239
static const std::string type
Definition: aprioriTypes.h:35
RecordCounter< ALLOC > _counter
the record counter used for the countings over discrete variables
Definition: score.h:242
Size NodeId
Type for node ids.
Definition: graphElements.h:97