aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
BayesNetFactory.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 /**
23  * @file
24  * @brief Headers of the BayesNetFactory class.
25  *
26  * @author Lionel TORTI and Pierre-Henri WUILLEMIN(@LIP6)
27  */
28 
29 #ifndef GUM_BAYESNET_FACTORY_H
30 #define GUM_BAYESNET_FACTORY_H
31 
32 #include <string>
33 #include <vector>
34 
35 #include <agrum/BN/BayesNet.h>
36 #include <agrum/BN/IBayesNetFactory.h>
37 
38 namespace gum {
39 
40  /**
41  * @class BayesNetFactory
42  * @headerfile BayesNetFactory.h <agrum/BN/BayesNetFactory.h>
43  * @brief A factory class to ease BayesNet construction.
44  * @ingroup bn_group
45  *
46  * A BayesNetFactory will never create a BayesNet and works on only one
47  * BayesNet.
48  *
49  * The only exception of this behaviour is when you create a copy of the
50  * factory, it will create a copy of it's BayesNet. This is useful if you
51  * want to create two BayesNet sharing a common base.
52  *
53  * However be very careful because the copy will not delete it's BayesNet.
54  *
55  * Each method will raise an OperationNotAllowed if you call it when the
56  * factory is not in a valid state for that call. The error message is
57  * "Illegal state.".
58  *
59  */
60  template < typename GUM_SCALAR >
61  class BayesNetFactory: public IBayesNetFactory {
62  public:
63  // ==========================================================================
64  /// @name Constructor & destructor.
65  // ==========================================================================
66  /// @{
67 
68  /**
69  * Use this constructor if you want to use an already created BayesNet.
70  * @param bn A pointer over the BayesNet filled by this factory.
71  * @throw DuplicateElement Raised if two variables in bn share the same
72  * name.
73  */
74  explicit BayesNetFactory(BayesNet< GUM_SCALAR >* bn);
75 
76  /**
77  * @brief Copy constructor.
78  * The copy will have an exact copy of the constructed BayesNet in source.
79  * @warning You can only copy a factory if its current state is NONE or
80  * NETWORK.
81  *
82  * @throw OperationNotAllowed Raised if the state of source is not NONE or
83  * NETWORK.
84  */
85  BayesNetFactory(const BayesNetFactory< GUM_SCALAR >& source);
86 
87  /**
88  * @brief Destructor.
89  *
90  * To prevent strange behaviour you should always destroy a BayesNetFactory
91  * when it's state equals NONE.
92  *
93  * @throw FatalError Raised if the state of the factory prevents it to die
94  * peacefully.
95  */
96  virtual ~BayesNetFactory();
97 
98  /// @}
99  // ==========================================================================
100  /// @name Getter and setters.
101  // ==========================================================================
102  /// @{
103 
104  /**
105  * Returns the BayesNet created by this factory.
106  * @throw OperationNotAllowed Raise if the state of the factory is different
107  * than NONE.
108  */
110 
111  /** short-cut accessor for a DiscreveVariable in the BN */
112  const DiscreteVariable& varInBN(NodeId id) final;
113 
114  /// Returns the current state of the factory.
115  factory_state state() const final;
116 
117  /// Returns the NodeId of a variable given it's name.
118  /// @throw NotFound Raised if no variable matches the name.
119  NodeId variableId(const std::string& name) const final;
120 
121  /// Returns a constant reference on a variable given it's name.
122  /// @throw NotFound Raised if no variable matches the name.
123  const DiscreteVariable& variable(const std::string& name) const;
124 
125  /// Returns the domainSize of the cpt for the node n.
126  /// @throw NotFound raised if no such NodeId exists.
127  Size cptDomainSize(NodeId n) const final;
128 
129  /// @}
130  // ==========================================================================
131  /// @name Network declaration methods (NONE -> NETWORK)
132  // ==========================================================================
133  /// @{
134 
135  /// Tells the factory that we're in a network declaration.
137 
138  /// Tells the factory the current variable's type.
139  void variableType(const VarType& type);
140 
141  /// Tells the factory to add a property to the current network.
142  void addNetworkProperty(const std::string& propName, const std::string& propValue) final;
143 
144  /// Tells the factory that we're out of a network declaration.
146 
147  /// @}
148  // ==========================================================================
149  /// @name Variable declaration methods (NONE -> VARIABLE)
150  // ==========================================================================
151  /// @{
152 
153  /// Tells the factory that we're in a variable declaration.
155 
156  /// Tells the factory the current variable's name.
157  /// @throw DuplicateElement Raised if a variable with the same name already
158  /// exist.
159  void variableName(const std::string& name) final;
160 
161  /// Tells the factory the current variable's description.
162  void variableDescription(const std::string& desc) final;
163 
164  /// Adds a modality to the current labelized variable.
165  void addModality(const std::string& name) final;
166 
167  /// Adds the min value of the current range variable.
168  void addMin(const long& min);
169 
170  /// Adds the max value of the current range variable.
171  void addMax(const long& max);
172 
173  /// Adds a tick to the current Discretized variable.
174  void addTick(const GUM_SCALAR& tick);
175 
176  /**
177  * @brief Defines the implementation to use for var's Potential.
178  *
179  * @warning The implementation must be empty.
180  *
181  * @warning The pointer is always delegated to var's Potential! No copy of
182  * it is made.
183  *
184  * @todo When copy of a MultiDimImplementation is available use a copy
185  * behaviour for this method.
186  *
187  * @throw NotFound Raised if no variable matches var.
188  * @throw OperationNotAllowed Raised if impl is not empty.
189  * @throw OperationNotAllowed If an implementation is already defined for
190  * the current variable.
191  */
192  void setVariableCPTImplementation(MultiDimAdressable* adressable) final;
193 
194  /**
195  * Tells the factory that we're out of a variable declaration.
196  * @return The Node id of the created variable.
197  * @throw gum::OperationNotAllowed Raised if the variable isn't defined
198  * (or / not enough defined).
199  */
201 
202  /// @}
203  // ==========================================================================
204  /// @name Parents declaration methods (NONE -> PARENTS)
205  // ==========================================================================
206  /// @{
207 
208  /// Tells the factory that we're declaring parents for some variable.
209  /// @param var The concerned variable's name.
210  /// @throw NotFound Raised if var does not exists.
211  void startParentsDeclaration(const std::string& var) final;
212 
213  /// Tells the factory for which variable we're declaring parents.
214  /// @param var The parent's name.
215  /// @throw NotFound Raised if var does not exists.
216  void addParent(const std::string& var) final;
217 
218  /// Tells the factory that we've finished declaring parents for some
219  /// variable.
220  /// @warning When parents exist, endParentsDeclaration creates some arcs.
221  /// Due to
222  /// the order used
223  /// in BIF file for probability specification, these arcs are created in the
224  /// inverse order of
225  /// the order of the parent specifications.
227 
228  /// @}
229  // ==========================================================================
230  /// @name Raw Probability table declaration methods (NONE -> RAW_CPT)
231  // ==========================================================================
232  /// @{
233 
234  /// Tells the factory that we're declaring a conditional probability table
235  /// for some variable.
236  /// @param var The concerned variable's name.
237  void startRawProbabilityDeclaration(const std::string& var) final;
238 
239  /**
240  * @brief Fills the variable's table with the values in rawTable.
241  *
242  * Parse the parents in the same order in variables
243  *
244  * Given a sequence [var, p_1, p_2, ...,p_n-1, p_n] of parents, modalities
245  * are parsed in the given order (if all p_i are binary):
246  * \verbatim
247  * [0, 0, ..., 0, 0],
248  * [0, 0, ..., 0, 1],
249  * [0, 0, ..., 1, 0],
250  * [0, 0, ..., 1, 1],
251  * ...,
252  * [1, 1, ..., 1, 0],
253  * [1, 1, ..., 1, 1].
254  * \endverbatim
255  *
256  * @param variables the vector giving the order of parents
257  * @param rawTable The raw table.
258  */
259  void rawConditionalTable(const std::vector< std::string >& variables,
260  const std::vector< float >& rawTable) final;
261 
262  /**
263  * @brief Fills the variable's table with the values in rawTable.
264  *
265  * use the canonical ordering for the variables (e.g. see BIF format) ...
266  *
267  * @param rawTable The raw table.
268  */
269  void rawConditionalTable(const std::vector< float >& rawTable) final;
270 
271  /// Tells the factory that we finished declaring a conditional probability
272  /// table.
274 
275  /// @}
276  // ==========================================================================
277  /// \name Factorized probability table declaration methods
278  // (NONE -> RAW_CPT)
279  // ==========================================================================
280  /// @{
281 
282  /// Tells the factory that we're starting a factorized declaration.
283  void startFactorizedProbabilityDeclaration(const std::string& var) final;
284 
285  /// Tells the factory that we start an entry of a factorized conditional
286  /// probability table.
288 
289  /// Tells the factory that we end an entry of a factorized conditional
290  /// probability table.
291  void endFactorizedEntry() final;
292 
293  /// Tells the factory on which modality we want to instantiate one of
294  /// variable's parent.
295  void setParentModality(const std::string& parent, const std::string& modality) final;
296 
297  /**
298  * @brief Gives the values of the variable with respect to precedent
299  * parents modality.
300  * If some parents have no modality set, then we apply values for all
301  * instantiations of that parent.
302  *
303  * This means you can declare a default value for the table by doing
304  * @code
305  * BayesNetFactory factory;
306  * // Do stuff
307  * factory.startVariableDeclaration();
308  * factory.variableName("foo");
309  * factory.endVariableDeclaration();
310  * factory.startParentsDeclaration("foo");
311  * // add parents
312  * factory.endParentsDeclaration();
313  * factory.startFactorizedProbabilityDeclaration("foo");
314  * std::vector<double> seq;
315  * seq.insert(0.4); // if foo true
316  * seq.insert(O.6); // if foo false
317  * factory.setVariableValues(seq); // fills the table with a default value
318  * // finish your stuff
319  * factory.endFactorizedProbabilityDeclaration();
320  * @endcode
321  * as for rawProba, if value's size is different than the number of
322  *modalities of
323  *the current variable,
324  * we don't use the supplementary values and we fill by 0 the missing
325  *values.
326  */
327  void setVariableValuesUnchecked(const std::vector< float >& values) final;
328 
329  /**
330  * @brief same than below with gum::OperationNotAllowed exception if value's
331  * size
332  * not OK.
333  */
334  void setVariableValues(const std::vector< float >& values) final;
335 
336  /// Tells the factory that we finished declaring a conditional probability
337  /// table.
339 
340  /// @}
341  // ==========================================================================
342  /// \name Delegated CPT definitions methods
343  /// (NONE, NETWORK)
344  // ==========================================================================
345  /// @{
346 
347  /**
348  * @brief Define a variable.
349  *
350  * You can only call this method is the factory is in the NONE or NETWORK
351  * state.
352  *
353  * The variable is added by copy.
354  *
355  * @param var The pointer over a DiscreteVariable used to define a new
356  * variable in the built BayesNet.
357  * @throw DuplicateElement Raised if a variable with the same name already
358  * exists.
359  * @throw OperationNotAllowed Raised if redefineParents == false and if
360  * table is not a valid CPT for var in the current state of the BayesNet.
361  */
362  void setVariable(const DiscreteVariable& var) final;
363 
364  /**
365  * @brief Define a variable's CPT.
366  *
367  * You can only call this method if the factory is in the NONE or NETWORK
368  * state.
369  *
370  * Be careful that table is given to the built BayesNet, so it will be
371  * deleted with it, and you should not directly access it after you call
372  * this method.
373  *
374  * When the redefineParents flag is set to true the constructed BayesNet's
375  * DAG is changed to fit with table's definition.
376  *
377  * @param varName The name of the concerned variable.
378  * @param table A pointer over the CPT used for var.
379  * @param redefineParents If true redefine var's parents to match table's
380  * variables set.
381  *
382  * @throw NotFound Raised if no variable matches var.
383  * @throw OperationNotAllowed Raised if redefineParents == false and if
384  * table is not a valid CPT for var in the current state of the BayesNet.
385  */
386  void setVariableCPT(const std::string& varName,
387  MultiDimAdressable* table,
388  bool redefineParents) final;
389 
390  /// @}
391 
392  private:
393  // ==========================================================================
394  /// @name Current constructed BayesNet's parts.
395  // ==========================================================================
396  /// @{
397 
398  /// Depending on the context this flag is used for some VERY important
399  /// reasons.
401 
402  /// Depending on the context this flag is used for some VERY important
403  /// reasons.
405 
406  /// Just to keep track of strings between two start/end calls.
408 
409  /// Used when a factorized CPT is built.
411 
412  /// Implementation of variable between two
413  /// startVariableDeclaration/endVariableDeclaration calls.
415 
416  /// @}
417 
418  /// State stack.
419  std::vector< factory_state > _states_;
420 
421  /// The constructed BayesNet.
423 
424  /// Mapping between a declared variable's name and it's node id.
426 
427  /// Copy operator is illegal, use only copy constructor.
428  BayesNetFactory< GUM_SCALAR >& operator=(const BayesNetFactory< GUM_SCALAR >& source) = delete;
429 
430  /// Raise an OperationNotAllowed with the message "Illegal state."
431  void _illegalStateError_(const std::string& s);
432 
433  /// Check if a variable with the given name exists, if not raise an NotFound
434  /// exception.
435  void _checkVariableName_(const std::string& name);
436 
437  /// Check if var exists and if mod is one of it's modality, if not raise an
438  /// NotFound exception.
440 
441  /// Check if in _stringBag_ there is no other modality with the same name.
442  void _checkModalityInBag_(const std::string& mod);
443 
444  /// Sub method of setVariableCPT() which redefine the BayesNet's DAG with
445  /// respect to table.
446  void _setCPTAndParents_(const DiscreteVariable& var, Potential< GUM_SCALAR >* table);
447 
448  /// Reset the different parts used to constructed the BayesNet.
449  void _resetParts_();
450 
451  /// Fill a potential from a raw CPT.
452  void _fillProbaWithValuesTable_(const std::vector< std::string >& variables,
453  const std::vector< float >& rawTable);
454  /// Fill a potential from a raw CPT.(using the canonical order of vars)
455  void _fillProbaWithValuesTable_(const std::vector< float >& rawTable);
456 
457  /// Increment a modality counter for the _fillProbaWithValuesTable_ method.
458  bool _increment_(std::vector< gum::Idx >& modCounter, List< const DiscreteVariable* >& varList);
459  };
460 
461 
462 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
463  extern template class BayesNetFactory< double >;
464 #endif
465 
466 } /* namespace gum */
467 
468 #include <agrum/BN/BayesNetFactory_tpl.h>
469 
470 #endif // GUM_BAYESNET_FACTORY_H
void endRawProbabilityDeclaration() final
Tells the factory that we finished declaring a conditional probability table.
void variableName(const std::string &name) final
Tells the factory the current variable&#39;s name.
BayesNet< GUM_SCALAR > * _bn_
The constructed BayesNet.
void rawConditionalTable(const std::vector< float > &rawTable) final
Fills the variable&#39;s table with the values in rawTable.
void endFactorizedEntry() final
Tells the factory that we end an entry of a factorized conditional probability table.
void setVariableCPTImplementation(MultiDimAdressable *adressable) final
Defines the implementation to use for var&#39;s Potential.
void startFactorizedEntry() final
Tells the factory that we start an entry of a factorized conditional probability table.
BayesNetFactory(BayesNet< GUM_SCALAR > *bn)
Use this constructor if you want to use an already created BayesNet.
void addParent(const std::string &var) final
Tells the factory for which variable we&#39;re declaring parents.
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
void setVariable(const DiscreteVariable &var) final
Define a variable.
BayesNet< GUM_SCALAR > * bayesNet()
Returns the BayesNet created by this factory.
factory_state state() const final
Returns the current state of the factory.
void addNetworkProperty(const std::string &propName, const std::string &propValue) final
Tells the factory to add a property to the current network.
void startParentsDeclaration(const std::string &var) final
Tells the factory that we&#39;re declaring parents for some variable.
std::vector< std::string > _stringBag_
Just to keep track of strings between two start/end calls.
HashTable< std::string, NodeId > _varNameMap_
Mapping between a declared variable&#39;s name and it&#39;s node id.
void _checkModalityInBag_(const std::string &mod)
Check if in stringBag there is no other modality with the same name.
void endParentsDeclaration() final
Tells the factory that we&#39;ve finished declaring parents for some variable.
void _resetParts_()
Reset the different parts used to constructed the BayesNet.
void variableType(const VarType &type)
Tells the factory the current variable&#39;s type.
MultiDimImplementation< GUM_SCALAR > * _impl_
Implementation of variable between two startVariableDeclaration/endVariableDeclaration calls...
Idx _checkVariableModality_(const std::string &name, const std::string &mod)
Check if var exists and if mod is one of it&#39;s modality, if not raise an NotFound exception.
std::vector< factory_state > _states_
State stack.
void startFactorizedProbabilityDeclaration(const std::string &var) final
Tells the factory that we&#39;re starting a factorized declaration.
NodeId variableId(const std::string &name) const final
Returns the NodeId of a variable given it&#39;s name.
void startNetworkDeclaration() final
Tells the factory that we&#39;re in a network declaration.
bool _bar_flag_
Depending on the context this flag is used for some VERY important reasons.
void startVariableDeclaration() final
Tells the factory that we&#39;re in a variable declaration.
void _setCPTAndParents_(const DiscreteVariable &var, Potential< GUM_SCALAR > *table)
Sub method of setVariableCPT() which redefine the BayesNet&#39;s DAG with respect to table.
void addMax(const long &max)
Adds the max value of the current range variable.
NodeId endVariableDeclaration() final
Tells the factory that we&#39;re out of a variable declaration.
Size cptDomainSize(NodeId n) const final
Returns the domainSize of the cpt for the node n.
void startRawProbabilityDeclaration(const std::string &var) final
Tells the factory that we&#39;re declaring a conditional probability table for some variable.
const DiscreteVariable & varInBN(NodeId id) final
short-cut accessor for a DiscreveVariable in the BN
void setVariableValuesUnchecked(const std::vector< float > &values) final
Gives the values of the variable with respect to precedent parents modality.
void _checkVariableName_(const std::string &name)
Check if a variable with the given name exists, if not raise an NotFound exception.
void setVariableCPT(const std::string &varName, MultiDimAdressable *table, bool redefineParents) final
Define a variable&#39;s CPT.
void endFactorizedProbabilityDeclaration() final
Tells the factory that we finished declaring a conditional probability table.
BayesNetFactory< GUM_SCALAR > & operator=(const BayesNetFactory< GUM_SCALAR > &source)=delete
Copy operator is illegal, use only copy constructor.
void _fillProbaWithValuesTable_(const std::vector< float > &rawTable)
Fill a potential from a raw CPT.(using the canonical order of vars)
void addMin(const long &min)
Adds the min value of the current range variable.
void variableDescription(const std::string &desc) final
Tells the factory the current variable&#39;s description.
BayesNetFactory(const BayesNetFactory< GUM_SCALAR > &source)
Copy constructor.
bool _foo_flag_
Depending on the context this flag is used for some VERY important reasons.
void rawConditionalTable(const std::vector< std::string > &variables, const std::vector< float > &rawTable) final
Fills the variable&#39;s table with the values in rawTable.
void _fillProbaWithValuesTable_(const std::vector< std::string > &variables, const std::vector< float > &rawTable)
Fill a potential from a raw CPT.
void addTick(const GUM_SCALAR &tick)
Adds a tick to the current Discretized variable.
void endNetworkDeclaration() final
Tells the factory that we&#39;re out of a network declaration.
const DiscreteVariable & variable(const std::string &name) const
Returns a constant reference on a variable given it&#39;s name.
void addModality(const std::string &name) final
Adds a modality to the current labelized variable.
Instantiation * _parents_
Used when a factorized CPT is built.
void _illegalStateError_(const std::string &s)
Raise an OperationNotAllowed with the message "Illegal state.".
bool _increment_(std::vector< gum::Idx > &modCounter, List< const DiscreteVariable * > &varList)
Increment a modality counter for the fillProbaWithValuesTable method.
void setVariableValues(const std::vector< float > &values) final
same than below with gum::OperationNotAllowed exception if value&#39;s size not OK.
virtual ~BayesNetFactory()
Destructor.
void setParentModality(const std::string &parent, const std::string &modality) final
Tells the factory on which modality we want to instantiate one of variable&#39;s parent.