aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
PRMClass_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /**
23  * @file
24  * @brief 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),
41  implements__(nullptr), bijection__(nullptr) {
42  GUM_CONSTRUCTOR(PRMClass);
43  }
44 
45  template < typename GUM_SCALAR >
48  bool delayInheritance) :
50  superClass__(&super), implements__(nullptr),
52  new Bijection< const DiscreteVariable*, const DiscreteVariable* >()) {
54  if (!delayInheritance) {
57  }
58  }
59 
60  template < typename GUM_SCALAR >
62  const Set< PRMInterface< GUM_SCALAR >* >& set,
63  bool delayInheritance) :
65  superClass__(nullptr),
67  bijection__(nullptr) {
69 
70  if (!delayInheritance) { implementInterfaces__(false); }
71  }
72 
73  template < typename GUM_SCALAR >
76  const Set< PRMInterface< GUM_SCALAR >* >& set,
77  bool delayInheritance) :
79  superClass__(&super), implements__(nullptr),
81  new Bijection< const DiscreteVariable*, const DiscreteVariable* >()) {
83  if (!delayInheritance) {
86  }
87 
88  // Adding other implementation
89  if (implements__ == nullptr) { // super has not created implements__
91  } else { // we just add the new implementations
92  for (const auto elt: set) {
94  }
95  }
96 
97  if (!delayInheritance) { implementInterfaces__(false); }
98  }
99 
100  template < typename GUM_SCALAR >
102  for (const auto impl: *implements__) {
103  impl->addImplementation__(this);
104  if ((!superClass__) || (!super().isSubTypeOf(*impl))
105  || delayedInheritance) {
106  // Reserve reference id in DAG
107  for (auto ref: impl->referenceSlots()) {
109  }
110  // Reserve attribute id in DAG
111  for (auto attr: impl->attributes()) {
113  }
114  }
115  }
116  }
117 
118  template < typename GUM_SCALAR >
121 
122  for (const auto& elt: nodeIdMap__) {
123  delete elt.second;
124  }
125 
126  if (implements__) { delete implements__; }
127 
128  if (bijection__) { delete bijection__; }
129  }
130 
131  template < typename GUM_SCALAR >
133  if (superClass__) {
135  // Adding implemented interfaces, if any
136  if (superClass__->implements__) {
137  if (!implements__) {
140  } else {
141  for (auto i: *(superClass__->implements__)) {
143  }
144  }
145  }
146  }
147  if (implements__) { implementInterfaces__(true); }
148  }
149 
150  template < typename GUM_SCALAR >
152  if (superClass__) {
153  // Copying reference slots
154  for (const auto c_refslot: superClass__->referenceSlots__) {
155  auto ref = new PRMReferenceSlot< GUM_SCALAR >(
156  c_refslot->name(),
157  const_cast< PRMClassElementContainer< GUM_SCALAR >& >(
158  c_refslot->slotType()),
159  c_refslot->isArray());
160 
161  ref->setId(c_refslot->id());
162  // Not reserved by an interface
163  if (!dag__.existsNode(ref->id())) { dag__.addNodeWithId(ref->id()); }
164  nodeIdMap__.insert(ref->id(), ref);
166 
169  nameMap__.insert(ref->name(), ref);
170  }
171 
173  }
174  }
175  }
176 
177  template < typename GUM_SCALAR >
179  if (superClass__) {
180  // Copying parameters
181  for (const auto c_param: superClass__->parameters__) {
182  auto param = new PRMParameter< GUM_SCALAR >(c_param->name(),
183  c_param->valueType(),
184  c_param->value());
185 
187 
188  param->setId(c_param->id());
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 
205  &(attr->type().variable()));
206  attr->setId(c_attr->id());
207  try {
209  } catch (gum::Exception&) {
210  // Node reserved by an interface
211  }
214 
218  }
219 
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 >(c_agg->name(),
233  c_agg->agg_type(),
234  c_agg->type(),
235  c_agg->label());
236  } catch (OperationNotAllowed&) {
237  agg = new PRMAggregate< GUM_SCALAR >(c_agg->name(),
238  c_agg->agg_type(),
239  c_agg->type());
242  }
243 
245  &(agg->type().variable()));
246  agg->setId(c_agg->id());
248  nodeIdMap__.insert(agg->id(), agg);
250 
253  nameMap__.insert(agg->name(), agg);
254 
256  }
257  }
258  }
259 
260  template < typename GUM_SCALAR >
262  if (superClass__) {
263  // Copying slot chains
264  for (const auto c_sc: superClass__->slotChains__) {
265  // Because of aggregators, some slotchains may exists already
266  if (!(nameMap__.exists(c_sc->name())
267  && nameMap__.exists(c_sc->safeName()))) {
268  // We just need to change the first PRMReferenceSlot<GUM_SCALAR> in
269  // the
270  // chain
271  auto chain = c_sc->chain();
272 
273  chain.setAtPos(0, nameMap__[c_sc->chain().front()->name()]);
274 
275  auto sc = new PRMSlotChain< GUM_SCALAR >(c_sc->name(), chain);
277  &(sc->type().variable()));
278  sc->setId(c_sc->id());
279  dag__.addNodeWithId(sc->id());
280  nodeIdMap__.insert(sc->id(), sc);
282 
283  if (!nameMap__.exists(sc->name())) {
284  nameMap__.insert(sc->name(), sc);
285  }
286  if (!nameMap__.exists(sc->safeName())) {
288  }
289  }
290  }
291  }
292  }
293 
294  template < typename GUM_SCALAR >
296  if (superClass__) {
297  auto& elt = this->get(name);
301  "you can only complete inheritance for attributes");
302  }
303 
304  for (const auto& prnt: super().containerDag().parents(elt.id())) {
305  this->addArc(super().get(prnt).safeName(), elt.safeName());
306  }
307 
309  auto& attr = static_cast< PRMAttribute< GUM_SCALAR >& >(elt);
310  auto& super_attr
311  = static_cast< const PRMAttribute< GUM_SCALAR >& >(super().get(name));
313  }
314  }
315  }
316 
317  template < typename GUM_SCALAR >
319  if (superClass__) {
321  // Adding implemented interfaces of c, if any
322  if (c.implements__) {
323  if (!implements__) {
325  = new Set< PRMInterface< GUM_SCALAR >* >(*(c.implements__));
326  } else {
327  for (auto i: *(c.implements__)) {
329  }
330  }
331  }
332 
333  // Copying attributes, the bijection's firsts are attributes in this and
334  // its
335  // seconds are attributes
336  // in c.
338 
339  // Copying parameters
340  for (const auto c_param: c.parameters__) {
341  auto param = new PRMParameter< GUM_SCALAR >(c_param->name(),
342  c_param->valueType(),
343  c_param->value());
344 
346 
347  param->setId(c_param->id());
350  }
351 
352  // Copying attributes
353  for (const auto c_attr: c.attributes__) {
354  // using multiDimSparse to prevent unecessary memory allocation for
355  // large arrays (the potentials are copied latter)
356  auto attr = c_attr->newFactory(*this);
357 
358  bij.insert(&(c_attr->type().variable()), &(attr->type().variable()));
359  attr->setId(c_attr->id());
362 
363  if (c.nameMap__[c_attr->name()] == c.nameMap__[c_attr->safeName()]) {
365  }
366 
368  }
369 
370  // Copying aggregates
371  for (const auto c_agg: c.aggregates__) {
372  PRMAggregate< GUM_SCALAR >* agg = nullptr;
373 
374  try {
375  agg = new PRMAggregate< GUM_SCALAR >(c_agg->name(),
376  c_agg->agg_type(),
377  c_agg->type(),
378  c_agg->label());
379  } catch (OperationNotAllowed&) {
380  agg = new PRMAggregate< GUM_SCALAR >(c_agg->name(),
381  c_agg->agg_type(),
382  c_agg->type());
383  }
384 
385  bij.insert(&(c_agg->type().variable()), &(agg->type().variable()));
386  agg->setId(c_agg->id());
387  nodeIdMap__.insert(agg->id(), agg);
389 
390  if (c.nameMap__[c_agg->name()] == c.nameMap__[c_agg->safeName()])
391  nameMap__.insert(agg->name(), agg);
392 
394  }
395 
396  // Copying reference slots
397  for (const auto c_refslot: c.referenceSlots__) {
399  c_refslot->name(),
400  const_cast< PRMClassElementContainer< GUM_SCALAR >& >(
401  c_refslot->slotType()),
402  c_refslot->isArray());
403 
404  ref->setId(c_refslot->id());
405  nodeIdMap__.insert(ref->id(), ref);
407 
409  nameMap__.insert(ref->name(), ref);
410 
412  }
413 
414  // Copying slot chains
415  for (const auto c_slotchain: c.slotChains__) {
416  // We just need to change the first PRMReferenceSlot<GUM_SCALAR> in
417  // the
418  // chain
420 
422 
425  bij.insert(&(c_slotchain->type().variable()), &(sc->type().variable()));
426  sc->setId(c_slotchain->id());
427  nodeIdMap__.insert(sc->id(), sc);
429 
430  nameMap__.insert(sc->name(), sc);
432  }
433 
434  // Copying dependencies yield by arcs
435  for (const auto& arc: c.containerDag().arcs()) {
438  }
439 
440  // Copying the IO flag
441  this->copyIOFlags_(c);
442  // Copying content of CPF
443  for (const auto attr: c.attributes__) {
444  auto a = static_cast< PRMAttribute< GUM_SCALAR >* >(
445  nameMap__[attr->safeName()]);
446  a->copyCpf(bij, *attr);
447  }
448  }
449  }
450 
451  template < typename GUM_SCALAR >
453  const PRMClassElementContainer< GUM_SCALAR >& cec) const {
454  switch (cec.obj_type()) {
455  case PRMObject::prm_type::CLASS: {
456  const PRMClass< GUM_SCALAR >* current = this;
457 
458  while (current != 0) {
459  if (current == &(cec)) return true;
460 
462  }
463 
464  return false;
465  }
466 
468  if (implements__ != nullptr) {
469  const PRMInterface< GUM_SCALAR >& i
470  = static_cast< const PRMInterface< GUM_SCALAR >& >(cec);
471 
472  if (implements__->exists(
473  const_cast< PRMInterface< GUM_SCALAR >* >(&i)))
474  return true;
475 
476  for (const auto impl: *implements__)
477  if (impl->isSubTypeOf(i)) return true;
478  }
479 
480  return false;
481  }
482 
483  default: {
484  GUM_ERROR(FatalError, "unknown ClassElementContainer<GUM_SCALAR>");
485  }
486  }
487  }
488 
489  template < typename GUM_SCALAR >
491  const std::string& head_name) {
494 
495  try {
498  } catch (NotFound&) {
500  "tail and/or head of arc does not exists in this Class");
501  }
502 
506  "a PRMReferenceSlot<GUM_SCALAR> can "
507  "not on neither side of an arc");
508  }
509 
513  "illegal insertion of an arc between two SlotChain<GUM_SCALAR>");
514  }
515 
516  if (!dag__.existsArc(Arc(tail->id(), head->id()))) {
517  dag__.addArc(tail->id(), head->id());
518  } else {
520  "duplicate arc " << tail_name << "->" << head_name);
521  }
522 
523  get(tail->id()).addChild(get(head->id()));
524  get(head->id()).addParent(get(tail->id()));
525 
526  // Defining input / output nodes
529  = static_cast< PRMSlotChain< GUM_SCALAR >* >(tail);
530  this->setInputNode(*head, true);
531  sc->end().setOutputNode(sc->end().get(sc->lastElt().safeName()), true);
532  }
533  }
534 
535  template < typename GUM_SCALAR >
538  try {
539  for (auto i: implements()) {
540  if (i->exists(elt->name())) { checkInterface__(elt, i); }
541  }
542  } catch (NotFound&) {
543  // No interface
544  }
545  }
546 
547  template < typename GUM_SCALAR >
548  void
550  PRMInterface< GUM_SCALAR >* i) {
551  const auto& i_elt = i->get(elt->name());
554 
555  if (!(is_attr || is_agg)) {
556  GUM_ERROR(OperationNotAllowed, "Class does not respect it's interface");
557  }
558 
559  if (!elt->type().isSubTypeOf(i_elt.type())) {
561  "Attribute type does not respect class interface");
562  }
563 
564  if (elt->type() != i_elt.type()) {
565  if (!this->exists(i_elt.safeName())) {
567  "Attribute type does not respect class interface");
568  }
569  elt = &(this->get(i_elt.safeName()));
570  }
571 
572  // Node must be reserved by constructor
573  if (!dag__.existsNode(i_elt.id())) {
574  GUM_ERROR(FatalError, "Class does not reserved implemented nodes");
575  }
576 
577  // Removing unused node and changing to proper node
578  if (elt->id() != i_elt.id()) {
579  // Update cast descendants
580  for (auto child: dag__.children(elt->id())) {
581  dag__.addArc(i_elt.id(), child);
582  }
583  dag__.eraseNode(elt->id());
584  }
585  nodeIdMap__.erase(elt->id());
586  elt->setId(i_elt.id());
587  nodeIdMap__.insert(elt->id(), elt);
588  }
589 
590  template < typename GUM_SCALAR >
593  try {
594  for (auto i: implements()) {
595  if (i->exists(ref->name())) { checkRefInterface__(ref, i); }
596  }
597  } catch (NotFound&) {
598  // No interface to check
599  }
600  }
601 
602  template < typename GUM_SCALAR >
605  PRMInterface< GUM_SCALAR >* i) {
606  auto& i_elt = i->get(ref->name());
607  if (i_elt.elt_type() != ref->elt_type()) {
608  GUM_ERROR(OperationNotAllowed, "Class does not respect it's interface");
609  }
610  auto& i_ref = static_cast< PRMReferenceSlot< GUM_SCALAR >& >(i_elt);
611  if (!ref->slotType().isSubTypeOf(i_ref.slotType())) {
613  "ReferenceSlot type does not respect class interface");
614  }
615  // Node must be reserved by constructor
616  if (!dag__.exists(i_ref.id())) {
618  "class " << this->name() << " does not respect interface "
619  << i->name() << " implementation");
620  }
621  // Removing unused node and changin to propoer node
622  if (ref->id() != i_ref.id()) { dag__.eraseNode(ref->id()); }
623  nodeIdMap__.erase(ref->id());
624  ref->setId(i_ref.id());
625  nodeIdMap__.insert(ref->id(), ref);
626  }
627 
628  template < typename GUM_SCALAR >
630  if (nameMap__.exists(elt->name())) {
632  "name " << elt->name()
633  << " already used by another ClassElement");
634  }
635 
636  elt->setId(nextNodeId());
638  nodeIdMap__.insert(elt->id(), elt);
639  nameMap__.insert(elt->name(), elt);
640 
641  try {
643  } catch (DuplicateElement& e) {
646  throw DuplicateElement(e);
647  }
648  }
649 
650  switch (elt->elt_type()) {
652  attributes__.insert(static_cast< PRMAttribute< GUM_SCALAR >* >(elt));
653  addCastDescendants__(static_cast< PRMAttribute< GUM_SCALAR >* >(elt));
654 
655  // Update attribute or cast descendant id to respect implemented
656  // interface
658 
660  break;
661  }
662 
664  aggregates__.insert(static_cast< PRMAggregate< GUM_SCALAR >* >(elt));
665  addCastDescendants__(static_cast< PRMAttribute< GUM_SCALAR >* >(elt));
666 
667  // Update attribute or cast descendant id to respect implemented
668  // interface
670 
672  break;
673  }
674 
676  auto ref = static_cast< PRMReferenceSlot< GUM_SCALAR >* >(elt);
678 
679  // Updating ref's id if ref implements an interface
681  break;
682  }
683 
685  slotChains__.insert(static_cast< PRMSlotChain< GUM_SCALAR >* >(elt));
686  break;
687  }
688 
690  parameters__.insert(static_cast< PRMParameter< GUM_SCALAR >* >(elt));
691  break;
692  }
693 
694  default: {
695  GUM_ERROR(FatalError, "unknown ClassElement<GUM_SCALAR> type");
696  }
697  }
698 
699  return elt->id();
700  }
701 
702  template < typename GUM_SCALAR >
705  auto parent = attr;
706  PRMAttribute< GUM_SCALAR >* child = 0;
707 
708  while (parent->type().isSubType()) {
710 
711  // Check if id was reserved by one of the class interfaces
712  bool found = false;
713  try {
714  for (auto i: implements()) {
715  if (i->exists(child->safeName())) {
716  child->setId(i->get(child->safeName()).id());
717  found = true;
718  break;
719  }
720  }
721  } catch (NotFound&) {
722  // No interface
723  }
724  if (!found) {
725  child->setId(nextNodeId());
727  }
729  // Only use child's safe name when adding to the name map!
732  // Do not use Class<GUM_SCALAR>::insertArc(), child's CPF is already
733  // initialized properly
734  dag__.addArc(parent->id(), child->id());
735 
736  parent = child;
737  }
738  }
739 
740  template < typename GUM_SCALAR >
743  try {
744  if (!super().exists(overloader->name())) {
746  "found no ClassElement<GUM_SCALAR> to overload");
747  }
748  } catch (NotFound&) {
750  "overload is possible only with subclasses");
751  }
752 
754  if (overloaded == overloader) {
756  "dupplicate ClassElement " << overloader->name());
757  }
758  // Checking overload legality
760  GUM_ERROR(OperationNotAllowed, "illegal overload");
761  }
762 
763  switch (overloader->elt_type()) {
765  auto overloader_attr
766  = static_cast< PRMAttribute< GUM_SCALAR >* >(overloader);
767  auto overloaded_attr
768  = static_cast< PRMAttribute< GUM_SCALAR >* >(overloaded);
771  break;
772  }
773 
776  static_cast< PRMAggregate< GUM_SCALAR >* >(overloader),
777  overloaded);
779  break;
780  }
781 
783  // checkOverloadLegality__ guaranties that overloaded is a
784  // PRMReferenceSlot<GUM_SCALAR>
785  auto overloader_ref
786  = static_cast< PRMReferenceSlot< GUM_SCALAR >* >(overloader);
787  auto overloaded_ref
788  = static_cast< PRMReferenceSlot< GUM_SCALAR >* >(overloaded);
790  break;
791  }
792 
795  "SlotChain<GUM_SCALAR> can not be overloaded");
796  break;
797  }
798 
800  auto overloaded_param
801  = static_cast< PRMParameter< GUM_SCALAR >* >(overloaded);
802  auto overloader_param
803  = static_cast< PRMParameter< GUM_SCALAR >* >(overloader);
805  break;
806  }
807  default: {
808  GUM_ERROR(OperationNotAllowed, "unknown ClassElement<GUM_SCALAR> type");
809  }
810  }
811 
812  return overloader->id();
813  }
814 
815  template < typename GUM_SCALAR >
820 
821  // Checking if we have to add cast descendant
822  if (overloader->type() != overloaded->type()) {
830  } else {
838  delete overloaded;
839  }
840  }
841 
842  template < typename GUM_SCALAR >
846  // Adding overloading reference
852  PRMSlotChain< GUM_SCALAR >* sc = 0;
856 
857  // Updating PRMSlotChain<GUM_SCALAR> which started with overloaded
858  for (const auto slotchain: slotChains__) {
859  // If the attribute pointed by this slotchain is overloaded, we need to
860  // change the slotchain
861  // names to it's safename version: ref.attr is replaced by
862  // ref.(type)attr.
863  if ((slotchain->chain().atPos(0) == overloaded)) {
866 
867  auto elt = ++(slotchain->chain().begin());
868 
869  while (elt != slotchain->chain().end()) {
870  ref = static_cast< PRMReferenceSlot< GUM_SCALAR >* >(seq.back());
871  next = &(ref->slotType().get((*elt)->name()));
872  seq.insert(next);
873  ++elt;
874  }
875 
876  // If the slotchain last element type changes, we change the slotchain
877  // to
878  // point towards the cast decendant
879  // with the correct type
880  if (seq.back()->type() != slotchain->lastElt().type()) {
881  seq.erase(seq.back());
882  seq.insert(&(static_cast< PRMReferenceSlot< GUM_SCALAR >* >(seq.back())
883  ->slotType()
884  .get(slotchain->lastElt().safeName())));
885  std::string sc_name;
886  std::string dot = ".";
887 
888  for (Size i = 0; i < seq.size() - 1; ++i) {
889  sc_name += seq.atPos(i)->name() + dot;
890  }
891 
892  sc_name += seq.back()->safeName();
893  sc = new PRMSlotChain< GUM_SCALAR >(sc_name, seq);
894  sc->setId(slotchain->id());
895 
896  for (const auto child: this->containerDag().children(sc->id())) {
897  auto& elt = get(child);
899  auto& attr = static_cast< PRMAttribute< GUM_SCALAR >& >(elt);
900  auto& old_type = slotchain->lastElt().type();
901  auto& new_type = sc->lastElt().type();
903  } else {
904  GUM_ERROR(OperationNotAllowed, "unexpected ClassElement");
905  // get( child ).cpf().replace(
906  // slotchain->lastElt().type().variable(),
907  // sc->lastElt().type().variable() );
908  }
909  }
910 
911  toAdd.push_back(sc);
913  } else {
914  // Types are identical, we just need to change the first reference
916  }
917  }
918  }
919 
920  for (const auto torem: toRemove) {
923  delete torem;
924  }
925 
926  for (const auto toadd: toAdd) {
928  nodeIdMap__[toadd->id()] = toadd;
930  }
931 
932  // Removing overloaded PRMReferenceSlot<GUM_SCALAR>
935  delete overloaded;
936  }
937 
938  template < typename GUM_SCALAR >
948  delete overloaded;
949  }
950 
951  template < typename GUM_SCALAR >
956  PRMAttribute< GUM_SCALAR >* child = 0;
957 
958  while (parent->type().superType() != end->type()) {
960  child->setId(nextNodeId());
963  // Only use child's safe name when adding to the name map!
967  // Do not use Class<GUM_SCALAR>::insertArc(), child's CPF is already
968  // initialized properly
969  dag__.addArc(parent->id(), child->id());
970  parent = child;
971  }
972 
974  dag__.addArc(parent->id(), end->id());
975  }
976 
977  template < typename GUM_SCALAR >
980  for (auto ext: extensions__) {
981  set.insert(ext);
983  }
984  }
985 
986  template < typename GUM_SCALAR >
989  // We only add IO Flags if elt matches is required by and interface
990  if (implements__ != nullptr) {
991  for (const auto impl: *implements__) {
993  while (super) {
994  // If the attribute is defined in an interface, we set it as an
995  // OutputNode
996  if (impl->exists(elt->name())) {
997  try {
998  this->getIOFlag_(*elt).second = true;
999  } catch (NotFound&) {
1000  this->setIOFlag_(*elt, std::make_pair(false, true));
1001  }
1002  }
1003  try {
1004  super = &(super->super());
1005  } catch (NotFound&) { super = nullptr; }
1006  }
1007  }
1008  }
1009  }
1010 
1011  template < typename GUM_SCALAR >
1013  const PRMClassElement< GUM_SCALAR >& elt) {
1014  // for ( const auto ext : extensions__ ) {
1015  // // We test to prevent unnecessary recursive call from iter
1016  // if ( !ext->isOutputNode( elt ) ) {
1017  // ext->setOutputNode( elt, true );
1018  // }
1019  //}
1020  }
1021 
1022  template < typename GUM_SCALAR >
1024  return PRMObject::prm_type::CLASS;
1025  }
1026 
1027  template < typename GUM_SCALAR >
1028  INLINE const DAG& PRMClass< GUM_SCALAR >::dag_() const {
1029  return dag__;
1030  }
1031 
1032  template < typename GUM_SCALAR >
1034  return dag__;
1035  }
1036 
1037  template < typename GUM_SCALAR >
1039  try {
1040  return *(nodeIdMap__[id]);
1041  } catch (NotFound&) {
1042  GUM_ERROR(NotFound, "no ClassElement<GUM_SCALAR> with the given NodeId");
1043  }
1044  }
1045 
1046  template < typename GUM_SCALAR >
1049  try {
1050  return *(nodeIdMap__[id]);
1051  } catch (NotFound&) {
1053  "no ClassElement<GUM_SCALAR> with the given NodeId (" << id
1054  << ")");
1055  }
1056  }
1057 
1058  template < typename GUM_SCALAR >
1061  try {
1062  return *(nameMap__[name]);
1063  } catch (NotFound&) {
1065  "no ClassElement<GUM_SCALAR> with the given name (" << name
1066  << ")");
1067  }
1068  }
1069 
1070  template < typename GUM_SCALAR >
1072  PRMClass< GUM_SCALAR >::get(const std::string& name) const {
1073  try {
1074  return *(nameMap__[name]);
1075  } catch (NotFound&) {
1077  "no ClassElement<GUM_SCALAR> with the given name (" << name
1078  << ")");
1079  }
1080  }
1081 
1082  template < typename GUM_SCALAR >
1083  INLINE const Set< PRMAttribute< GUM_SCALAR >* >&
1085  return attributes__;
1086  }
1087 
1088  template < typename GUM_SCALAR >
1089  INLINE const Set< PRMParameter< GUM_SCALAR >* >&
1091  return parameters__;
1092  }
1093 
1094  // Private struct for retrieving all params in scope
1095  template < typename GUM_SCALAR >
1098  const PRMClass< GUM_SCALAR >* c;
1100 
1102  const PRMReferenceSlot< GUM_SCALAR >& ref,
1103  Idx d) :
1104  prefix(s + ref.name() + "."),
1105  c(static_cast< const PRMClass< GUM_SCALAR >* >(&(ref.slotType()))),
1106  depth(d) {}
1107  };
1108 
1109  template < typename GUM_SCALAR >
1110  INLINE HashTable< std::string, const PRMParameter< GUM_SCALAR >* >
1111  PRMClass< GUM_SCALAR >::scope() const {
1113 
1114  for (const auto p: parameters()) {
1115  params.insert(p->name(), p);
1116  }
1117 
1119 
1120  for (const auto ref: referenceSlots()) {
1121  if (PRMObject::isClass(ref->slotType())) {
1122  queue.push(ParamScopeData< GUM_SCALAR >("", *ref, 1));
1123  }
1124  }
1125 
1126  while (!queue.empty()) {
1127  auto data = queue.front();
1128  queue.pop();
1129 
1130  if (data.depth < 5) {
1131  for (const auto p: data.c->parameters()) {
1132  params.insert(data.prefix + p->name(), p);
1133  }
1134 
1135  for (const auto ref: data.c->referenceSlots()) {
1136  if (PRMObject::isClass(ref->slotType())) {
1137  queue.push(
1139  }
1140  }
1141  } else {
1142  // @todo depth>5 is a workaround. Cycle detection is needed here !
1143  GUM_TRACE("Depth limit reached when looking up parameters");
1144  }
1145  }
1146 
1147  return params;
1148  }
1149 
1150  template < typename GUM_SCALAR >
1151  INLINE const Set< PRMAggregate< GUM_SCALAR >* >&
1153  return aggregates__;
1154  }
1155 
1156  template < typename GUM_SCALAR >
1157  INLINE const Set< PRMReferenceSlot< GUM_SCALAR >* >&
1159  return referenceSlots__;
1160  }
1161 
1162  template < typename GUM_SCALAR >
1163  INLINE const Set< PRMSlotChain< GUM_SCALAR >* >&
1165  return slotChains__;
1166  }
1167 
1168  template < typename GUM_SCALAR >
1170  if (superClass__) {
1171  return *superClass__;
1172  } else {
1173  GUM_ERROR(NotFound, "this Class is not a subclass");
1174  }
1175  }
1176 
1177  template < typename GUM_SCALAR >
1178  INLINE const Set< PRMInterface< GUM_SCALAR >* >&
1180  if (implements__) {
1181  return *implements__;
1182  } else {
1184  "this Class does not implement any Interface<GUM_SCALAR>");
1185  }
1186  }
1187 
1188  template < typename GUM_SCALAR >
1191  return get(id);
1192  }
1193 
1194  template < typename GUM_SCALAR >
1197  return get(id);
1198  }
1199 
1200  template < typename GUM_SCALAR >
1203  return get(name);
1204  }
1205 
1206  template < typename GUM_SCALAR >
1208  PRMClass< GUM_SCALAR >::operator[](const std::string& name) const {
1209  return get(name);
1210  }
1211 
1212  template < typename GUM_SCALAR >
1218  }
1219 
1220  template < typename GUM_SCALAR >
1224  if (overloaded->elt_type() != overloader->elt_type()) { return false; }
1225 
1226  switch (overloaded->elt_type()) {
1228  if (!overloader->type().isSubTypeOf(overloaded->type())) {
1229  return false;
1230  }
1231  break;
1232  }
1233 
1235  const auto& new_slot_type
1236  = static_cast< const PRMReferenceSlot< GUM_SCALAR >* >(overloader)
1237  ->slotType();
1238  const auto& old_slot_type
1239  = static_cast< const PRMReferenceSlot< GUM_SCALAR >* >(overloaded)
1240  ->slotType();
1241 
1242  if (!new_slot_type.isSubTypeOf(old_slot_type)) { return false; }
1243 
1244  break;
1245  }
1246 
1248  auto overloaded_param
1249  = static_cast< const PRMParameter< GUM_SCALAR >* >(overloaded);
1250  auto overloader_param
1251  = static_cast< const PRMParameter< GUM_SCALAR >* >(overloader);
1252 
1254  break;
1255  }
1256 
1257  default: {
1258  return false;
1259  }
1260  }
1261  return true;
1262  }
1263 
1264  template < typename GUM_SCALAR >
1265  INLINE const Set< PRMClass< GUM_SCALAR >* >&
1267  return extensions__;
1268  }
1269 
1270  template < typename GUM_SCALAR >
1273  }
1274 
1275  template < typename GUM_SCALAR >
1277  const std::string& safe_name) const {
1279 
1280  try {
1281  return elt.type().name() == get(elt.name()).type().name();
1282  } catch (OperationNotAllowed&) {
1283  GUM_ERROR(NotFound, "no attribute with the given name");
1284  }
1285  }
1286 
1287  template < typename GUM_SCALAR >
1289  const PRMClassElement< GUM_SCALAR >& elt) const {
1290  try {
1291  if (!this->getIOFlag_(elt).second) {
1292  if (implements__) {
1293  for (auto i: *implements__) {
1294  if (i->isOutputNode(elt)) { return true; }
1295  }
1296  }
1297 
1298  if (superClass__ && (superClass__->isOutputNode(elt))) { return true; }
1299 
1300  } else {
1301  return true;
1302  }
1303  } catch (NotFound&) {}
1304  return false;
1305  }
1306 
1307 
1308  } /* namespace prm */
1309 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669
ParamScopeData(const std::string &s, const PRMReferenceSlot< GUM_SCALAR > &ref, Idx d)