aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
multiDimFunctionGraphManager_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /**
23  * @file
24  * @brief 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
40  MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::MultiDimFunctionGraphManager(
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 >
56  const NodeId& root) {
58  }
59 
60  // Inserts a new non terminal node in graph.
61  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
63  const DiscreteVariable* var,
64  NodeId nid) {
66 
68 
70 
71  return nid;
72  }
73 
74  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
76  const DiscreteVariable* var) {
81 
82  return nid;
83  }
84 
85  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
87  const DiscreteVariable* var,
88  NodeId* sons) {
93  for (Idx i = 0; i < newNodeStruct->nbSons(); i++)
96 
97  return nid;
98  }
99 
100  // Adds a value to the MultiDimFunctionGraph.
101  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
103  const GUM_SCALAR& value) {
106 
109  return node;
110  }
111 
112  // Erases a node from the diagram.
113  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
114  void
117  bool updateParents) {
119  GUM_ERROR(NotFound, "Node : " << eraseId << " doesn't exists in the graph")
120 
124  ++iterVar) {
126  while (nodeIter != nullptr) {
127  for (Idx modality = 0; modality < (*iterVar)->domainSize(); ++modality)
130 
132  }
133  }
135 
136  } else {
138 
139  if (updateParents) {
140  Link< Parent >* picle = eraseNode->parents();
141  while (picle != nullptr) {
143  picle = picle->nextLink();
144  }
145  }
146 
149 
152  }
153 
155 
157  }
158 
159  /// Sets nodes son for given modality to designated son node
160  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
161  INLINE void
163  const Idx& modality,
164  const NodeId& sonNode) {
165  // Ensuring that both nodes exists in the graph
167  GUM_ERROR(NotFound, "Node : " << node << " doesn't exists in the graph")
169  GUM_ERROR(NotFound, "Node : " << sonNode << " doesn't exists in the graph")
170 
171  // Check if starting node is not terminal
173  GUM_ERROR(InvalidNode, "You cannot insert an arc from terminal node : " << node)
174 
175  // Check if associated modality is lower than node bound variable domain
176  // size
180  "Modality " << modality << "is higher than domain size "
182  << "minus 1 of variable "
184 
185  // Check if variable order is respected
192  "Variable " << _functionGraph_->_internalNodeMap_[node]->nodeVar()
193  << " is after variable "
195  << "in Function Graph order.")
196 
200  }
201 
202  // Changes var position in variable sequence
203  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
205  // Ordering variables by number of nodes asssociated to them
211  ++varIter) {
213  Idx nbElem = 0;
214  for (; curElem != nullptr; nbElem++, curElem = curElem->nextLink())
215  ;
219  while (pos > 0 && varLvlSize[siftingSeq.atPos(pos - 1)] > nbElem) {
220  siftingSeq.swap(pos - 1, pos);
221  pos--;
222  }
223  }
224 
225  // Sifting var par var
228  ++sifIter) {
229  // Initialization
233 
234 
235  // Sifting towards upper places
236  while (currentPos > 0) {
237  moveTo(*sifIter, currentPos - 1);
239  if (_functionGraph_->realSize() < bestSize) {
242  }
243  }
244 
245  // Sifting towards lower places
246  while (currentPos < _functionGraph_->variablesSequence().size() - 1) {
247  moveTo(*sifIter, currentPos + 1);
249  if (_functionGraph_->realSize() < bestSize) {
252  }
253  }
254 
256  }
257  }
258 
259  // Changes var position in variable sequence
260  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
262  const DiscreteVariable* movedVar,
263  Idx desiredPos) {
264  // First we determine the position of both variable
265  // We also determine which one precede the other
269  currentPos--) {
275  }
276  else
279  currentPos++) {
285  }
286  }
287 
288  // Swap two adjacent variable.
289  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
291  const DiscreteVariable* x,
292  const DiscreteVariable* y) {
297 
298 
299  InternalNode* currentOldXNode = nullptr;
300  NodeId* currentNewXNodeSons = nullptr;
301  Idx indx = 0;
302 
303  NodeId* currentNewYNodeSons = nullptr;
305  Idx indy = 0;
306 
307  while (oldxNodes->list()) {
308  // Recuperating a node associated to variables x
310 
311  // Creating a new node associated to variable y
313 
314  // Now the graph needs to be remap by inserting nodes bound to x
315  // for each values assumed by y
316  for (indy = 0; indy < y->domainSize(); ++indy) {
317  // Creating a new node bound to x that will be the son of the node
318  // tied to y for the current value assumed by y
320 
321  // Iterating on the different values taht x can assumed to do the remap
322  for (indx = 0; indx < x->domainSize(); ++indx) {
328  }
329 
330  // Inserting the new node bound to x
332  }
333 
334  // Replacing old node x by new node y
339  } else {
341  if (currentNewYNodeId != 0) {
344  } else {
345  // Updating the sons (they must not consider old x as their parent)
346  for (Idx i = 0; i < currentOldXNode->nodeVar()->domainSize(); ++i) {
349  oldxNodes->list()->element(),
350  i);
351  }
352  }
353  // Reaffecting old node x internal attributes to correct new one
355  // Updating new sons (they must consider the node as a parent)
356  for (Idx i = 0; i < currentOldXNode->nodeVar()->domainSize(); ++i) {
359  oldxNodes->list()->element(),
360  i);
361  }
362  }
363 
365  }
366  }
367 
369  }
370  delete oldxNodes;
371 
372  while (oldyNodes->list()) {
374  if (_functionGraph_->_internalNodeMap_[curId]->parents() == nullptr) {
379  ->removeParent(curId, i);
383  } else {
385  }
387  }
388  delete oldyNodes;
389  }
390 
391  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
393  const NodeId& origin,
394  const NodeId& destination) {
396  // Upating parents after the change
397  Link< Parent >* picle = org->parents();
398  while (picle != nullptr) {
400  picle = picle->nextLink();
401  }
402 
403  // Updating sons after the change
404  for (Idx i = 0; i < org->nbSons(); ++i)
407 
408  delete org;
411 
413  }
414 
415  // Checks if a similar node does not already exists in the graph or
416  // if it has the same child for every variable value.
417  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
418  INLINE NodeId
420  const DiscreteVariable* var,
421  NodeId* sonsIds) {
422  NodeId newNode = sonsIds[0];
423 
424  if (_isRedundant_(var, sonsIds)) {
425  SOA_DEALLOCATE(sonsIds, sizeof(NodeId) * var->domainSize());
426  } else {
428  if (newNode == 0) {
430  } else {
431  SOA_DEALLOCATE(sonsIds, sizeof(NodeId) * var->domainSize());
432  }
433  }
434 
435  return newNode;
436  }
437 
438  // Checks if a similar node does not already exists in the graph.
439  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
441  const DiscreteVariable* var,
442  NodeId* sons) {
443  const InternalNode* nody = nullptr;
444  Idx i = 0;
445 
446  // Check abscence of identical node
448  while (currentElem != nullptr) {
450 
451  // Check on the other sons
452  i = 0;
453  while (i < var->domainSize() && sons[i] == nody->son(i))
454  ++i;
455  if (i == var->domainSize()) return currentElem->element();
456 
458  }
459  return 0;
460  }
461 
462  // Checks if node has the same child for every variable value
463  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
465  const DiscreteVariable* var,
466  NodeId* sons) {
467  for (Idx m = 1; m < var->domainSize(); m++)
468  if (sons[m] != sons[0]) return false;
469  return true;
470  }
471 
472  // Ensures that every isomorphic subgraphs are merged together.
473  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
475  Link< NodeId >* currentNodeId = nullptr;
476  Link< NodeId >* nextNodeId = nullptr;
477  InternalNode* currentNode = nullptr;
478  bool theSame = true;
479  Idx currentInd;
480 
484  --varIter) {
486 
487  while (currentNodeId != nullptr) {
490 
491  // First isomorphism to handle is the one where all node children are
492  // the same
493  theSame = true;
494  for (currentInd = 1; currentInd < (*varIter)->domainSize(); currentInd++) {
495  if (currentNode->son(currentInd) != currentNode->son(0)) {
496  theSame = false;
497  break;
498  }
499  }
500 
501  if (theSame == true) {
505  continue;
506  }
507 
508  // Second isomorphism to handle is the one where two nodes have same
509  // variable and same children
510  if (nextNodeId) {
512  InternalNode* anotherNode = nullptr;
513  Idx modality = 0;
514  while (anotherNodeId->nextLink() != nullptr) {
517 
518  // Check on the other sons
519  for (modality = 0; modality < (*varIter)->domainSize(); ++modality) {
520  if (anotherNode->son(modality) != currentNode->son(modality)) break;
521  if (modality == (*varIter)->domainSize() - 1) {
525  }
526  }
527 
529  }
530  }
532  }
533  }
534  }
535 
536  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
540  varIter != oldSequence.end();
541  ++varIter)
543  }
544 
545  // ==========================================================================
546  // MultiDimFunctionGraphTreeManager
547  // ==========================================================================
548 
549  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
555  }
556 
557  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
561  }
562 
563  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
565  const DiscreteVariable* var,
566  NodeId* sons) {
567  return this->addInternalNode_(var, sons);
568  }
569 
570  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
572 
573  // ===========================================================================
574  // MultiDimFunctionGraphROManager
575  // ===========================================================================
576 
577  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 >
592  const DiscreteVariable* var,
593  NodeId* sons) {
594  return this->nodeRedundancyCheck_(var, sons);
595  }
596 
597  template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
599  this->reduce_();
600  }
601 
602 } // namespace gum
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643