aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
scorefNML_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 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,
43  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
45  const typename ScorefNML< ALLOC >::allocator_type& alloc) :
49  }
50 
51 
52  /// default constructor
53  template < template < typename > class ALLOC >
56  const Apriori< ALLOC >& apriori,
57  const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >&
59  const typename ScorefNML< ALLOC >::allocator_type& alloc) :
63  }
64 
65 
66  /// copy constructor with a given allocator
67  template < template < typename > class ALLOC >
69  const ScorefNML< ALLOC >& from,
70  const typename ScorefNML< ALLOC >::allocator_type& alloc) :
71  Score< ALLOC >(from, alloc),
74  }
75 
76 
77  /// copy constructor
78  template < template < typename > class ALLOC >
81 
82 
83  /// move constructor with a given allocator
84  template < template < typename > class ALLOC >
86  ScorefNML< ALLOC >&& from,
87  const typename ScorefNML< ALLOC >::allocator_type& alloc) :
88  Score< ALLOC >(std::move(from), alloc),
91  }
92 
93 
94  /// move constructor
95  template < template < typename > class ALLOC >
98 
99 
100  /// virtual copy constructor with a given allocator
101  template < template < typename > class ALLOC >
103  const typename ScorefNML< ALLOC >::allocator_type& alloc) const {
106  try {
108  } catch (...) {
110  throw;
111  }
112 
113  return new_score;
114  }
115 
116 
117  /// virtual copy constructor
118  template < template < typename > class ALLOC >
119  ScorefNML< ALLOC >* ScorefNML< ALLOC >::clone() const {
120  return clone(this->getAllocator());
121  }
122 
123 
124  /// destructor
125  template < template < typename > class ALLOC >
126  ScorefNML< ALLOC >::~ScorefNML() {
128  }
129 
130 
131  /// copy operator
132  template < template < typename > class ALLOC >
133  ScorefNML< ALLOC >&
134  ScorefNML< ALLOC >::operator=(const ScorefNML< ALLOC >& from) {
135  if (this != &from) {
136  Score< ALLOC >::operator=(from);
138  }
139  return *this;
140  }
141 
142 
143  /// move operator
144  template < template < typename > class ALLOC >
146  if (this != &from) {
147  Score< ALLOC >::operator=(std::move(from));
149  }
150  return *this;
151  }
152 
153 
154  /// indicates whether the apriori is compatible (meaningful) with the score
155  template < template < typename > class ALLOC >
156  std::string
158  double weight) {
159  // check that the apriori is compatible with the score
163  return "";
164  }
165 
166  // apriori types unsupported by the type checker
168  msg << "The apriori '" << apriori_type
169  << "' is not yet supported by method isAprioriCompatible os Score fNML";
170  return msg.str();
171  }
172 
173 
174  /// indicates whether the apriori is compatible (meaningful) with the score
175  template < template < typename > class ALLOC >
176  INLINE std::string
179  }
180 
181 
182  /// indicates whether the apriori is compatible (meaningful) with the score
183  template < template < typename > class ALLOC >
185  return isAprioriCompatible(*(this->apriori_));
186  }
187 
188 
189  /// returns the internal apriori of the score
190  template < template < typename > class ALLOC >
191  INLINE const Apriori< ALLOC >& ScorefNML< ALLOC >::internalApriori() const {
192  return internal_apriori__;
193  }
194 
195 
196  /// returns the score corresponding to a given nodeset
197  template < template < typename > class ALLOC >
198  double ScorefNML< ALLOC >::score_(const IdCondSet< ALLOC >& idset) {
199  // get the counts for all the nodes in the idset and add the apriori
200  std::vector< double, ALLOC< double > > N_ijk(
201  this->counter_.counts(idset, true));
205  const std::size_t all_size = N_ijk.size();
206 
207  // here, we distinguish idsets with conditioning nodes from those
208  // without conditioning nodes
209  if (idset.hasConditioningSet()) {
210  // get the counts for the conditioning nodes
211  std::vector< double, ALLOC< double > > N_ij(
212  this->marginalize_(idset[0], N_ijk));
213  const std::size_t target_domsize = all_size / N_ij.size();
214 
215  // compute the score: it remains to compute the log likelihood, i.e.,
216  // sum_k=1^r_i sum_j=1^q_i N_ijk log (N_ijk / N_ij), which is also
217  // equivalent to:
218  // 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
219  double score = 0.0;
220  for (const auto n_ijk: N_ijk) {
221  if (n_ijk) { score += n_ijk * std::log(n_ijk); }
222  }
223  for (const auto n_ij: N_ij) {
224  if (n_ij) { score -= n_ij * std::log(n_ij); }
225  }
226 
227  // divide by log(2), since the log likelihood uses log_2
228  score *= this->one_log2_;
229 
230  // finally, remove the penalty
231  double penalty = 0.0;
232  for (const auto n_ij: N_ij) {
234  }
235 
236  score -= penalty;
237 
238  return score;
239  } else {
240  // here, there are no conditioning nodes
241 
242  // compute the score: it remains to compute the log likelihood, i.e.,
243  // sum_k=1^r_i N_ijk log (N_ijk / N), which is also
244  // equivalent to:
245  // sum_j=1^q_i sum_k=1^r_i N_ijk log N_ijk - N log N
246  double N = 0.0;
247  double score = 0.0;
248  for (const auto n_ijk: N_ijk) {
249  if (n_ijk) {
250  score += n_ijk * std::log(n_ijk);
251  N += n_ijk;
252  }
253  }
254  score -= N * std::log(N);
255 
256  // divide by log(2), since the log likelihood uses log_2
257  score *= this->one_log2_;
258 
259  // finally, remove the penalty
261 
262  return score;
263  }
264  }
265 
266  } /* namespace learning */
267 
268 } /* namespace gum */
269 
270 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669
Database(const std::string &filename, const BayesNet< GUM_SCALAR > &bn, const std::vector< std::string > &missing_symbols)