aGrUM  0.16.0
PRMClass_tpl.h
Go to the documentation of this file.
1 
30 // to ease parsing
31 #include <queue>
32 
34 
36 
37 namespace gum {
38  namespace prm {
39  template < typename GUM_SCALAR >
40  PRMClass< GUM_SCALAR >::PRMClass(const std::string& name) :
41  PRMClassElementContainer< GUM_SCALAR >(name), __superClass(nullptr),
42  __implements(nullptr), __bijection(nullptr) {
43  GUM_CONSTRUCTOR(PRMClass);
44  }
45 
46  template < typename GUM_SCALAR >
47  PRMClass< GUM_SCALAR >::PRMClass(const std::string& name,
49  bool delayInheritance) :
50  PRMClassElementContainer< GUM_SCALAR >(name),
51  __superClass(&super), __implements(nullptr),
52  __bijection(
53  new Bijection< const DiscreteVariable*, const DiscreteVariable* >()) {
54  GUM_CONSTRUCTOR(PRMClass);
55  if (!delayInheritance) {
56  __dag = super.containerDag();
57  __inheritClass(super);
58  }
59  }
60 
61  template < typename GUM_SCALAR >
62  PRMClass< GUM_SCALAR >::PRMClass(const std::string& name,
63  const Set< PRMInterface< GUM_SCALAR >* >& set,
64  bool delayInheritance) :
65  PRMClassElementContainer< GUM_SCALAR >(name),
66  __superClass(nullptr),
67  __implements(new Set< PRMInterface< GUM_SCALAR >* >(set)),
68  __bijection(nullptr) {
69  GUM_CONSTRUCTOR(PRMClass);
70 
71  if (!delayInheritance) { __implementInterfaces(false); }
72  }
73 
74  template < typename GUM_SCALAR >
75  PRMClass< GUM_SCALAR >::PRMClass(const std::string& name,
77  const Set< PRMInterface< GUM_SCALAR >* >& set,
78  bool delayInheritance) :
79  PRMClassElementContainer< GUM_SCALAR >(name),
80  __superClass(&super), __implements(nullptr),
81  __bijection(
82  new Bijection< const DiscreteVariable*, const DiscreteVariable* >()) {
83  GUM_CONSTRUCTOR(PRMClass);
84  if (!delayInheritance) {
85  __dag = super.containerDag();
86  __inheritClass(super);
87  }
88 
89  // Adding other implementation
90  if (__implements == nullptr) { // super has not created __implements
91  __implements = new Set< PRMInterface< GUM_SCALAR >* >(set);
92  } else { // we just add the new implementations
93  for (const auto elt : set) {
94  __implements->insert(elt);
95  }
96  }
97 
98  if (!delayInheritance) { __implementInterfaces(false); }
99  }
100 
101  template < typename GUM_SCALAR >
102  void PRMClass< GUM_SCALAR >::__implementInterfaces(bool delayedInheritance) {
103  for (const auto impl : *__implements) {
104  impl->__addImplementation(this);
105  if ((!__superClass) || (!super().isSubTypeOf(*impl))
106  || delayedInheritance) {
107  // Reserve reference id in DAG
108  for (auto ref : impl->referenceSlots()) {
109  __dag.addNodeWithId(ref->id());
110  }
111  // Reserve attribute id in DAG
112  for (auto attr : impl->attributes()) {
113  __dag.addNodeWithId(attr->id());
114  }
115  }
116  }
117  }
118 
119  template < typename GUM_SCALAR >
121  GUM_DESTRUCTOR(PRMClass);
122 
123  for (const auto& elt : __nodeIdMap) {
124  delete elt.second;
125  }
126 
127  if (__implements) { delete __implements; }
128 
129  if (__bijection) { delete __bijection; }
130  }
131 
132  template < typename GUM_SCALAR >
134  if (__superClass) {
135  __superClass->__addExtension(this);
136  // Adding implemented interfaces, if any
137  if (__superClass->__implements) {
138  if (!__implements) {
139  __implements = new Set< PRMInterface< GUM_SCALAR >* >(
140  *(__superClass->__implements));
141  } else {
142  for (auto i : *(__superClass->__implements)) {
143  __implements->insert(i);
144  }
145  }
146  }
147  }
148  if (__implements) { __implementInterfaces(true); }
149  }
150 
151  template < typename GUM_SCALAR >
153  if (__superClass) {
154  // Copying reference slots
155  for (const auto c_refslot : __superClass->__referenceSlots) {
156  auto ref = new PRMReferenceSlot< GUM_SCALAR >(
157  c_refslot->name(),
159  c_refslot->slotType()),
160  c_refslot->isArray());
161 
162  ref->setId(c_refslot->id());
163  // Not reserved by an interface
164  if (!__dag.existsNode(ref->id())) { __dag.addNodeWithId(ref->id()); }
165  __nodeIdMap.insert(ref->id(), ref);
166  __referenceSlots.insert(ref);
167 
168  if (__superClass->__nameMap[c_refslot->name()]
169  == __superClass->__nameMap[c_refslot->safeName()]) {
170  __nameMap.insert(ref->name(), ref);
171  }
172 
173  __nameMap.insert(ref->safeName(), ref);
174  }
175  }
176  }
177 
178  template < typename GUM_SCALAR >
180  if (__superClass) {
181  // Copying parameters
182  for (const auto c_param : __superClass->__parameters) {
183  auto param = new PRMParameter< GUM_SCALAR >(
184  c_param->name(), c_param->valueType(), c_param->value());
185 
186  __parameters.insert(param);
187 
188  param->setId(c_param->id());
189  __dag.addNodeWithId(param->id());
190  __nodeIdMap.insert(param->id(), param);
191  __nameMap.insert(param->name(), param);
192  }
193  }
194  }
195 
196  template < typename GUM_SCALAR >
198  if (__superClass) {
199  for (const auto c_attr : __superClass->__attributes) {
200  // using multiDimSparse to prevent unecessary memory allocation for
201  // large arrays (the potentials are copied latter)
202  auto attr = c_attr->newFactory(*this);
203 
204  __bijection->insert(&(c_attr->type().variable()),
205  &(attr->type().variable()));
206  attr->setId(c_attr->id());
207  try {
208  __dag.addNodeWithId(attr->id());
209  } catch (gum::Exception&) {
210  // Node reserved by an interface
211  }
212  __nodeIdMap.insert(attr->id(), attr);
213  __attributes.insert(attr);
214 
215  if (__superClass->__nameMap[c_attr->name()]
216  == __superClass->__nameMap[c_attr->safeName()]) {
217  __nameMap.insert(attr->name(), attr);
218  }
219 
220  __nameMap.insert(attr->safeName(), attr);
221  }
222  }
223  }
224 
225  template < typename GUM_SCALAR >
227  if (__superClass) {
228  for (const auto c_agg : __superClass->__aggregates) {
229  PRMAggregate< GUM_SCALAR >* agg = nullptr;
230 
231  try {
232  agg = new PRMAggregate< GUM_SCALAR >(
233  c_agg->name(), c_agg->agg_type(), c_agg->type(), c_agg->label());
234  } catch (OperationNotAllowed&) {
235  agg = new PRMAggregate< GUM_SCALAR >(
236  c_agg->name(), c_agg->agg_type(), c_agg->type());
237  agg->sharedLabel(c_agg->sharedLabel());
238  agg->setLabel(c_agg->labelValue());
239  }
240 
241  __bijection->insert(&(c_agg->type().variable()),
242  &(agg->type().variable()));
243  agg->setId(c_agg->id());
244  __dag.addNodeWithId(agg->id());
245  __nodeIdMap.insert(agg->id(), agg);
246  __aggregates.insert(agg);
247 
248  if (__superClass->__nameMap[c_agg->name()]
249  == __superClass->__nameMap[c_agg->safeName()])
250  __nameMap.insert(agg->name(), agg);
251 
252  __nameMap.insert(agg->safeName(), agg);
253  }
254  }
255  }
256 
257  template < typename GUM_SCALAR >
259  if (__superClass) {
260  // Copying slot chains
261  for (const auto c_sc : __superClass->__slotChains) {
262  // Because of aggregators, some slotchains may exists already
263  if (!(__nameMap.exists(c_sc->name())
264  && __nameMap.exists(c_sc->safeName()))) {
265  // We just need to change the first PRMReferenceSlot<GUM_SCALAR> in
266  // the
267  // chain
268  auto chain = c_sc->chain();
269 
270  chain.setAtPos(0, __nameMap[c_sc->chain().front()->name()]);
271 
272  auto sc = new PRMSlotChain< GUM_SCALAR >(c_sc->name(), chain);
273  __bijection->insert(&(c_sc->type().variable()),
274  &(sc->type().variable()));
275  sc->setId(c_sc->id());
276  __dag.addNodeWithId(sc->id());
277  __nodeIdMap.insert(sc->id(), sc);
278  __slotChains.insert(sc);
279 
280  if (!__nameMap.exists(sc->name())) {
281  __nameMap.insert(sc->name(), sc);
282  }
283  if (!__nameMap.exists(sc->safeName())) {
284  __nameMap.insert(sc->safeName(), sc);
285  }
286  }
287  }
288  }
289  }
290 
291  template < typename GUM_SCALAR >
292  void PRMClass< GUM_SCALAR >::completeInheritance(const std::string& name) {
293  if (__superClass) {
294  auto& elt = this->get(name);
298  "you can only complete inheritance for attributes");
299  }
300 
301  for (const auto& prnt : super().containerDag().parents(elt.id())) {
302  this->addArc(super().get(prnt).safeName(), elt.safeName());
303  }
304 
306  auto& attr = static_cast< PRMAttribute< GUM_SCALAR >& >(elt);
307  auto& super_attr =
308  static_cast< const PRMAttribute< GUM_SCALAR >& >(super().get(name));
309  attr.copyCpf(*__bijection, super_attr);
310  }
311  }
312  }
313 
314  template < typename GUM_SCALAR >
316  if (__superClass) {
317  __superClass->__addExtension(this);
318  // Adding implemented interfaces of c, if any
319  if (c.__implements) {
320  if (!__implements) {
321  __implements =
323  } else {
324  for (auto i : *(c.__implements)) {
325  __implements->insert(i);
326  }
327  }
328  }
329 
330  // Copying attributes, the bijection's firsts are attributes in this and
331  // its
332  // seconds are attributes
333  // in c.
335 
336  // Copying parameters
337  for (const auto c_param : c.__parameters) {
338  auto param = new PRMParameter< GUM_SCALAR >(
339  c_param->name(), c_param->valueType(), c_param->value());
340 
341  __parameters.insert(param);
342 
343  param->setId(c_param->id());
344  __nodeIdMap.insert(param->id(), param);
345  __nameMap.insert(param->name(), param);
346  }
347 
348  // Copying attributes
349  for (const auto c_attr : c.__attributes) {
350  // using multiDimSparse to prevent unecessary memory allocation for
351  // large arrays (the potentials are copied latter)
352  auto attr = c_attr->newFactory(*this);
353 
354  bij.insert(&(c_attr->type().variable()), &(attr->type().variable()));
355  attr->setId(c_attr->id());
356  __nodeIdMap.insert(attr->id(), attr);
357  __attributes.insert(attr);
358 
359  if (c.__nameMap[c_attr->name()] == c.__nameMap[c_attr->safeName()]) {
360  __nameMap.insert(attr->name(), attr);
361  }
362 
363  __nameMap.insert(attr->safeName(), attr);
364  }
365 
366  // Copying aggregates
367  for (const auto c_agg : c.__aggregates) {
368  PRMAggregate< GUM_SCALAR >* agg = nullptr;
369 
370  try {
371  agg = new PRMAggregate< GUM_SCALAR >(
372  c_agg->name(), c_agg->agg_type(), c_agg->type(), c_agg->label());
373  } catch (OperationNotAllowed&) {
374  agg = new PRMAggregate< GUM_SCALAR >(
375  c_agg->name(), c_agg->agg_type(), c_agg->type());
376  }
377 
378  bij.insert(&(c_agg->type().variable()), &(agg->type().variable()));
379  agg->setId(c_agg->id());
380  __nodeIdMap.insert(agg->id(), agg);
381  __aggregates.insert(agg);
382 
383  if (c.__nameMap[c_agg->name()] == c.__nameMap[c_agg->safeName()])
384  __nameMap.insert(agg->name(), agg);
385 
386  __nameMap.insert(agg->safeName(), agg);
387  }
388 
389  // Copying reference slots
390  for (const auto c_refslot : c.__referenceSlots) {
392  c_refslot->name(),
394  c_refslot->slotType()),
395  c_refslot->isArray());
396 
397  ref->setId(c_refslot->id());
398  __nodeIdMap.insert(ref->id(), ref);
399  __referenceSlots.insert(ref);
400 
401  if (c.__nameMap[c_refslot->name()] == c.__nameMap[c_refslot->safeName()])
402  __nameMap.insert(ref->name(), ref);
403 
404  __nameMap.insert(ref->safeName(), ref);
405  }
406 
407  // Copying slot chains
408  for (const auto c_slotchain : c.__slotChains) {
409  // We just need to change the first PRMReferenceSlot<GUM_SCALAR> in
410  // the
411  // chain
412  Sequence< PRMClassElement< GUM_SCALAR >* > chain(c_slotchain->chain());
413 
414  chain.setAtPos(0, __nameMap[c_slotchain->chain().front()->name()]);
415 
417  new PRMSlotChain< GUM_SCALAR >(c_slotchain->name(), chain);
418  bij.insert(&(c_slotchain->type().variable()), &(sc->type().variable()));
419  sc->setId(c_slotchain->id());
420  __nodeIdMap.insert(sc->id(), sc);
421  __slotChains.insert(sc);
422 
423  __nameMap.insert(sc->name(), sc);
424  __nameMap.insert(sc->safeName(), sc);
425  }
426 
427  // Copying dependencies yield by arcs
428  for (const auto& arc : c.containerDag().arcs()) {
429  __nodeIdMap[arc.tail()]->addChild(*(__nodeIdMap[arc.head()]));
430  __nodeIdMap[arc.head()]->addParent(*(__nodeIdMap[arc.tail()]));
431  }
432 
433  // Copying the IO flag
434  this->_copyIOFlags(c);
435  // Copying content of CPF
436  for (const auto attr : c.__attributes) {
437  auto a = static_cast< PRMAttribute< GUM_SCALAR >* >(
438  __nameMap[attr->safeName()]);
439  a->copyCpf(bij, *attr);
440  }
441  }
442  }
443 
444  template < typename GUM_SCALAR >
446  const PRMClassElementContainer< GUM_SCALAR >& cec) const {
447  switch (cec.obj_type()) {
448  case PRMObject::prm_type::CLASS: {
449  const PRMClass< GUM_SCALAR >* current = this;
450 
451  while (current != 0) {
452  if (current == &(cec)) return true;
453 
454  current = current->__superClass;
455  }
456 
457  return false;
458  }
459 
460  case PRMObject::prm_type::PRM_INTERFACE: {
461  if (__implements != nullptr) {
462  const PRMInterface< GUM_SCALAR >& i =
463  static_cast< const PRMInterface< GUM_SCALAR >& >(cec);
464 
465  if (__implements->exists(
466  const_cast< PRMInterface< GUM_SCALAR >* >(&i)))
467  return true;
468 
469  for (const auto impl : *__implements)
470  if (impl->isSubTypeOf(i)) return true;
471  }
472 
473  return false;
474  }
475 
476  default: {
477  GUM_ERROR(FatalError, "unknown ClassElementContainer<GUM_SCALAR>");
478  }
479  }
480  }
481 
482  template < typename GUM_SCALAR >
483  void PRMClass< GUM_SCALAR >::addArc(const std::string& tail_name,
484  const std::string& head_name) {
487 
488  try {
489  tail = __nameMap[tail_name];
490  head = __nameMap[head_name];
491  } catch (NotFound&) {
493  "tail and/or head of arc does not exists in this Class");
494  }
495 
499  "a PRMReferenceSlot<GUM_SCALAR> can "
500  "not on neither side of an arc");
501  }
502 
506  "illegal insertion of an arc between two SlotChain<GUM_SCALAR>");
507  }
508 
509  if (!__dag.existsArc(Arc(tail->id(), head->id()))) {
510  __dag.addArc(tail->id(), head->id());
511  } else {
513  "duplicate arc " << tail_name << "->" << head_name);
514  }
515 
516  get(tail->id()).addChild(get(head->id()));
517  get(head->id()).addParent(get(tail->id()));
518 
519  // Defining input / output nodes
522  static_cast< PRMSlotChain< GUM_SCALAR >* >(tail);
523  this->setInputNode(*head, true);
524  sc->end().setOutputNode(sc->end().get(sc->lastElt().safeName()), true);
525  }
526  }
527 
528  template < typename GUM_SCALAR >
531  try {
532  for (auto i : implements()) {
533  if (i->exists(elt->name())) { __checkInterface(elt, i); }
534  }
535  } catch (NotFound&) {
536  // No interface
537  }
538  }
539 
540  template < typename GUM_SCALAR >
541  void
544  const auto& i_elt = i->get(elt->name());
545  bool is_attr = PRMClassElement< GUM_SCALAR >::isAttribute(i_elt);
546  bool is_agg = PRMClassElement< GUM_SCALAR >::isAggregate(i_elt);
547 
548  if (!(is_attr || is_agg)) {
549  GUM_ERROR(OperationNotAllowed, "Class does not respect it's interface");
550  }
551 
552  if (!elt->type().isSubTypeOf(i_elt.type())) {
554  "Attribute type does not respect class interface");
555  }
556 
557  if (elt->type() != i_elt.type()) {
558  if (!this->exists(i_elt.safeName())) {
560  "Attribute type does not respect class interface");
561  }
562  elt = &(this->get(i_elt.safeName()));
563  }
564 
565  // Node must be reserved by constructor
566  if (!__dag.existsNode(i_elt.id())) {
567  GUM_ERROR(FatalError, "Class does not reserved implemented nodes");
568  }
569 
570  // Removing unused node and changing to proper node
571  if (elt->id() != i_elt.id()) {
572  // Update cast descendants
573  for (auto child : __dag.children(elt->id())) {
574  __dag.addArc(i_elt.id(), child);
575  }
576  __dag.eraseNode(elt->id());
577  }
578  __nodeIdMap.erase(elt->id());
579  elt->setId(i_elt.id());
580  __nodeIdMap.insert(elt->id(), elt);
581  }
582 
583  template < typename GUM_SCALAR >
586  try {
587  for (auto i : implements()) {
588  if (i->exists(ref->name())) { __checkRefInterface(ref, i); }
589  }
590  } catch (NotFound&) {
591  // No interface to check
592  }
593  }
594 
595  template < typename GUM_SCALAR >
598  auto& i_elt = i->get(ref->name());
599  if (i_elt.elt_type() != ref->elt_type()) {
600  GUM_ERROR(OperationNotAllowed, "Class does not respect it's interface");
601  }
602  auto& i_ref = static_cast< PRMReferenceSlot< GUM_SCALAR >& >(i_elt);
603  if (!ref->slotType().isSubTypeOf(i_ref.slotType())) {
605  "ReferenceSlot type does not respect class interface");
606  }
607  // Node must be reserved by constructor
608  if (!__dag.exists(i_ref.id())) {
610  "class " << this->name() << " does not respect interface "
611  << i->name() << " implementation");
612  }
613  // Removing unused node and changin to propoer node
614  if (ref->id() != i_ref.id()) { __dag.eraseNode(ref->id()); }
615  __nodeIdMap.erase(ref->id());
616  ref->setId(i_ref.id());
617  __nodeIdMap.insert(ref->id(), ref);
618  }
619 
620  template < typename GUM_SCALAR >
622  if (__nameMap.exists(elt->name())) {
624  "name " << elt->name()
625  << " already used by another ClassElement");
626  }
627 
628  elt->setId(nextNodeId());
629  __dag.addNodeWithId(elt->id());
630  __nodeIdMap.insert(elt->id(), elt);
631  __nameMap.insert(elt->name(), elt);
632 
633  try {
634  __nameMap.insert(elt->safeName(), elt);
635  } catch (DuplicateElement& e) {
638  throw DuplicateElement(e);
639  }
640  }
641 
642  switch (elt->elt_type()) {
644  __attributes.insert(static_cast< PRMAttribute< GUM_SCALAR >* >(elt));
645  __addCastDescendants(static_cast< PRMAttribute< GUM_SCALAR >* >(elt));
646 
647  // Update attribute or cast descendant id to respect implemented
648  // interface
649  __checkInterfaces(elt);
650 
651  __addIOInterfaceFlags(elt);
652  break;
653  }
654 
656  __aggregates.insert(static_cast< PRMAggregate< GUM_SCALAR >* >(elt));
657  __addCastDescendants(static_cast< PRMAttribute< GUM_SCALAR >* >(elt));
658 
659  // Update attribute or cast descendant id to respect implemented
660  // interface
661  __checkInterfaces(elt);
662 
663  __addIOInterfaceFlags(elt);
664  break;
665  }
666 
668  auto ref = static_cast< PRMReferenceSlot< GUM_SCALAR >* >(elt);
669  __referenceSlots.insert(ref);
670 
671  // Updating ref's id if ref implements an interface
672  __checkRefInterfaces(ref);
673  break;
674  }
675 
677  __slotChains.insert(static_cast< PRMSlotChain< GUM_SCALAR >* >(elt));
678  break;
679  }
680 
682  __parameters.insert(static_cast< PRMParameter< GUM_SCALAR >* >(elt));
683  break;
684  }
685 
686  default: {
687  GUM_ERROR(FatalError, "unknown ClassElement<GUM_SCALAR> type");
688  }
689  }
690 
691  return elt->id();
692  }
693 
694  template < typename GUM_SCALAR >
697  auto parent = attr;
698  PRMAttribute< GUM_SCALAR >* child = 0;
699 
700  while (parent->type().isSubType()) {
701  child = parent->getCastDescendant();
702 
703  // Check if id was reserved by one of the class interfaces
704  bool found = false;
705  try {
706  for (auto i : implements()) {
707  if (i->exists(child->safeName())) {
708  child->setId(i->get(child->safeName()).id());
709  found = true;
710  break;
711  }
712  }
713  } catch (NotFound&) {
714  // No interface
715  }
716  if (!found) {
717  child->setId(nextNodeId());
718  __dag.addNodeWithId(child->id());
719  }
720  __nodeIdMap.insert(child->id(), child);
721  // Only use child's safe name when adding to the name map!
722  __nameMap.insert(child->safeName(), child);
723  __attributes.insert(child);
724  // Do not use Class<GUM_SCALAR>::insertArc(), child's CPF is already
725  // initialized properly
726  __dag.addArc(parent->id(), child->id());
727 
728  parent = child;
729  }
730  }
731 
732  template < typename GUM_SCALAR >
734  PRMClassElement< GUM_SCALAR >* overloader) {
735  try {
736  if (!super().exists(overloader->name())) {
738  "found no ClassElement<GUM_SCALAR> to overload");
739  }
740  } catch (NotFound&) {
742  "overload is possible only with subclasses");
743  }
744 
745  PRMClassElement< GUM_SCALAR >* overloaded = __nameMap[overloader->name()];
746  if (overloaded == overloader) {
748  "dupplicate ClassElement " << overloader->name());
749  }
750  // Checking overload legality
751  if (!__checkOverloadLegality(overloaded, overloader)) {
752  GUM_ERROR(OperationNotAllowed, "illegal overload");
753  }
754 
755  switch (overloader->elt_type()) {
757  auto overloader_attr =
758  static_cast< PRMAttribute< GUM_SCALAR >* >(overloader);
759  auto overloaded_attr =
760  static_cast< PRMAttribute< GUM_SCALAR >* >(overloaded);
761  __overloadAttribute(overloader_attr, overloaded_attr);
762  __addIOInterfaceFlags(overloader);
763  break;
764  }
765 
767  __overloadAggregate(
768  static_cast< PRMAggregate< GUM_SCALAR >* >(overloader), overloaded);
769  __addIOInterfaceFlags(overloader);
770  break;
771  }
772 
774  // __checkOverloadLegality guaranties that overloaded is a
775  // PRMReferenceSlot<GUM_SCALAR>
776  auto overloader_ref =
777  static_cast< PRMReferenceSlot< GUM_SCALAR >* >(overloader);
778  auto overloaded_ref =
779  static_cast< PRMReferenceSlot< GUM_SCALAR >* >(overloaded);
780  __overloadReference(overloader_ref, overloaded_ref);
781  break;
782  }
783 
786  "SlotChain<GUM_SCALAR> can not be overloaded");
787  break;
788  }
789 
791  auto overloaded_param =
792  static_cast< PRMParameter< GUM_SCALAR >* >(overloaded);
793  auto overloader_param =
794  static_cast< PRMParameter< GUM_SCALAR >* >(overloader);
795  __overloadParameter(overloader_param, overloaded_param);
796  break;
797  }
798  default: {
799  GUM_ERROR(OperationNotAllowed, "unknown ClassElement<GUM_SCALAR> type");
800  }
801  }
802 
803  return overloader->id();
804  }
805 
806  template < typename GUM_SCALAR >
808  PRMAttribute< GUM_SCALAR >* overloader,
809  PRMAttribute< GUM_SCALAR >* overloaded) {
810  __dag.eraseParents(overloaded->id());
811 
812  // Checking if we have to add cast descendant
813  if (overloader->type() != overloaded->type()) {
814  overloader->setId(nextNodeId());
815  __dag.addNodeWithId(overloader->id());
816  __nodeIdMap.insert(overloader->id(), overloader);
817  __nameMap[overloader->name()] = overloader;
818  __nameMap.insert(overloader->safeName(), overloader);
819  __attributes.insert(overloader);
820  __addCastDescendants(overloader, overloaded);
821  } else {
822  overloader->setId(overloaded->id());
823  __nodeIdMap[overloader->id()] = overloader;
824  __nameMap[overloader->name()] = overloader;
825  __nameMap[overloader->safeName()] = overloader;
826  __attributes.erase(overloaded);
827  __attributes.insert(overloader);
828  overloader->overload(overloaded);
829  delete overloaded;
830  }
831  }
832 
833  template < typename GUM_SCALAR >
835  PRMReferenceSlot< GUM_SCALAR >* overloader,
836  PRMReferenceSlot< GUM_SCALAR >* overloaded) {
837  // Adding overloading reference
838  overloader->setId(overloaded->id());
839  __nodeIdMap[overloader->id()] = overloader;
840  __nameMap[overloader->name()] = overloader;
841  __nameMap.insert(overloader->safeName(), overloader);
842  __referenceSlots.insert(overloader);
846  std::vector< PRMSlotChain< GUM_SCALAR >* > toRemove, toAdd;
847 
848  // Updating PRMSlotChain<GUM_SCALAR> which started with overloaded
849  for (const auto slotchain : __slotChains) {
850  // If the attribute pointed by this slotchain is overloaded, we need to
851  // change the slotchain
852  // names to it's safename version: ref.attr is replaced by
853  // ref.(type)attr.
854  if ((slotchain->chain().atPos(0) == overloaded)) {
856  seq.insert(overloader);
857 
858  auto elt = ++(slotchain->chain().begin());
859 
860  while (elt != slotchain->chain().end()) {
861  ref = static_cast< PRMReferenceSlot< GUM_SCALAR >* >(seq.back());
862  next = &(ref->slotType().get((*elt)->name()));
863  seq.insert(next);
864  ++elt;
865  }
866 
867  // If the slotchain last element type changes, we change the slotchain
868  // to
869  // point towards the cast decendant
870  // with the correct type
871  if (seq.back()->type() != slotchain->lastElt().type()) {
872  seq.erase(seq.back());
873  seq.insert(&(static_cast< PRMReferenceSlot< GUM_SCALAR >* >(seq.back())
874  ->slotType()
875  .get(slotchain->lastElt().safeName())));
876  std::string sc_name;
877  std::string dot = ".";
878 
879  for (Size i = 0; i < seq.size() - 1; ++i) {
880  sc_name += seq.atPos(i)->name() + dot;
881  }
882 
883  sc_name += seq.back()->safeName();
884  sc = new PRMSlotChain< GUM_SCALAR >(sc_name, seq);
885  sc->setId(slotchain->id());
886 
887  for (const auto child : this->containerDag().children(sc->id())) {
888  auto& elt = get(child);
890  auto& attr = static_cast< PRMAttribute< GUM_SCALAR >& >(elt);
891  auto& old_type = slotchain->lastElt().type();
892  auto& new_type = sc->lastElt().type();
893  attr.swap(old_type, new_type);
894  } else {
895  GUM_ERROR(OperationNotAllowed, "unexpected ClassElement");
896  // get( child ).cpf().replace(
897  // slotchain->lastElt().type().variable(),
898  // sc->lastElt().type().variable() );
899  }
900  }
901 
902  toAdd.push_back(sc);
903  toRemove.push_back(slotchain);
904  } else {
905  // Types are identical, we just need to change the first reference
906  slotchain->chain().setAtPos(0, overloader);
907  }
908  }
909  }
910 
911  for (const auto torem : toRemove) {
912  __nameMap.erase(torem->name());
913  __slotChains.erase(torem);
914  delete torem;
915  }
916 
917  for (const auto toadd : toAdd) {
918  __nameMap.insert(toadd->name(), toadd);
919  __nodeIdMap[toadd->id()] = toadd;
920  __slotChains.insert(sc);
921  }
922 
923  // Removing overloaded PRMReferenceSlot<GUM_SCALAR>
924  __referenceSlots.erase(overloaded);
925  __nameMap.erase(overloaded->safeName());
926  delete overloaded;
927  }
928 
929  template < typename GUM_SCALAR >
931  PRMParameter< GUM_SCALAR >* overloader,
932  PRMParameter< GUM_SCALAR >* overloaded) {
933  overloader->setId(overloaded->id());
934  __nodeIdMap[overloader->id()] = overloader;
935  __nameMap[overloader->name()] = overloader;
936  __nameMap[overloader->safeName()] = overloader;
937  __parameters.erase(overloaded);
938  __parameters.insert(overloader);
939  delete overloaded;
940  }
941 
942  template < typename GUM_SCALAR >
945  PRMAttribute< GUM_SCALAR >* parent = start;
946  PRMAttribute< GUM_SCALAR >* child = 0;
947 
948  while (parent->type().superType() != end->type()) {
949  child = parent->getCastDescendant();
950  child->setId(nextNodeId());
951  __nodeIdMap.insert(child->id(), child);
952  __dag.addNodeWithId(child->id());
953  // Only use child's safe name when adding to the name map!
954  __nameMap.insert(child->safeName(), child);
955  __attributes.insert(child);
956  __addIOInterfaceFlags(child);
957  // Do not use Class<GUM_SCALAR>::insertArc(), child's CPF is already
958  // initialized properly
959  __dag.addArc(parent->id(), child->id());
960  parent = child;
961  }
962 
963  parent->setAsCastDescendant(end);
964  __dag.addArc(parent->id(), end->id());
965  }
966 
967  template < typename GUM_SCALAR >
970  for (auto ext : __extensions) {
971  set.insert(ext);
972  ext->_findAllSubtypes(set);
973  }
974  }
975 
976  template < typename GUM_SCALAR >
979  // We only add IO Flags if elt matches is required by and interface
980  if (__implements != nullptr) {
981  for (const auto impl : *__implements) {
982  PRMInterface< GUM_SCALAR >* super = impl;
983  while (super) {
984  // If the attribute is defined in an interface, we set it as an
985  // OutputNode
986  if (impl->exists(elt->name())) {
987  try {
988  this->_getIOFlag(*elt).second = true;
989  } catch (NotFound&) {
990  this->_setIOFlag(*elt, std::make_pair(false, true));
991  }
992  }
993  try {
994  super = &(super->super());
995  } catch (NotFound&) { super = nullptr; }
996  }
997  }
998  }
999  }
1000 
1001  template < typename GUM_SCALAR >
1003  const PRMClassElement< GUM_SCALAR >& elt) {
1004  // for ( const auto ext : __extensions ) {
1005  // // We test to prevent unnecessary recursive call from iter
1006  // if ( !ext->isOutputNode( elt ) ) {
1007  // ext->setOutputNode( elt, true );
1008  // }
1009  //}
1010  }
1011 
1012  template < typename GUM_SCALAR >
1014  return PRMObject::prm_type::CLASS;
1015  }
1016 
1017  template < typename GUM_SCALAR >
1018  INLINE const DAG& PRMClass< GUM_SCALAR >::_dag() const {
1019  return __dag;
1020  }
1021 
1022  template < typename GUM_SCALAR >
1024  return __dag;
1025  }
1026 
1027  template < typename GUM_SCALAR >
1029  try {
1030  return *(__nodeIdMap[id]);
1031  } catch (NotFound&) {
1032  GUM_ERROR(NotFound, "no ClassElement<GUM_SCALAR> with the given NodeId");
1033  }
1034  }
1035 
1036  template < typename GUM_SCALAR >
1037  INLINE const PRMClassElement< GUM_SCALAR >&
1039  try {
1040  return *(__nodeIdMap[id]);
1041  } catch (NotFound&) {
1043  "no ClassElement<GUM_SCALAR> with the given NodeId (" << id
1044  << ")");
1045  }
1046  }
1047 
1048  template < typename GUM_SCALAR >
1050  PRMClass< GUM_SCALAR >::get(const std::string& name) {
1051  try {
1052  return *(__nameMap[name]);
1053  } catch (NotFound&) {
1055  "no ClassElement<GUM_SCALAR> with the given name (" << name
1056  << ")");
1057  }
1058  }
1059 
1060  template < typename GUM_SCALAR >
1061  INLINE const PRMClassElement< GUM_SCALAR >&
1062  PRMClass< GUM_SCALAR >::get(const std::string& name) const {
1063  try {
1064  return *(__nameMap[name]);
1065  } catch (NotFound&) {
1067  "no ClassElement<GUM_SCALAR> with the given name (" << name
1068  << ")");
1069  }
1070  }
1071 
1072  template < typename GUM_SCALAR >
1073  INLINE const Set< PRMAttribute< GUM_SCALAR >* >&
1075  return __attributes;
1076  }
1077 
1078  template < typename GUM_SCALAR >
1079  INLINE const Set< PRMParameter< GUM_SCALAR >* >&
1081  return __parameters;
1082  }
1083 
1084  // Private struct for retrieving all params in scope
1085  template < typename GUM_SCALAR >
1087  std::string prefix;
1090 
1091  ParamScopeData(const std::string& s,
1092  const PRMReferenceSlot< GUM_SCALAR >& ref,
1093  Idx d) :
1094  prefix(s + ref.name() + "."),
1095  c(static_cast< const PRMClass< GUM_SCALAR >* >(&(ref.slotType()))),
1096  depth(d) {}
1097  };
1098 
1099  template < typename GUM_SCALAR >
1103 
1104  for (const auto p : parameters()) {
1105  params.insert(p->name(), p);
1106  }
1107 
1108  std::queue< ParamScopeData< GUM_SCALAR > > queue;
1109 
1110  for (const auto ref : referenceSlots()) {
1111  if (PRMObject::isClass(ref->slotType())) {
1112  queue.push(ParamScopeData< GUM_SCALAR >("", *ref, 1));
1113  }
1114  }
1115 
1116  while (!queue.empty()) {
1117  auto data = queue.front();
1118  queue.pop();
1119 
1120  if (data.depth < 5) {
1121  for (const auto p : data.c->parameters()) {
1122  params.insert(data.prefix + p->name(), p);
1123  }
1124 
1125  for (const auto ref : data.c->referenceSlots()) {
1126  if (PRMObject::isClass(ref->slotType())) {
1127  queue.push(
1128  ParamScopeData< GUM_SCALAR >(data.prefix, *ref, data.depth + 1));
1129  }
1130  }
1131  } else {
1132  // @todo depth>5 is a workaround. Cycle detection is needed here !
1133  GUM_TRACE("Depth limit reached when looking up parameters");
1134  }
1135  }
1136 
1137  return params;
1138  }
1139 
1140  template < typename GUM_SCALAR >
1141  INLINE const Set< PRMAggregate< GUM_SCALAR >* >&
1143  return __aggregates;
1144  }
1145 
1146  template < typename GUM_SCALAR >
1147  INLINE const Set< PRMReferenceSlot< GUM_SCALAR >* >&
1149  return __referenceSlots;
1150  }
1151 
1152  template < typename GUM_SCALAR >
1153  INLINE const Set< PRMSlotChain< GUM_SCALAR >* >&
1155  return __slotChains;
1156  }
1157 
1158  template < typename GUM_SCALAR >
1160  if (__superClass) {
1161  return *__superClass;
1162  } else {
1163  GUM_ERROR(NotFound, "this Class is not a subclass");
1164  }
1165  }
1166 
1167  template < typename GUM_SCALAR >
1168  INLINE const Set< PRMInterface< GUM_SCALAR >* >&
1170  if (__implements) {
1171  return *__implements;
1172  } else {
1174  "this Class does not implement any Interface<GUM_SCALAR>");
1175  }
1176  }
1177 
1178  template < typename GUM_SCALAR >
1181  return get(id);
1182  }
1183 
1184  template < typename GUM_SCALAR >
1186  operator[](NodeId id) const {
1187  return get(id);
1188  }
1189 
1190  template < typename GUM_SCALAR >
1192  operator[](const std::string& name) {
1193  return get(name);
1194  }
1195 
1196  template < typename GUM_SCALAR >
1198  operator[](const std::string& name) const {
1199  return get(name);
1200  }
1201 
1202  template < typename GUM_SCALAR >
1204  PRMAggregate< GUM_SCALAR >* overloader,
1205  PRMClassElement< GUM_SCALAR >* overloaded) {
1206  __nameMap.insert(overloader->safeName(), overloader);
1207  __aggregates.insert(overloader);
1208  }
1209 
1210  template < typename GUM_SCALAR >
1212  const PRMClassElement< GUM_SCALAR >* overloaded,
1213  const PRMClassElement< GUM_SCALAR >* overloader) {
1214  if (overloaded->elt_type() != overloader->elt_type()) { return false; }
1215 
1216  switch (overloaded->elt_type()) {
1218  if (!overloader->type().isSubTypeOf(overloaded->type())) {
1219  return false;
1220  }
1221  break;
1222  }
1223 
1225  const auto& new_slot_type =
1226  static_cast< const PRMReferenceSlot< GUM_SCALAR >* >(overloader)
1227  ->slotType();
1228  const auto& old_slot_type =
1229  static_cast< const PRMReferenceSlot< GUM_SCALAR >* >(overloaded)
1230  ->slotType();
1231 
1232  if (!new_slot_type.isSubTypeOf(old_slot_type)) { return false; }
1233 
1234  break;
1235  }
1236 
1238  auto overloaded_param =
1239  static_cast< const PRMParameter< GUM_SCALAR >* >(overloaded);
1240  auto overloader_param =
1241  static_cast< const PRMParameter< GUM_SCALAR >* >(overloader);
1242 
1243  return overloaded_param->valueType() == overloader_param->valueType();
1244  break;
1245  }
1246 
1247  default: {
1248  return false;
1249  }
1250  }
1251  return true;
1252  }
1253 
1254  template < typename GUM_SCALAR >
1255  INLINE const Set< PRMClass< GUM_SCALAR >* >&
1257  return __extensions;
1258  }
1259 
1260  template < typename GUM_SCALAR >
1262  __extensions.insert(c);
1263  }
1264 
1265  template < typename GUM_SCALAR >
1267  const std::string& safe_name) const {
1268  const PRMClassElement< GUM_SCALAR >& elt = get(safe_name);
1269 
1270  try {
1271  return elt.type().name() == get(elt.name()).type().name();
1272  } catch (OperationNotAllowed&) {
1273  GUM_ERROR(NotFound, "no attribute with the given name");
1274  }
1275  }
1276 
1277  template < typename GUM_SCALAR >
1279  const PRMClassElement< GUM_SCALAR >& elt) const {
1280  try {
1281  if (!this->_getIOFlag(elt).second) {
1282  if (__implements) {
1283  for (auto i : *__implements) {
1284  if (i->isOutputNode(elt)) { return true; }
1285  }
1286  }
1287 
1288  if (__superClass && (__superClass->isOutputNode(elt))) { return true; }
1289 
1290  } else {
1291  return true;
1292  }
1293  } catch (NotFound&) {}
1294  return false;
1295  }
1296 
1297 
1298  } /* namespace prm */
1299 } /* namespace gum */
void insert(const T1 &first, const T2 &second)
Inserts a new association in the gum::Bijection.
PRMParameter is a member of a Class in a PRM.
Definition: PRMParameter.h:52
PRMClass< GUM_SCALAR > * __superClass
The alternate PRMClassElementContainer<GUM_SCALAR> searched for elements defined in this...
Definition: PRMClass.h:391
virtual PRMAttribute< GUM_SCALAR > * getCastDescendant() const =0
Returns a proper cast descendant of this PRMAttribute.
const std::string & name() const
Returns the name of this object.
Definition: PRMObject_inl.h:35
const PRMClass< GUM_SCALAR > * c
Size size() const noexcept
Returns the size of the sequence.
Definition: sequence_tpl.h:38
virtual PRMType & type()=0
See gum::PRMClassElement::type().
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
The generic class for storing (ordered) sequences of objects.
Definition: sequence.h:1022
virtual prm_type obj_type() const =0
Returns the type of this object.
Abstract class representing an element of PRM class.
Set< PRMReferenceSlot< GUM_SCALAR > *> __referenceSlots
The sequence of PRMReferenceSlot<GUM_SCALAR>.
Definition: PRMClass.h:362
Base class for discrete random variable.
Set< PRMAggregate< GUM_SCALAR > *> __aggregates
The sequence of aggregate.
Definition: PRMClass.h:365
virtual PRMType & type()
This is similar to the following call: this->lastElt().type()
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
Definition: agrum.h:25
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
void setLabel(Idx idx)
Set the aggregator&#39;s label.
A PRMReferenceSlot represent a relation between two PRMClassElementContainer.
Definition: PRMObject.h:223
PRMClassElementContainer< GUM_SCALAR > & slotType()
Returns the type of this slot, which is a PRMClassElementContainer (it is not the type of PRMObject)...
The class for generic Hash Tables.
Definition: hashTable.h:679
void _findAllSubtypes(Set< PRMClassElementContainer< GUM_SCALAR > * > &set)
Fills set with all the subtypes of this Class<GUM_SCALAR>.
Definition: PRMClass_tpl.h:968
Set< PRMSlotChain< GUM_SCALAR > *> __slotChains
The set of gum::PRMSlotChain<GUM_SCALAR>s.
Definition: PRMClass.h:368
virtual PRMClassElement< GUM_SCALAR >::ClassElementType elt_type() const
Implementation of the pure virtual method of PRMObject.
Set< PRMInterface< GUM_SCALAR > *> * __implements
The Set of implemented interface of this.
Definition: PRMClass.h:394
Representation of a setA Set is a structure that contains arbitrary elements.
Definition: set.h:165
const std::string & safeName() const
Returns the safe name of this PRMClassElement, if any.
std::shared_ptr< Idx > sharedLabel() const
Returns the shared_ptr holding this Aggregate label.
prm_type
Enumeration of the different types of objects handled by a PRM.
Definition: PRMObject.h:69
virtual void overload(PRMAttribute< GUM_SCALAR > *source)
Set this as overload of source (necessayr to preserver internal pointers for MultiDims).
The base class for all directed edgesThis class is used as a basis for manipulating all directed edge...
PRMClass(const std::string &name)
Default constructor.
Definition: PRMClass_tpl.h:40
ParamScopeData(const std::string &s, const PRMReferenceSlot< GUM_SCALAR > &ref, Idx d)
PRMClassElementContainer< GUM_SCALAR > & end()
Returns the PRMClassElement<GUM_SCALAR>Container over which this slot chain ends. ...
Base class for all aGrUM&#39;s exceptions.
Definition: exceptions.h:106
Set of pairs of elements with fast search for both elements.
Definition: bijection.h:1805
An PRMInterface is implemented by a Class<GUM_SCALAR> and defines a set of PRMReferenceSlot<GUM_SCALA...
Definition: PRMClass.h:54
virtual ClassElementType elt_type() const =0
Return the type of class element this object is.
virtual PRMType & type()=0
Return a reference over the gum::PRMType of this class element.
A PRMSlotChain represents a sequence of gum::prm::PRMClassElement<GUM_SCALAR> where the n-1 first gum...
Definition: PRMObject.h:221
PRMInterface< GUM_SCALAR > & super()
Returns the superInterface of this PRMInterface.
NodeId nextNodeId()
Returns the next value of an unique counter for PRM&#39;s node id.
Definition: utils_prm.cpp:65
virtual PRMType & type()
See gum::PRMClassElement::type().
void erase(const Key &k)
Remove an element from the sequence.
Definition: sequence_tpl.h:453
virtual PRMClassElement< GUM_SCALAR > & get(NodeId id)
See gum::prm::PRMClassElementContainer<GUM_SCALAR>::get(NodeId).
<agrum/PRM/classElementContainer.h>
NodeId id() const
Returns the NodeId of this element in it&#39;s class DAG.
virtual void setId(NodeId id)
Used to assign the id of this element.
A PRMClass is an object of a PRM representing a fragment of a Bayesian Network which can be instantia...
Definition: PRMClass.h:66
virtual void setAsCastDescendant(PRMAttribute< GUM_SCALAR > *attr)=0
Define attr as a cast descendant of this PRMAttribute.
void __addExtension(PRMClass< GUM_SCALAR > *c)
This method is called when a sub-Class<GUM_SCALAR> of this Class<GUM_SCALAR> is created.
Size Idx
Type for indexes.
Definition: types.h:53
ParameterType valueType() const
See gum::PRMClassElement::elt_type().
virtual void copyCpf(const Bijection< const DiscreteVariable *, const DiscreteVariable * > &bif, const PRMAttribute< GUM_SCALAR > &source)=0
See gum::PRMClassElement::elt_type().
Set< PRMAttribute< GUM_SCALAR > *> __attributes
The sequence of PRMAttribute<GUM_SCALAR>s.
Definition: PRMClass.h:359
PRMAttribute is a member of a Class in a PRM.
Definition: PRMAttribute.h:61
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition: types.h:48
PRMClassElement< GUM_SCALAR > & lastElt()
Returns the last element of the slot chain, typically this is an gum::PRMAttribute or a gum::PRMAggre...
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
HashTable< std::string, PRMClassElement< GUM_SCALAR > *> __nameMap
Mapping between a member&#39;s name and itself. Used for fast access to a member given it&#39;s name...
Definition: PRMClass.h:356
virtual const DAG & containerDag() const
Returns the gum::DAG of this PRMClassElementContainer.
Base class for dag.
Definition: DAG.h:102
void setAtPos(Idx i, const Key &newKey)
Change the value.
Definition: sequence_tpl.h:525
Size NodeId
Type for node ids.
Definition: graphElements.h:98
void insert(const Key &k)
Inserts a new element into the set.
Definition: set_tpl.h:613
const Key & back() const
Returns the last element of the sequence.
Definition: sequence_tpl.h:568
#define GUM_ERROR(type, msg)
Definition: exceptions.h:55
const Key & atPos(Idx i) const
Returns the object at the pos i.
Definition: sequence_tpl.h:500
Set< PRMParameter< GUM_SCALAR > *> __parameters
The Set of parameters in this Class<GUM_SCALAR>.
Definition: PRMClass.h:371
void insert(const Key &k)
Insert an element at the end of the sequence.
Definition: sequence_tpl.h:408