aGrUM  0.16.0
scoreAIC_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 ScoreAIC< ALLOC >::allocator_type& alloc) :
48  Score< ALLOC >(parser, apriori, ranges, nodeId2columns, alloc),
49  __internal_apriori(parser.database(), nodeId2columns) {
50  GUM_CONSTRUCTOR(ScoreAIC);
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 ScoreAIC< ALLOC >::allocator_type& alloc) :
62  Score< ALLOC >(parser, apriori, nodeId2columns, alloc),
63  __internal_apriori(parser.database(), nodeId2columns) {
64  GUM_CONSTRUCTOR(ScoreAIC);
65  }
66 
67 
69  template < template < typename > class ALLOC >
71  const ScoreAIC< ALLOC >& from,
72  const typename ScoreAIC< ALLOC >::allocator_type& alloc) :
73  Score< ALLOC >(from, alloc),
74  __internal_apriori(from.__internal_apriori, alloc) {
75  GUM_CONS_CPY(ScoreAIC);
76  }
77 
78 
80  template < template < typename > class ALLOC >
81  INLINE ScoreAIC< ALLOC >::ScoreAIC(const ScoreAIC< ALLOC >& from) :
82  ScoreAIC< ALLOC >(from, from.getAllocator()) {}
83 
84 
86  template < template < typename > class ALLOC >
88  ScoreAIC< ALLOC >&& from,
89  const typename ScoreAIC< ALLOC >::allocator_type& alloc) :
90  Score< ALLOC >(std::move(from), alloc),
91  __internal_apriori(std::move(from.__internal_apriori), alloc) {
92  GUM_CONS_MOV(ScoreAIC);
93  }
94 
95 
97  template < template < typename > class ALLOC >
98  INLINE ScoreAIC< ALLOC >::ScoreAIC(ScoreAIC< ALLOC >&& from) :
99  ScoreAIC< ALLOC >(std::move(from), from.getAllocator()) {}
100 
101 
103  template < template < typename > class ALLOC >
104  ScoreAIC< ALLOC >* ScoreAIC< ALLOC >::clone(
105  const typename ScoreAIC< ALLOC >::allocator_type& alloc) const {
106  ALLOC< ScoreAIC< ALLOC > > allocator(alloc);
107  ScoreAIC< ALLOC >* new_score = allocator.allocate(1);
108  try {
109  allocator.construct(new_score, *this, alloc);
110  } catch (...) {
111  allocator.deallocate(new_score, 1);
112  throw;
113  }
114 
115  return new_score;
116  }
117 
118 
120  template < template < typename > class ALLOC >
121  ScoreAIC< ALLOC >* ScoreAIC< ALLOC >::clone() const {
122  return clone(this->getAllocator());
123  }
124 
125 
127  template < template < typename > class ALLOC >
129  GUM_DESTRUCTOR(ScoreAIC);
130  }
131 
132 
134  template < template < typename > class ALLOC >
135  ScoreAIC< ALLOC >& ScoreAIC< ALLOC >::
136  operator=(const ScoreAIC< ALLOC >& from) {
137  if (this != &from) {
139  __internal_apriori = from.__internal_apriori;
140  }
141  return *this;
142  }
143 
144 
146  template < template < typename > class ALLOC >
147  ScoreAIC< ALLOC >& ScoreAIC< ALLOC >::operator=(ScoreAIC< ALLOC >&& from) {
148  if (this != &from) {
149  Score< ALLOC >::operator=(std::move(from));
150  __internal_apriori = std::move(from.__internal_apriori);
151  }
152  return *this;
153  }
154 
155 
157  template < template < typename > class ALLOC >
158  std::string
159  ScoreAIC< ALLOC >::isAprioriCompatible(const std::string& apriori_type,
160  double weight) {
161  // check that the apriori is compatible with the score
162  if ((apriori_type == AprioriDirichletType::type)
163  || (apriori_type == AprioriSmoothingType::type)
164  || (apriori_type == AprioriNoAprioriType::type)) {
165  return "";
166  }
167 
168  // apriori types unsupported by the type checker
169  std::stringstream msg;
170  msg << "The apriori '" << apriori_type
171  << "' is not yet supported by method isAprioriCompatible os Score AIC";
172  return msg.str();
173  }
174 
175 
177  template < template < typename > class ALLOC >
178  INLINE std::string
179  ScoreAIC< ALLOC >::isAprioriCompatible(const Apriori< ALLOC >& apriori) {
180  return isAprioriCompatible(apriori.getType(), apriori.weight());
181  }
182 
183 
185  template < template < typename > class ALLOC >
186  INLINE std::string ScoreAIC< ALLOC >::isAprioriCompatible() const {
187  return isAprioriCompatible(*(this->_apriori));
188  }
189 
190 
192  template < template < typename > class ALLOC >
193  INLINE const Apriori< ALLOC >& ScoreAIC< ALLOC >::internalApriori() const {
194  return __internal_apriori;
195  }
196 
197 
199  template < template < typename > class ALLOC >
200  double ScoreAIC< ALLOC >::_score(const IdSet< ALLOC >& idset) {
201  // get the counts for all the nodes in the idset and add the apriori
202  std::vector< double, ALLOC< double > > N_ijk(
203  this->_counter.counts(idset, true));
204  const bool informative_external_apriori = this->_apriori->isInformative();
205  if (informative_external_apriori)
206  this->_apriori->addAllApriori(idset, N_ijk);
207  const std::size_t all_size = N_ijk.size();
208 
209  // here, we distinguish idsets with conditioning nodes from those
210  // without conditioning nodes
211  if (idset.hasConditioningSet()) {
212  // get the counts for the conditioning nodes
213  std::vector< double, ALLOC< double > > N_ij(
214  this->_marginalize(idset[0], N_ijk));
215  const std::size_t conditioning_size = N_ij.size();
216 
217  // initialize the score: this should be the penalty of the AIC score,
218  // i.e., -(ri-1 ) * qi
219  const std::size_t target_domsize = all_size / conditioning_size;
220  const double penalty =
221  conditioning_size * double(target_domsize - std::size_t(1));
222 
223  // compute the score: it remains to compute the log likelihood, i.e.,
224  // sum_k=1^r_i sum_j=1^q_i N_ijk log (N_ijk / N_ij), which is also
225  // equivalent to:
226  // 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
227  double score = 0.0;
228  for (const auto n_ijk : N_ijk) {
229  if (n_ijk) { score += n_ijk * std::log(n_ijk); }
230  }
231  for (const auto n_ij : N_ij) {
232  if (n_ij) { score -= n_ij * std::log(n_ij); }
233  }
234 
235  // divide by log(2), since the log likelihood uses log_2
236  score *= this->_1log2;
237 
238  // finally, remove the penalty
239  score -= penalty;
240 
241  return score;
242  } else {
243  // here, there are no conditioning nodes
244 
245  // initialize the score: this should be the penalty of the AIC score,
246  // i.e., -(ri-1 )
247  const double penalty = double(all_size - std::size_t(1));
248 
249  // compute the score: it remains to compute the log likelihood, i.e.,
250  // sum_k=1^r_i N_ijk log (N_ijk / N), which is also
251  // equivalent to:
252  // sum_j=1^q_i sum_k=1^r_i N_ijk log N_ijk - N log N
253  double N = 0.0;
254  double score = 0.0;
255  for (const auto n_ijk : N_ijk) {
256  if (n_ijk) {
257  score += n_ijk * std::log(n_ijk);
258  N += n_ijk;
259  }
260  }
261  score -= N * std::log(N);
262 
263  // divide by log(2), since the log likelihood uses log_2
264  score *= this->_1log2;
265 
266  // finally, remove the penalty
267  score -= penalty;
268 
269  return score;
270  }
271  }
272 
273  } /* namespace learning */
274 
275 } /* namespace gum */
276 
277 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
ALLOC< NodeId > allocator_type
type for the allocators passed in arguments of methods
Definition: scoreAIC.h:55
const DatabaseTable< ALLOC > & database() const
return the database used by the score
double score(const NodeId var)
returns the score of a single node
static const std::string type
Definition: aprioriTypes.h:43
virtual ~ScoreAIC()
destructor
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
STL namespace.
const double _1log2
1 / log(2)
Definition: score.h:239
ScoreAIC< ALLOC > & operator=(const ScoreAIC< ALLOC > &from)
copy operator
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
virtual ScoreAIC< ALLOC > * clone() const
virtual copy constructor
virtual const Apriori< ALLOC > & internalApriori() const final
returns the internal apriori of the score
ScoreAIC(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
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
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
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
RecordCounter< ALLOC > _counter
the record counter used for the countings over discrete variables
Definition: score.h:245
virtual std::string isAprioriCompatible() const final
indicates whether the apriori is compatible (meaningful) with the score
Size NodeId
Type for node ids.
Definition: graphElements.h:98