aGrUM  0.14.2
scorefNML_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 
30 namespace gum {
31 
32  namespace learning {
33 
35  template < template < typename > class ALLOC >
37  const DBRowGeneratorParser< ALLOC >& parser,
38  const Apriori< ALLOC >& apriori,
39  const std::vector< std::pair< std::size_t, std::size_t >,
40  ALLOC< std::pair< std::size_t, std::size_t > > >& ranges,
41  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
42  nodeId2columns,
43  const typename ScorefNML< ALLOC >::allocator_type& alloc) :
44  Score< ALLOC >(parser, apriori, ranges, nodeId2columns, alloc),
45  __internal_apriori(parser.database(), nodeId2columns) {
46  GUM_CONSTRUCTOR(ScorefNML);
47  }
48 
49 
51  template < template < typename > class ALLOC >
53  const DBRowGeneratorParser< ALLOC >& parser,
54  const Apriori< ALLOC >& apriori,
55  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
56  nodeId2columns,
57  const typename ScorefNML< ALLOC >::allocator_type& alloc) :
58  Score< ALLOC >(parser, apriori, nodeId2columns, alloc),
59  __internal_apriori(parser.database(), nodeId2columns) {
60  GUM_CONSTRUCTOR(ScorefNML);
61  }
62 
63 
65  template < template < typename > class ALLOC >
67  const ScorefNML< ALLOC >& from,
68  const typename ScorefNML< ALLOC >::allocator_type& alloc) :
69  Score< ALLOC >(from, alloc),
70  __internal_apriori(from.__internal_apriori, alloc) {
71  GUM_CONS_CPY(ScorefNML);
72  }
73 
74 
76  template < template < typename > class ALLOC >
77  INLINE ScorefNML< ALLOC >::ScorefNML(const ScorefNML< ALLOC >& from) :
78  ScorefNML< ALLOC >(from, from.getAllocator()) {}
79 
80 
82  template < template < typename > class ALLOC >
84  ScorefNML< ALLOC >&& from,
85  const typename ScorefNML< ALLOC >::allocator_type& alloc) :
86  Score< ALLOC >(std::move(from), alloc),
87  __internal_apriori(std::move(from.__internal_apriori), alloc) {
88  GUM_CONS_MOV(ScorefNML);
89  }
90 
91 
93  template < template < typename > class ALLOC >
94  INLINE ScorefNML< ALLOC >::ScorefNML(ScorefNML< ALLOC >&& from) :
95  ScorefNML< ALLOC >(std::move(from), from.getAllocator()) {}
96 
97 
99  template < template < typename > class ALLOC >
100  ScorefNML< ALLOC >* ScorefNML< ALLOC >::clone(
101  const typename ScorefNML< ALLOC >::allocator_type& alloc) const {
102  ALLOC< ScorefNML< ALLOC > > allocator(alloc);
103  ScorefNML< ALLOC >* new_score = allocator.allocate(1);
104  try {
105  allocator.construct(new_score, *this, alloc);
106  } catch (...) {
107  allocator.deallocate(new_score, 1);
108  throw;
109  }
110 
111  return new_score;
112  }
113 
114 
116  template < template < typename > class ALLOC >
117  ScorefNML< ALLOC >* ScorefNML< ALLOC >::clone() const {
118  return clone(this->getAllocator());
119  }
120 
121 
123  template < template < typename > class ALLOC >
125  GUM_DESTRUCTOR(ScorefNML);
126  }
127 
128 
130  template < template < typename > class ALLOC >
131  ScorefNML< ALLOC >& ScorefNML< ALLOC >::
132  operator=(const ScorefNML< ALLOC >& from) {
133  if (this != &from) {
135  __internal_apriori = from.__internal_apriori;
136  }
137  return *this;
138  }
139 
140 
142  template < template < typename > class ALLOC >
143  ScorefNML< ALLOC >& ScorefNML< ALLOC >::operator=(ScorefNML< ALLOC >&& from) {
144  if (this != &from) {
145  Score< ALLOC >::operator=(std::move(from));
146  __internal_apriori = std::move(from.__internal_apriori);
147  }
148  return *this;
149  }
150 
151 
153  template < template < typename > class ALLOC >
154  std::string
155  ScorefNML< ALLOC >::isAprioriCompatible(const std::string& apriori_type,
156  double weight) {
157  // check that the apriori is compatible with the score
158  if ((apriori_type == AprioriDirichletType::type)
159  || (apriori_type == AprioriSmoothingType::type)
160  || (apriori_type == AprioriNoAprioriType::type)) {
161  return "";
162  }
163 
164  // apriori types unsupported by the type checker
165  std::stringstream msg;
166  msg << "The apriori '" << apriori_type
167  << "' is not yet supported by method isAprioriCompatible os Score fNML";
168  return msg.str();
169  }
170 
171 
173  template < template < typename > class ALLOC >
174  INLINE std::string
175  ScorefNML< ALLOC >::isAprioriCompatible(const Apriori< ALLOC >& apriori) {
176  return isAprioriCompatible(apriori.getType(), apriori.weight());
177  }
178 
179 
181  template < template < typename > class ALLOC >
182  INLINE std::string ScorefNML< ALLOC >::isAprioriCompatible() const {
183  return isAprioriCompatible(*(this->_apriori));
184  }
185 
186 
188  template < template < typename > class ALLOC >
189  INLINE const Apriori< ALLOC >& ScorefNML< ALLOC >::internalApriori() const {
190  return __internal_apriori;
191  }
192 
193 
195  template < template < typename > class ALLOC >
196  double ScorefNML< ALLOC >::_score(const IdSet< ALLOC >& idset) {
197  // get the counts for all the nodes in the idset and add the apriori
198  std::vector< double, ALLOC< double > > N_ijk(
199  this->_counter.counts(idset, true));
200  const bool informative_external_apriori = this->_apriori->isInformative();
201  if (informative_external_apriori)
202  this->_apriori->addAllApriori(idset, N_ijk);
203  const std::size_t all_size = N_ijk.size();
204 
205  // here, we distinguish idsets with conditioning nodes from those
206  // without conditioning nodes
207  if (idset.hasConditioningSet()) {
208  // get the counts for the conditioning nodes
209  std::vector< double, ALLOC< double > > N_ij(
210  this->_marginalize(idset[0], N_ijk));
211  const std::size_t target_domsize = all_size / N_ij.size();
212 
213  // compute the score: it remains to compute the log likelihood, i.e.,
214  // sum_k=1^r_i sum_j=1^q_i N_ijk log (N_ijk / N_ij), which is also
215  // equivalent to:
216  // 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
217  double score = 0.0;
218  for (const auto n_ijk : N_ijk) {
219  if (n_ijk) { score += n_ijk * std::log(n_ijk); }
220  }
221  for (const auto n_ij : N_ij) {
222  if (n_ij) { score -= n_ij * std::log(n_ij); }
223  }
224 
225  // divide by log(2), since the log likelihood uses log_2
226  score *= this->_1log2;
227 
228  // finally, remove the penalty
229  double penalty = 0.0;
230  for (const auto n_ij : N_ij) {
231  penalty += __ctable.log2Cnr(target_domsize, n_ij);
232  }
233 
234  score -= penalty;
235 
236  return score;
237  } else {
238  // here, there are no conditioning nodes
239 
240  // compute the score: it remains to compute the log likelihood, i.e.,
241  // sum_k=1^r_i N_ijk log (N_ijk / N), which is also
242  // equivalent to:
243  // sum_j=1^q_i sum_k=1^r_i N_ijk log N_ijk - N log N
244  double N = 0.0;
245  double score = 0.0;
246  for (const auto n_ijk : N_ijk) {
247  if (n_ijk) {
248  score += n_ijk * std::log(n_ijk);
249  N += n_ijk;
250  }
251  }
252  score -= N * std::log(N);
253 
254  // divide by log(2), since the log likelihood uses log_2
255  score *= this->_1log2;
256 
257  // finally, remove the penalty
258  score -= __ctable.log2Cnr(all_size, N);
259 
260  return score;
261  }
262  }
263 
264  } /* namespace learning */
265 
266 } /* namespace gum */
267 
268 #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
virtual std::string isAprioriCompatible() const final
indicates whether the apriori is compatible (meaningful) with the score
static const std::string type
Definition: aprioriTypes.h:40
the class for computing fNML scores
virtual ScorefNML< ALLOC > * clone() const
virtual copy constructor
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 ~ScorefNML()
destructor
virtual const Apriori< ALLOC > & internalApriori() const final
returns the internal apriori of the score
ScorefNML(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
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
ScorefNML< ALLOC > & operator=(const ScorefNML< ALLOC > &from)
copy operator
ALLOC< NodeId > allocator_type
type for the allocators passed in arguments of methods
Definition: scorefNML.h:54
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
Score< ALLOC > & operator=(const Score< ALLOC > &from)
copy operator
virtual double _score(const IdSet< ALLOC > &idset) final
returns the score for a given IdSet
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