aGrUM  0.18.1
a C++ library for (probabilistic) graphical models
BayesNetFactory_tpl.h
Go to the documentation of this file.
1 
32 
33 #define VERBOSITY(x) \
34  { \
35  if (isVerbose()) std::cerr << "[BN factory] " << x << std::endl; \
36  }
37 
38 namespace gum {
39 
40  // Default constructor.
41  // @param bn A pointer over the BayesNet filled by this factory.
42  // @throw DuplicateElement Raised if two variables in bn share the same
43  // name.
44  template < typename GUM_SCALAR >
45  INLINE
47  parents__(0),
48  impl__(0), bn__(bn) {
49  GUM_CONSTRUCTOR(BayesNetFactory);
50  states__.push_back(factory_state::NONE);
51 
52  for (auto node: bn->nodes()) {
53  if (varNameMap__.exists(bn->variable(node).name()))
55  "Name already used: " << bn->variable(node).name());
56 
57  varNameMap__.insert(bn->variable(node).name(), node);
58  }
59 
60  resetVerbose();
61  }
62 
63  // Copy constructor.
64  // The copy will have an exact copy of the constructed BayesNet in source.
65  template < typename GUM_SCALAR >
67  const BayesNetFactory< GUM_SCALAR >& source) :
68  parents__(0),
69  impl__(0), bn__(0) {
70  GUM_CONS_CPY(BayesNetFactory);
71 
72  if (source.state() != factory_state::NONE) {
73  GUM_ERROR(OperationNotAllowed, "Illegal state to proceed make a copy.");
74  } else {
75  states__ = source.states__;
76  bn__ = new BayesNet< GUM_SCALAR >(*(source.bn__));
77  }
78  }
79 
80  // Destructor
81  template < typename GUM_SCALAR >
83  GUM_DESTRUCTOR(BayesNetFactory);
84 
85  if (parents__ != 0) delete parents__;
86 
87  if (impl__ != 0) {
88  //@todo better than throwing an exception from inside a destructor but
89  // still ...
90  std::cerr
91  << "[BN factory] Implementation defined for a variable but not used. "
92  "You should call endVariableDeclaration() before "
93  "deleting me."
94  << std::endl;
95  exit(1000);
96  }
97  }
98 
99  // Returns the BayesNet created by this factory.
100  template < typename GUM_SCALAR >
102  return bn__;
103  }
104 
105  template < typename GUM_SCALAR >
106  INLINE const DiscreteVariable&
108  return bn__->variable(id);
109  }
110 
111  // Returns the current state of the factory.
112  template < typename GUM_SCALAR >
115  // This is ok because there is alway at least the state NONE in the stack.
116  return states__.back();
117  }
118 
119  // Returns the NodeId of a variable given it's name.
120  // @throw NotFound Raised if no variable matches the name.
121  template < typename GUM_SCALAR >
122  INLINE NodeId
123  BayesNetFactory< GUM_SCALAR >::variableId(const std::string& name) const {
124  try {
125  return varNameMap__[name];
126  } catch (NotFound&) { GUM_ERROR(NotFound, name); }
127  }
128 
129  // Returns a constant reference on a variable given it's name.
130  // @throw NotFound Raised if no variable matches the name.
131  template < typename GUM_SCALAR >
132  INLINE const DiscreteVariable&
133  BayesNetFactory< GUM_SCALAR >::variable(const std::string& name) const {
134  try {
135  return bn__->variable(variableId(name));
136  } catch (NotFound&) { GUM_ERROR(NotFound, name); }
137  }
138 
139  // Returns the domainSize of the cpt for the node n.
140  // @throw NotFound raised if no such NodeId exists.
141  // @throw OperationNotAllowed if there is no bayesian networks.
142  template < typename GUM_SCALAR >
144  return bn__->cpt(n).domainSize();
145  }
146 
147  // Tells the factory that we're in a network declaration.
148  template < typename GUM_SCALAR >
150  if (state() != factory_state::NONE) {
151  illegalStateError__("startNetworkDeclaration");
152  } else {
153  states__.push_back(factory_state::NETWORK);
154  }
155 
156  VERBOSITY("starting network");
157  }
158 
159  // Tells the factory to add a property to the current network.
160  template < typename GUM_SCALAR >
162  const std::string& propName, const std::string& propValue) {
163  bn__->setProperty(propName, propValue);
164  }
165 
166  // Tells the factory that we're out of a network declaration.
167  template < typename GUM_SCALAR >
169  if (state() != factory_state::NETWORK) {
170  illegalStateError__("endNetworkDeclaration");
171  } else {
172  states__.pop_back();
173  }
174 
175  VERBOSITY("network OK");
176  }
177 
178  // Tells the factory that we're in a variable declaration.
179  // A variable is considered as a LabelizedVariable while its type is not defined.
180  template < typename GUM_SCALAR >
182  if (state() != factory_state::NONE) {
183  illegalStateError__("startVariableDeclaration");
184  } else {
186  stringBag__.push_back("name");
187  stringBag__.push_back("desc");
188  stringBag__.push_back("L");
189  }
190 
191  VERBOSITY(" starting variable");
192  }
193 
194  // Tells the factory the current variable's name.
195  template < typename GUM_SCALAR >
196  INLINE void
198  if (state() != factory_state::VARIABLE) {
199  illegalStateError__("variableName");
200  } else {
201  if (varNameMap__.exists(name)) {
202  GUM_ERROR(DuplicateElement, "Name already used: " << name);
203  }
204 
205  foo_flag__ = true;
206  stringBag__[0] = name;
207  VERBOSITY(" -- variable " << name);
208  }
209  }
210 
211  // Tells the factory the current variable's description.
212  template < typename GUM_SCALAR >
213  INLINE void
215  if (state() != factory_state::VARIABLE) {
216  illegalStateError__("variableDescription");
217  } else {
218  bar_flag__ = true;
219  stringBag__[1] = desc;
220  }
221  }
222 
223  // Tells the factory the current variable's type.
224  // L : Labelized
225  // R : Range
226  // C : Continuous
227  // D : Discretized
228  template < typename GUM_SCALAR >
229  INLINE void
231  if (state() != factory_state::VARIABLE) {
232  illegalStateError__("variableType");
233  } else {
234  switch (type) {
235  case VarType::Discretized: stringBag__[2] = "D"; break;
236  case VarType::Range: stringBag__[2] = "R"; break;
237  case VarType::Continuous:
239  "Continuous variable (" + stringBag__[0]
240  + ") are not supported in bayesian networks.");
241  case VarType::Labelized: stringBag__[2] = "L"; break;
242  }
243  }
244  }
245 
246  // Adds a modality to the current variable.
247  // @throw DuplicateElement If the current variable already has a modality
248  // with the same name.
249  template < typename GUM_SCALAR >
250  INLINE void BayesNetFactory< GUM_SCALAR >::addModality(const std::string& name) {
251  if (state() != factory_state::VARIABLE) {
252  illegalStateError__("addModality");
253  } else {
254  checkModalityInBag__(name);
255  stringBag__.push_back(name);
256  }
257  }
258 
259  // Adds a modality to the current variable.
260  // @throw DuplicateElement If the current variable already has a modality
261  // with the same name.
262  template < typename GUM_SCALAR >
263  INLINE void BayesNetFactory< GUM_SCALAR >::addMin(const long& min) {
264  if (state() != factory_state::VARIABLE) {
265  illegalStateError__("addMin");
266  } else {
267  stringBag__.push_back(std::to_string(min));
268  }
269  }
270 
271  // Adds a modality to the current variable.
272  // @throw DuplicateElement If the current variable already has a modality
273  // with the same name.
274  template < typename GUM_SCALAR >
275  INLINE void BayesNetFactory< GUM_SCALAR >::addMax(const long& max) {
276  if (state() != factory_state::VARIABLE) {
277  illegalStateError__("addMin");
278  } else {
279  stringBag__.push_back(std::to_string(max));
280  }
281  }
282 
283  // Adds a modality to the current variable.
284  // @throw DuplicateElement If the current variable already has a modality
285  // with the same name.
286  template < typename GUM_SCALAR >
287  INLINE void BayesNetFactory< GUM_SCALAR >::addTick(const GUM_SCALAR& tick) {
288  if (state() != factory_state::VARIABLE) {
289  illegalStateError__("addTick");
290  } else {
291  stringBag__.push_back(std::to_string(tick));
292  }
293  }
294 
295  // @brief Defines the implementation to use for var's Potential.
296  // @warning The implementation must be empty.
297  // @warning The pointer is always delegated to var's Potential! No copy of it
298  // is made.
299  // @todo When copy of a MultiDimImplementation is available use a copy
300  // behaviour for this method.
301  // @throw NotFound Raised if no variable matches var.
302  // @throw OperationNotAllowed Raised if impl is not empty.
303  // @throw OperationNotAllowed If an implementation is already defined for the
304  // current variable.
305  template < typename GUM_SCALAR >
307  MultiDimAdressable* adressable) {
309  dynamic_cast< MultiDimImplementation< GUM_SCALAR >* >(adressable);
310 
311  if (state() != factory_state::VARIABLE) {
312  illegalStateError__("setVariableCPTImplementation");
313  } else {
314  if (impl == 0) {
316  "An implementation for this variable is already "
317  "defined.");
318  } else if (impl->nbrDim() > 0) {
319  GUM_ERROR(OperationNotAllowed, "This implementation is not empty.");
320  }
321 
322  impl__ = impl;
323  }
324  }
325 
326  // Tells the factory that we're out of a variable declaration.
327  template < typename GUM_SCALAR >
329  if (state() != factory_state::VARIABLE) {
330  illegalStateError__("endVariableDeclaration");
331  } else if (foo_flag__ && (stringBag__.size() > 4)) {
332  DiscreteVariable* var = nullptr;
333 
334  // if the current variable is a LabelizedVariable
335  if (stringBag__[2] == "L") {
337  stringBag__[0], (bar_flag__) ? stringBag__[1] : "", 0);
338 
339  for (size_t i = 3; i < stringBag__.size(); ++i) {
340  l->addLabel(stringBag__[i]);
341  }
342 
343  var = l;
344  // if the current variable is a RangeVariable
345  } else if (stringBag__[2] == "R") {
347  (bar_flag__) ? stringBag__[1] : "",
348  std::stol(stringBag__[3]),
349  std::stol(stringBag__[4]));
350 
351  var = r;
352  // if the current variable is a DiscretizedVariable
353  } else if (stringBag__[2] == "D") {
356  stringBag__[0], (bar_flag__) ? stringBag__[1] : "");
357 
358  for (size_t i = 3; i < stringBag__.size(); ++i) {
359  d->addTick(std::stof(stringBag__[i]));
360  }
361 
362  var = d;
363  }
364 
365  if (impl__ != 0) {
366  varNameMap__.insert(var->name(), bn__->add(*var, impl__));
367  impl__ = 0;
368  } else {
369  varNameMap__.insert(var->name(), bn__->add(*var));
370  }
371 
372  NodeId retVal = varNameMap__[var->name()];
373 
374  delete var;
375 
376  resetParts__();
377  states__.pop_back();
378 
379  VERBOSITY(" variable " << var->name() << " OK");
380  return retVal;
381  } else {
382  std::stringstream msg;
383  msg << "Not enough modalities (";
384 
385  if (stringBag__.size() > 3) {
386  msg << stringBag__.size() - 3;
387  } else {
388  msg << 0;
389  }
390 
391  msg << ") declared for variable ";
392 
393  if (foo_flag__) {
394  msg << stringBag__[0];
395  } else {
396  msg << "unknown";
397  }
398 
399  resetParts__();
400 
401  states__.pop_back();
402  GUM_ERROR(OperationNotAllowed, msg.str());
403  }
404 
405  // For noisy compilers
406  return 0;
407  }
408 
409  // Tells the factory that we're declaring parents for some variable.
410  // @var The concerned variable's name.
411  template < typename GUM_SCALAR >
413  const std::string& var) {
414  if (state() != factory_state::NONE) {
415  illegalStateError__("startParentsDeclaration");
416  } else {
417  checkVariableName__(var);
418  std::vector< std::string >::iterator iter = stringBag__.begin();
419  stringBag__.insert(iter, var);
420  states__.push_back(factory_state::PARENTS);
421  }
422 
423  VERBOSITY("starting parents for " << var);
424  }
425 
426  // Tells the factory for which variable we're declaring parents.
427  // @var The parent's name.
428  // @throw NotFound Raised if var does not exists.
429  template < typename GUM_SCALAR >
430  INLINE void BayesNetFactory< GUM_SCALAR >::addParent(const std::string& var) {
431  if (state() != factory_state::PARENTS) {
432  illegalStateError__("addParent");
433  } else {
434  checkVariableName__(var);
435  stringBag__.push_back(var);
436  }
437  }
438 
439  // Tells the factory that we've finished declaring parents for some
440  // variable. When parents exist, endParentsDeclaration creates some arcs.
441  // These arcs are created in the inverse order of the order of the parent
442  // specification.
443  template < typename GUM_SCALAR >
445  if (state() != factory_state::PARENTS) {
446  illegalStateError__("endParentsDeclaration");
447  } else {
449 
450  // PLEASE NOTE THAT THE ORDER IS INVERSE
451 
452  for (size_t i = stringBag__.size() - 1; i > 0; --i) {
453  bn__->addArc(varNameMap__[stringBag__[i]], id);
454  VERBOSITY(" adding parent " << stringBag__[i] << " for "
455  << stringBag__[0]);
456  }
457 
458  resetParts__();
459 
460  states__.pop_back();
461  }
462 
463  VERBOSITY("end of parents for " << stringBag__[0]);
464  }
465 
466  // Tells the factory that we're declaring a conditional probability table
467  // for some variable.
468  // @param var The concerned variable's name.
469  template < typename GUM_SCALAR >
471  const std::string& var) {
472  if (state() != factory_state::NONE) {
473  illegalStateError__("startRawProbabilityDeclaration");
474  } else {
475  checkVariableName__(var);
476  stringBag__.push_back(var);
477  states__.push_back(factory_state::RAW_CPT);
478  }
479 
480  VERBOSITY(" cpt starting for " << var);
481  }
482 
483  // @brief Fills the variable's table with the values in rawTable.
484  // Parse the parents in the same order in which they were added to the
485  // variable.
486  // Given a sequence [var, p_1, p_2, ...,p_n-1, p_n] of parents, modalities are
487  // parsed
488  // in the given order (if all p_i are binary):
489  // [0, 0, ..., 0, 0], [0, 0, ..., 0, 1],
490  // [0, 0, ..., 1, 0], [0, 0, ..., 1, 1],
491  // ...,
492  // [1, 1, ..., 1, 0], [1, 1, ..., 1, 1].
493  // @param rawTable The raw table.
494  template < typename GUM_SCALAR >
496  const std::vector< std::string >& variables,
497  const std::vector< float >& rawTable) {
498  if (state() != factory_state::RAW_CPT) {
499  illegalStateError__("rawConditionalTable");
500  } else {
501  fillProbaWithValuesTable__(variables, rawTable);
502  }
503  }
504 
505  template < typename GUM_SCALAR >
507  const std::vector< std::string >& variables,
508  const std::vector< float >& rawTable) {
509  const Potential< GUM_SCALAR >& table = bn__->cpt(varNameMap__[stringBag__[0]]);
510  Instantiation cptInst(table);
511 
513 
514  for (size_t i = 0; i < variables.size(); ++i) {
515  varList.pushBack(&(bn__->variable(varNameMap__[variables[i]])));
516  }
517 
518  // varList.pushFront(&(bn__->variable(varNameMap__[stringBag__[0]])));
519 
520  Idx nbrVar = varList.size();
521 
522  std::vector< Idx > modCounter;
523 
524  // initializing the array
525  for (NodeId i = 0; i < nbrVar; i++) {
526  modCounter.push_back(Idx(0));
527  }
528 
529  Idx j = 0;
530 
531  do {
532  for (NodeId i = 0; i < nbrVar; i++) {
533  cptInst.chgVal(*(varList[i]), modCounter[i]);
534  }
535 
536  if (j < rawTable.size()) {
537  table.set(cptInst, (GUM_SCALAR)rawTable[j]);
538  } else {
539  table.set(cptInst, (GUM_SCALAR)0);
540  }
541 
542  j++;
543  } while (increment__(modCounter, varList));
544  }
545 
546  template < typename GUM_SCALAR >
548  const std::vector< float >& rawTable) {
549  if (state() != factory_state::RAW_CPT) {
550  illegalStateError__("rawConditionalTable");
551  } else {
552  fillProbaWithValuesTable__(rawTable);
553  }
554  }
555 
556  template < typename GUM_SCALAR >
558  const std::vector< float >& rawTable) {
559  const Potential< GUM_SCALAR >& table = bn__->cpt(varNameMap__[stringBag__[0]]);
560 
561  Instantiation cptInst(table);
562 
563  // the main loop is on the first variables. The others are in the right
564  // order.
565  const DiscreteVariable& first = table.variable(0);
566  Idx j = 0;
567 
568  for (cptInst.setFirstVar(first); !cptInst.end(); cptInst.incVar(first)) {
569  for (cptInst.setFirstNotVar(first); !cptInst.end(); cptInst.incNotVar(first))
570  table.set(cptInst,
571  (j < rawTable.size()) ? (GUM_SCALAR)rawTable[j++]
572  : (GUM_SCALAR)0);
573 
574  cptInst.unsetEnd();
575  }
576  }
577 
578  template < typename GUM_SCALAR >
580  std::vector< gum::Idx >& modCounter,
582  bool last = true;
583 
584  for (NodeId j = 0; j < modCounter.size(); j++) {
585  last = (modCounter[j] == (varList[j]->domainSize() - 1)) && last;
586 
587  if (!last) break;
588  }
589 
590  if (last) { return false; }
591 
592  bool add = false;
593 
594  NodeId i = NodeId(varList.size() - 1);
595 
596  do {
597  if (modCounter[i] == (varList[i]->domainSize() - 1)) {
598  modCounter[i] = 0;
599  add = true;
600  } else {
601  modCounter[i] += 1;
602  add = false;
603  }
604 
605  i--;
606  } while (add);
607 
608  return true;
609  }
610 
611  // Tells the factory that we finished declaring a conditional probability
612  // table.
613  template < typename GUM_SCALAR >
615  if (state() != factory_state::RAW_CPT) {
616  illegalStateError__("endRawProbabilityDeclaration");
617  } else {
618  resetParts__();
619  states__.pop_back();
620  }
621 
622  VERBOSITY(" cpt ending for " << stringBag__[0]);
623  }
624 
625  // Tells the factory that we're starting a factorized declaration.
626  template < typename GUM_SCALAR >
628  const std::string& var) {
629  if (state() != factory_state::NONE) {
630  illegalStateError__("startFactorizedProbabilityDeclaration");
631  } else {
632  checkVariableName__(var);
633  std::vector< std::string >::iterator iter = stringBag__.begin();
634  stringBag__.insert(iter, var);
636  }
637  }
638 
639  // Tells the factory that we start an entry of a factorized conditional
640  // probability table.
641  template < typename GUM_SCALAR >
643  if (state() != factory_state::FACT_CPT) {
644  illegalStateError__("startFactorizedEntry");
645  } else {
646  parents__ = new Instantiation();
648  }
649  }
650 
651  // Tells the factory that we finished declaring a conditional probability
652  // table.
653  template < typename GUM_SCALAR >
655  if (state() != factory_state::FACT_ENTRY) {
656  illegalStateError__("endFactorizedEntry");
657  } else {
658  delete parents__;
659  parents__ = 0;
660  states__.pop_back();
661  }
662  }
663 
664  // Tells the factory on which modality we want to instantiate one of
665  // variable's parent.
666  template < typename GUM_SCALAR >
668  const std::string& parent, const std::string& modality) {
669  if (state() != factory_state::FACT_ENTRY) {
670  illegalStateError__("string");
671  } else {
672  checkVariableName__(parent);
673  Idx id = checkVariableModality__(parent, modality);
674  (*parents__) << bn__->variable(varNameMap__[parent]);
675  parents__->chgVal(bn__->variable(varNameMap__[parent]), id);
676  }
677  }
678 
679  // @brief Gives the values of the variable with respect to precedent
680  // parents modality.
681  // If some parents have no modality set, then we apply values for all
682  // instantiations of that parent.
683  //
684  // This means you can declare a default value for the table by doing
685  // @code
686  // BayesNetFactory factory;
687  // // Do stuff
688  // factory.startVariableDeclaration();
689  // factory.variableName("foo");
690  // factory.endVariableDeclaration();
691  // factory.startParentsDeclaration("foo");
692  // // add parents
693  // factory.endParentsDeclaration();
694  // factory.startFactorizedProbabilityDeclaration("foo");
695  // std::vector<float> seq;
696  // seq.insert(0.4); // if foo true
697  // seq.insert(O.6); // if foo false
698  // factory.setVariableValues(seq); // fills the table with a default value
699  // // finish your stuff
700  // factory.endFactorizedProbabilityDeclaration();
701  // @code
702  // as for rawProba, if value's size is different than the number of modalities
703  // of
704  // the current variable,
705  // we don't use the supplementary values and we fill by 0 the missign values.
706  template < typename GUM_SCALAR >
708  const std::vector< float >& values) {
709  if (state() != factory_state::FACT_ENTRY) {
710  illegalStateError__("setVariableValues");
711  } else {
712  const DiscreteVariable& var = bn__->variable(varNameMap__[stringBag__[0]]);
713  NodeId varId = varNameMap__[stringBag__[0]];
714 
715  if (parents__->domainSize() > 0) {
716  Instantiation inst(bn__->cpt(varNameMap__[var.name()]));
717  inst.setVals(*parents__);
718  // Creating an instantiation containing all the variables not ins
719  // parents__.
720  Instantiation inst_default;
721  inst_default << var;
722 
723  for (auto node: bn__->parents(varId)) {
724  if (!parents__->contains(bn__->variable(node))) {
725  inst_default << bn__->variable(node);
726  }
727  }
728 
729  // Filling the variable's table.
730  for (inst.setFirstIn(inst_default); !inst.end();
731  inst.incIn(inst_default)) {
732  (bn__->cpt(varId))
733  .set(inst,
734  inst.val(var) < values.size() ? (GUM_SCALAR)values[inst.val(var)]
735  : (GUM_SCALAR)0);
736  }
737  } else {
738  Instantiation inst(bn__->cpt(varNameMap__[var.name()]));
739  Instantiation var_inst;
740  var_inst << var;
741 
742  for (var_inst.setFirst(); !var_inst.end(); ++var_inst) {
743  inst.setVals(var_inst);
744 
745  for (inst.setFirstOut(var_inst); !inst.end(); inst.incOut(var_inst)) {
746  (bn__->cpt(varId))
747  .set(inst,
748  inst.val(var) < values.size()
749  ? (GUM_SCALAR)values[inst.val(var)]
750  : (GUM_SCALAR)0);
751  }
752  }
753  }
754  }
755  }
756 
757  template < typename GUM_SCALAR >
759  const std::vector< float >& values) {
760  if (state() != factory_state::FACT_ENTRY) {
761  illegalStateError__("setVariableValues");
762  } else {
763  const DiscreteVariable& var = bn__->variable(varNameMap__[stringBag__[0]]);
764  // Checking consistency between values and var.
765 
766  if (values.size() != var.domainSize()) {
768  var.name()
769  << " : invalid number of modalities: found " << values.size()
770  << " while needed " << var.domainSize());
771  }
772 
774  }
775  }
776 
777  // Tells the factory that we finished declaring a conditional probability
778  // table.
779  template < typename GUM_SCALAR >
780  INLINE void
782  if (state() != factory_state::FACT_CPT) {
783  illegalStateError__("endFactorizedProbabilityDeclaration");
784  } else {
785  resetParts__();
786  states__.pop_back();
787  }
788  }
789 
790  // @brief Define a variable.
791  // You can only call this method is the factory is in the NONE or NETWORK
792  // state.
793  // The variable is added by copy.
794  // @param var The pointer over a DiscreteVariable used to define a new
795  // variable in the built BayesNet.
796  // @throw DuplicateElement Raised if a variable with the same name already
797  // exists.
798  // @throw OperationNotAllowed Raised if redefineParents == false and if table
799  // is not a valid CPT for var in the current state
800  // of the BayesNet.
801  template < typename GUM_SCALAR >
802  INLINE void
804  if ((state() != factory_state::NONE)) {
805  illegalStateError__("setVariable");
806  } else {
807  try {
808  checkVariableName__(var.name());
809  GUM_ERROR(DuplicateElement, "Name already used: " << var.name());
810  } catch (NotFound&) {
811  // The var name is unused
812  varNameMap__.insert(var.name(), bn__->add(var));
813  }
814  }
815  }
816 
817  // @brief Define a variable's CPT.
818  // You can only call this method if the factory is in the NONE or NETWORK
819  // state.
820  // Be careful that table is given to the built BayesNet, so it will be
821  // deleted with it, and you should not directly access it after you call
822  // this method.
823  // When the redefineParents flag is set to true the constructed BayesNet's
824  // DAG is changed to fit with table's definition.
825  // @param var The name of the concerned variable.
826  // @param table A pointer over the CPT used for var.
827  // @param redefineParents If true redefine var's parents to match table's
828  // variables set.
829  //
830  // @throw NotFound Raised if no variable matches var.
831  // @throw OperationNotAllowed Raised if redefineParents == false and if table
832  // is not a valid CPT for var in the current state
833  // of the BayesNet.
834  template < typename GUM_SCALAR >
836  const std::string& varName, MultiDimAdressable* table, bool redefineParents) {
837  auto pot = dynamic_cast< Potential< GUM_SCALAR >* >(table);
838 
839  if (state() != factory_state::NONE) {
840  illegalStateError__("setVariableCPT");
841  } else {
842  checkVariableName__(varName);
843  const DiscreteVariable& var = bn__->variable(varNameMap__[varName]);
844  NodeId varId = varNameMap__[varName];
845  // If we have to change the structure of the BayesNet, then we call a sub
846  // method.
847 
848  if (redefineParents) {
849  setCPTAndParents__(var, pot);
850  } else if (pot->contains(var)) {
851  for (auto node: bn__->parents(varId)) {
852  if (!pot->contains(bn__->variable(node))) {
854  "The CPT is not valid in the current BayesNet.");
855  }
856  }
857 
858  // CPT are created when a variable is added.
859  bn__->unsafeChangePotential_(varId, pot);
860  }
861  }
862  }
863 
864  // Copy operator is illegal, use only copy constructor.
865  template < typename GUM_SCALAR >
867  const BayesNetFactory< GUM_SCALAR >& source) {
868  GUM_ERROR(OperationNotAllowed, "Illegal!");
869  // For noisy compilers
870  return *this;
871  }
872 
873  // Raise an OperationNotAllowed with the message "Illegal state."
874  template < typename GUM_SCALAR >
875  INLINE void
877  std::string msg = "Illegal state call (";
878  msg += s;
879  msg += ") in state ";
880 
881  switch (state()) {
882  case factory_state::NONE: {
883  msg += "NONE";
884  break;
885  }
886 
887  case factory_state::NETWORK: {
888  msg += "NETWORK";
889  break;
890  }
891 
893  msg += "VARIABLE";
894  break;
895  }
896 
897  case factory_state::PARENTS: {
898  msg += "PARENTS";
899  break;
900  }
901 
902  case factory_state::RAW_CPT: {
903  msg += "RAW_CPT";
904  break;
905  }
906 
908  msg += "FACT_CPT";
909  break;
910  }
911 
913  msg += "FACT_ENTRY";
914  break;
915  }
916 
917  default: {
918  msg += "Unknown state";
919  }
920  }
921 
923  }
924 
925  // Check if a variable with the given name exists, if not raise an NotFound
926  // exception.
927  template < typename GUM_SCALAR >
928  INLINE void
930  if (!varNameMap__.exists(name)) { GUM_ERROR(NotFound, name); }
931  }
932 
933  // Check if var exists and if mod is one of it's modality, if not raise an
934  // NotFound exception.
935  template < typename GUM_SCALAR >
937  const std::string& name, const std::string& mod) {
938  checkVariableName__(name);
939  const DiscreteVariable& var = bn__->variable(varNameMap__[name]);
940 
941  for (Idx i = 0; i < var.domainSize(); ++i) {
942  if (mod == var.label(i)) { return i; }
943  }
944 
945  GUM_ERROR(NotFound, mod);
946  }
947 
948  // Check if in stringBag__ there is no other modality with the same name.
949  template < typename GUM_SCALAR >
950  INLINE void
952  for (size_t i = 3; i < stringBag__.size(); ++i) {
953  if (mod == stringBag__[i]) {
954  GUM_ERROR(DuplicateElement, "Label already used: " << mod);
955  }
956  }
957  }
958 
959  // Sub method of setVariableCPT() which redefine the BayesNet's DAG with
960  // respect to table.
961  template < typename GUM_SCALAR >
963  const DiscreteVariable& var, Potential< GUM_SCALAR >* table) {
964  NodeId varId = varNameMap__[var.name()];
965  bn__->dag_.eraseParents(varId);
966 
967  for (auto v: table->variablesSequence()) {
968  if (v != (&var)) {
969  checkVariableName__(v->name());
970  bn__->dag_.addArc(varNameMap__[v->name()], varId);
971  }
972  }
973 
974  // CPT are created when a variable is added.
975  bn__->unsafeChangePotential_(varId, table);
976  }
977 
978  // Reset the different parts used to constructed the BayesNet.
979  template < typename GUM_SCALAR >
981  foo_flag__ = false;
982  bar_flag__ = false;
983  stringBag__.clear();
984  }
985 } /* namespace gum */
aGrUM&#39;s Potential is a multi-dimensional array with tensor operators.
Definition: potential.h:60
Class representing a Bayesian Network.
Definition: BayesNet.h:78
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.
const DiscreteVariable & variable(NodeId id) const final
Returns a gum::DiscreteVariable given its gum::NodeId in the gum::BayesNet.
Definition: BayesNet_tpl.h:214
class LabelizedVariable
Size domainSize() const final
Returns the product of the variable&#39;s domain size in the Instantiation.
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.
#define VERBOSITY(x)
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.
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.
Class for discretized random variable.
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.
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
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.
Instantiation & chgVal(const DiscreteVariable &v, Idx newval)
Assign newval to variable v in the Instantiation.
void illegalStateError__(const std::string &s)
Raise an OperationNotAllowed with the message "Illegal state.".
Base class for discrete random variable.
Generic doubly linked lists.
Definition: list.h:372
void incNotVar(const DiscreteVariable &v)
Operator increment for vars which are not v.
Copyright 2005-2020 Pierre-Henri WUILLEMIN() & Christophe GONZALES() info_at_agrum_dot_org.
Definition: agrum.h:25
void incVar(const DiscreteVariable &v)
Operator increment for variable v only.
Instantiation & setVals(const Instantiation &i)
Assign the values from i in the Instantiation.
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 setFirstNotVar(const DiscreteVariable &v)
Assign the first values to variables different of v.
void unsetEnd()
Alias for unsetOverflow().
Idx val(Idx i) const
Returns the current value of the variable at position i.
virtual Size domainSize() const =0
void incOut(const Instantiation &i)
Operator increment for the variables not in i.
void setFirstIn(const Instantiation &i)
Assign the first values in the Instantiation for the variables in i.
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.
Copyright 2005-2020 Pierre-Henri WUILLEMIN() & Christophe GONZALES() info_at_agrum_dot_org.
std::string to_string(const Formula &f)
Definition: formula_inl.h:499
void startNetworkDeclaration() final
Tells the factory that we&#39;re in a network declaration.
DiscretizedVariable & addTick(const T_TICKS &aTick)
add a tick.
void setFirstVar(const DiscreteVariable &v)
Assign the first value in the Instantiation for var v.
const NodeGraphPart & nodes() const
Returns a constant reference to the dag of this Bayes Net.
Definition: DAGmodel_inl.h:70
virtual std::string label(Idx i) const =0
get the indice-th label. This method is pure virtual.
Size size() const noexcept
Returns the number of elements in the list.
Definition: list_tpl.h:1852
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.
Val & pushBack(const Val &val)
Inserts a new element (a copy) at the end of the chained list.
Definition: list_tpl.h:1593
factory_state
The enumeration of states in which the factory can be in.
std::vector< factory_state > states__
State stack.
VarType
Definition: variable.h:41
virtual const DiscreteVariable & variable(Idx) const final
Returns a const ref to the ith var.
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.
Defines a discrete random variable over an integer interval.
Definition: rangeVariable.h:54
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.
void incIn(const Instantiation &i)
Operator increment for the variables in i.
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
Abstract base class for all multi dimensionnal addressable.
void setVariableValuesUnchecked(const std::vector< float > &values) final
Gives the values of the variable with respect to precedent parents modality.
virtual Idx nbrDim() const override
Returns the number of vars in the multidimensional container.
Class for assigning/browsing values to tuples of discrete variables.
Definition: instantiation.h:83
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.
bool contains(const DiscreteVariable &v) const final
Indicates whether a given variable belongs to the Instantiation.
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.
virtual void set(const Instantiation &i, const GUM_SCALAR &value) const final
Default implementation of MultiDimContainer::set().
void setFirst()
Assign the first values to the tuple of the Instantiation.
void variableDescription(const std::string &desc) final
Tells the factory the current variable&#39;s description.
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.
<agrum/tools/multidim/multiDimImplementation.h>
Size Idx
Type for indexes.
Definition: types.h:53
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.
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition: types.h:48
void resetParts__()
Reset the different parts used to constructed the BayesNet.
virtual const Sequence< const DiscreteVariable *> & variablesSequence() const final
Returns a const ref to the sequence of DiscreteVariable*.
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
const std::string & name() const
returns the name of the variable
LabelizedVariable & addLabel(const std::string &aLabel)
add a label with a new index (we assume that we will NEVER remove a label)
Size NodeId
Type for node ids.
Definition: graphElements.h:98
void setVariableValues(const std::vector< float > &values) final
same than below with gum::OperationNotAllowed exception if value&#39;s size not OK.
#define GUM_ERROR(type, msg)
Definition: exceptions.h:55
A factory class to ease BayesNet construction.
Definition: BayesNet.h:45
bool end() const
Returns true if the Instantiation reached the end.
virtual ~BayesNetFactory()
Destructor.
void setFirstOut(const Instantiation &i)
Assign the first values in the Instantiation for the variables not in i.
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.