aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
multiDimFunctionGraphManager_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 Template methods of gum::MultiDimFunctionGraphManager.
25  *
26  * @author Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
27  * @author Pierre-Henri WUILLEMIN(@LIP6) and Jean-Christophe MAGNAN and Christophe
28  * GONZALES(@AMU)
29  *
30  */
31 #include <agrum/tools/core/sequence.h>
32 #include <agrum/tools/multidim/implementations/multiDimFunctionGraphManager.h>
33 #include <agrum/tools/multidim/utils/FunctionGraphUtilities/link.h>
34 
35 namespace gum {
36 
37  // Default constructor
38  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
39  INLINE MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::
44  }
45 
46  // Destructor
47  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
51  }
52 
53  /// Sets root node of decision diagram
54  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
55  INLINE void
57  const NodeId& root) {
59  }
60 
61  // Inserts a new non terminal node in graph.
62  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
66 
68 
70 
71  return nid;
72  }
73 
74  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
81 
82  return nid;
83  }
84 
85  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
92  for (Idx i = 0; i < newNodeStruct->nbSons(); i++)
95 
96  return nid;
97  }
98 
99  // Adds a value to the MultiDimFunctionGraph.
100  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
105 
108  return node;
109  }
110 
111  // Erases a node from the diagram.
112  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
114  NodeId eraseId,
116  bool updateParents) {
118  GUM_ERROR(NotFound, "Node : " << eraseId << " doesn't exists in the graph")
119 
123  ++iterVar) {
124  Link< NodeId >* nodeIter
126  while (nodeIter != nullptr) {
127  for (Idx modality = 0; modality < (*iterVar)->domainSize(); ++modality)
129  == eraseId)
131 
133  }
134  }
136 
137  } else {
139 
140  if (updateParents) {
141  Link< Parent >* picle = eraseNode->parents();
142  while (picle != nullptr) {
145  replacingId);
146  picle = picle->nextLink();
147  }
148  }
149 
153 
156  }
157 
159 
161  }
162 
163  /// Sets nodes son for given modality to designated son node
164  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
165  INLINE void
167  const NodeId& node,
168  const Idx& modality,
169  const NodeId& sonNode) {
170  // Ensuring that both nodes exists in the graph
172  GUM_ERROR(NotFound, "Node : " << node << " doesn't exists in the graph")
174  GUM_ERROR(NotFound, "Node : " << sonNode << " doesn't exists in the graph")
175 
176  // Check if starting node is not terminal
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
184  && modality
186  - 1)
187  GUM_ERROR(
189  "Modality "
190  << modality << "is higher than domain size "
192  << "minus 1 of variable "
194 
195  // Check if variable order is respected
201  GUM_ERROR(
203  "Variable " << functionGraph__->internalNodeMap__[node]->nodeVar()
204  << " is after variable "
206  << "in Function Graph order.")
207 
211  }
212 
213  // Changes var position in variable sequence
214  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
217  // Ordering variables by number of nodes asssociated to them
223  ++varIter) {
224  const Link< NodeId >* curElem
226  Idx nbElem = 0;
227  for (; curElem != nullptr; nbElem++, curElem = curElem->nextLink())
228  ;
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
240  = siftingSeq.beginSafe();
242  ++sifIter) {
243  // Initialization
247 
248 
249  // Sifting towards upper places
250  while (currentPos > 0) {
251  moveTo(*sifIter, currentPos - 1);
253  if (functionGraph__->realSize() < bestSize) {
256  }
257  }
258 
259  // Sifting towards lower places
260  while (currentPos < functionGraph__->variablesSequence().size() - 1) {
261  moveTo(*sifIter, currentPos + 1);
263  if (functionGraph__->realSize() < bestSize) {
266  }
267  }
268 
270  }
271  }
272 
273  // Changes var position in variable sequence
274  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
276  const DiscreteVariable* movedVar,
277  Idx desiredPos) {
278  // First we determine the position of both variable
279  // We also determine which one precede the other
283  currentPos--) {
284  const DiscreteVariable* preVar
290  }
291  else
294  currentPos++) {
295  const DiscreteVariable* suiVar
301  }
302  }
303 
304  // Swap two adjacent variable.
305  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
312 
313 
314  InternalNode* currentOldXNode = nullptr;
315  NodeId* currentNewXNodeSons = nullptr;
316  Idx indx = 0;
317 
318  NodeId* currentNewYNodeSons = nullptr;
320  Idx indy = 0;
321 
322  while (oldxNodes->list()) {
323  // Recuperating a node associated to variables x
326 
327  // Creating a new node associated to variable 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
336 
337  // Iterating on the different values taht x can assumed to do the remap
338  for (indx = 0; indx < x->domainSize(); ++indx) {
344  }
345 
346  // Inserting the new node bound to x
348  }
349 
350  // Replacing old node x by new node y
355  } else {
357  if (currentNewYNodeId != 0) {
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) {
364  currentOldXNode->son(i))) {
366  ->removeParent(oldxNodes->list()->element(), i);
367  }
368  }
369  // Reaffecting old node x internal attributes to correct new one
371  // Updating new sons (they must consider the node as a parent)
372  for (Idx i = 0; i < currentOldXNode->nodeVar()->domainSize(); ++i) {
376  ->addParent(oldxNodes->list()->element(), i);
377  }
378  }
379 
381  oldxNodes->list()->element());
382  }
383  }
384 
386  }
387  delete oldxNodes;
388 
389  while (oldyNodes->list()) {
391  if (functionGraph__->internalNodeMap__[curId]->parents() == nullptr) {
392  for (Idx i = 0;
393  i
395  ++i)
400  i)]
401  ->removeParent(curId, i);
405  } else {
407  }
409  }
410  delete oldyNodes;
411  }
412 
413  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
414  INLINE void
416  const NodeId& origin,
417  const NodeId& destination) {
419  // Upating parents after the change
420  Link< Parent >* picle = org->parents();
421  while (picle != nullptr) {
423  picle = picle->nextLink();
424  }
425 
426  // Updating sons after the change
427  for (Idx i = 0; i < org->nbSons(); ++i)
430 
431  delete org;
434 
436  }
437 
438  // Checks if a similar node does not already exists in the graph or
439  // if it has the same child for every variable value.
440  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
443  NodeId newNode = sonsIds[0];
444 
445  if (isRedundant__(var, sonsIds)) {
446  SOA_DEALLOCATE(sonsIds, sizeof(NodeId) * var->domainSize());
447  } else {
449  if (newNode == 0) {
451  } else {
452  SOA_DEALLOCATE(sonsIds, sizeof(NodeId) * var->domainSize());
453  }
454  }
455 
456  return newNode;
457  }
458 
459  // Checks if a similar node does not already exists in the graph.
460  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
463  const InternalNode* nody = nullptr;
464  Idx i = 0;
465 
466  // Check abscence of identical node
468  while (currentElem != nullptr) {
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 
478  }
479  return 0;
480  }
481 
482  // Checks if node has the same child for every variable value
483  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
484  INLINE bool
486  const DiscreteVariable* var,
487  NodeId* sons) {
488  for (Idx m = 1; m < var->domainSize(); m++)
489  if (sons[m] != sons[0]) return false;
490  return true;
491  }
492 
493  // Ensures that every isomorphic subgraphs are merged together.
494  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
495  INLINE void
497  Link< NodeId >* currentNodeId = nullptr;
498  Link< NodeId >* nextNodeId = nullptr;
499  InternalNode* currentNode = nullptr;
500  bool theSame = true;
501  Idx currentInd;
502 
506  --varIter) {
508 
509  while (currentNodeId != nullptr) {
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) {
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) {
535  InternalNode* anotherNode = nullptr;
536  Idx modality = 0;
537  while (anotherNodeId->nextLink() != nullptr) {
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) {
549  }
550  }
551 
553  }
554  }
556  }
557  }
558  }
559 
560  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
561  INLINE void
566  varIter != oldSequence.end();
567  ++varIter)
570  }
571 
572  // ==========================================================================
573  // MultiDimFunctionGraphTreeManager
574  // ==========================================================================
575 
576  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
582  }
583 
584  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
588  }
589 
590  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
593  return this->addInternalNode_(var, sons);
594  }
595 
596  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
597  void
599  }
600 
601  // ===========================================================================
602  // MultiDimFunctionGraphROManager
603  // ===========================================================================
604 
605  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
611  }
612 
613  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
617  }
618 
619  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
622  return this->nodeRedundancyCheck_(var, sons);
623  }
624 
625  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
627  this->reduce_();
628  }
629 
630 } // namespace gum
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669