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