aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
BayesNetFactory.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 /**
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,
143  const std::string& propValue) final;
144 
145  /// Tells the factory that we're out of a network declaration.
147 
148  /// @}
149  // ==========================================================================
150  /// @name Variable declaration methods (NONE -> VARIABLE)
151  // ==========================================================================
152  /// @{
153 
154  /// Tells the factory that we're in a variable declaration.
156 
157  /// Tells the factory the current variable's name.
158  /// @throw DuplicateElement Raised if a variable with the same name already
159  /// exist.
160  void variableName(const std::string& name) final;
161 
162  /// Tells the factory the current variable's description.
163  void variableDescription(const std::string& desc) final;
164 
165  /// Adds a modality to the current labelized variable.
166  void addModality(const std::string& name) final;
167 
168  /// Adds the min value of the current range variable.
169  void addMin(const long& min);
170 
171  /// Adds the max value of the current range variable.
172  void addMax(const long& max);
173 
174  /// Adds a tick to the current Discretized variable.
175  void addTick(const GUM_SCALAR& tick);
176 
177  /**
178  * @brief Defines the implementation to use for var's Potential.
179  *
180  * @warning The implementation must be empty.
181  *
182  * @warning The pointer is always delegated to var's Potential! No copy of
183  * it is made.
184  *
185  * @todo When copy of a MultiDimImplementation is available use a copy
186  * behaviour for this method.
187  *
188  * @throw NotFound Raised if no variable matches var.
189  * @throw OperationNotAllowed Raised if impl is not empty.
190  * @throw OperationNotAllowed If an implementation is already defined for
191  * the current variable.
192  */
193  void setVariableCPTImplementation(MultiDimAdressable* adressable) final;
194 
195  /**
196  * Tells the factory that we're out of a variable declaration.
197  * @return The Node id of the created variable.
198  * @throw gum::OperationNotAllowed Raised if the variable isn't defined
199  * (or / not enough defined).
200  */
202 
203  /// @}
204  // ==========================================================================
205  /// @name Parents declaration methods (NONE -> PARENTS)
206  // ==========================================================================
207  /// @{
208 
209  /// Tells the factory that we're declaring parents for some variable.
210  /// @param var The concerned variable's name.
211  /// @throw NotFound Raised if var does not exists.
212  void startParentsDeclaration(const std::string& var) final;
213 
214  /// Tells the factory for which variable we're declaring parents.
215  /// @param var The parent's name.
216  /// @throw NotFound Raised if var does not exists.
217  void addParent(const std::string& var) final;
218 
219  /// Tells the factory that we've finished declaring parents for some
220  /// variable.
221  /// @warning When parents exist, endParentsDeclaration creates some arcs.
222  /// Due to
223  /// the order used
224  /// in BIF file for probability specification, these arcs are created in the
225  /// inverse order of
226  /// the order of the parent specifications.
228 
229  /// @}
230  // ==========================================================================
231  /// @name Raw Probability table declaration methods (NONE -> RAW_CPT)
232  // ==========================================================================
233  /// @{
234 
235  /// Tells the factory that we're declaring a conditional probability table
236  /// for some variable.
237  /// @param var The concerned variable's name.
238  void startRawProbabilityDeclaration(const std::string& var) final;
239 
240  /**
241  * @brief Fills the variable's table with the values in rawTable.
242  *
243  * Parse the parents in the same order in variables
244  *
245  * Given a sequence [var, p_1, p_2, ...,p_n-1, p_n] of parents, modalities
246  * are parsed in the given order (if all p_i are binary):
247  * \verbatim
248  * [0, 0, ..., 0, 0],
249  * [0, 0, ..., 0, 1],
250  * [0, 0, ..., 1, 0],
251  * [0, 0, ..., 1, 1],
252  * ...,
253  * [1, 1, ..., 1, 0],
254  * [1, 1, ..., 1, 1].
255  * \endverbatim
256  *
257  * @param variables the vector giving the order of parents
258  * @param rawTable The raw table.
259  */
260  void rawConditionalTable(const std::vector< std::string >& variables,
261  const std::vector< float >& rawTable) final;
262 
263  /**
264  * @brief Fills the variable's table with the values in rawTable.
265  *
266  * use the canonical ordering for the variables (e.g. see BIF format) ...
267  *
268  * @param rawTable The raw table.
269  */
270  void rawConditionalTable(const std::vector< float >& rawTable) final;
271 
272  /// Tells the factory that we finished declaring a conditional probability
273  /// table.
275 
276  /// @}
277  // ==========================================================================
278  /// \name Factorized probability table declaration methods
279  // (NONE -> RAW_CPT)
280  // ==========================================================================
281  /// @{
282 
283  /// Tells the factory that we're starting a factorized declaration.
284  void startFactorizedProbabilityDeclaration(const std::string& var) final;
285 
286  /// Tells the factory that we start an entry of a factorized conditional
287  /// probability table.
289 
290  /// Tells the factory that we end an entry of a factorized conditional
291  /// probability table.
292  void endFactorizedEntry() final;
293 
294  /// Tells the factory on which modality we want to instantiate one of
295  /// variable's parent.
296  void setParentModality(const std::string& parent,
297  const std::string& modality) final;
298 
299  /**
300  * @brief Gives the values of the variable with respect to precedent
301  * parents modality.
302  * If some parents have no modality set, then we apply values for all
303  * instantiations of that parent.
304  *
305  * This means you can declare a default value for the table by doing
306  * @code
307  * BayesNetFactory factory;
308  * // Do stuff
309  * factory.startVariableDeclaration();
310  * factory.variableName("foo");
311  * factory.endVariableDeclaration();
312  * factory.startParentsDeclaration("foo");
313  * // add parents
314  * factory.endParentsDeclaration();
315  * factory.startFactorizedProbabilityDeclaration("foo");
316  * std::vector<double> seq;
317  * seq.insert(0.4); // if foo true
318  * seq.insert(O.6); // if foo false
319  * factory.setVariableValues(seq); // fills the table with a default value
320  * // finish your stuff
321  * factory.endFactorizedProbabilityDeclaration();
322  * @endcode
323  * as for rawProba, if value's size is different than the number of
324  *modalities of
325  *the current variable,
326  * we don't use the supplementary values and we fill by 0 the missing
327  *values.
328  */
329  void setVariableValuesUnchecked(const std::vector< float >& values) final;
330 
331  /**
332  * @brief same than below with gum::OperationNotAllowed exception if value's
333  * size
334  * not OK.
335  */
336  void setVariableValues(const std::vector< float >& values) final;
337 
338  /// Tells the factory that we finished declaring a conditional probability
339  /// table.
341 
342  /// @}
343  // ==========================================================================
344  /// \name Delegated CPT definitions methods
345  /// (NONE, NETWORK)
346  // ==========================================================================
347  /// @{
348 
349  /**
350  * @brief Define a variable.
351  *
352  * You can only call this method is the factory is in the NONE or NETWORK
353  * state.
354  *
355  * The variable is added by copy.
356  *
357  * @param var The pointer over a DiscreteVariable used to define a new
358  * variable in the built BayesNet.
359  * @throw DuplicateElement Raised if a variable with the same name already
360  * exists.
361  * @throw OperationNotAllowed Raised if redefineParents == false and if
362  * table is not a valid CPT for var in the current state of the BayesNet.
363  */
364  void setVariable(const DiscreteVariable& var) final;
365 
366  /**
367  * @brief Define a variable's CPT.
368  *
369  * You can only call this method if the factory is in the NONE or NETWORK
370  * state.
371  *
372  * Be careful that table is given to the built BayesNet, so it will be
373  * deleted with it, and you should not directly access it after you call
374  * this method.
375  *
376  * When the redefineParents flag is set to true the constructed BayesNet's
377  * DAG is changed to fit with table's definition.
378  *
379  * @param varName The name of the concerned variable.
380  * @param table A pointer over the CPT used for var.
381  * @param redefineParents If true redefine var's parents to match table's
382  * variables set.
383  *
384  * @throw NotFound Raised if no variable matches var.
385  * @throw OperationNotAllowed Raised if redefineParents == false and if
386  * table is not a valid CPT for var in the current state of the BayesNet.
387  */
388  void setVariableCPT(const std::string& varName,
389  MultiDimAdressable* table,
390  bool redefineParents) final;
391 
392  /// @}
393 
394  private:
395  // ==========================================================================
396  /// @name Current constructed BayesNet's parts.
397  // ==========================================================================
398  /// @{
399 
400  /// Depending on the context this flag is used for some VERY important
401  /// reasons.
403 
404  /// Depending on the context this flag is used for some VERY important
405  /// reasons.
407 
408  /// Just to keep track of strings between two start/end calls.
410 
411  /// Used when a factorized CPT is built.
413 
414  /// Implementation of variable between two
415  /// startVariableDeclaration/endVariableDeclaration calls.
417 
418  /// @}
419 
420  /// State stack.
421  std::vector< factory_state > states__;
422 
423  /// The constructed BayesNet.
425 
426  /// Mapping between a declared variable's name and it's node id.
428 
429  /// Copy operator is illegal, use only copy constructor.
430  BayesNetFactory< GUM_SCALAR >&
431  operator=(const BayesNetFactory< GUM_SCALAR >& source);
432 
433  /// Raise an OperationNotAllowed with the message "Illegal state."
434  void illegalStateError__(const std::string& s);
435 
436  /// Check if a variable with the given name exists, if not raise an NotFound
437  /// exception.
438  void checkVariableName__(const std::string& name);
439 
440  /// Check if var exists and if mod is one of it's modality, if not raise an
441  /// NotFound exception.
443 
444  /// Check if in stringBag__ there is no other modality with the same name.
445  void checkModalityInBag__(const std::string& mod);
446 
447  /// Sub method of setVariableCPT() which redefine the BayesNet's DAG with
448  /// respect to table.
449  void setCPTAndParents__(const DiscreteVariable& var,
450  Potential< GUM_SCALAR >* table);
451 
452  /// Reset the different parts used to constructed the BayesNet.
453  void resetParts__();
454 
455  /// Fill a potential from a raw CPT.
456  void fillProbaWithValuesTable__(const std::vector< std::string >& variables,
457  const std::vector< float >& rawTable);
458  /// Fill a potential from a raw CPT.(using the canonical order of vars)
459  void fillProbaWithValuesTable__(const std::vector< float >& rawTable);
460 
461  /// Increment a modality counter for the fillProbaWithValuesTable__ method.
462  bool increment__(std::vector< gum::Idx >& modCounter,
463  List< const DiscreteVariable* >& varList);
464  };
465 
466 
467 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
468  extern template class BayesNetFactory< double >;
469 #endif
470 
471 } /* namespace gum */
472 
473 #include <agrum/BN/BayesNetFactory_tpl.h>
474 
475 #endif // GUM_BAYESNET_FACTORY_H
bool foo_flag__
Depending on the context this flag is used for some VERY important reasons.
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.
void rawConditionalTable(const std::vector< float > &rawTable) final
Fills the variable&#39;s table with the values in rawTable.
bool bar_flag__
Depending on the context this flag is used for some VERY important reasons.
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.
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.
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669
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.
MultiDimImplementation< GUM_SCALAR > * impl__
Implementation of variable between two startVariableDeclaration/endVariableDeclaration calls...
void checkVariableName__(const std::string &name)
Check if a variable with the given name exists, if not raise an NotFound exception.
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 illegalStateError__(const std::string &s)
Raise an OperationNotAllowed with the message "Illegal state.".
BayesNet< GUM_SCALAR > * bn__
The constructed BayesNet.
BayesNetFactory< GUM_SCALAR > & operator=(const BayesNetFactory< GUM_SCALAR > &source)
Copy operator is illegal, use only copy constructor.
void variableType(const VarType &type)
Tells the factory the current variable&#39;s type.
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.
std::vector< std::string > stringBag__
Just to keep track of strings between two start/end calls.
void startVariableDeclaration() final
Tells the factory that we&#39;re in a variable declaration.
std::vector< factory_state > states__
State stack.
HashTable< std::string, NodeId > varNameMap__
Mapping between a declared variable&#39;s name and it&#39;s node id.
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.
Instantiation * parents__
Used when a factorized CPT is built.
bool increment__(std::vector< gum::Idx > &modCounter, List< const DiscreteVariable * > &varList)
Increment a modality counter for the fillProbaWithValuesTable__ method.
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 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.
void fillProbaWithValuesTable__(const std::vector< std::string > &variables, const std::vector< float > &rawTable)
Fill a potential from a raw CPT.
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.
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 addTick(const GUM_SCALAR &tick)
Adds a tick to the current Discretized variable.
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 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.
void resetParts__()
Reset the different parts used to constructed the BayesNet.
void fillProbaWithValuesTable__(const std::vector< float > &rawTable)
Fill a potential from a raw CPT.(using the canonical order of vars)
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.