aGrUM  0.14.2
PRMInterface_tpl.h
Go to the documentation of this file.
1 /**************************************************************************
2  * Copyright (C) 2005 by Christophe GONZALES and Pierre-Henri WUILLEMIN *
3  * {prenom.nom}_at_lip6.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ***************************************************************************/
27 
29 
30 namespace gum {
31  namespace prm {
32 
33  template < typename GUM_SCALAR >
34  PRMInterface< GUM_SCALAR >::PRMInterface(const std::string& name) :
35  PRMClassElementContainer< GUM_SCALAR >(name), __superInterface(0) {
36  GUM_CONSTRUCTOR(PRMInterface);
37  }
38 
39  template < typename GUM_SCALAR >
42  bool delayInheritance) :
43  PRMClassElementContainer< GUM_SCALAR >(name),
44  __superInterface(&super) {
45  GUM_CONSTRUCTOR(PRMInterface);
46  if (!delayInheritance) { __inheritInterface(super); }
47  }
48 
49  template < typename GUM_SCALAR >
51  const PRMInterface< GUM_SCALAR >& source) :
52  PRMClassElementContainer< GUM_SCALAR >(source.name()),
53  __dag(source.__dag), __superInterface(source.__superInterface) {
54  GUM_CONS_CPY(PRMInterface);
55  GUM_ERROR(FatalError, "don't copy an interface");
56  }
57 
58  template < typename GUM_SCALAR >
60  GUM_DESTRUCTOR(PRMInterface);
61 
62  for (const auto& elt : __nodeIdMap) {
63  delete elt.second;
64  }
65  }
66 
67  template < typename GUM_SCALAR >
69  if (__superInterface != nullptr) { __inheritInterface(*__superInterface); }
70  }
71 
72  template < typename GUM_SCALAR >
74  const PRMInterface< GUM_SCALAR >& i) {
75  // Copying attributes
76  for (const auto i_attr : i.__attributes) {
77  auto attr =
78  new PRMScalarAttribute< GUM_SCALAR >(i_attr->name(), i_attr->type());
79  attr->setId(i_attr->id());
80  __nodeIdMap.insert(attr->id(), attr);
81  __attributes.insert(attr);
82 
83  if (i.__nameMap[i_attr->name()] == i.__nameMap[i_attr->safeName()]) {
84  __nameMap.insert(attr->name(), attr);
85  }
86 
87  __nameMap.insert(attr->safeName(), attr);
88  __dag.addNodeWithId(attr->id());
89  }
90 
91  // Copying reference slots
92  for (const auto i_ref : i.__referenceSlots) {
93  auto ref = new PRMReferenceSlot< GUM_SCALAR >(
94  i_ref->name(),
96  i_ref->slotType()),
97  i_ref->isArray());
98 
99  ref->setId(i_ref->id());
100  __nodeIdMap.insert(ref->id(), ref);
101  __referenceSlots.insert(ref);
102 
103  if (i.__nameMap.exists(ref->name())) {
104  __nameMap.insert(ref->name(), ref);
105  }
106 
107  __nameMap.insert(ref->safeName(), ref);
108  __dag.addNodeWithId(ref->id());
109  }
110  }
111 
112  template < typename GUM_SCALAR >
114  if (__nameMap.exists(elt->name())) {
116  "name '" << elt->name()
117  << "' is already used by another ClassElement");
118  }
119 
122  static_cast< PRMAttribute< GUM_SCALAR >* >(elt);
123  __nameMap.insert(attr->name(), attr);
124 
125  while (true) {
126  attr->setId(nextNodeId());
127  __dag.addNodeWithId(attr->id());
128  __nodeIdMap.insert(attr->id(), attr);
129  __nameMap.insert(attr->safeName(), attr);
130  __attributes.insert(attr);
131 
132  if (attr->type().isSubType()) {
133  attr = attr->getCastDescendant();
134  } else {
135  break;
136  }
137  }
139  elt->setId(nextNodeId());
140  __dag.addNodeWithId(elt->id());
141  __nodeIdMap.insert(elt->id(), elt);
142  __referenceSlots.insert(
143  static_cast< PRMReferenceSlot< GUM_SCALAR >* >(elt));
144  __nameMap.insert(elt->name(), elt);
145  __nameMap.insert(elt->safeName(), elt);
146  } else {
148  "illegal ClassElement<GUM_SCALAR> for an Interface");
149  }
150 
151  return elt->id();
152  }
153 
154  template < typename GUM_SCALAR >
156  PRMClassElement< GUM_SCALAR >* overloader) {
157  try {
158  if (!super().exists(overloader->name())) {
160  "found no ClassElement<GUM_SCALAR> to overload");
161  }
162  } catch (NotFound&) {
164  "overload is possible only with sub interfaces");
165  }
166 
167  PRMClassElement< GUM_SCALAR >* overloaded = __nameMap[overloader->name()];
168  if (overloaded == overloader) {
170  "duplicate ClassElement '" << overloader->name() << "'");
171  }
172  if (!__checkOverloadLegality(overloaded, overloader)) {
173  GUM_ERROR(OperationNotAllowed, "illegal overload");
174  }
175 
176  switch (overloader->elt_type()) {
178  auto attr_overloader =
179  static_cast< PRMAttribute< GUM_SCALAR >* >(overloader);
180  auto attr_overloaded =
181  static_cast< PRMAttribute< GUM_SCALAR >* >(overloaded);
182  __overloadAttribute(attr_overloader, attr_overloaded);
183  break;
184  }
185 
187  auto ref_overloader =
188  static_cast< PRMReferenceSlot< GUM_SCALAR >* >(overloader);
189  auto ref_overloaded =
190  static_cast< PRMReferenceSlot< GUM_SCALAR >* >(overloaded);
191  __overloadReferenceSlot(ref_overloader, ref_overloaded);
192  break;
193  }
194 
197  auto msg = "element can ! be overloaded";
199  break;
200  }
201 
202  default: {
203  GUM_ERROR(FatalError, "unknown ClassElement<GUM_SCALAR> type");
204  }
205  }
206 
207  return overloader->id();
208  }
209 
210  template < typename GUM_SCALAR >
212  PRMAttribute< GUM_SCALAR >* overloader,
213  PRMAttribute< GUM_SCALAR >* overloaded) {
214  if (overloader->type() != overloaded->type()) {
215  overloader->setId(nextNodeId());
216  __dag.addNodeWithId(overloader->id());
217  __nodeIdMap.insert(overloader->id(), overloader);
218  __nameMap[overloader->name()] = overloader;
219  __nameMap.insert(overloader->safeName(), overloader);
220  __attributes.insert(overloader);
221  __addCastDescendants(overloader, overloaded);
222  } else {
223  overloader->setId(overloaded->id());
224  __nodeIdMap[overloader->id()] = overloader;
225  __nameMap[overloader->name()] = overloader;
226  __nameMap[overloader->safeName()] = overloader;
227  __attributes.erase(overloaded);
228  __attributes.insert(overloader);
229  // Swapping types, ugly but necessary to preserve the
230  // PRMType<GUM_SCALAR>
231  // pointer of overloaded
232  overloader->overload(overloaded);
233  delete overloaded;
234  }
235  }
236 
237  template < typename GUM_SCALAR >
239  PRMReferenceSlot< GUM_SCALAR >* overloader,
240  PRMReferenceSlot< GUM_SCALAR >* overloaded) {
241  // Adding overloading reference
242  overloader->setId(overloaded->id());
243  __nodeIdMap[overloader->id()] = overloader;
244  __nameMap[overloader->name()] = overloader;
245  __nameMap.insert(overloader->safeName(), overloader);
246  __referenceSlots.insert(overloader);
247  // Removing overloaded PRMReferenceSlot<GUM_SCALAR>
248  __referenceSlots.erase(overloaded);
249  __nameMap.erase(overloaded->safeName());
250  delete overloaded;
251  }
252 
253  template < typename GUM_SCALAR >
256  PRMAttribute< GUM_SCALAR >* parent = start;
257  PRMAttribute< GUM_SCALAR >* child = nullptr;
258 
259  while (parent->type().superType() != end->type()) {
260  child = parent->getCastDescendant();
261  child->setId(nextNodeId());
262  __dag.addNodeWithId(child->id());
263  __nodeIdMap.insert(child->id(), child);
264  // Only use child's safe name when adding to the name map!
265  __nameMap.insert(child->safeName(), child);
266  __attributes.insert(child);
267  // Do ! use Class<GUM_SCALAR>::insertArc(), child's CPF is already
268  // initialized properly
269  parent = child;
270  }
271 
272  parent->setAsCastDescendant(end);
273  }
274 
275  template < typename GUM_SCALAR >
277  const PRMClassElement< GUM_SCALAR >* overloaded,
278  const PRMClassElement< GUM_SCALAR >* overloader) {
279  if (overloaded->elt_type() != overloader->elt_type()) { return false; }
280 
282  if (!overloader->type().isSubTypeOf(overloaded->type())) { return false; }
283  } else if (overloaded->elt_type()
285  auto ref_overloader =
286  static_cast< const PRMReferenceSlot< GUM_SCALAR >* >(overloader);
287  auto ref_overloaded =
288  static_cast< const PRMReferenceSlot< GUM_SCALAR >* >(overloaded);
289  if (!ref_overloader->slotType().isSubTypeOf(ref_overloaded->slotType())) {
290  return false;
291  }
292  } else {
293  return false;
294  }
295  return true;
296  }
297 
298  template < typename GUM_SCALAR >
300  const PRMClassElementContainer< GUM_SCALAR >& cec) const {
301  switch (cec.obj_type()) {
303  return false;
304  }
305 
307  const PRMInterface* current = this;
308 
309  while (current != 0) {
310  if (current == &(cec)) return true;
311 
312  current = current->__superInterface;
313  }
314 
315  return false;
316  }
317 
318  default: {
319  GUM_ERROR(FatalError, "unknown ClassElementContainer<GUM_SCALAR>");
320  }
321  }
322  }
323 
324  template < typename GUM_SCALAR >
326  const PRMClassElement< GUM_SCALAR >& elt) {
327  // for ( const auto ext : __extensions )
328  // if ( !ext->isOutputNode( elt ) ) ext->setOutputNode( elt, true );
329 
330  // for ( const auto impl : __implementations ) {
331  // // Because of cyclic dependencies we must use a reinterpret cast.
332  // PRMClassElementContainer<GUM_SCALAR>* c =
333  // reinterpret_cast<PRMClassElementContainer<GUM_SCALAR>*>( impl );
334 
335  // if ( ! c->isOutputNode( elt ) ) c->setOutputNode( elt, true );
336  //}
337  }
338 
339  template < typename GUM_SCALAR >
342  return __nodeIdMap.begin();
343  }
344 
345  template < typename GUM_SCALAR >
346  INLINE const typename PRMInterface< GUM_SCALAR >::ClassEltIterator&
348  return __nodeIdMap.end();
349  }
350 
351  template < typename GUM_SCALAR >
354  return __nodeIdMap.begin();
355  }
356 
357  template < typename GUM_SCALAR >
360  return __nodeIdMap.end();
361  }
362 
363  template < typename GUM_SCALAR >
364  INLINE void PRMInterface< GUM_SCALAR >::addArc(const std::string& tail,
365  const std::string& head) {
366  GUM_ERROR(OperationNotAllowed, "an Interface does ! have arcs");
367  }
368 
369  template < typename GUM_SCALAR >
371  if (__superInterface)
372  return *__superInterface;
373  else
374  GUM_ERROR(NotFound, "this Interface is ! a sub interface");
375  }
376 
377  template < typename GUM_SCALAR >
378  INLINE const PRMInterface< GUM_SCALAR >&
380  if (__superInterface)
381  return *__superInterface;
382  else
383  GUM_ERROR(NotFound, "this Interface is ! a sub interface");
384  }
385 
386  template < typename GUM_SCALAR >
387  INLINE void
389  __implementations.insert(c);
390  }
391 
392  template < typename GUM_SCALAR >
393  INLINE void
395  __extensions.insert(i);
396  }
397 
398  template < typename GUM_SCALAR >
401  return get(id);
402  }
403 
404  template < typename GUM_SCALAR >
406  operator[](NodeId id) const {
407  return get(id);
408  }
409 
410  template < typename GUM_SCALAR >
412  operator[](const std::string& name) {
413  return get(name);
414  }
415 
416  template < typename GUM_SCALAR >
418  operator[](const std::string& name) const {
419  return get(name);
420  }
421 
422  template < typename GUM_SCALAR >
423  INLINE typename PRMObject::prm_type
425  return PRMObject::prm_type::PRM_INTERFACE;
426  }
427 
428  template < typename GUM_SCALAR >
429  INLINE const DAG& PRMInterface< GUM_SCALAR >::_dag() const {
430  return __dag;
431  }
432 
433  template < typename GUM_SCALAR >
435  return __dag;
436  }
437 
438  template < typename GUM_SCALAR >
441  try {
442  return *(__nodeIdMap[id]);
443  } catch (NotFound&) {
444  GUM_ERROR(NotFound, "no ClassElement<GUM_SCALAR> with the given NodeId");
445  }
446  }
447 
448  template < typename GUM_SCALAR >
449  INLINE const PRMClassElement< GUM_SCALAR >&
451  try {
452  return *(__nodeIdMap[id]);
453  } catch (NotFound&) {
454  GUM_ERROR(NotFound, "no ClassElement<GUM_SCALAR> with the given NodeId");
455  }
456  }
457 
458  template < typename GUM_SCALAR >
460  PRMInterface< GUM_SCALAR >::get(const std::string& name) {
461  try {
462  return *(__nameMap[name]);
463  } catch (NotFound&) {
464  GUM_ERROR(NotFound, "no ClassElement<GUM_SCALAR> with the given name");
465  }
466  }
467 
468  template < typename GUM_SCALAR >
469  INLINE const PRMClassElement< GUM_SCALAR >&
470  PRMInterface< GUM_SCALAR >::get(const std::string& name) const {
471  try {
472  return *(__nameMap[name]);
473  } catch (NotFound&) {
474  GUM_ERROR(NotFound, "no ClassElement<GUM_SCALAR> with the given name");
475  }
476  }
477 
478  template < typename GUM_SCALAR >
479  INLINE const Set< PRMAttribute< GUM_SCALAR >* >&
481  return __attributes;
482  }
483 
484  template < typename GUM_SCALAR >
485  INLINE const Set< PRMReferenceSlot< GUM_SCALAR >* >&
487  return __referenceSlots;
488  }
489 
490  template < typename GUM_SCALAR >
491  INLINE Set< PRMClass< GUM_SCALAR >* >&
493  return __implementations;
494  }
495 
496  template < typename GUM_SCALAR >
497  INLINE const Set< PRMClass< GUM_SCALAR >* >&
499  return __implementations;
500  }
501 
502  template < typename GUM_SCALAR >
505  for (const auto impl : __implementations) {
506  set.insert(impl);
507  impl->_findAllSubtypes(set);
508  }
509 
510  for (const auto ext : __extensions) {
511  set.insert(ext);
512  ext->_findAllSubtypes(set);
513  }
514  }
515 
516  template < typename GUM_SCALAR >
518  const PRMClassElement< GUM_SCALAR >& elt) const {
519  try {
520  if (!this->_getIOFlag(elt).second) {
521  for (auto i : __implementations) {
522  if (i->isOutputNode(elt)) { return true; }
523  }
524 
525  if (__superInterface && __superInterface->isOutputNode(elt)) {
526  return true;
527  }
528 
529  } else {
530  return true;
531  }
532  } catch (NotFound&) {}
533  return false;
534  }
535  } /* namespace prm */
536 } /* namespace gum */
Unsafe Const Iterators for hashtablesHashTableConstIterator provides a fast but unsafe way to parse H...
Definition: hashTable.h:2462
virtual PRMAttribute< GUM_SCALAR > * getCastDescendant() const =0
Returns a proper cast descendant of this PRMAttribute.
ClassEltIterator begin()
const std::string & name() const
Returns the name of this object.
Definition: PRMObject_inl.h:32
virtual PRMType & type()=0
See gum::PRMClassElement::type().
Headers of gum::prm::Class<GUM_SCALAR>.
Unsafe Iterators for hashtablesHashTableIterator provides a fast but unsafe way to parse HashTables...
Definition: hashTable.h:2747
virtual prm_type obj_type() const =0
Returns the type of this object.
Abstract class representing an element of PRM class.
void _findAllSubtypes(Set< PRMClassElementContainer< GUM_SCALAR > * > &set)
Fills set with all the subtypes of this PRMInterface, this includes extensions and implementations...
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
Headers of gum::prm::PRMInterface.
A PRMReferenceSlot represent a relation between two PRMClassElementContainer.
Definition: PRMObject.h:220
PRMClassElementContainer< GUM_SCALAR > & slotType()
Returns the type of this slot, which is a PRMClassElementContainer (it is not the type of PRMObject)...
Representation of a setA Set is a structure that contains arbitrary elements.
Definition: set.h:162
const std::string & safeName() const
Returns the safe name of this PRMClassElement, if any.
prm_type
Enumeration of the different types of objects handled by a PRM.
Definition: PRMObject.h:66
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: PRMInterface.h:338
virtual void overload(PRMAttribute< GUM_SCALAR > *source)
Set this as overload of source (necessayr to preserver internal pointers for MultiDims).
PRMInterface(const std::string &name)
Default constructor.
An PRMInterface is implemented by a Class<GUM_SCALAR> and defines a set of PRMReferenceSlot<GUM_SCALA...
Definition: PRMClass.h:51
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.
NodeId nextNodeId()
Returns the next value of an unique counter for PRM&#39;s node id.
Definition: utils_prm.cpp:63
<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.
Set< PRMAttribute< GUM_SCALAR > *> __attributes
The sequence of PRMAttribute<GUM_SCALAR>s.
Definition: PRMInterface.h:341
A PRMClass is an object of a PRM representing a fragment of a Bayesian Network which can be instantia...
Definition: PRMClass.h:63
virtual void setAsCastDescendant(PRMAttribute< GUM_SCALAR > *attr)=0
Define attr as a cast descendant of this PRMAttribute.
const ClassEltIterator & end()
PRMInterface< GUM_SCALAR > * __superInterface
The alternate PRMClassElementContainer<GUM_SCALAR> searched for elements defined in this...
Definition: PRMInterface.h:356
Set< PRMReferenceSlot< GUM_SCALAR > *> __referenceSlots
The sequence of PRMReferenceSlot<GUM_SCALAR>.
Definition: PRMInterface.h:344
PRMAttribute is a member of a Class in a PRM.
Definition: PRMAttribute.h:58
<agrum/PRM/elements/scalarAttribute.h>
Base class for dag.
Definition: DAG.h:99
Size NodeId
Type for node ids.
Definition: graphElements.h:97
#define GUM_ERROR(type, msg)
Definition: exceptions.h:52