aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
scoreK2.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 K2 scores (actually their log2 value)
24  *
25  * @warning This class does not actually compute a K2 score but rather the
26  * log in base 2 of the K2 score
27  *
28  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
29  */
30 
31 #ifndef GUM_LEARNING_SCORE_K2_H
32 #define GUM_LEARNING_SCORE_K2_H
33 
34 #include <string>
35 
36 #include <agrum/agrum.h>
37 #include <agrum/tools/core/math/math_utils.h>
38 #include <agrum/tools/core/math/gammaLog2.h>
39 #include <agrum/BN/learning/scores_and_tests/score.h>
40 #include <agrum/BN/learning/aprioris/aprioriK2.h>
41 
42 namespace gum {
43 
44  namespace learning {
45 
46  /** @class ScoreK2
47  * @brief the class for computing K2 scores (actually their log2 value)
48  * @headerfile scoreK2.h <agrum/BN/learning/scores_and_tests/scoreK2.h>
49  * @ingroup learning_scores
50  *
51  * @warning As the K2 score already includes an implicit Laplace apriori on
52  * all the cells of contingency tables, the apriori passed to the score should
53  * be a NoApriori. But aGrUM will let you use another (certainly incompatible)
54  * apriori with the score. In this case, this additional apriori will be
55  * included in addition to the implicit Laplace apriori in a BD fashion,
56  * i.e., we will resort to the Bayesian Dirichlet (BD) formula to include
57  * the sum of the two aprioris into the score.
58  */
59  template < template < typename > class ALLOC = std::allocator >
60  class ScoreK2: public Score< ALLOC > {
61  public:
62  /// type for the allocators passed in arguments of methods
64 
65  // ##########################################################################
66  /// @name Constructors / Destructors
67  // ##########################################################################
68  /// @{
69 
70  /// default constructor
71  /** @param parser the parser used to parse the database
72  * @param apriori An apriori that we add to the computation of the score
73  * @param ranges a set of pairs {(X1,Y1),...,(Xn,Yn)} of database's rows
74  * indices. The countings are then performed only on the union of the
75  * rows [Xi,Yi), i in {1,...,n}. This is useful, e.g, when performing
76  * cross validation tasks, in which part of the database should be ignored.
77  * An empty set of ranges is equivalent to an interval [X,Y) ranging over
78  * the whole database.
79  * @param nodeId2Columns a mapping from the ids of the nodes in the
80  * graphical model to the corresponding column in the DatabaseTable
81  * parsed by the parser. This enables estimating from a database in
82  * which variable A corresponds to the 2nd column the parameters of a BN
83  * in which variable A has a NodeId of 5. An empty nodeId2Columns
84  * bijection means that the mapping is an identity, i.e., the value of a
85  * NodeId is equal to the index of the column in the DatabaseTable.
86  * @param alloc the allocator used to allocate the structures within the
87  * Score.
88  * @warning If nodeId2columns is not empty, then only the scores over the
89  * ids belonging to this bijection can be computed: applying method
90  * score() over other ids will raise exception NotFound. */
91  ScoreK2(const DBRowGeneratorParser< ALLOC >& parser,
92  const Apriori< ALLOC >& apriori,
93  const std::vector< std::pair< std::size_t, std::size_t >,
94  ALLOC< std::pair< std::size_t, std::size_t > > >& ranges,
96  = Bijection< NodeId, std::size_t, ALLOC< std::size_t > >(),
98 
99 
100  /// default constructor
101  /** @param parser the parser used to parse the database
102  * @param apriori An apriori that we add to the computation of the score
103  * @param nodeId2Columns a mapping from the ids of the nodes in the
104  * graphical model to the corresponding column in the DatabaseTable
105  * parsed by the parser. This enables estimating from a database in
106  * which variable A corresponds to the 2nd column the parameters of a BN
107  * in which variable A has a NodeId of 5. An empty nodeId2Columns
108  * bijection means that the mapping is an identity, i.e., the value of a
109  * NodeId is equal to the index of the column in the DatabaseTable.
110  * @param alloc the allocator used to allocate the structures within the
111  * Score.
112  * @warning If nodeId2columns is not empty, then only the scores over the
113  * ids belonging to this bijection can be computed: applying method
114  * score() over other ids will raise exception NotFound. */
115  ScoreK2(const DBRowGeneratorParser< ALLOC >& parser,
116  const Apriori< ALLOC >& apriori,
118  = Bijection< NodeId, std::size_t, ALLOC< std::size_t > >(),
119  const allocator_type& alloc = allocator_type());
120 
121  /// copy constructor
122  ScoreK2(const ScoreK2< ALLOC >& from);
123 
124  /// copy constructor with a given allocator
125  ScoreK2(const ScoreK2< ALLOC >& from, const allocator_type& alloc);
126 
127  /// move constructor
128  ScoreK2(ScoreK2< ALLOC >&& from);
129 
130  /// move constructor with a given allocator
131  ScoreK2(ScoreK2< ALLOC >&& from, const allocator_type& alloc);
132 
133  /// virtual copy constructor
134  virtual ScoreK2< ALLOC >* clone() const;
135 
136  /// virtual copy constructor with a given allocator
137  virtual ScoreK2< ALLOC >* clone(const allocator_type& alloc) const;
138 
139  /// destructor
140  virtual ~ScoreK2();
141 
142  /// @}
143 
144 
145  // ##########################################################################
146  /// @name Operators
147  // ##########################################################################
148 
149  /// @{
150 
151  /// copy operator
152  ScoreK2< ALLOC >& operator=(const ScoreK2< ALLOC >& from);
153 
154  /// move operator
155  ScoreK2< ALLOC >& operator=(ScoreK2< ALLOC >&& from);
156 
157  /// @}
158 
159 
160  // ##########################################################################
161  /// @name Accessors / Modifiers
162  // ##########################################################################
163  /// @{
164 
165  /// indicates whether the apriori is compatible (meaningful) with the score
166  /** The combination of some scores and aprioris can be meaningless. For
167  * instance, adding a Dirichlet apriori to the K2 score is not very
168  * meaningful since K2 corresponds to a BD score with a 1-smoothing
169  * apriori.
170  * aGrUM allows you to perform such combination, but you can check with
171  * method isAprioriCompatible () whether the result the score will give
172  * you is meaningful or not.
173  * @returns a non empty string if the apriori is compatible with the
174  * score.*/
175  virtual std::string isAprioriCompatible() const final;
176 
177  /// returns the internal apriori of the score
178  /** Some scores include an apriori. For instance, the K2 score is a BD
179  * score with a Laplace Apriori ( smoothing(1) ). K2 is a BD score with
180  * a N'/(r_i * q_i) apriori, where N' is an effective sample size and r_i
181  * is the domain size of the target variable and q_i is the domain size of
182  * the Cartesian product of its parents. The goal of the score's internal
183  * apriori classes is to enable to account for these aprioris outside the
184  * score, e.g., when performing parameter estimation. It is important to
185  * note that, to be meaningful, a structure + parameter learning requires
186  * that the same aprioris are taken into account during structure learning
187  * and parameter learning. */
188  virtual const Apriori< ALLOC >& internalApriori() const final;
189 
190  /// @}
191 
192 
193  /// indicates whether the apriori is compatible (meaningful) with the score
194  /** @returns a non empty string if the apriori is compatible with the score.
195  */
196  static std::string isAprioriCompatible(const std::string& apriori_type, double weight = 1.0f);
197 
198  /// indicates whether the apriori is compatible (meaningful) with the score
199  /** a non empty string if the apriori is compatible with the score. */
200  static std::string isAprioriCompatible(const Apriori< ALLOC >& apriori);
201 
202 
203  protected:
204  /// returns the score for a given IdCondSet
205  /** @throws OperationNotAllowed is raised if the score does not support
206  * calling method score such an idset (due to too many/too few variables
207  * in the left hand side or the right hand side of the idset). */
208  virtual double score_(const IdCondSet< ALLOC >& idset) final;
209 
210 
211 #ifndef DOXYGEN_SHOULD_SKIP_THIS
212 
213  private:
214  /// the internal apriori of the score
215  AprioriK2< ALLOC > _internal_apriori_;
216 
217  /// the log(gamma (n)) function: generalizes log((n-1)!)
218  GammaLog2 _gammalog2_;
219 
220 
221 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
222  };
223 
224  } /* namespace learning */
225 
226 } /* namespace gum */
227 
228 
229 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
230 extern template class gum::learning::ScoreK2<>;
231 #endif
232 
233 
234 // always include the template implementation
235 #include <agrum/BN/learning/scores_and_tests/scoreK2_tpl.h>
236 
237 #endif /* GUM_LEARNING_SCORE_K2_H */
ScoreK2(ScoreK2< ALLOC > &&from)
move constructor
virtual double score_(const IdCondSet< ALLOC > &idset) final
returns the score for a given IdCondSet
ScoreK2(ScoreK2< ALLOC > &&from, const allocator_type &alloc)
move constructor with a given allocator
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
static std::string isAprioriCompatible(const Apriori< ALLOC > &apriori)
indicates whether the apriori is compatible (meaningful) with the score
the class for computing K2 scores (actually their log2 value)
Definition: scoreK2.h:60
ScoreK2(const ScoreK2< ALLOC > &from, const allocator_type &alloc)
copy constructor with a given allocator
ScoreK2< ALLOC > & operator=(const ScoreK2< ALLOC > &from)
copy operator
virtual ScoreK2< ALLOC > * clone() const
virtual copy constructor
ScoreK2(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
ScoreK2< ALLOC > & operator=(ScoreK2< ALLOC > &&from)
move operator
virtual const Apriori< ALLOC > & internalApriori() const final
returns the internal apriori of the score
virtual std::string isAprioriCompatible() const final
indicates whether the apriori is compatible (meaningful) with the score
virtual ~ScoreK2()
destructor
static std::string isAprioriCompatible(const std::string &apriori_type, double weight=1.0f)
indicates whether the apriori is compatible (meaningful) with the score
ScoreK2(const DBRowGeneratorParser< ALLOC > &parser, const Apriori< ALLOC > &apriori, 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
virtual ScoreK2< ALLOC > * clone(const allocator_type &alloc) const
virtual copy constructor with a given allocator
ScoreK2(const ScoreK2< ALLOC > &from)
copy constructor
Database(const std::string &filename, const BayesNet< GUM_SCALAR > &bn, const std::vector< std::string > &missing_symbols)