aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
PRMClass_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /**
23  * @file
24  * @brief Inline implementation of gum::Class
25  *
26  * @author Lionel TORTI and Pierre-Henri WUILLEMIN(@LIP6)
27  */
28 
29 // to ease parsing
30 #include <queue>
31 
32 #include <agrum/PRM/elements/PRMClass.h>
33 
34 #include <agrum/PRM/elements/PRMInterface.h>
35 
36 namespace gum {
37  namespace prm {
38  template < typename GUM_SCALAR >
39  PRMClass< GUM_SCALAR >::PRMClass(const std::string& name) :
40  PRMClassElementContainer< GUM_SCALAR >(name), _superClass_(nullptr), _implements_(nullptr),
41  _bijection_(nullptr) {
42  GUM_CONSTRUCTOR(PRMClass);
43  }
44 
45  template < typename GUM_SCALAR >
48  bool delayInheritance) :
50  _superClass_(&super), _implements_(nullptr),
51  _bijection_(new Bijection< const DiscreteVariable*, const DiscreteVariable* >()) {
53  if (!delayInheritance) {
56  }
57  }
58 
59  template < typename GUM_SCALAR >
61  const Set< PRMInterface< GUM_SCALAR >* >& set,
62  bool delayInheritance) :
64  _superClass_(nullptr), _implements_(new Set< PRMInterface< GUM_SCALAR >* >(set)),
65  _bijection_(nullptr) {
67 
68  if (!delayInheritance) { _implementInterfaces_(false); }
69  }
70 
71  template < typename GUM_SCALAR >
74  const Set< PRMInterface< GUM_SCALAR >* >& set,
75  bool delayInheritance) :
77  _superClass_(&super), _implements_(nullptr),
78  _bijection_(new Bijection< const DiscreteVariable*, const DiscreteVariable* >()) {
80  if (!delayInheritance) {
83  }
84 
85  // Adding other implementation
86  if (_implements_ == nullptr) { // super has not created _implements_
88  } else { // we just add the new implementations
89  for (const auto elt: set) {
91  }
92  }
93 
94  if (!delayInheritance) { _implementInterfaces_(false); }
95  }
96 
97  template < typename GUM_SCALAR >
99  for (const auto impl: *_implements_) {
100  impl->_addImplementation_(this);
101  if ((!_superClass_) || (!super().isSubTypeOf(*impl)) || delayedInheritance) {
102  // Reserve reference id in DAG
103  for (auto ref: impl->referenceSlots()) {
105  }
106  // Reserve attribute id in DAG
107  for (auto attr: impl->attributes()) {
109  }
110  }
111  }
112  }
113 
114  template < typename GUM_SCALAR >
117 
118  for (const auto& elt: _nodeIdMap_) {
119  delete elt.second;
120  }
121 
122  if (_implements_) { delete _implements_; }
123 
124  if (_bijection_) { delete _bijection_; }
125  }
126 
127  template < typename GUM_SCALAR >
129  if (_superClass_) {
131  // Adding implemented interfaces, if any
132  if (_superClass_->_implements_) {
133  if (!_implements_) {
135  } else {
136  for (auto i: *(_superClass_->_implements_)) {
138  }
139  }
140  }
141  }
142  if (_implements_) { _implementInterfaces_(true); }
143  }
144 
145  template < typename GUM_SCALAR >
147  if (_superClass_) {
148  // Copying reference slots
149  for (const auto c_refslot: _superClass_->_referenceSlots_) {
150  auto ref = new PRMReferenceSlot< GUM_SCALAR >(
151  c_refslot->name(),
153  c_refslot->isArray());
154 
155  ref->setId(c_refslot->id());
156  // Not reserved by an interface
157  if (!_dag_.existsNode(ref->id())) { _dag_.addNodeWithId(ref->id()); }
158  _nodeIdMap_.insert(ref->id(), ref);
160 
163  _nameMap_.insert(ref->name(), ref);
164  }
165 
167  }
168  }
169  }
170 
171  template < typename GUM_SCALAR >
173  if (_superClass_) {
174  // Copying parameters
175  for (const auto c_param: _superClass_->_parameters_) {
176  auto param = new PRMParameter< GUM_SCALAR >(c_param->name(),
177  c_param->valueType(),
178  c_param->value());
179 
181 
182  param->setId(c_param->id());
186  }
187  }
188  }
189 
190  template < typename GUM_SCALAR >
192  if (_superClass_) {
193  for (const auto c_attr: _superClass_->_attributes_) {
194  // using multiDimSparse to prevent unecessary memory allocation for
195  // large arrays (the potentials are copied latter)
196  auto attr = c_attr->newFactory(*this);
197 
198  _bijection_->insert(&(c_attr->type().variable()), &(attr->type().variable()));
199  attr->setId(c_attr->id());
200  try {
202  } catch (gum::Exception&) {
203  // Node reserved by an interface
204  }
207 
211  }
212 
214  }
215  }
216  }
217 
218  template < typename GUM_SCALAR >
220  if (_superClass_) {
221  for (const auto c_agg: _superClass_->_aggregates_) {
222  PRMAggregate< GUM_SCALAR >* agg = nullptr;
223 
224  try {
225  agg = new PRMAggregate< GUM_SCALAR >(c_agg->name(),
226  c_agg->agg_type(),
227  c_agg->type(),
228  c_agg->label());
229  } catch (OperationNotAllowed&) {
233  }
234 
235  _bijection_->insert(&(c_agg->type().variable()), &(agg->type().variable()));
236  agg->setId(c_agg->id());
238  _nodeIdMap_.insert(agg->id(), agg);
240 
242  _nameMap_.insert(agg->name(), agg);
243 
245  }
246  }
247  }
248 
249  template < typename GUM_SCALAR >
251  if (_superClass_) {
252  // Copying slot chains
253  for (const auto c_sc: _superClass_->_slotChains_) {
254  // Because of aggregators, some slotchains may exists already
255  if (!(_nameMap_.exists(c_sc->name()) && _nameMap_.exists(c_sc->safeName()))) {
256  // We just need to change the first PRMReferenceSlot<GUM_SCALAR> in
257  // the
258  // chain
259  auto chain = c_sc->chain();
260 
261  chain.setAtPos(0, _nameMap_[c_sc->chain().front()->name()]);
262 
263  auto sc = new PRMSlotChain< GUM_SCALAR >(c_sc->name(), chain);
264  _bijection_->insert(&(c_sc->type().variable()), &(sc->type().variable()));
265  sc->setId(c_sc->id());
266  _dag_.addNodeWithId(sc->id());
267  _nodeIdMap_.insert(sc->id(), sc);
269 
270  if (!_nameMap_.exists(sc->name())) { _nameMap_.insert(sc->name(), sc); }
271  if (!_nameMap_.exists(sc->safeName())) { _nameMap_.insert(sc->safeName(), sc); }
272  }
273  }
274  }
275  }
276 
277  template < typename GUM_SCALAR >
279  if (_superClass_) {
280  auto& elt = this->get(name);
283  GUM_ERROR(OperationNotAllowed, "you can only complete inheritance for attributes")
284  }
285 
286  for (const auto& prnt: super().containerDag().parents(elt.id())) {
287  this->addArc(super().get(prnt).safeName(), elt.safeName());
288  }
289 
291  auto& attr = static_cast< PRMAttribute< GUM_SCALAR >& >(elt);
292  auto& super_attr = static_cast< const PRMAttribute< GUM_SCALAR >& >(super().get(name));
294  }
295  }
296  }
297 
298  template < typename GUM_SCALAR >
300  if (_superClass_) {
302  // Adding implemented interfaces of c, if any
303  if (c._implements_) {
304  if (!_implements_) {
306  } else {
307  for (auto i: *(c._implements_)) {
309  }
310  }
311  }
312 
313  // Copying attributes, the bijection's firsts are attributes in this and
314  // its
315  // seconds are attributes
316  // in c.
318 
319  // Copying parameters
320  for (const auto c_param: c._parameters_) {
321  auto param = new PRMParameter< GUM_SCALAR >(c_param->name(),
322  c_param->valueType(),
323  c_param->value());
324 
326 
327  param->setId(c_param->id());
330  }
331 
332  // Copying attributes
333  for (const auto c_attr: c._attributes_) {
334  // using multiDimSparse to prevent unecessary memory allocation for
335  // large arrays (the potentials are copied latter)
336  auto attr = c_attr->newFactory(*this);
337 
338  bij.insert(&(c_attr->type().variable()), &(attr->type().variable()));
339  attr->setId(c_attr->id());
342 
343  if (c._nameMap_[c_attr->name()] == c._nameMap_[c_attr->safeName()]) {
345  }
346 
348  }
349 
350  // Copying aggregates
351  for (const auto c_agg: c._aggregates_) {
352  PRMAggregate< GUM_SCALAR >* agg = nullptr;
353 
354  try {
355  agg = new PRMAggregate< GUM_SCALAR >(c_agg->name(),
356  c_agg->agg_type(),
357  c_agg->type(),
358  c_agg->label());
359  } catch (OperationNotAllowed&) {
361  }
362 
363  bij.insert(&(c_agg->type().variable()), &(agg->type().variable()));
364  agg->setId(c_agg->id());
365  _nodeIdMap_.insert(agg->id(), agg);
367 
368  if (c._nameMap_[c_agg->name()] == c._nameMap_[c_agg->safeName()])
369  _nameMap_.insert(agg->name(), agg);
370 
372  }
373 
374  // Copying reference slots
375  for (const auto c_refslot: c._referenceSlots_) {
377  c_refslot->name(),
379  c_refslot->isArray());
380 
381  ref->setId(c_refslot->id());
382  _nodeIdMap_.insert(ref->id(), ref);
384 
386  _nameMap_.insert(ref->name(), ref);
387 
389  }
390 
391  // Copying slot chains
392  for (const auto c_slotchain: c._slotChains_) {
393  // We just need to change the first PRMReferenceSlot<GUM_SCALAR> in
394  // the
395  // chain
397 
399 
402  bij.insert(&(c_slotchain->type().variable()), &(sc->type().variable()));
403  sc->setId(c_slotchain->id());
404  _nodeIdMap_.insert(sc->id(), sc);
406 
407  _nameMap_.insert(sc->name(), sc);
409  }
410 
411  // Copying dependencies yield by arcs
412  for (const auto& arc: c.containerDag().arcs()) {
415  }
416 
417  // Copying the IO flag
418  this->copyIOFlags_(c);
419  // Copying content of CPF
420  for (const auto attr: c._attributes_) {
421  auto a = static_cast< PRMAttribute< GUM_SCALAR >* >(_nameMap_[attr->safeName()]);
422  a->copyCpf(bij, *attr);
423  }
424  }
425  }
426 
427  template < typename GUM_SCALAR >
429  const PRMClassElementContainer< GUM_SCALAR >& cec) const {
430  switch (cec.obj_type()) {
431  case PRMObject::prm_type::CLASS: {
432  const PRMClass< GUM_SCALAR >* current = this;
433 
434  while (current != 0) {
435  if (current == &(cec)) return true;
436 
438  }
439 
440  return false;
441  }
442 
444  if (_implements_ != nullptr) {
445  const PRMInterface< GUM_SCALAR >& i
446  = static_cast< const PRMInterface< GUM_SCALAR >& >(cec);
447 
448  if (_implements_->exists(const_cast< PRMInterface< GUM_SCALAR >* >(&i))) return true;
449 
450  for (const auto impl: *_implements_)
451  if (impl->isSubTypeOf(i)) return true;
452  }
453 
454  return false;
455  }
456 
457  default: {
458  GUM_ERROR(FatalError, "unknown ClassElementContainer<GUM_SCALAR>")
459  }
460  }
461  }
462 
463  template < typename GUM_SCALAR >
465  const std::string& head_name) {
468 
469  try {
472  } catch (NotFound&) {
473  GUM_ERROR(NotFound, "tail and/or head of arc does not exists in this Class")
474  }
475 
479  "a PRMReferenceSlot<GUM_SCALAR> can "
480  "not on neither side of an arc");
481  }
482 
486  "illegal insertion of an arc between two SlotChain<GUM_SCALAR>")
487  }
488 
489  if (!_dag_.existsArc(Arc(tail->id(), head->id()))) {
490  _dag_.addArc(tail->id(), head->id());
491  } else {
492  GUM_ERROR(DuplicateElement, "duplicate arc " << tail_name << "->" << head_name)
493  }
494 
495  get(tail->id()).addChild(get(head->id()));
496  get(head->id()).addParent(get(tail->id()));
497 
498  // Defining input / output nodes
500  PRMSlotChain< GUM_SCALAR >* sc = static_cast< PRMSlotChain< GUM_SCALAR >* >(tail);
501  this->setInputNode(*head, true);
502  sc->end().setOutputNode(sc->end().get(sc->lastElt().safeName()), true);
503  }
504  }
505 
506  template < typename GUM_SCALAR >
508  try {
509  for (auto i: implements()) {
510  if (i->exists(elt->name())) { _checkInterface_(elt, i); }
511  }
512  } catch (NotFound&) {
513  // No interface
514  }
515  }
516 
517  template < typename GUM_SCALAR >
519  PRMInterface< GUM_SCALAR >* i) {
520  const auto& i_elt = i->get(elt->name());
523 
524  if (!(is_attr || is_agg)) {
525  GUM_ERROR(OperationNotAllowed, "Class does not respect it's interface")
526  }
527 
528  if (!elt->type().isSubTypeOf(i_elt.type())) {
529  GUM_ERROR(OperationNotAllowed, "Attribute type does not respect class interface")
530  }
531 
532  if (elt->type() != i_elt.type()) {
533  if (!this->exists(i_elt.safeName())) {
534  GUM_ERROR(OperationNotAllowed, "Attribute type does not respect class interface")
535  }
536  elt = &(this->get(i_elt.safeName()));
537  }
538 
539  // Node must be reserved by constructor
540  if (!_dag_.existsNode(i_elt.id())) {
541  GUM_ERROR(FatalError, "Class does not reserved implemented nodes")
542  }
543 
544  // Removing unused node and changing to proper node
545  if (elt->id() != i_elt.id()) {
546  // Update cast descendants
547  for (auto child: _dag_.children(elt->id())) {
548  _dag_.addArc(i_elt.id(), child);
549  }
550  _dag_.eraseNode(elt->id());
551  }
552  _nodeIdMap_.erase(elt->id());
553  elt->setId(i_elt.id());
554  _nodeIdMap_.insert(elt->id(), elt);
555  }
556 
557  template < typename GUM_SCALAR >
559  try {
560  for (auto i: implements()) {
561  if (i->exists(ref->name())) { _checkRefInterface_(ref, i); }
562  }
563  } catch (NotFound&) {
564  // No interface to check
565  }
566  }
567 
568  template < typename GUM_SCALAR >
570  PRMInterface< GUM_SCALAR >* i) {
571  auto& i_elt = i->get(ref->name());
572  if (i_elt.elt_type() != ref->elt_type()) {
573  GUM_ERROR(OperationNotAllowed, "Class does not respect it's interface")
574  }
575  auto& i_ref = static_cast< PRMReferenceSlot< GUM_SCALAR >& >(i_elt);
576  if (!ref->slotType().isSubTypeOf(i_ref.slotType())) {
577  GUM_ERROR(OperationNotAllowed, "ReferenceSlot type does not respect class interface")
578  }
579  // Node must be reserved by constructor
580  if (!_dag_.exists(i_ref.id())) {
582  "class " << this->name() << " does not respect interface " << i->name()
583  << " implementation");
584  }
585  // Removing unused node and changin to propoer node
586  if (ref->id() != i_ref.id()) { _dag_.eraseNode(ref->id()); }
587  _nodeIdMap_.erase(ref->id());
588  ref->setId(i_ref.id());
589  _nodeIdMap_.insert(ref->id(), ref);
590  }
591 
592  template < typename GUM_SCALAR >
594  if (_nameMap_.exists(elt->name())) {
596  "name " << elt->name() << " already used by another ClassElement");
597  }
598 
599  elt->setId(nextNodeId());
601  _nodeIdMap_.insert(elt->id(), elt);
602  _nameMap_.insert(elt->name(), elt);
603 
604  try {
606  } catch (DuplicateElement& e) {
609  throw DuplicateElement(e);
610  }
611  }
612 
613  switch (elt->elt_type()) {
615  _attributes_.insert(static_cast< PRMAttribute< GUM_SCALAR >* >(elt));
616  _addCastDescendants_(static_cast< PRMAttribute< GUM_SCALAR >* >(elt));
617 
618  // Update attribute or cast descendant id to respect implemented
619  // interface
621 
623  break;
624  }
625 
627  _aggregates_.insert(static_cast< PRMAggregate< GUM_SCALAR >* >(elt));
628  _addCastDescendants_(static_cast< PRMAttribute< GUM_SCALAR >* >(elt));
629 
630  // Update attribute or cast descendant id to respect implemented
631  // interface
633 
635  break;
636  }
637 
639  auto ref = static_cast< PRMReferenceSlot< GUM_SCALAR >* >(elt);
641 
642  // Updating ref's id if ref implements an interface
644  break;
645  }
646 
648  _slotChains_.insert(static_cast< PRMSlotChain< GUM_SCALAR >* >(elt));
649  break;
650  }
651 
653  _parameters_.insert(static_cast< PRMParameter< GUM_SCALAR >* >(elt));
654  break;
655  }
656 
657  default: {
658  GUM_ERROR(FatalError, "unknown ClassElement<GUM_SCALAR> type")
659  }
660  }
661 
662  return elt->id();
663  }
664 
665  template < typename GUM_SCALAR >
667  auto parent = attr;
668  PRMAttribute< GUM_SCALAR >* child = 0;
669 
670  while (parent->type().isSubType()) {
672 
673  // Check if id was reserved by one of the class interfaces
674  bool found = false;
675  try {
676  for (auto i: implements()) {
677  if (i->exists(child->safeName())) {
678  child->setId(i->get(child->safeName()).id());
679  found = true;
680  break;
681  }
682  }
683  } catch (NotFound&) {
684  // No interface
685  }
686  if (!found) {
687  child->setId(nextNodeId());
689  }
691  // Only use child's safe name when adding to the name map!
694  // Do not use Class<GUM_SCALAR>::insertArc(), child's CPF is already
695  // initialized properly
696  _dag_.addArc(parent->id(), child->id());
697 
698  parent = child;
699  }
700  }
701 
702  template < typename GUM_SCALAR >
704  try {
705  if (!super().exists(overloader->name())) {
706  GUM_ERROR(OperationNotAllowed, "found no ClassElement<GUM_SCALAR> to overload")
707  }
708  } catch (NotFound&) {
709  GUM_ERROR(OperationNotAllowed, "overload is possible only with subclasses")
710  }
711 
713  if (overloaded == overloader) {
714  GUM_ERROR(DuplicateElement, "dupplicate ClassElement " << overloader->name())
715  }
716  // Checking overload legality
718  GUM_ERROR(OperationNotAllowed, "illegal overload")
719  }
720 
721  switch (overloader->elt_type()) {
723  auto overloader_attr = static_cast< PRMAttribute< GUM_SCALAR >* >(overloader);
724  auto overloaded_attr = static_cast< PRMAttribute< GUM_SCALAR >* >(overloaded);
727  break;
728  }
729 
733  break;
734  }
735 
737  // _checkOverloadLegality_ guaranties that overloaded is a
738  // PRMReferenceSlot<GUM_SCALAR>
739  auto overloader_ref = static_cast< PRMReferenceSlot< GUM_SCALAR >* >(overloader);
740  auto overloaded_ref = static_cast< PRMReferenceSlot< GUM_SCALAR >* >(overloaded);
742  break;
743  }
744 
746  GUM_ERROR(OperationNotAllowed, "SlotChain<GUM_SCALAR> can not be overloaded")
747  break;
748  }
749 
751  auto overloaded_param = static_cast< PRMParameter< GUM_SCALAR >* >(overloaded);
752  auto overloader_param = static_cast< PRMParameter< GUM_SCALAR >* >(overloader);
754  break;
755  }
756  default: {
757  GUM_ERROR(OperationNotAllowed, "unknown ClassElement<GUM_SCALAR> type")
758  }
759  }
760 
761  return overloader->id();
762  }
763 
764  template < typename GUM_SCALAR >
768 
769  // Checking if we have to add cast descendant
770  if (overloader->type() != overloaded->type()) {
778  } else {
786  delete overloaded;
787  }
788  }
789 
790  template < typename GUM_SCALAR >
793  // Adding overloading reference
799  PRMSlotChain< GUM_SCALAR >* sc = 0;
803 
804  // Updating PRMSlotChain<GUM_SCALAR> which started with overloaded
805  for (const auto slotchain: _slotChains_) {
806  // If the attribute pointed by this slotchain is overloaded, we need to
807  // change the slotchain
808  // names to it's safename version: ref.attr is replaced by
809  // ref.(type)attr.
810  if ((slotchain->chain().atPos(0) == overloaded)) {
813 
814  auto elt = ++(slotchain->chain().begin());
815 
816  while (elt != slotchain->chain().end()) {
817  ref = static_cast< PRMReferenceSlot< GUM_SCALAR >* >(seq.back());
818  next = &(ref->slotType().get((*elt)->name()));
819  seq.insert(next);
820  ++elt;
821  }
822 
823  // If the slotchain last element type changes, we change the slotchain
824  // to
825  // point towards the cast decendant
826  // with the correct type
827  if (seq.back()->type() != slotchain->lastElt().type()) {
828  seq.erase(seq.back());
829  seq.insert(&(static_cast< PRMReferenceSlot< GUM_SCALAR >* >(seq.back())
830  ->slotType()
831  .get(slotchain->lastElt().safeName())));
832  std::string sc_name;
833  std::string dot = ".";
834 
835  for (Size i = 0; i < seq.size() - 1; ++i) {
836  sc_name += seq.atPos(i)->name() + dot;
837  }
838 
839  sc_name += seq.back()->safeName();
840  sc = new PRMSlotChain< GUM_SCALAR >(sc_name, seq);
841  sc->setId(slotchain->id());
842 
843  for (const auto child: this->containerDag().children(sc->id())) {
844  auto& elt = get(child);
846  auto& attr = static_cast< PRMAttribute< GUM_SCALAR >& >(elt);
847  auto& old_type = slotchain->lastElt().type();
848  auto& new_type = sc->lastElt().type();
850  } else {
851  GUM_ERROR(OperationNotAllowed, "unexpected ClassElement")
852  // get( child ).cpf().replace(
853  // slotchain->lastElt().type().variable(),
854  // sc->lastElt().type().variable() );
855  }
856  }
857 
858  toAdd.push_back(sc);
860  } else {
861  // Types are identical, we just need to change the first reference
863  }
864  }
865  }
866 
867  for (const auto torem: toRemove) {
870  delete torem;
871  }
872 
873  for (const auto toadd: toAdd) {
875  _nodeIdMap_[toadd->id()] = toadd;
877  }
878 
879  // Removing overloaded PRMReferenceSlot<GUM_SCALAR>
882  delete overloaded;
883  }
884 
885  template < typename GUM_SCALAR >
894  delete overloaded;
895  }
896 
897  template < typename GUM_SCALAR >
901  PRMAttribute< GUM_SCALAR >* child = 0;
902 
903  while (parent->type().superType() != end->type()) {
905  child->setId(nextNodeId());
908  // Only use child's safe name when adding to the name map!
912  // Do not use Class<GUM_SCALAR>::insertArc(), child's CPF is already
913  // initialized properly
914  _dag_.addArc(parent->id(), child->id());
915  parent = child;
916  }
917 
919  _dag_.addArc(parent->id(), end->id());
920  }
921 
922  template < typename GUM_SCALAR >
925  for (auto ext: _extensions_) {
926  set.insert(ext);
928  }
929  }
930 
931  template < typename GUM_SCALAR >
933  // We only add IO Flags if elt matches is required by and interface
934  if (_implements_ != nullptr) {
935  for (const auto impl: *_implements_) {
937  while (super) {
938  // If the attribute is defined in an interface, we set it as an
939  // OutputNode
940  if (impl->exists(elt->name())) {
941  try {
942  this->getIOFlag_(*elt).second = true;
943  } catch (NotFound&) { this->setIOFlag_(*elt, std::make_pair(false, true)); }
944  }
945  try {
946  super = &(super->super());
947  } catch (NotFound&) { super = nullptr; }
948  }
949  }
950  }
951  }
952 
953  template < typename GUM_SCALAR >
955  // for ( const auto ext : _extensions_ ) {
956  // // We test to prevent unnecessary recursive call from iter
957  // if ( !ext->isOutputNode( elt ) ) {
958  // ext->setOutputNode( elt, true );
959  // }
960  //}
961  }
962 
963  template < typename GUM_SCALAR >
965  return PRMObject::prm_type::CLASS;
966  }
967 
968  template < typename GUM_SCALAR >
969  INLINE const DAG& PRMClass< GUM_SCALAR >::dag_() const {
970  return _dag_;
971  }
972 
973  template < typename GUM_SCALAR >
975  return _dag_;
976  }
977 
978  template < typename GUM_SCALAR >
980  try {
981  return *(_nodeIdMap_[id]);
982  } catch (NotFound&) {
983  GUM_ERROR(NotFound, "no ClassElement<GUM_SCALAR> with the given NodeId")
984  }
985  }
986 
987  template < typename GUM_SCALAR >
989  try {
990  return *(_nodeIdMap_[id]);
991  } catch (NotFound&) {
992  GUM_ERROR(NotFound, "no ClassElement<GUM_SCALAR> with the given NodeId (" << id << ")");
993  }
994  }
995 
996  template < typename GUM_SCALAR >
998  try {
999  return *(_nameMap_[name]);
1000  } catch (NotFound&) {
1001  GUM_ERROR(NotFound, "no ClassElement<GUM_SCALAR> with the given name (" << name << ")");
1002  }
1003  }
1004 
1005  template < typename GUM_SCALAR >
1007  PRMClass< GUM_SCALAR >::get(const std::string& name) const {
1008  try {
1009  return *(_nameMap_[name]);
1010  } catch (NotFound&) {
1011  GUM_ERROR(NotFound, "no ClassElement<GUM_SCALAR> with the given name (" << name << ")");
1012  }
1013  }
1014 
1015  template < typename GUM_SCALAR >
1017  return _attributes_;
1018  }
1019 
1020  template < typename GUM_SCALAR >
1022  return _parameters_;
1023  }
1024 
1025  // Private struct for retrieving all params in scope
1026  template < typename GUM_SCALAR >
1029  const PRMClass< GUM_SCALAR >* c;
1031 
1033  prefix(s + ref.name() + "."),
1034  c(static_cast< const PRMClass< GUM_SCALAR >* >(&(ref.slotType()))), depth(d) {}
1035  };
1036 
1037  template < typename GUM_SCALAR >
1038  INLINE HashTable< std::string, const PRMParameter< GUM_SCALAR >* >
1039  PRMClass< GUM_SCALAR >::scope() const {
1041 
1042  for (const auto p: parameters()) {
1043  params.insert(p->name(), p);
1044  }
1045 
1047 
1048  for (const auto ref: referenceSlots()) {
1049  if (PRMObject::isClass(ref->slotType())) {
1050  queue.push(ParamScopeData< GUM_SCALAR >("", *ref, 1));
1051  }
1052  }
1053 
1054  while (!queue.empty()) {
1055  auto data = queue.front();
1056  queue.pop();
1057 
1058  if (data.depth < 5) {
1059  for (const auto p: data.c->parameters()) {
1060  params.insert(data.prefix + p->name(), p);
1061  }
1062 
1063  for (const auto ref: data.c->referenceSlots()) {
1064  if (PRMObject::isClass(ref->slotType())) {
1066  }
1067  }
1068  } else {
1069  // @todo depth>5 is a workaround. Cycle detection is needed here !
1070  GUM_ERROR(FatalError, "Depth limit reached when looking up parameters")
1071  }
1072  }
1073 
1074  return params;
1075  }
1076 
1077  template < typename GUM_SCALAR >
1079  return _aggregates_;
1080  }
1081 
1082  template < typename GUM_SCALAR >
1083  INLINE const Set< PRMReferenceSlot< GUM_SCALAR >* >&
1085  return _referenceSlots_;
1086  }
1087 
1088  template < typename GUM_SCALAR >
1090  return _slotChains_;
1091  }
1092 
1093  template < typename GUM_SCALAR >
1095  if (_superClass_) {
1096  return *_superClass_;
1097  } else {
1098  GUM_ERROR(NotFound, "this Class is not a subclass")
1099  }
1100  }
1101 
1102  template < typename GUM_SCALAR >
1104  if (_implements_) {
1105  return *_implements_;
1106  } else {
1107  GUM_ERROR(NotFound, "this Class does not implement any Interface<GUM_SCALAR>")
1108  }
1109  }
1110 
1111  template < typename GUM_SCALAR >
1113  return get(id);
1114  }
1115 
1116  template < typename GUM_SCALAR >
1119  return get(id);
1120  }
1121 
1122  template < typename GUM_SCALAR >
1125  return get(name);
1126  }
1127 
1128  template < typename GUM_SCALAR >
1130  PRMClass< GUM_SCALAR >::operator[](const std::string& name) const {
1131  return get(name);
1132  }
1133 
1134  template < typename GUM_SCALAR >
1135  INLINE void
1140  }
1141 
1142  template < typename GUM_SCALAR >
1146  if (overloaded->elt_type() != overloader->elt_type()) { return false; }
1147 
1148  switch (overloaded->elt_type()) {
1150  if (!overloader->type().isSubTypeOf(overloaded->type())) { return false; }
1151  break;
1152  }
1153 
1155  const auto& new_slot_type
1156  = static_cast< const PRMReferenceSlot< GUM_SCALAR >* >(overloader)->slotType();
1157  const auto& old_slot_type
1158  = static_cast< const PRMReferenceSlot< GUM_SCALAR >* >(overloaded)->slotType();
1159 
1160  if (!new_slot_type.isSubTypeOf(old_slot_type)) { return false; }
1161 
1162  break;
1163  }
1164 
1166  auto overloaded_param = static_cast< const PRMParameter< GUM_SCALAR >* >(overloaded);
1167  auto overloader_param = static_cast< const PRMParameter< GUM_SCALAR >* >(overloader);
1168 
1170  break;
1171  }
1172 
1173  default: {
1174  return false;
1175  }
1176  }
1177  return true;
1178  }
1179 
1180  template < typename GUM_SCALAR >
1182  return _extensions_;
1183  }
1184 
1185  template < typename GUM_SCALAR >
1188  }
1189 
1190  template < typename GUM_SCALAR >
1193 
1194  try {
1195  return elt.type().name() == get(elt.name()).type().name();
1196  } catch (OperationNotAllowed&) { GUM_ERROR(NotFound, "no attribute with the given name") }
1197  }
1198 
1199  template < typename GUM_SCALAR >
1200  INLINE bool
1202  try {
1203  if (!this->getIOFlag_(elt).second) {
1204  if (_implements_) {
1205  for (auto i: *_implements_) {
1206  if (i->isOutputNode(elt)) { return true; }
1207  }
1208  }
1209 
1210  if (_superClass_ && (_superClass_->isOutputNode(elt))) { return true; }
1211 
1212  } else {
1213  return true;
1214  }
1215  } catch (NotFound&) {}
1216  return false;
1217  }
1218 
1219 
1220  } /* namespace prm */
1221 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
ParamScopeData(const std::string &s, const PRMReferenceSlot< GUM_SCALAR > &ref, Idx d)