aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy > Class Template Referenceabstract

Class implementingting a function graph manager. More...

#include <multiDimFunctionGraph.h>

+ Inheritance diagram for gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >:

Public Member Functions

void clean ()
 Removes var without nodes in the diagram. More...
 

Constructors / Destructors

MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy > * MultiDimFunctionGraph ()
 This friend methods from is the only way to get an instance of a manager. More...
 
 MultiDimFunctionGraphManager (MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > *master)
 Default constructor. More...
 
virtual ~MultiDimFunctionGraphManager ()
 Class destructor. More...
 

Nodes manipulation methods.

NodeId addInternalNode_ (const DiscreteVariable *var, NodeId *sons)
 Adds an internal node. More...
 
void setRootNode (const NodeId &root)
 Sets root node of decision diagram. More...
 
NodeId addInternalNode (const DiscreteVariable *var)
 Inserts a new non terminal node in graph. More...
 
virtual NodeId addInternalNode (const DiscreteVariable *var, NodeId *sons)=0
 Inserts a new non terminal node in graph. More...
 
NodeId addInternalNode (const DiscreteVariable *var, NodeId nid)
 Inserts a new non terminal node in graph. More...
 
NodeId addTerminalNode (const GUM_SCALAR &value)
 Adds a value to the MultiDimFunctionGraph. More...
 
void eraseNode (NodeId id, NodeId replacingId=0, bool updateParents=true)
 Erases a node from the diagram. More...
 

Manipulation methods.

void migrateNode_ (const NodeId &x, const NodeId &y)
 Remaps all arcs going to ou going from the first given node to the second node, then delete first node. More...
 
void setSon (const NodeId &node, const Idx &modality, const NodeId &sonNode)
 Sets nodes son for given modality to designated son node. More...
 
void minimizeSize ()
 Performs a sifting in search of a(local) minimal size. More...
 
void moveTo (const DiscreteVariable *x, Idx desiredPos)
 Changes var position in variable sequence. More...
 
void adjacentSwap__ (const DiscreteVariable *x, const DiscreteVariable *y)
 Swap two adjacent variable. More...
 

Redundancy methods.

NodeId nodeRedundancyCheck_ (const DiscreteVariable *var, NodeId *sonsMap)
 Check for redundancy. More...
 
void reduce_ ()
 Ensures that every isomorphic subgraphs are merged together. More...
 
virtual void reduce ()=0
 Ensures that every isomorphic subgraphs are merged together. More...
 
NodeId checkIsomorphism__ (const DiscreteVariable *var, NodeId *sons)
 Checks if a similar node does not already exists in the graph. More...
 
bool isRedundant__ (const DiscreteVariable *var, NodeId *sons)
 Checks if node has the same child for every variable value. More...
 

Detailed Description

template<typename GUM_SCALAR, template< typename > class TerminalNodePolicy>
class gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >

Class implementingting a function graph manager.

Warning
Doxygen does not like spanning command on multiple line, so we could not configure it with the correct include directive. Use the following code snippet to include this file.

This class provides methods to edit a Function Graph. Any modification on a MultiDimFunctionGraph graph must be done via this class.

This class is a singleton and its unique instance ca be accessed using the MultiDimFunctionGraph::getManager() method.

To do so :

// You can also use getTreeInstance()
auto * func_graph =
auto manager = dg->manager();
Template Parameters
GUM_SCALARThe type of scalars stored in the multidimensional table.
TerminalNodePolicyThe terminal node policy to use.

Definition at line 52 of file multiDimFunctionGraph.h.

Constructor & Destructor Documentation

◆ MultiDimFunctionGraphManager()

template<typename GUM_SCALAR, template< class > class TerminalNodePolicy>
INLINE gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::MultiDimFunctionGraphManager ( MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > *  master)
explicitprotected

Default constructor.

You have to call MultiDimFunctionGraph::getManager() to get the instance of MultiDimFunctionGraphManager bound to your function graph.

Definition at line 40 of file multiDimFunctionGraphManager_tpl.h.

41  {
42  GUM_CONSTRUCTOR(MultiDimFunctionGraphManager);
43  functionGraph__ = mddg;
44  }
MultiDimFunctionGraphManager(MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > *master)
Default constructor.
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * functionGraph__
The multidimdecisiongraph supposed to be edited.

◆ ~MultiDimFunctionGraphManager()

template<typename GUM_SCALAR , template< class > class TerminalNodePolicy>
INLINE gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::~MultiDimFunctionGraphManager ( )
virtual

Class destructor.

Definition at line 49 of file multiDimFunctionGraphManager_tpl.h.

49  {
50  GUM_DESTRUCTOR(MultiDimFunctionGraphManager);
51  }
MultiDimFunctionGraphManager(MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > *master)
Default constructor.

Member Function Documentation

◆ addInternalNode() [1/3]

template<typename GUM_SCALAR , template< class > class TerminalNodePolicy>
INLINE NodeId gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::addInternalNode ( const DiscreteVariable var)

Inserts a new non terminal node in graph.

NodeId of this node is generated automatically.

Parameters
varAssociated variable
Returns
The id of the added non terminal node.

Definition at line 76 of file multiDimFunctionGraphManager_tpl.h.

76  {
77  InternalNode* newNodeStruct = new InternalNode(var);
78  NodeId nid = functionGraph__->model__.addNode();
79  functionGraph__->internalNodeMap__.insert(nid, newNodeStruct);
80  functionGraph__->var2NodeIdMap__[var]->addLink(nid);
81 
82  return nid;
83  }
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * functionGraph__
The multidimdecisiongraph supposed to be edited.
Size NodeId
Type for node ids.
Definition: graphElements.h:97

◆ addInternalNode() [2/3]

template<typename GUM_SCALAR, template< typename > class TerminalNodePolicy>
virtual NodeId gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::addInternalNode ( const DiscreteVariable var,
NodeId sons 
)
pure virtual

Inserts a new non terminal node in graph.

NodeId of this node is generated automatically.

Parameters
varThe associated variable.
sonsA table of size var->domainSize() containing nodeid of sons nodes.
Returns
Returns the id of the added non terminal node.
Exceptions
OperationNotAllowedRaised if MultiDimFunctionGraph has no variable yet.

Implemented in gum::MultiDimFunctionGraphROManager< GUM_SCALAR, TerminalNodePolicy >, and gum::MultiDimFunctionGraphTreeManager< GUM_SCALAR, TerminalNodePolicy >.

◆ addInternalNode() [3/3]

template<typename GUM_SCALAR , template< class > class TerminalNodePolicy>
INLINE NodeId gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::addInternalNode ( const DiscreteVariable var,
NodeId  nid 
)

Inserts a new non terminal node in graph.

NodeId of this node is generated automatically.

Parameters
varThe ssociated variable.
nidThe desired id for that node.
Returns
Returns the id of the added non terminal node.
Exceptions
OperationNotAllowedRaised if MultiDimFunctionGraph has no variable yet.

Definition at line 64 of file multiDimFunctionGraphManager_tpl.h.

64  {
65  InternalNode* newNodeStruct = new InternalNode(var);
66 
67  functionGraph__->internalNodeMap__.insert(nid, newNodeStruct);
68 
69  functionGraph__->var2NodeIdMap__[var]->addLink(nid);
70 
71  return nid;
72  }
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * functionGraph__
The multidimdecisiongraph supposed to be edited.

◆ addInternalNode_()

template<typename GUM_SCALAR , template< class > class TerminalNodePolicy>
INLINE NodeId gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::addInternalNode_ ( const DiscreteVariable var,
NodeId sons 
)
protected

Adds an internal node.

Parameters
varThe node to add.
sonsThe node sons.
Returns
Returns the added node id.

Definition at line 87 of file multiDimFunctionGraphManager_tpl.h.

87  {
88  InternalNode* newNodeStruct = new InternalNode(var, sons);
89  NodeId nid = functionGraph__->model__.addNode();
90  functionGraph__->internalNodeMap__.insert(nid, newNodeStruct);
91  functionGraph__->var2NodeIdMap__[var]->addLink(nid);
92  for (Idx i = 0; i < newNodeStruct->nbSons(); i++)
93  if (!functionGraph__->isTerminalNode(sons[i]))
94  functionGraph__->internalNodeMap__[sons[i]]->addParent(nid, i);
95 
96  return nid;
97  }
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * functionGraph__
The multidimdecisiongraph supposed to be edited.
Size NodeId
Type for node ids.
Definition: graphElements.h:97

◆ addTerminalNode()

template<typename GUM_SCALAR, template< class > class TerminalNodePolicy>
INLINE NodeId gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::addTerminalNode ( const GUM_SCALAR &  value)

Adds a value to the MultiDimFunctionGraph.

This will create a terminal node, which of id is returned. If a terminal node with such value already exists, its id will be return instead.

Parameters
valueThe value added by copy.
Returns
Returns he id of the terminal node hence created.

Definition at line 102 of file multiDimFunctionGraphManager_tpl.h.

102  {
103  if (functionGraph__->existsTerminalNodeWithValue(value))
104  return functionGraph__->terminalNodeId(value);
105 
106  NodeId node = functionGraph__->model__.addNode();
107  functionGraph__->addTerminalNode(node, value);
108  return node;
109  }
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * functionGraph__
The multidimdecisiongraph supposed to be edited.
Size NodeId
Type for node ids.
Definition: graphElements.h:97

◆ adjacentSwap__()

template<typename GUM_SCALAR , template< class > class TerminalNodePolicy>
void gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::adjacentSwap__ ( const DiscreteVariable x,
const DiscreteVariable y 
)
private

Swap two adjacent variable.

Order is important here. X must precede Y before the swap (at the end Y will then precede X). Not respecting this constraint leads to unattended behaviour.

Parameters
xThe first variable to swap.
yThe second variable to swap.

Definition at line 307 of file multiDimFunctionGraphManager_tpl.h.

307  {
308  LinkedList< NodeId >* oldxNodes = functionGraph__->var2NodeIdMap__[x];
309  functionGraph__->var2NodeIdMap__[x] = new LinkedList< NodeId >();
310  LinkedList< NodeId >* oldyNodes = functionGraph__->var2NodeIdMap__[y];
311  functionGraph__->var2NodeIdMap__[y] = new LinkedList< NodeId >();
312 
313 
314  InternalNode* currentOldXNode = nullptr;
315  NodeId* currentNewXNodeSons = nullptr;
316  Idx indx = 0;
317 
318  NodeId* currentNewYNodeSons = nullptr;
319  NodeId currentNewYNodeId = 0;
320  Idx indy = 0;
321 
322  while (oldxNodes->list()) {
323  // Recuperating a node associated to variables x
324  currentOldXNode
325  = functionGraph__->internalNodeMap__[oldxNodes->list()->element()];
326 
327  // Creating a new node associated to variable y
328  currentNewYNodeSons = InternalNode::allocateNodeSons(y);
329 
330  // Now the graph needs to be remap by inserting nodes bound to x
331  // for each values assumed by y
332  for (indy = 0; indy < y->domainSize(); ++indy) {
333  // Creating a new node bound to x that will be the son of the node
334  // tied to y for the current value assumed by y
335  currentNewXNodeSons = InternalNode::allocateNodeSons(x);
336 
337  // Iterating on the different values taht x can assumed to do the remap
338  for (indx = 0; indx < x->domainSize(); ++indx) {
339  currentNewXNodeSons[indx] = currentOldXNode->son(indx);
340  if (!functionGraph__->isTerminalNode(currentOldXNode->son(indx))
341  && functionGraph__->node(currentOldXNode->son(indx))->nodeVar() == y)
342  currentNewXNodeSons[indx]
343  = functionGraph__->node(currentOldXNode->son(indx))->son(indy);
344  }
345 
346  // Inserting the new node bound to x
347  currentNewYNodeSons[indy] = nodeRedundancyCheck_(x, currentNewXNodeSons);
348  }
349 
350  // Replacing old node x by new node y
351  currentNewYNodeId = currentNewYNodeSons[0];
352  if (isRedundant__(y, currentNewYNodeSons)) {
353  migrateNode_(oldxNodes->list()->element(), currentNewYNodeId);
354  SOA_DEALLOCATE(currentNewYNodeSons, y->domainSize() * sizeof(NodeId));
355  } else {
356  currentNewYNodeId = checkIsomorphism__(y, currentNewYNodeSons);
357  if (currentNewYNodeId != 0) {
358  migrateNode_(oldxNodes->list()->element(), currentNewYNodeId);
359  SOA_DEALLOCATE(currentNewYNodeSons, y->domainSize() * sizeof(NodeId));
360  } else {
361  // Updating the sons (they must not consider old x as their parent)
362  for (Idx i = 0; i < currentOldXNode->nodeVar()->domainSize(); ++i) {
363  if (functionGraph__->internalNodeMap__.exists(
364  currentOldXNode->son(i))) {
365  functionGraph__->internalNodeMap__[currentOldXNode->son(i)]
366  ->removeParent(oldxNodes->list()->element(), i);
367  }
368  }
369  // Reaffecting old node x internal attributes to correct new one
370  currentOldXNode->setNode(y, currentNewYNodeSons);
371  // Updating new sons (they must consider the node as a parent)
372  for (Idx i = 0; i < currentOldXNode->nodeVar()->domainSize(); ++i) {
373  if (functionGraph__->internalNodeMap__.exists(
374  currentNewYNodeSons[i])) {
375  functionGraph__->internalNodeMap__[currentNewYNodeSons[i]]
376  ->addParent(oldxNodes->list()->element(), i);
377  }
378  }
379 
380  functionGraph__->var2NodeIdMap__[y]->addLink(
381  oldxNodes->list()->element());
382  }
383  }
384 
385  oldxNodes->searchAndRemoveLink(oldxNodes->list()->element());
386  }
387  delete oldxNodes;
388 
389  while (oldyNodes->list()) {
390  NodeId curId = oldyNodes->list()->element();
391  if (functionGraph__->internalNodeMap__[curId]->parents() == nullptr) {
392  for (Idx i = 0;
393  i
394  < functionGraph__->internalNodeMap__[curId]->nodeVar()->domainSize();
395  ++i)
396  if (functionGraph__->internalNodeMap__.exists(
397  functionGraph__->internalNodeMap__[curId]->son(i)))
399  ->internalNodeMap__[functionGraph__->internalNodeMap__[curId]->son(
400  i)]
401  ->removeParent(curId, i);
402  delete functionGraph__->internalNodeMap__[curId];
403  functionGraph__->internalNodeMap__.erase(curId);
404  functionGraph__->model__.eraseNode(curId);
405  } else {
406  functionGraph__->var2NodeIdMap__[y]->addLink(curId);
407  }
408  oldyNodes->searchAndRemoveLink(curId);
409  }
410  delete oldyNodes;
411  }
NodeId nodeRedundancyCheck_(const DiscreteVariable *var, NodeId *sonsMap)
Check for redundancy.
static NodeId * allocateNodeSons(const DiscreteVariable *v)
Allocates a table of nodeid of the size given in parameter.
NodeId checkIsomorphism__(const DiscreteVariable *var, NodeId *sons)
Checks if a similar node does not already exists in the graph.
#define SOA_DEALLOCATE(x, y)
void migrateNode_(const NodeId &x, const NodeId &y)
Remaps all arcs going to ou going from the first given node to the second node, then delete first nod...
bool isRedundant__(const DiscreteVariable *var, NodeId *sons)
Checks if node has the same child for every variable value.
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * functionGraph__
The multidimdecisiongraph supposed to be edited.
Size NodeId
Type for node ids.
Definition: graphElements.h:97

◆ checkIsomorphism__()

template<typename GUM_SCALAR , template< class > class TerminalNodePolicy>
INLINE NodeId gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::checkIsomorphism__ ( const DiscreteVariable var,
NodeId sons 
)
private

Checks if a similar node does not already exists in the graph.

Tow nodes are similar if for every value assumed by the associated variable, these two nodes have the same children.

Warning
This will not free sons.
Parameters
varThe node to check for.
sonsThe node sons.
Returns
Returns the node id if found, 0 otherwhise.

Definition at line 462 of file multiDimFunctionGraphManager_tpl.h.

462  {
463  const InternalNode* nody = nullptr;
464  Idx i = 0;
465 
466  // Check abscence of identical node
467  Link< NodeId >* currentElem = functionGraph__->var2NodeIdMap__[var]->list();
468  while (currentElem != nullptr) {
469  nody = functionGraph__->internalNodeMap__[currentElem->element()];
470 
471  // Check on the other sons
472  i = 0;
473  while (i < var->domainSize() && sons[i] == nody->son(i))
474  ++i;
475  if (i == var->domainSize()) return currentElem->element();
476 
477  currentElem = currentElem->nextLink();
478  }
479  return 0;
480  }
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * functionGraph__
The multidimdecisiongraph supposed to be edited.

◆ clean()

template<typename GUM_SCALAR , template< class > class TerminalNodePolicy>
INLINE void gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::clean ( )

Removes var without nodes in the diagram.

Definition at line 562 of file multiDimFunctionGraphManager_tpl.h.

562  {
563  Sequence< const DiscreteVariable* > oldSequence(
564  functionGraph__->variablesSequence());
565  for (SequenceIterator< const DiscreteVariable* > varIter = oldSequence.begin();
566  varIter != oldSequence.end();
567  ++varIter)
568  if (!functionGraph__->varNodeListe(*varIter)->list())
569  functionGraph__->erase(**varIter);
570  }
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * functionGraph__
The multidimdecisiongraph supposed to be edited.

◆ eraseNode()

template<typename GUM_SCALAR , template< class > class TerminalNodePolicy>
void gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::eraseNode ( NodeId  id,
NodeId  replacingId = 0,
bool  updateParents = true 
)

Erases a node from the diagram.

Parameters
idThe id of the variable to erase.
replacingIdOffers the possibility to reroute any parent to the given node.
updateParentsIndicates if such remapping has to be done.
Exceptions
NotFoundRaised if node isn't in diagram.

Definition at line 113 of file multiDimFunctionGraphManager_tpl.h.

116  {
117  if (!functionGraph__->model__.exists(eraseId))
118  GUM_ERROR(NotFound, "Node : " << eraseId << " doesn't exists in the graph")
119 
120  if (functionGraph__->isTerminalNode(eraseId)) {
121  for (auto iterVar = functionGraph__->variablesSequence().begin();
122  iterVar != functionGraph__->variablesSequence().end();
123  ++iterVar) {
124  Link< NodeId >* nodeIter
125  = functionGraph__->var2NodeIdMap__[*iterVar]->list();
126  while (nodeIter != nullptr) {
127  for (Idx modality = 0; modality < (*iterVar)->domainSize(); ++modality)
128  if (functionGraph__->node(nodeIter->element())->son(modality)
129  == eraseId)
130  setSon(nodeIter->element(), modality, replacingId);
131 
132  nodeIter = nodeIter->nextLink();
133  }
134  }
135  functionGraph__->eraseTerminalNode(eraseId);
136 
137  } else {
138  InternalNode* eraseNode = functionGraph__->internalNodeMap__[eraseId];
139 
140  if (updateParents) {
141  Link< Parent >* picle = eraseNode->parents();
142  while (picle != nullptr) {
143  setSon(picle->element().parentId,
144  picle->element().modality,
145  replacingId);
146  picle = picle->nextLink();
147  }
148  }
149 
151  ->var2NodeIdMap__[functionGraph__->internalNodeMap__[eraseId]->nodeVar()]
152  ->searchAndRemoveLink(eraseId);
153 
154  delete functionGraph__->internalNodeMap__[eraseId];
155  functionGraph__->internalNodeMap__.erase(eraseId);
156  }
157 
158  functionGraph__->model__.eraseNode(eraseId);
159 
160  if (functionGraph__->root__ == eraseId) functionGraph__->root__ = replacingId;
161  }
void setSon(const NodeId &node, const Idx &modality, const NodeId &sonNode)
Sets nodes son for given modality to designated son node.
void eraseNode(NodeId id, NodeId replacingId=0, bool updateParents=true)
Erases a node from the diagram.
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * functionGraph__
The multidimdecisiongraph supposed to be edited.
#define GUM_ERROR(type, msg)
Definition: exceptions.h:54

◆ isRedundant__()

template<typename GUM_SCALAR , template< class > class TerminalNodePolicy>
INLINE bool gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::isRedundant__ ( const DiscreteVariable var,
NodeId sons 
)
private

Checks if node has the same child for every variable value.

Warning
WON'T deallocate sons
Parameters
varThe node to check for.
sonsThe node sons.
Returns
Returns true if the node is redundant.

Definition at line 485 of file multiDimFunctionGraphManager_tpl.h.

487  {
488  for (Idx m = 1; m < var->domainSize(); m++)
489  if (sons[m] != sons[0]) return false;
490  return true;
491  }

◆ migrateNode_()

template<typename GUM_SCALAR , template< class > class TerminalNodePolicy>
INLINE void gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::migrateNode_ ( const NodeId x,
const NodeId y 
)
protected

Remaps all arcs going to ou going from the first given node to the second node, then delete first node.

Parameters
xThe variable from which all arcs are removed.
yThe variable for which all of x arcs are added.

Definition at line 415 of file multiDimFunctionGraphManager_tpl.h.

417  {
418  InternalNode* org = functionGraph__->internalNodeMap__[origin];
419  // Upating parents after the change
420  Link< Parent >* picle = org->parents();
421  while (picle != nullptr) {
422  setSon(picle->element().parentId, picle->element().modality, destination);
423  picle = picle->nextLink();
424  }
425 
426  // Updating sons after the change
427  for (Idx i = 0; i < org->nbSons(); ++i)
428  if (functionGraph__->internalNodeMap__.exists(org->son(i)))
429  functionGraph__->internalNodeMap__[org->son(i)]->removeParent(origin, i);
430 
431  delete org;
432  functionGraph__->internalNodeMap__.erase(origin);
433  functionGraph__->model__.eraseNode(origin);
434 
435  if (functionGraph__->root() == origin) this->setRootNode(destination);
436  }
void setSon(const NodeId &node, const Idx &modality, const NodeId &sonNode)
Sets nodes son for given modality to designated son node.
void setRootNode(const NodeId &root)
Sets root node of decision diagram.
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * functionGraph__
The multidimdecisiongraph supposed to be edited.

◆ minimizeSize()

template<typename GUM_SCALAR , template< class > class TerminalNodePolicy>
void gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::minimizeSize ( )

Performs a sifting in search of a(local) minimal size.

Definition at line 216 of file multiDimFunctionGraphManager_tpl.h.

216  {
217  // Ordering variables by number of nodes asssociated to them
218  Sequence< const DiscreteVariable* > siftingSeq;
219  HashTable< const DiscreteVariable*, Idx > varLvlSize;
220  for (SequenceIteratorSafe< const DiscreteVariable* > varIter
221  = functionGraph__->variablesSequence().beginSafe();
222  varIter != functionGraph__->variablesSequence().endSafe();
223  ++varIter) {
224  const Link< NodeId >* curElem
225  = functionGraph__->var2NodeIdMap__[*varIter]->list();
226  Idx nbElem = 0;
227  for (; curElem != nullptr; nbElem++, curElem = curElem->nextLink())
228  ;
229  varLvlSize.insert(*varIter, nbElem);
230  siftingSeq.insert(*varIter);
231  Idx pos = siftingSeq.pos(*varIter);
232  while (pos > 0 && varLvlSize[siftingSeq.atPos(pos - 1)] > nbElem) {
233  siftingSeq.swap(pos - 1, pos);
234  pos--;
235  }
236  }
237 
238  // Sifting var par var
239  for (SequenceIteratorSafe< const DiscreteVariable* > sifIter
240  = siftingSeq.beginSafe();
241  sifIter != siftingSeq.endSafe();
242  ++sifIter) {
243  // Initialization
244  Idx currentPos = functionGraph__->variablesSequence().pos(*sifIter);
245  Idx bestSize = functionGraph__->realSize();
246  Idx bestPos = currentPos;
247 
248 
249  // Sifting towards upper places
250  while (currentPos > 0) {
251  moveTo(*sifIter, currentPos - 1);
252  currentPos = functionGraph__->variablesSequence().pos(*sifIter);
253  if (functionGraph__->realSize() < bestSize) {
254  bestPos = currentPos;
255  bestSize = functionGraph__->realSize();
256  }
257  }
258 
259  // Sifting towards lower places
260  while (currentPos < functionGraph__->variablesSequence().size() - 1) {
261  moveTo(*sifIter, currentPos + 1);
262  currentPos = functionGraph__->variablesSequence().pos(*sifIter);
263  if (functionGraph__->realSize() < bestSize) {
264  bestPos = currentPos;
265  bestSize = functionGraph__->realSize();
266  }
267  }
268 
269  moveTo(*sifIter, bestPos);
270  }
271  }
void moveTo(const DiscreteVariable *x, Idx desiredPos)
Changes var position in variable sequence.
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * functionGraph__
The multidimdecisiongraph supposed to be edited.

◆ moveTo()

template<typename GUM_SCALAR , template< class > class TerminalNodePolicy>
void gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::moveTo ( const DiscreteVariable x,
Idx  desiredPos 
)

Changes var position in variable sequence.

Parameters
xThe varaible to change.
desiredPosThe new posiition.

Definition at line 275 of file multiDimFunctionGraphManager_tpl.h.

277  {
278  // First we determine the position of both variable
279  // We also determine which one precede the other
280  if (functionGraph__->variablesSequence().pos(movedVar) > desiredPos)
281  for (Idx currentPos = functionGraph__->variablesSequence().pos(movedVar);
282  currentPos != desiredPos;
283  currentPos--) {
284  const DiscreteVariable* preVar
285  = functionGraph__->variablesSequence().atPos(currentPos - 1);
286  if (functionGraph__->var2NodeIdMap__[preVar]->list()
287  && functionGraph__->var2NodeIdMap__[movedVar]->list())
288  adjacentSwap__(preVar, movedVar);
289  functionGraph__->invert_(currentPos - 1, currentPos);
290  }
291  else
292  for (Idx currentPos = functionGraph__->variablesSequence().pos(movedVar);
293  currentPos != desiredPos;
294  currentPos++) {
295  const DiscreteVariable* suiVar
296  = functionGraph__->variablesSequence().atPos(currentPos + 1);
297  if (functionGraph__->var2NodeIdMap__[suiVar]->list()
298  && functionGraph__->var2NodeIdMap__[movedVar]->list())
299  adjacentSwap__(movedVar, suiVar);
300  functionGraph__->invert_(currentPos, currentPos + 1);
301  }
302  }
void adjacentSwap__(const DiscreteVariable *x, const DiscreteVariable *y)
Swap two adjacent variable.
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * functionGraph__
The multidimdecisiongraph supposed to be edited.

◆ nodeRedundancyCheck_()

template<typename GUM_SCALAR , template< class > class TerminalNodePolicy>
INLINE NodeId gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::nodeRedundancyCheck_ ( const DiscreteVariable var,
NodeId sonsMap 
)
protected

Check for redundancy.

Checks if a similar node does not already exists in the graph or if it has the same child for every variable value. If no node is a match, this node is added to the graph.

Warning
: will free by itslef sonsMap if a match exists.
Parameters
varThe node to add in the graph.
sonsMapThe node sons.
Returns
Returns the nodes id in the graph.

Definition at line 442 of file multiDimFunctionGraphManager_tpl.h.

442  {
443  NodeId newNode = sonsIds[0];
444 
445  if (isRedundant__(var, sonsIds)) {
446  SOA_DEALLOCATE(sonsIds, sizeof(NodeId) * var->domainSize());
447  } else {
448  newNode = checkIsomorphism__(var, sonsIds);
449  if (newNode == 0) {
450  newNode = addInternalNode_(var, sonsIds);
451  } else {
452  SOA_DEALLOCATE(sonsIds, sizeof(NodeId) * var->domainSize());
453  }
454  }
455 
456  return newNode;
457  }
NodeId checkIsomorphism__(const DiscreteVariable *var, NodeId *sons)
Checks if a similar node does not already exists in the graph.
#define SOA_DEALLOCATE(x, y)
NodeId addInternalNode_(const DiscreteVariable *var, NodeId *sons)
Adds an internal node.
bool isRedundant__(const DiscreteVariable *var, NodeId *sons)
Checks if node has the same child for every variable value.
Size NodeId
Type for node ids.
Definition: graphElements.h:97

◆ reduce()

template<typename GUM_SCALAR, template< typename > class TerminalNodePolicy>
virtual void gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::reduce ( )
pure virtual

◆ reduce_()

template<typename GUM_SCALAR , template< class > class TerminalNodePolicy>
INLINE void gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::reduce_ ( )
protected

Ensures that every isomorphic subgraphs are merged together.

Definition at line 496 of file multiDimFunctionGraphManager_tpl.h.

496  {
497  Link< NodeId >* currentNodeId = nullptr;
498  Link< NodeId >* nextNodeId = nullptr;
499  InternalNode* currentNode = nullptr;
500  bool theSame = true;
501  Idx currentInd;
502 
503  for (SequenceIterator< const DiscreteVariable* > varIter
504  = functionGraph__->variablesSequence().rbegin();
505  varIter != functionGraph__->variablesSequence().rend();
506  --varIter) {
507  currentNodeId = functionGraph__->var2NodeIdMap__[*varIter]->list();
508 
509  while (currentNodeId != nullptr) {
510  nextNodeId = currentNodeId->nextLink();
511  currentNode = functionGraph__->internalNodeMap__[currentNodeId->element()];
512 
513  // First isomorphism to handle is the one where all node children are
514  // the same
515  theSame = true;
516  for (currentInd = 1; currentInd < (*varIter)->domainSize(); currentInd++) {
517  if (currentNode->son(currentInd) != currentNode->son(0)) {
518  theSame = false;
519  break;
520  }
521  }
522 
523  if (theSame == true) {
524  migrateNode_(currentNodeId->element(), currentNode->son(0));
525  functionGraph__->var2NodeIdMap__[*varIter]->searchAndRemoveLink(
526  currentNodeId->element());
527  currentNodeId = nextNodeId;
528  continue;
529  }
530 
531  // Second isomorphism to handle is the one where two nodes have same
532  // variable and same children
533  if (nextNodeId) {
534  Link< NodeId >* anotherNodeId = currentNodeId->nextLink();
535  InternalNode* anotherNode = nullptr;
536  Idx modality = 0;
537  while (anotherNodeId->nextLink() != nullptr) {
538  nextNodeId = anotherNodeId->nextLink();
539  anotherNode
540  = functionGraph__->internalNodeMap__[anotherNodeId->element()];
541 
542  // Check on the other sons
543  for (modality = 0; modality < (*varIter)->domainSize(); ++modality) {
544  if (anotherNode->son(modality) != currentNode->son(modality)) break;
545  if (modality == (*varIter)->domainSize() - 1) {
546  migrateNode_(anotherNodeId->element(), currentNodeId->element());
547  functionGraph__->var2NodeIdMap__[*varIter]->searchAndRemoveLink(
548  anotherNodeId->element());
549  }
550  }
551 
552  anotherNodeId = nextNodeId;
553  }
554  }
555  currentNodeId = currentNodeId->nextLink();
556  }
557  }
558  }
void migrateNode_(const NodeId &x, const NodeId &y)
Remaps all arcs going to ou going from the first given node to the second node, then delete first nod...
NodeId nextNodeId()
Returns the next value of an unique counter for PRM&#39;s node id.
Definition: utils_prm.cpp:64
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * functionGraph__
The multidimdecisiongraph supposed to be edited.

◆ setRootNode()

template<typename GUM_SCALAR , template< class > class TerminalNodePolicy>
INLINE void gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::setRootNode ( const NodeId root)

Sets root node of decision diagram.

Parameters
rootThe node to set as root.

Definition at line 56 of file multiDimFunctionGraphManager_tpl.h.

57  {
58  functionGraph__->root__ = root;
59  }
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * functionGraph__
The multidimdecisiongraph supposed to be edited.

◆ setSon()

template<typename GUM_SCALAR , template< class > class TerminalNodePolicy>
INLINE void gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::setSon ( const NodeId node,
const Idx modality,
const NodeId sonNode 
)

Sets nodes son for given modality to designated son node.

Parameters
nodeThe node to which a node is added.
modalityThe modality for which sonNode is added to node.
sonNodeThe node to add as a son to node.

Definition at line 166 of file multiDimFunctionGraphManager_tpl.h.

169  {
170  // Ensuring that both nodes exists in the graph
171  if (!functionGraph__->model__.exists(node))
172  GUM_ERROR(NotFound, "Node : " << node << " doesn't exists in the graph")
173  if (!functionGraph__->model__.exists(sonNode))
174  GUM_ERROR(NotFound, "Node : " << sonNode << " doesn't exists in the graph")
175 
176  // Check if starting node is not terminal
177  if (functionGraph__->isTerminalNode(node))
178  GUM_ERROR(InvalidNode,
179  "You cannot insert an arc from terminal node : " << node)
180 
181  // Check if associated modality is lower than node bound variable domain
182  // size
183  if (functionGraph__->isInternalNode(node)
184  && modality
185  > functionGraph__->internalNodeMap__[node]->nodeVar()->domainSize()
186  - 1)
187  GUM_ERROR(
188  InvalidArgument,
189  "Modality "
190  << modality << "is higher than domain size "
191  << functionGraph__->internalNodeMap__[node]->nodeVar()->domainSize()
192  << "minus 1 of variable "
193  << functionGraph__->internalNodeMap__[node]->nodeVar()->name())
194 
195  // Check if variable order is respected
196  if (functionGraph__->isInternalNode(sonNode)
197  && functionGraph__->variablesSequence().pos(
198  functionGraph__->internalNodeMap__[node]->nodeVar())
199  >= functionGraph__->variablesSequence().pos(
200  functionGraph__->internalNodeMap__[sonNode]->nodeVar()))
201  GUM_ERROR(
202  OperationNotAllowed,
203  "Variable " << functionGraph__->internalNodeMap__[node]->nodeVar()
204  << " is after variable "
205  << functionGraph__->internalNodeMap__[sonNode]->nodeVar()
206  << "in Function Graph order.")
207 
208  functionGraph__->internalNodeMap__[node]->setSon(modality, sonNode);
209  if (sonNode && !functionGraph__->isTerminalNode(sonNode))
210  functionGraph__->internalNodeMap__[sonNode]->addParent(node, modality);
211  }
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * functionGraph__
The multidimdecisiongraph supposed to be edited.
#define GUM_ERROR(type, msg)
Definition: exceptions.h:54

Friends And Related Function Documentation

◆ MultiDimFunctionGraph

template<typename GUM_SCALAR, template< typename > class TerminalNodePolicy>
MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >* MultiDimFunctionGraph ( )
friend

This friend methods from is the only way to get an instance of a manager.

See class description for more info.

Member Data Documentation

◆ functionGraph__

template<typename GUM_SCALAR, template< typename > class TerminalNodePolicy>
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy >* gum::MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::functionGraph__
private

The multidimdecisiongraph supposed to be edited.

Definition at line 313 of file multiDimFunctionGraphManager.h.


The documentation for this class was generated from the following files: