28 #ifndef DOXYGEN_SHOULD_SKIP_THIS 30 # include <agrum/BN/learning/scores_and_tests/scoreBDeu.h> 38 template <
template <
typename >
class ALLOC >
39 INLINE ScoreBDeu< ALLOC >::ScoreBDeu(
40 const DBRowGeneratorParser< ALLOC >& parser,
41 const Apriori< ALLOC >& apriori,
42 const std::vector< std::pair< std::size_t, std::size_t >,
43 ALLOC< std::pair< std::size_t, std::size_t > > >& ranges,
44 const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >& nodeId2columns,
45 const typename ScoreBDeu< ALLOC >::allocator_type& alloc) :
46 Score< ALLOC >(parser, apriori, ranges, nodeId2columns, alloc),
47 _internal_apriori_(parser.database(), nodeId2columns) {
48 GUM_CONSTRUCTOR(ScoreBDeu);
53 template <
template <
typename >
class ALLOC >
54 INLINE ScoreBDeu< ALLOC >::ScoreBDeu(
55 const DBRowGeneratorParser< ALLOC >& parser,
56 const Apriori< ALLOC >& apriori,
57 const Bijection< NodeId, std::size_t, ALLOC< std::size_t > >& nodeId2columns,
58 const typename ScoreBDeu< ALLOC >::allocator_type& alloc) :
59 Score< ALLOC >(parser, apriori, nodeId2columns, alloc),
60 _internal_apriori_(parser.database(), nodeId2columns) {
61 GUM_CONSTRUCTOR(ScoreBDeu);
66 template <
template <
typename >
class ALLOC >
67 INLINE ScoreBDeu< ALLOC >::ScoreBDeu(
const ScoreBDeu< ALLOC >& from,
68 const typename ScoreBDeu< ALLOC >::allocator_type& alloc) :
69 Score< ALLOC >(from, alloc),
70 _internal_apriori_(from._internal_apriori_, alloc), _gammalog2_(from._gammalog2_) {
71 GUM_CONS_CPY(ScoreBDeu);
76 template <
template <
typename >
class ALLOC >
77 INLINE ScoreBDeu< ALLOC >::ScoreBDeu(
const ScoreBDeu< ALLOC >& from) :
78 ScoreBDeu< ALLOC >(from, from.getAllocator()) {}
82 template <
template <
typename >
class ALLOC >
83 INLINE ScoreBDeu< ALLOC >::ScoreBDeu(ScoreBDeu< ALLOC >&& from,
84 const typename ScoreBDeu< ALLOC >::allocator_type& alloc) :
85 Score< ALLOC >(std::move(from), alloc),
86 _internal_apriori_(std::move(from._internal_apriori_), alloc),
87 _gammalog2_(std::move(from._gammalog2_)) {
88 GUM_CONS_MOV(ScoreBDeu);
93 template <
template <
typename >
class ALLOC >
94 INLINE ScoreBDeu< ALLOC >::ScoreBDeu(ScoreBDeu< ALLOC >&& from) :
95 ScoreBDeu< ALLOC >(std::move(from), from.getAllocator()) {}
99 template <
template <
typename >
class ALLOC >
101 ScoreBDeu< ALLOC >::clone(
const typename ScoreBDeu< ALLOC >::allocator_type& alloc)
const {
102 ALLOC< ScoreBDeu< ALLOC > > allocator(alloc);
103 ScoreBDeu< ALLOC >* new_score = allocator.allocate(1);
105 allocator.construct(new_score, *
this, alloc);
107 allocator.deallocate(new_score, 1);
116 template <
template <
typename >
class ALLOC >
117 ScoreBDeu< ALLOC >* ScoreBDeu< ALLOC >::clone()
const {
118 return clone(
this->getAllocator());
123 template <
template <
typename >
class ALLOC >
124 ScoreBDeu< ALLOC >::~ScoreBDeu() {
125 GUM_DESTRUCTOR(ScoreBDeu);
130 template <
template <
typename >
class ALLOC >
131 ScoreBDeu< ALLOC >& ScoreBDeu< ALLOC >::operator=(
const ScoreBDeu< ALLOC >& from) {
133 Score< ALLOC >::operator=(from);
134 _internal_apriori_ = from._internal_apriori_;
141 template <
template <
typename >
class ALLOC >
142 ScoreBDeu< ALLOC >& ScoreBDeu< ALLOC >::operator=(ScoreBDeu< ALLOC >&& from) {
144 Score< ALLOC >::operator=(std::move(from));
145 _internal_apriori_ = std::move(from._internal_apriori_);
152 template <
template <
typename >
class ALLOC >
153 std::string ScoreBDeu< ALLOC >::isAprioriCompatible(
const std::string& apriori_type,
156 if (apriori_type == AprioriNoAprioriType::type) {
return ""; }
159 return "The apriori is currently compatible with the BDeu score but " 160 "if you change the weight, it will become incompatible.";
164 if ((apriori_type == AprioriDirichletType::type)
165 || (apriori_type == AprioriSmoothingType::type)) {
166 return "The BDeu score already contains a different 'implicit' apriori. " 167 "Therefore, the learning will probably be biased.";
171 std::stringstream msg;
172 msg <<
"The apriori '" << apriori_type
173 <<
"' is not yet supported by method isAprioriCompatible os Score BDeu";
179 template <
template <
typename >
class ALLOC >
180 INLINE std::string ScoreBDeu< ALLOC >::isAprioriCompatible(
const Apriori< ALLOC >& apriori) {
181 return isAprioriCompatible(apriori.getType(), apriori.weight());
186 template <
template <
typename >
class ALLOC >
187 INLINE std::string ScoreBDeu< ALLOC >::isAprioriCompatible()
const {
188 return isAprioriCompatible(*(
this->apriori_));
193 template <
template <
typename >
class ALLOC >
194 INLINE
const Apriori< ALLOC >& ScoreBDeu< ALLOC >::internalApriori()
const {
195 return _internal_apriori_;
200 template <
template <
typename >
class ALLOC >
201 INLINE
void ScoreBDeu< ALLOC >::setEffectiveSampleSize(
double ess) {
203 GUM_ERROR(OutOfBounds,
204 "The effective sample size of the BDeu's " 205 "internal apriori must be positive");
207 _internal_apriori_.setEffectiveSampleSize(ess);
213 template <
template <
typename >
class ALLOC >
214 double ScoreBDeu< ALLOC >::score_(
const IdCondSet< ALLOC >& idset) {
216 std::vector<
double, ALLOC<
double > > N_ijk(
this->counter_.counts(idset,
true));
217 const std::size_t all_size = N_ijk.size();
220 const double ess = _internal_apriori_.weight();
221 const bool informative_external_apriori =
this->apriori_->isInformative();
226 if (idset.hasConditioningSet()) {
228 std::vector<
double, ALLOC<
double > > N_ij(
this->marginalize_(idset[0], N_ijk));
229 const std::size_t conditioning_size = N_ij.size();
230 const double ess_qi = ess / conditioning_size;
231 const double ess_riqi = ess / all_size;
233 if (informative_external_apriori) {
238 std::vector<
double, ALLOC<
double > > N_prime_ijk(all_size, 0.0);
239 this->apriori_->addAllApriori(idset, N_prime_ijk);
240 std::vector<
double, ALLOC<
double > > N_prime_ij(N_ij.size(), 0.0);
241 this->apriori_->addConditioningApriori(idset, N_prime_ij);
248 for (std::size_t j = std::size_t(0); j < conditioning_size; ++j) {
249 score += _gammalog2_(N_prime_ij[j] + ess_qi)
250 - _gammalog2_(N_ij[j] + N_prime_ij[j] + ess_qi);
252 for (std::size_t k = std::size_t(0); k < all_size; ++k) {
253 score += _gammalog2_(N_ijk[k] + N_prime_ijk[k] + ess_riqi)
254 - _gammalog2_(N_prime_ijk[k] + ess_riqi);
262 score = conditioning_size * _gammalog2_(ess_qi) - all_size * _gammalog2_(ess_riqi);
264 for (
const auto n_ij: N_ij) {
265 score -= _gammalog2_(n_ij + ess_qi);
267 for (
const auto n_ijk: N_ijk) {
268 score += _gammalog2_(n_ijk + ess_riqi);
273 const double ess_ri = ess / all_size;
275 if (informative_external_apriori) {
280 std::vector<
double, ALLOC<
double > > N_prime_ijk(all_size, 0.0);
281 this->apriori_->addAllApriori(idset, N_prime_ijk);
288 double N_prime = 0.0;
289 for (std::size_t k = std::size_t(0); k < all_size; ++k) {
290 score += _gammalog2_(N_ijk[k] + N_prime_ijk[k] + ess_ri)
291 - _gammalog2_(N_prime_ijk[k] + ess_ri);
293 N_prime += N_prime_ijk[k];
295 score += _gammalog2_(N_prime + ess) - _gammalog2_(N + N_prime + ess);
302 score = _gammalog2_(ess) - all_size * _gammalog2_(ess_ri);
304 for (
const auto n_ijk: N_ijk) {
305 score += _gammalog2_(n_ijk + ess_ri);
308 score -= _gammalog2_(N + ess);