aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
PRMFactory.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 PRMFactory.
25  *
26  * @author Lionel TORTI and Pierre-Henri WUILLEMIN(@LIP6)
27  */
28 
29 #ifndef GUM_PRM_FACTORY_H
30 #define GUM_PRM_FACTORY_H
31 
32 #include <iostream>
33 #include <limits>
34 #include <sstream>
35 #include <string>
36 #include <vector>
37 
38 #include <agrum/agrum.h>
39 #include <agrum/tools/core/list.h>
40 
41 #include <agrum/tools/multidim/implementations/multiDimSparse.h>
42 #include <agrum/tools/variables/discreteVariable.h>
43 
44 #include <agrum/PRM/IPRMFactory.h>
45 #include <agrum/PRM/PRM.h>
46 #include <agrum/PRM/utils_prm.h>
47 
48 namespace gum {
49 
50  namespace prm {
51  /**
52  * @class PRMFactory
53  * @brief Factory which builds a PRM<GUM_SCALAR>.
54  *
55  * The Factory always create one PRM<GUM_SCALAR> which is not deleted with
56  *the
57  *factory, so
58  * be very careful to delete the PRM<GUM_SCALAR> built by this factory.
59  *
60  * The factory does not allow any sequence of calls, if you call a method
61  *when
62  * the factory is in an incoherent state it will raise a FactoryInvalidState
63  * exception.
64  *
65  * Keep in mind that most methods could raise gum::FatalError if something
66  * unexpected happens, since the framework is meant to evolve it is
67  *possible.
68  *
69  * @see PRM<GUM_SCALAR> PRMObject
70  * @ingroup prm_group
71  */
72  // ==========================================================================
73  template < typename GUM_SCALAR >
74  class PRMFactory: public IPRMFactory {
75  public:
76  // ======================================================================
77  /// @name Constructors & destructor
78  // ======================================================================
79  /// @{
80 
81  /**
82  * Default constructor.
83  */
84  PRMFactory();
85 
86  /**
87  * This constructor let you set on which PRM instance the factory works.
88  */
89  PRMFactory(PRM< GUM_SCALAR >* prm);
90 
91  /// Copy constructor. Don't use it.
92  PRMFactory(const PRMFactory& from) = delete;
93 
94  /// Copy operator. Don't use it.
95  PRMFactory& operator=(const PRMFactory& from) = delete;
96  /**
97  * Destructor.
98  */
99  virtual ~PRMFactory();
100 
101  /// @}
102  // ========================================================================
103  /// @name Getters & Setters
104  // ========================================================================
105  /// @{
106 
107  /**
108  * Returns a pointer on the PRM<GUM_SCALAR> created by this factory.
109  * This pointer will not be deleted when the factory is destroyed.
110  *
111  * @return Returns the PRM<GUM_SCALAR> created by this factory.
112  */
113  PRM< GUM_SCALAR >* prm() const;
114 
115  /**
116  * @return Returns the PRMObject type of the object begin built.
117  * @throw NotFound if no type is being built.
118  */
119  virtual PRMObject::prm_type currentType() const override;
120 
121  /**
122  * @return the current PRMObject being built by this factory.
123  * @throw NotFound if nothing is being built.
124  */
125  virtual PRMObject* getCurrent() override;
126  virtual const PRMObject* getCurrent() const override;
127 
128  /**
129  * @brief Close current object being built.
130  *
131  * Nothing is done in particular except removing the current object from
132  * the factory's stack. If the object was not added to a container it will
133  * not be deleted properly, so you might want to delete it yourself (at
134  * your own risks!).
135  *
136  * @return Returns the top most object removed in this factory's stack
137  * before. If their is no such object, 0 is returned.
138  */
139  virtual PRMObject* closeCurrent() override;
140 
141  /**
142  * @return Returns the current package name.
143  */
144  virtual std::string currentPackage() const override;
145 
146  /**
147  * @brief Returns a reference over a Class<GUM_SCALAR> given its name.
148  *
149  * This methods adds if necessary the current package as a prefix to name.
150  * @param name The name of the Class<GUM_SCALAR>.
151  * @return the Class<GUM_SCALAR> with the given name.
152  * @throw NotFound if no Class<GUM_SCALAR> matches the given name.
153  */
154  PRMClass< GUM_SCALAR >& retrieveClass(const std::string& name);
155 
156  /**
157  * @brief Returns a reference over a PRMType given its name.
158  *
159  * This methods adds if necessary the current package as a prefix to name.
160  * @param name The name of the PRMType.
161  * @return the PRMType with the given name.
162  * @throw NotFound if no PRMType matches the given name.
163  */
164  PRMType& retrieveType(const std::string& name);
165 
166 
167  /* @brief Retrieve the common PRMType of a vector of
168  *PRMClassElement<GUM_SCALAR>.
169  *
170  * The vector elts must only contains PRMClassElement<GUM_SCALAR> with a
171  *PRMType, i.e.
172  * PRMAttribute<GUM_SCALAR>, PRMAggregate and PRMSlotChain<GUM_SCALAR>. If
173  *not, a
174  *WrongClassElement is
175  * raised.
176  *
177  * A common PRMType is PRMType t such as
178  *t.isSuperTypeOf(elts[i]) for
179  * 0 < i < elts.size(), where elts is a PRMType container.
180  *
181  * @param elts A vector of PRMClassElement<GUM_SCALAR>.
182  * @return the common super PRMType of all
183  *PRMClassElement<GUM_SCALAR> un elts.
184  *
185  * @throw WrongClassElement Raised if elts contains a
186  *PRMClassElement<GUM_SCALAR>
187  * without a PRMType.
188  * @throw NotFound Raised if there exists no common super type of all
189  * PRMClassElement<GUM_SCALAR> in elts.
190  */
191  PRMType& retrieveCommonType(const std::vector< PRMClassElement< GUM_SCALAR >* >& elts);
192 
193  ///@}
194  // ======================================================================
195  /// @name Package construction methods.
196  // ======================================================================
197  /// @{
198 
199  /**
200  * @brief Define the current package.
201  *
202  * A stack is used to keep track of packages given the different
203  * imports.
204  *
205  * @param name The name of the package for all further objects.
206  */
207  virtual void pushPackage(const std::string& name) override;
208 
209  /**
210  * @brief Pop the current package from the package stack.
211  * @return the popped package or an empty string if there was
212  * nothing to pop.
213  */
214  virtual std::string popPackage() override;
215 
216  /// @}
217  // ======================================================================
218  /// @name Package construction methods.
219  // ======================================================================
220  /// @{
221 
222  /**
223  * @brief Add an import for namespace lookup.
224  *
225  * When loading a module, you should push all import declarations using
226  * this method. The order in which you add imports will impact name
227  * resolution (first found, first used).
228  *
229  * Imports are sync with packages: when you push a new package a new empty
230  * list of imports is added. When you pop a package the current list of
231  * imports is discarded and the previous one is restored.
232  *
233  * @param name The name of the package for all further objects.
234  */
235  virtual void addImport(const std::string& name) override;
236 
237  /// @}
238  // ======================================================================
239  /// @name PRMType construction methods.
240  // ======================================================================
241  /// @{
242 
243  /**
244  * Start a discrete subtype declaration.
245  *
246  * @param name The discrete type's name.
247  * @param super The super type of the declared discrete type.
248  *
249  * @throw DuplicateElement Raised if an object with the same name
250  * already exists.
251  */
252  virtual void startDiscreteType(const std::string& name, std::string super = "") override;
253 
254  /**
255  * Add a label to the current discrete type.
256  *
257  * @param l The label value.
258  * @param ext The super type label for which l is an extension.
259  *
260  * @throw OperationNotAllowed Raised if the current type does not have a
261  * super type, see PRMFactory::addLabel(const std::string&).
262  * @throw DuplicateElement Raised if a label with the same value already
263  * exists.
264  * @throw NotFound Raised if ext does not match any label in the
265  * current type's super type.
266  */
267  virtual void addLabel(const std::string& l, std::string ext = "") override;
268 
269  /**
270  * End the current discrete type declaration.
271  *
272  * @throw OperationNotAllowed Raised if the current type is not a valid
273  * discrete type.
274  */
275  virtual void endDiscreteType() override;
276 
277  /**
278  * Start a discretized type declaration.
279  *
280  * @param name The discretized type's name.
281  *
282  * @throw DuplicateElement Raised if an object with the same name
283  * already exists.
284  */
285  virtual void startDiscretizedType(const std::string& name) override;
286 
287  /**
288  * Add a tick to the current discretized type.
289  *
290  * @param tick The tick value.
291  */
292  virtual void addTick(double tick) override;
293 
294  /**
295  * End the current discretized type declaration.
296  *
297  * @throw OperationNotAllowed Raised if the current type is not a valid
298  * discrete type.
299  */
300  virtual void endDiscretizedType() override;
301 
302  /**
303  * Add a range variable type declaration.
304  *
305  * @param name The variable's name
306  * @param minVal The variable's lower bound.
307  * @param maxVal The variable's upper bound.
308  *
309  * @throw DuplicateElement Raised if an object with the same name
310  * already exists.
311  * @throw OperationNotAllowed Raised if the range variable is not a valid
312  * discrete type.
313  */
314  virtual void addRangeType(const std::string& name, long minVal, long maxVal) override;
315  /// @}
316 
317  ///@name several checks for parsers
318  /// @{
319  virtual bool isClassOrInterface(const std::string& type) const override;
320  virtual bool isArrayInCurrentSystem(const std::string& name) const override;
321  /// @}
322 
323 
324  /// @name Class<GUM_SCALAR> construction models.
325  /// @{
326 
327  /**
328  * @brief Tells the factory that we start a class declaration.
329  *
330  * Use the default values if you do not want c to be a subclass or to
331  * implement interfaces.
332  *
333  * @param c The class name.
334  * @param ext The name of the super class of c.
335  * @param implements The list of interface implemented by c.
336  * @param delayInheritance If true, the created gum::prm::Class
337  * inheritance will be delayed.
338  *
339  * @throw OperationNotAllowed Raised if the given operation is illegal.
340  */
341  virtual void startClass(const std::string& c,
342  const std::string& ext = "",
343  const Set< std::string >* implements = nullptr,
344  bool delayInheritance = false) override;
345 
346  /**
347  * Continue the declaration of a class.
348  */
349  virtual void continueClass(const std::string& c) override;
350 
351  /**
352  * Tells the factory that we finished a class declaration.
353  *
354  * @throw PRMTypeError Raised if the current Class<GUM_SCALAR> does not
355  *respect one of
356  * it's PRMInterface<GUM_SCALAR>.
357  */
358  virtual void endClass(bool checkImplementations = true) override;
359 
360  /// @}
361  // ======================================================================
362  /// @name PRMInterface<GUM_SCALAR> construction models.
363  // ======================================================================
364  /// @{
365 
366  /**
367  * @brief Tells the factory that we start an interface declaration.
368  *
369  * Use the default values if you do not want c to be a subclass or to
370  * implement interfaces.
371  *
372  * @param i The interface name.
373  * @param ext The name of the super interface of i.
374  * @param delayInheritance If true, the created gum::prm::PRMInterface
375  * inheritance will be delayed.
376  *
377  * @throw NotFound Raised if ext does not match any declared
378  * PRMInterface<GUM_SCALAR>.
379  */
380  virtual void startInterface(const std::string& i,
381  const std::string& ext = "",
382  bool delayInheritance = false) override;
383 
384  /**
385  * Continue the declaration of an interface.
386  */
387  virtual void continueInterface(const std::string& name) override;
388 
389  /**
390  * @brief Add an attribute to an interface.
391  *
392  */
393  virtual void addAttribute(const std::string& type, const std::string& name) override;
394 
395  /**
396  * Tells the factory that we finished an interface declaration.
397  */
398  virtual void endInterface() override;
399 
400  /// @}
401  // ======================================================================
402  /// @name Attributes construction methods.
403  // ======================================================================
404  /// @{
405 
406  /** @brief Add an already created attribute to the current class.
407  *
408  * Use this method when you must add functions, such as Noisy-Or.
409  *
410  * Use this method when you need to add functions, such as Noisy-Or. The
411  * attribute CPT is checked for parents and arcs will be added using the
412  * DiscreteVariable pointers, thus be careful to use those of the
413  * attributes, aggregates and slotchains of the current class.
414  * gum::prm::Class<GUM_SCALAR>::insertArc() will be called for each found
415  * parent of attr, so you should overload
416  * gum::prm::PRMAttribute<GUM_SCALAR>::addParent() to prevent duplication
417  * errors. Such class exists: gum::prm::PRMFuncAttribute .
418  *
419  * The pointer is given to the class, so do not worry about deleting it.
420  *
421  * @param attr The attribute added to the current class.
422  *
423  * @throw NotFound Raised if one of the DiscreteVariable in attr CPT does
424  * not match any PRMClassElement<GUM_SCALAR> in this.
425  */
426  virtual void addAttribute(PRMAttribute< GUM_SCALAR >* attr);
427 
428  /**
429  * Tells the factory that we start an attribute declaration.
430  * @throw FatalError Raised if the given operation is illegal.
431  */
432  virtual void startAttribute(const std::string& type,
433  const std::string& name,
434  bool scalar_atttr = false) override;
435 
436  /**
437  * Continues the declaration of an attribute.
438  */
439  virtual void continueAttribute(const std::string& name) override;
440 
441  /**
442  * Tells the factory that we add a parent to the current declared
443  * attribute.
444  * The name can refer to an already declared attribute or aggregate of the
445  * same class. It can also be a slot chain only if there is no multiple
446  * reference in it.
447  * @throw OperationNotAllowed Raised if the given operation is illegal.
448  */
449  virtual void addParent(const std::string& name) override;
450 
451  /**
452  * Gives the factory the CPF in its raw form.
453  *
454  * The creation of the CPF is left to the factory because we do not know
455  * what level of complexity for CPF implementation can be handled by the
456  * PRM<GUM_SCALAR> implementation.
457  *
458  * How to fill a CPT? If you want to fill the CPT of P(A|B,C)
459  * with A, B and C boolean variables ( {f, t}, the order is
460  * important), then the following array is valid:
461  * @code
462  * [0.20, 0.80, // P(f|f, f) = 0.20 and P(t|f, f) = 0.80
463  * 0.50, 0.50, // P(f|t, f) = 0.50 and P(t|t, f) = 0.50
464  * 0.70, 0.30, // P(f|f, t) = 0.70 and P(t|f, t) = 0.30
465  * 0.01, 0.99] // P(f|t, t) = 0.01 and P(t|t, t) = 0.99
466  * @endcode
467  *
468  * @throw OperationNotAllowed Raised if the given operation is illegal.
469  */
470  void setRawCPFByLines(const std::vector< GUM_SCALAR >& array);
471 
472  /**
473  * @brief Gives the factory the CPF in its raw form.
474  *
475  * The creation of the CPF is left to the factory because we do not know
476  * what level of complexity for CPF implementation can be handled by the
477  * PRM<GUM_SCALAR> implementation.
478  *
479  * How to fill a CPT? If you want to fill the CPT of P(A|B,C)
480  * with A, B and C boolean variables ( {f, t}, the order is
481  * important), then the following array is valid:
482  * @code
483  * //P(A|f,f),P(A|f,t),P(A|t,f),P(A|t,t)
484  * [ 0.2, 0.7, 0.5, 0.01,
485  * 0.8, 0.3, 0.5, 0.99]
486  * @endcode
487  *
488  * See PRMFactory::setRawCPFByLines() for more details.
489  *
490  * @throw OperationNotAllowed Raised if the given operation is illegal.
491  */
492  void setRawCPFByColumns(const std::vector< GUM_SCALAR >& array);
493 
494  /**
495  * @brief Fills the CPF using a rule.
496  *
497  * The labels vector is filled with one of each parent's labels or
498  * with a wildcard ("*"). If a wildcard is used then all values of the
499  * corresponding parents are used. The sequence of parents must be the
500  * declaration order used when adding the current attribute's parents.
501  *
502  * @param labels The value of each parents.
503  * @param values The probability values of the current attribute given
504  * the values in parents.
505  */
506  virtual void setCPFByRule(const std::vector< std::string >& labels,
507  const std::vector< GUM_SCALAR >& values);
508 
509  /**
510  * @brief Fills the CPF using a rule and gum::Formula.
511  *
512  * The labels vector is filled with one of each parent's labels or
513  * with a wildcard ("*"). If a wildcard is used then all values of the
514  * corresponding parents are used. The sequence of parents must be the
515  * declaration order used when adding the current attribute's parents.
516  *
517  * @param labels The value of each parents.
518  * @param values The probability values of the current attribute given
519  * the values in parents.
520  */
521  virtual void setCPFByRule(const std::vector< std::string >& labels,
522  const std::vector< std::string >& values) override;
523 
524  /**
525  * @brief Gives the factory the CPF in its raw form.
526  *
527  * The creation of the CPF is left to the factory because we do not know
528  * what level of complexity for CPF implementation can be handled by the
529  * PRM<GUM_SCALAR> implementation.
530  *
531  * How to fill a CPT? If you want to fill the CPT of P(A|B,C)
532  * with A, B and C boolean variables ( {f, t}, the order is
533  * important), then the following array is valid:
534  * @code
535  * [0.20, 0.80, // P(f|f, f) = 0.20 and P(t|f, f) = 0.80
536  * 0.50, 0.50, // P(f|t, f) = 0.50 and P(t|t, f) = 0.50
537  * 0.70, 0.30, // P(f|f, t) = 0.70 and P(t|f, t) = 0.30
538  * 0.01, 0.99] // P(f|t, t) = 0.01 and P(t|t, t) = 0.99
539  * @endcode
540  *
541  * @throw OperationNotAllowed Raised if the given operation is illegal.
542  */
543  virtual void setRawCPFByFloatLines(const std::vector< float >& array) override;
544 
545  /**
546  * @brief Gives the factory the CPF in its raw form.
547  *
548  * The creation of the CPF is left to the factory because we do not know
549  * what level of complexity for CPF implementation can be handled by the
550  * PRM<GUM_SCALAR> implementation.
551  *
552  * How to fill a CPT? If you want to fill the CPT of P(A|B,C)
553  * with A, B and C boolean variables ( {f, t}, the order is
554  * important), then the following array is valid:
555  * @code
556  * //P(A|f,f),P(A|f,t),P(A|t,f),P(A|t,t)
557  * [ 0.2, 0.7, 0.5, 0.01,
558  * 0.8, 0.3, 0.5, 0.99]
559  * @endcode
560  *
561  * See PRMFactory::setRawCPFByLines() for more details.
562  *
563  * @throw OperationNotAllowed Raised if the given operation is illegal.
564  */
565  virtual void setRawCPFByFloatColumns(const std::vector< float >& array) override;
566 
567  /**
568  * @brief Gives the factory the CPF in its raw form use gum::Formula.
569  *
570  * The creation of the CPF is left to the factory because we do not know
571  * what level of complexity for CPF implementation can be handled by the
572  * PRM<GUM_SCALAR> implementation.
573  *
574  * How to fill a CPT? If you want to fill the CPT of P(A|B,C)
575  * with A, B and C boolean variables ( {f, t}, the order is
576  * important), then the following array is valid:
577  * @code
578  * //P(A|f,f),P(A|f,t),P(A|t,f),P(A|t,t)
579  * [ 0.2, 0.7, 0.5, 0.01,
580  * 0.8, 0.3, 0.5, 0.99]
581  * @endcode
582  *
583  * See PRMFactory::setRawCPFByLines() for more details.
584  *
585  * @throw OperationNotAllowed Raised if the given operation is illegal.
586  */
587  virtual void setRawCPFByColumns(const std::vector< std::string >& array) override;
588 
589  /**
590  * @brief Gives the factory the CPF in its raw form using gum::Formula.
591  *
592  * The creation of the CPF is left to the factory because we do not know
593  * what level of complexity for CPF implementation can be handled by the
594  * PRM<GUM_SCALAR> implementation.
595  *
596  * How to fill a CPT? If you want to fill the CPT of P(A|B,C)
597  * with A, B and C boolean variables ( {f, t}, the order is
598  * important), then the following array is valid:
599  * @code
600  * [0.20, 0.80, // P(f|f, f) = 0.20 and P(t|f, f) = 0.80
601  * 0.50, 0.50, // P(f|t, f) = 0.50 and P(t|t, f) = 0.50
602  * 0.70, 0.30, // P(f|f, t) = 0.70 and P(t|f, t) = 0.30
603  * 0.01, 0.99] // P(f|t, t) = 0.01 and P(t|t, t) = 0.99
604  * @endcode
605  *
606  * @throw OperationNotAllowed Raised if the given operation is illegal.
607  */
608  virtual void setRawCPFByLines(const std::vector< std::string >& array) override;
609 
610  /**
611  * @brief Fills the CPF using a rule.
612  *
613  * The labels vector is filled with one of each parent's labels or
614  * with a wildcard ("*"). If a wildcard is used then all values of the
615  * corresponding parents are used. The sequence of parents must be the
616  * declaration order used when adding the current attribute's parents.
617  *
618  * @param labels The value of each parents.
619  * @param values The probability values of the current attribute given
620  * the values in parenst.
621  */
622  virtual void setCPFByFloatRule(const std::vector< std::string >& labels,
623  const std::vector< float >& values) override;
624 
625  /**
626  * Tells the factory that we finished declaring an attribute.
627  * @throw OperationNotAllowed Raised if the given operation is illegal.
628  */
629  virtual void endAttribute() override;
630 
631  /// @}
632  // ======================================================================
633  /// @name Parameters construction methods.
634  // ======================================================================
635  /// @{
636 
637  /**
638  * Add a parameter to the current class with a default value.
639  *
640  * A parameter with a default value is an PRMAttribute<GUM_SCALAR> (aka
641  *mutable PRMAttribute<GUM_SCALAR>)
642  * with no parents and with a CPF filled with 1.
643  *
644  * @param type The type of this parameter.
645  * @param name The name of this parameter.
646  * @param value The label used as default value for this parameter.
647  */
648  void addParameter(const std::string& type, const std::string& name, double value) override;
649  /// @}
650  // ======================================================================
651  /// @name Aggregator and function construction methods.
652  // ======================================================================
653  /// @{
654 
655  /**
656  * @brief Add an aggregator in the current declared class.
657  *
658  * If at least one parent of an aggregator is a PRMSlotChain<GUM_SCALAR>,
659  * then all of it's parents must be PRMSlotChain<GUM_SCALAR>. When an
660  * aggregator parents are only composed of PRMAttribute<GUM_SCALAR> and
661  * PRMAggregate, then it is directly added as an PRMAttribute<GUM_SCALAR>
662  * to
663  * it's Class<GUM_SCALAR>.
664  *
665  * @param name The name of this aggregator.
666  * @param agg_type The name of the aggregator type of this aggregator.
667  * @param chains The set of chains on which this aggregate applies.
668  * @param params The list of parameters for this aggregator.
669  * @param type Some aggregators have a user defined type, use this
670  * parameter to define it.
671  *
672  * @throw OperationNotAllowed Raised if one or more parameters misses or
673  * are not correct.
674  * @throw TypeError Raised if the aggregator's type or one or more of the
675  * chains are not of the good type.
676  */
677  virtual void addAggregator(const std::string& name,
678  const std::string& agg_type,
679  const std::vector< std::string >& chains,
680  const std::vector< std::string >& params,
681  std::string type = "") override;
682 
683  /**
684  * @brief Start an aggregator declaration.
685  *
686  * @param name The aggregator's name.
687  * @param agg_type The aggregtor's type (@see Aggregate::agg_type()).
688  * @param rv_type The aggregator's random variable type (@see
689  * Aggregate::type()).
690  * @param params The aggregator's parameters.
691  */
692  void startAggregator(const std::string& name,
693  const std::string& agg_type,
694  const std::string& rv_type,
695  const std::vector< std::string >& params);
696 
697  /**
698  * @brief Conitnues an aggregator declaration.
699  */
700  void continueAggregator(const std::string& name);
701 
702 
703  /**
704  * @brief Finishes an aggregate declaration.
705  */
706  void endAggregator();
707 
708  /**
709  * @brief Add a compound noisy-or as an PRMAttribute<GUM_SCALAR> to the
710  *current Class<GUM_SCALAR>.
711  *
712  * The type of a noisy-or must be a boolean.
713  *
714  * @param name the name of the PRMAttribute<GUM_SCALAR> added as a
715  *noisy-or.
716  * @param chains the list of parents of the noisy-or.
717  * @param numbers the list of weights for each parent. Can consist of only
718  * one value which will be applied to all the parents.
719  * @param leak the leak
720  * @param label the label on which the noisy-or applies, can be an empty
721  * string (the noisy-or will behave as if chains are all
722  *booleans).
723  *
724  * @throw NotFound Raised if one of the chains or the label is not found.
725  * @throw FactoryInvalidState Raised if a Class<GUM_SCALAR> is not the
726  *current declared
727  * PRMObject.
728  * @throw OperationNotAllowed Raised if for some reasons the parameters
729  *are
730  * invalid.
731  */
732  virtual void addNoisyOrCompound(const std::string& name,
733  const std::vector< std::string >& chains,
734  const std::vector< float >& numbers,
735  float leak,
736  const std::vector< std::string >& label) override;
737  /// @}
738  // ======================================================================
739  /// @name PRMReferenceSlot<GUM_SCALAR> construction methods.
740  // ======================================================================
741  /// @{
742 
743  /**
744  * Tells the factory that we started declaring a slot.
745  * @throw OperationNotAllowed Raised if the given operation is illegal.
746  */
747  virtual void
748  addReferenceSlot(const std::string& type, const std::string& name, bool isArray) override;
749 
750  /// @}
751  // ======================================================================
752  /// @name Systems constructions methods.
753  // ======================================================================
754  /// @{
755 
756  /**
757  * Tells the factory that we started declaring a model.
758  * @throw OperationNotAllowed Raised if the given operation is illegal.
759  */
760  virtual void startSystem(const std::string& name) override;
761 
762  /**
763  * Tells the factory that we finished declaring a model.
764  * @throw OperationNotAllowed Raised if the given operation is illegal.
765  */
766  virtual void endSystem() override;
767 
768  /**
769  * Add an instance to the model.
770  */
771  virtual void addInstance(const std::string& type, const std::string& name) override;
772 
773  /**
774  * Add an instance with params as values of type's parameters.
775  */
776  void addInstance(const std::string& type,
777  const std::string& name,
778  const HashTable< std::string, double >& params) override;
779 
780  /**
781  * Creates an array with the given number of instances of the given type.
782  * PRMInstance<GUM_SCALAR> are name using "name" as prefix and adding the
783  * suffix "[i]",
784  * with "i" being the position of the instance in the array.
785  */
786  virtual void addArray(const std::string& type, const std::string& name, Size size) override;
787 
788  /**
789  * Add an instance to an array.
790  */
791  virtual void incArray(const std::string& l_i, const std::string& r_i) override;
792 
793  /**
794  * @brief Instantiate a reference in the current model.
795  *
796  * This is equivalent to the following SKOOL instruction:
797  * left_instance.left_reference = right_instance;
798  *
799  * right_instance's type must be compatible with the slot type of
800  * left_reference.
801  *
802  * @param left_instance The name of an instance in the model.
803  * @param left_reference The name of a reference of left_instance.
804  * @param right_instance The name of an instance or an array of instances
805  * in the model.
806  */
807  virtual void setReferenceSlot(const std::string& left_instance,
808  const std::string& left_reference,
809  const std::string& right_instance) override;
810 
811  /**
812  * @brief Instantiate a reference in the current model.
813  *
814  * This is equivalent to the following SKOOL instruction:
815  * left_instance.left_reference = right_instance;
816  *
817  * right_instance's type must be compatible with the slot type of
818  * left_reference.
819  *
820  * @param l_i A slot chain starting from an instance and ending over a
821  * reference slot.
822  * @param r_i The name of an instance or an array of instances in the
823  *model.
824  */
825  virtual void setReferenceSlot(const std::string& l_i, const std::string& r_i) override;
826 
827  /// @}
828 
829  private:
830  // TODELETE /// Decompose a string in v using dots ('.') as delimiters.
831  // TODELETE void _fill_sc_in_vector_(std::vector< std::string >& v,
832  // TODELETE const std::string& str);
833 
834  // ======================================================================
835  /// @name Private methods for type checking and exception handling.
836  // ======================================================================
837  /// @{
838 
839  /// Adds _prefix_ to str iff _prefix_ != ""
840  std::string _addPrefix_(const std::string& str) const;
841 
842  /// Return a pointer on a PRMObject at _stack_.size() - i position after
843  /// checking the type of the object given obj_type.
844  /// @throw FactoryInvalidState Raised if the stack isn't consistent with
845  /// the
846  // current declaration.
847  PRMObject* _checkStack_(Idx i, PRMObject::prm_type obj_type);
848 
849  PRMClassElement< GUM_SCALAR >*
850  _checkStack_(Idx i, typename PRMClassElement< GUM_SCALAR >::ClassElementType obj_type);
851 
852  PRMClassElementContainer< GUM_SCALAR >* _checkStackContainter_(Idx i);
853 
854  /// @}
855  // ======================================================================
856  /// @name Private getters
857  // ======================================================================
858  /// @{
859 
860  /// Returns a pointer on a PRMType given it's name. Since the
861  /// type can
862  /// be given either with it's local name (without the prefix), full name
863  /// (with the prefix) or can come from an import unit, or maybe one day
864  /// with a using declaration we need some processing to find it.
865  ///
866  /// The following precedences on finding the name is used:
867  /// * name
868  /// * prefix.name
869  /// * import_1.name
870  /// * import_2.name
871  /// * ...
872  /// * import_N.name
873  /// In the case a local name is used multiple time, it's preferable to
874  /// use it's full name.
875  /// @throw OperationNotAllowed If the type is undeclared.
876  PRMType* _retrieveType_(const std::string& name) const;
877 
878  /// Returns a pointer on a class given it's name. Used when building
879  /// models, meaning that the class name can either be local (need to
880  /// add the current prefix) or global (no prefix needed).
881  /// @throw NotFound If no class matching the name is found.
882  /// @see PRMFactory:: _retrieveType_
883  PRMClass< GUM_SCALAR >* _retrieveClass_(const std::string& name) const;
884 
885  /// Returns a pointer on an interface given it's name. Used when building
886  /// models, meaning that the interface name can either be local (need to
887  /// add the current prefix) or global (no prefix needed).
888  /// @throw NotFound If no class matching the name is found.
889  /// @see PRMFactory:: _retrieveType_
890  PRMInterface< GUM_SCALAR >* _retrieveInterface_(const std::string& name) const;
891 
892  /// @}
893  // ======================================================================
894  /// @name Private methods handling Class<GUM_SCALAR> and
895  /// PRMClassElement<GUM_SCALAR> creation.
896  // ======================================================================
897  /// @{
898 
899  /// This methods build a PRMSlotChain<GUM_SCALAR> given a starting element
900  /// and a string.
901  ///
902  /// @return Return a pointer over a PRMSlotChain<GUM_SCALAR> or 0 if no
903  /// PRMSlotChain<GUM_SCALAR> could be built.
904  ///
905  PRMSlotChain< GUM_SCALAR >* _buildSlotChain_(PRMClassElementContainer< GUM_SCALAR >* start,
906  const std::string& name);
907 
908  /// @brief Retrieve inputs for an PRMAggregate.
909  ///
910  /// The vector chains contains names of the PRMAggregate inputs. If a name
911  /// does not match an existing PRMClassElement<GUM_SCALAR> in c, then a
912  /// call
913  /// to
914  /// PRMFactory:: _buildSlotChains_() is made. Such created
915  /// PRMSlotChain<GUM_SCALAR> are
916  /// added to c.
917  ///
918  /// @param c The class in which the PRMAggregate is defined.
919  /// @param chains Vector of the PRMAggregate inputs names.
920  /// @param inputs Vector filled with the PRMClassElement<GUM_SCALAR>
921  /// matching
922  /// the names
923  /// in chains.
924  /// @return true if there was at least one slotchain in chains.
925  ///
926  /// @throw NotFound Raised if a name in chains does not match a legal
927  /// PRMSlotChain<GUM_SCALAR> or an existing
928  /// PRMClassElement<GUM_SCALAR> in c.
929  bool _retrieveInputs_(PRMClass< GUM_SCALAR >* c,
930  const std::vector< std::string >& chains,
931  std::vector< PRMClassElement< GUM_SCALAR >* >& inputs);
932 
933  /// @brief Retrieve the common PRMType of a vector of
934  /// PRMClassElement<GUM_SCALAR>.
935  ///
936  /// The vector elts must only contains PRMClassElement<GUM_SCALAR> with a
937  /// PRMType, i.e.
938  /// PRMAttribute<GUM_SCALAR>, PRMAggregate and PRMSlotChain<GUM_SCALAR>.
939  /// If not a
940  /// WrongClassElement is
941  /// raised.
942  ///
943  /// A common PRMType is PRMType t such as
944  /// t.isSuperTypeOf(elts[i]) for
945  /// 0 < i < elts.size(), where elts is a PRMType container.
946  ///
947  /// @param elts A vector of PRMClassElement<GUM_SCALAR>.
948  /// @return Returns the common super PRMType of all
949  /// PRMClassElement<GUM_SCALAR> un elts.
950  //
951  /// @throw WrongClassElement Raised if elts contains a
952  /// PRMClassElement<GUM_SCALAR> without a PRMType.
953  /// @throw NotFound Raised if there exists no common super type of all
954  /// PRMClassElement<GUM_SCALAR> in elts.
955  PRMType* _retrieveCommonType_(const std::vector< PRMClassElement< GUM_SCALAR >* >& elts);
956 
957  /// @brief Returns the inheritance depth of a PRMType.
958  ///
959  /// This used by PRMFactory:: _retrieveCommonType_.
960  /// This returns 0 if t does not have a super type.
961  ///
962  /// @param t The PRMType for which we compute its depth.
963  /// @return Returns the depth of t.
964  int _typeDepth_(const PRMType* t);
965 
966  /// Check if c implements correctly all his interfaces.
967  void _checkInterfaceImplementation_(PRMClass< GUM_SCALAR >* c);
968 
969  /// Add a parent to an attribute.
970  void _addParent_(PRMClassElementContainer< GUM_SCALAR >* c,
971  PRMAttribute< GUM_SCALAR >* agg,
972  const std::string& name);
973 
974  /// Add a parent to an aggregate.
975  void _addParent_(PRMClass< GUM_SCALAR >* c,
976  PRMAggregate< GUM_SCALAR >* agg,
977  const std::string& name);
978  /// @}
979  // ======================================================================
980  /// @name Private methods handling PRMSystem<GUM_SCALAR> and
981  /// PRMInstance<GUM_SCALAR> creation.
982  // ======================================================================
983  /// @{
984 
985  /// Adds a instance to the current model.
986  void _addInstance_(PRMClass< GUM_SCALAR >* type, const std::string& name);
987 
988  // Builds all PRMSlotChain<GUM_SCALAR><PRMInstance<GUM_SCALAR>> in the
989  // given model.
990  // @throw OperationNotAllowed If reference slots are left un affected
991  // ERROR? void _buildSlotChains_(PRMSystem< GUM_SCALAR >* model);
992 
993  /// Builds all Aggregates CPF in the given model.
994  /// This must be called after all the slot chains have been generated.
995  void _buildAggregateCPF_(PRMSystem< GUM_SCALAR >* model);
996 
997  /// Instantiate a slot chain in the given instance
998  void _instantiateSlotChain_(PRMSystem< GUM_SCALAR >* model,
999  PRMInstance< GUM_SCALAR >* inst,
1000  PRMReferenceSlot< GUM_SCALAR >* ref,
1001  PRMSlotChain< GUM_SCALAR >* sc);
1002 
1003  /// Fill seq with the sequence of instance build using inst as the
1004  /// instantiation of sc-> _class_ and seeking each instantiation of
1005  /// reference in sc.
1006  /// @return Returns the name of the corresponding
1007  /// PRMSlotChain<GUM_SCALAR>.
1008  std::string _retrieveInstanceSequence_(PRMInstance< GUM_SCALAR >* inst,
1009  Sequence< PRMInstance< GUM_SCALAR >* >& seq,
1010  PRMSlotChain< GUM_SCALAR >* sc);
1011 
1012  /// @}
1013  // ======================================================================
1014  /// @name Private members.
1015  // ======================================================================
1016  /// @{
1017 
1018  /// The prefix used for classes and types names. It is normally the
1019  /// namespace of the corresponding compilation unit.
1020  std::vector< std::string > _packages_;
1021 
1022  /// Set of all declared namespaces.
1023  std::vector< List< std::string >* > _namespaces_;
1024 
1025  /// The pointer on the PRM<GUM_SCALAR> built by this factory.
1026  PRM< GUM_SCALAR >* _prm_;
1027 
1028  /// A stack used to keep track of created PRMObject.
1029  std::vector< PRMObject* > _stack_;
1030 
1031  /// A mapping between aggregators and their parameters
1032  HashTable< PRMAggregate< GUM_SCALAR >*, std::vector< std::string > > _agg_params_;
1033 
1034  /// @}
1035  };
1036  } /* namespace prm */
1037 } /* namespace gum */
1038 
1039 #include <agrum/PRM/PRMFactory_tpl.h>
1040 
1041 #endif /* GUM_PRM_FACTORY_H */