aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
scorefNML_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /** @file
23  * @brief the class for computing fNML scores
24  *
25  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
26  */
27 
28 #ifndef DOXYGEN_SHOULD_SKIP_THIS
29 
30 # include <agrum/BN/learning/scores_and_tests/scorefNML.h>
31 
32 namespace gum {
33 
34  namespace learning {
35 
36  /// default constructor
37  template < template < typename > class ALLOC >
38  INLINE ScorefNML< ALLOC >::ScorefNML(
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,
44  const typename ScorefNML< ALLOC >::allocator_type& alloc) :
48  }
49 
50 
51  /// default constructor
52  template < template < typename > class ALLOC >
55  const Apriori< ALLOC >& apriori,
57  const typename ScorefNML< ALLOC >::allocator_type& alloc) :
61  }
62 
63 
64  /// copy constructor with a given allocator
65  template < template < typename > class ALLOC >
67  const typename ScorefNML< ALLOC >::allocator_type& alloc) :
68  Score< ALLOC >(from, alloc),
71  }
72 
73 
74  /// copy constructor
75  template < template < typename > class ALLOC >
78 
79 
80  /// move constructor with a given allocator
81  template < template < typename > class ALLOC >
83  const typename ScorefNML< ALLOC >::allocator_type& alloc) :
84  Score< ALLOC >(std::move(from), alloc),
87  }
88 
89 
90  /// move constructor
91  template < template < typename > class ALLOC >
94 
95 
96  /// virtual copy constructor with a given allocator
97  template < template < typename > class ALLOC >
98  ScorefNML< ALLOC >*
99  ScorefNML< ALLOC >::clone(const typename ScorefNML< ALLOC >::allocator_type& alloc) const {
102  try {
104  } catch (...) {
106  throw;
107  }
108 
109  return new_score;
110  }
111 
112 
113  /// virtual copy constructor
114  template < template < typename > class ALLOC >
115  ScorefNML< ALLOC >* ScorefNML< ALLOC >::clone() const {
116  return clone(this->getAllocator());
117  }
118 
119 
120  /// destructor
121  template < template < typename > class ALLOC >
122  ScorefNML< ALLOC >::~ScorefNML() {
124  }
125 
126 
127  /// copy operator
128  template < template < typename > class ALLOC >
129  ScorefNML< ALLOC >& ScorefNML< ALLOC >::operator=(const ScorefNML< ALLOC >& from) {
130  if (this != &from) {
131  Score< ALLOC >::operator=(from);
133  }
134  return *this;
135  }
136 
137 
138  /// move operator
139  template < template < typename > class ALLOC >
141  if (this != &from) {
142  Score< ALLOC >::operator=(std::move(from));
144  }
145  return *this;
146  }
147 
148 
149  /// indicates whether the apriori is compatible (meaningful) with the score
150  template < template < typename > class ALLOC >
152  double weight) {
153  // check that the apriori is compatible with the score
157  return "";
158  }
159 
160  // apriori types unsupported by the type checker
162  msg << "The apriori '" << apriori_type
163  << "' is not yet supported by method isAprioriCompatible os Score fNML";
164  return msg.str();
165  }
166 
167 
168  /// indicates whether the apriori is compatible (meaningful) with the score
169  template < template < typename > class ALLOC >
172  }
173 
174 
175  /// indicates whether the apriori is compatible (meaningful) with the score
176  template < template < typename > class ALLOC >
178  return isAprioriCompatible(*(this->apriori_));
179  }
180 
181 
182  /// returns the internal apriori of the score
183  template < template < typename > class ALLOC >
184  INLINE const Apriori< ALLOC >& ScorefNML< ALLOC >::internalApriori() const {
185  return _internal_apriori_;
186  }
187 
188 
189  /// returns the score corresponding to a given nodeset
190  template < template < typename > class ALLOC >
191  double ScorefNML< ALLOC >::score_(const IdCondSet< ALLOC >& idset) {
192  // get the counts for all the nodes in the idset and add the apriori
193  std::vector< double, ALLOC< double > > N_ijk(this->counter_.counts(idset, true));
196  const std::size_t all_size = N_ijk.size();
197 
198  // here, we distinguish idsets with conditioning nodes from those
199  // without conditioning nodes
200  if (idset.hasConditioningSet()) {
201  // get the counts for the conditioning nodes
202  std::vector< double, ALLOC< double > > N_ij(this->marginalize_(idset[0], N_ijk));
203  const std::size_t target_domsize = all_size / N_ij.size();
204 
205  // compute the score: it remains to compute the log likelihood, i.e.,
206  // sum_k=1^r_i sum_j=1^q_i N_ijk log (N_ijk / N_ij), which is also
207  // equivalent to:
208  // 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
209  double score = 0.0;
210  for (const auto n_ijk: N_ijk) {
211  if (n_ijk) { score += n_ijk * std::log(n_ijk); }
212  }
213  for (const auto n_ij: N_ij) {
214  if (n_ij) { score -= n_ij * std::log(n_ij); }
215  }
216 
217  // divide by log(2), since the log likelihood uses log_2
218  score *= this->one_log2_;
219 
220  // finally, remove the penalty
221  double penalty = 0.0;
222  for (const auto n_ij: N_ij) {
224  }
225 
226  score -= penalty;
227 
228  return score;
229  } else {
230  // here, there are no conditioning nodes
231 
232  // compute the score: it remains to compute the log likelihood, i.e.,
233  // sum_k=1^r_i N_ijk log (N_ijk / N), which is also
234  // equivalent to:
235  // sum_j=1^q_i sum_k=1^r_i N_ijk log N_ijk - N log N
236  double N = 0.0;
237  double score = 0.0;
238  for (const auto n_ijk: N_ijk) {
239  if (n_ijk) {
240  score += n_ijk * std::log(n_ijk);
241  N += n_ijk;
242  }
243  }
244  score -= N * std::log(N);
245 
246  // divide by log(2), since the log likelihood uses log_2
247  score *= this->one_log2_;
248 
249  // finally, remove the penalty
251 
252  return score;
253  }
254  }
255 
256  } /* namespace learning */
257 
258 } /* namespace gum */
259 
260 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
Database(const std::string &filename, const BayesNet< GUM_SCALAR > &bn, const std::vector< std::string > &missing_symbols)