aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
multiDimFunctionGraphManager_tpl.h
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2025 by *
5 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
6 * - Christophe GONZALES(_at_AMU) *
7 * *
8 * The aGrUM/pyAgrum library is free software; you can redistribute it *
9 * and/or modify it under the terms of either : *
10 * *
11 * - the GNU Lesser General Public License as published by *
12 * the Free Software Foundation, either version 3 of the License, *
13 * or (at your option) any later version, *
14 * - the MIT license (MIT), *
15 * - or both in dual license, as here. *
16 * *
17 * (see https://agrum.gitlab.io/articles/dual-licenses-lgplv3mit.html) *
18 * *
19 * This aGrUM/pyAgrum library is distributed in the hope that it will be *
20 * useful, but WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
21 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES MERCHANTABILITY or FITNESS *
22 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
26 * OTHER DEALINGS IN THE SOFTWARE. *
27 * *
28 * See LICENCES for more details. *
29 * *
30 * SPDX-FileCopyrightText: Copyright 2005-2025 *
31 * - Pierre-Henri WUILLEMIN(_at_LIP6) *
32 * - Christophe GONZALES(_at_AMU) *
33 * SPDX-License-Identifier: LGPL-3.0-or-later OR MIT *
34 * *
35 * Contact : info_at_agrum_dot_org *
36 * homepage : http://agrum.gitlab.io *
37 * gitlab : https://gitlab.com/agrumery/agrum *
38 * *
39 ****************************************************************************/
40#pragma once
41
42
55
56namespace gum {
57
58 // Default constructor
59 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
60 INLINE
66
67 // Destructor
68 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
69 INLINE MultiDimFunctionGraphManager< GUM_SCALAR,
70 TerminalNodePolicy >::~MultiDimFunctionGraphManager() {
71 GUM_DESTRUCTOR(MultiDimFunctionGraphManager);
72 }
73
75 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
80
81 // Inserts a new non terminal node in graph.
82 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
84 const DiscreteVariable* var,
85 NodeId nid) {
86 InternalNode* newNodeStruct = new InternalNode(var);
87
88 _functionGraph_->_internalNodeMap_.insert(nid, newNodeStruct);
89
90 _functionGraph_->_var2NodeIdMap_[var]->addLink(nid);
91
92 return nid;
93 }
94
95 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
97 const DiscreteVariable* var) {
98 InternalNode* newNodeStruct = new InternalNode(var);
99 NodeId nid = _functionGraph_->_model_.addNode();
100 _functionGraph_->_internalNodeMap_.insert(nid, newNodeStruct);
101 _functionGraph_->_var2NodeIdMap_[var]->addLink(nid);
102
103 return nid;
104 }
105
106 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
108 const DiscreteVariable* var,
109 NodeId* sons) {
110 InternalNode* newNodeStruct = new InternalNode(var, sons);
111 NodeId nid = _functionGraph_->_model_.addNode();
112 _functionGraph_->_internalNodeMap_.insert(nid, newNodeStruct);
113 _functionGraph_->_var2NodeIdMap_[var]->addLink(nid);
114 for (Idx i = 0; i < newNodeStruct->nbSons(); i++)
115 if (!_functionGraph_->isTerminalNode(sons[i]))
116 _functionGraph_->_internalNodeMap_[sons[i]]->addParent(nid, i);
117
118 return nid;
119 }
121 // Adds a value to the MultiDimFunctionGraph.
122 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
124 const GUM_SCALAR& value) {
125 if (_functionGraph_->existsTerminalNodeWithValue(value))
126 return _functionGraph_->terminalNodeId(value);
128 NodeId node = _functionGraph_->_model_.addNode();
129 _functionGraph_->addTerminalNode(node, value);
130 return node;
131 }
132
133 // Erases a node from the diagram.
134 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
136 NodeId eraseId,
137 NodeId replacingId,
138 bool updateParents) {
139 if (!_functionGraph_->_model_.exists(eraseId))
140 GUM_ERROR(NotFound, "Node : " << eraseId << " doesn't exists in the graph")
141
142 if (_functionGraph_->isTerminalNode(eraseId)) {
143 for (auto iterVar = _functionGraph_->variablesSequence().begin();
144 iterVar != _functionGraph_->variablesSequence().end();
145 ++iterVar) {
146 Link< NodeId >* nodeIter = _functionGraph_->_var2NodeIdMap_[*iterVar]->list();
147 while (nodeIter != nullptr) {
148 for (Idx modality = 0; modality < (*iterVar)->domainSize(); ++modality)
149 if (_functionGraph_->node(nodeIter->element())->son(modality) == eraseId)
150 setSon(nodeIter->element(), modality, replacingId);
151
152 nodeIter = nodeIter->nextLink();
153 }
154 }
155 _functionGraph_->eraseTerminalNode(eraseId);
156
157 } else {
158 InternalNode* eraseNode = _functionGraph_->_internalNodeMap_[eraseId];
159
160 if (updateParents) {
161 Link< Parent >* picle = eraseNode->parents();
162 while (picle != nullptr) {
163 setSon(picle->element().parentId, picle->element().modality, replacingId);
164 picle = picle->nextLink();
165 }
166 }
167
168 _functionGraph_->_var2NodeIdMap_[_functionGraph_->_internalNodeMap_[eraseId]->nodeVar()]
169 ->searchAndRemoveLink(eraseId);
170
171 delete _functionGraph_->_internalNodeMap_[eraseId];
172 _functionGraph_->_internalNodeMap_.erase(eraseId);
174
175 _functionGraph_->_model_.eraseNode(eraseId);
176
177 if (_functionGraph_->_root_ == eraseId) _functionGraph_->_root_ = replacingId;
178 }
179
181 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
183 const NodeId& node,
184 const Idx& modality,
185 const NodeId& sonNode) {
186 // Ensuring that both nodes exists in the graph
187 if (!_functionGraph_->_model_.exists(node))
188 GUM_ERROR(NotFound, "Node : " << node << " doesn't exists in the graph")
189 if (!_functionGraph_->_model_.exists(sonNode))
190 GUM_ERROR(NotFound, "Node : " << sonNode << " doesn't exists in the graph")
191
192 // Check if starting node is not terminal
193 if (_functionGraph_->isTerminalNode(node))
194 GUM_ERROR(InvalidNode, "You cannot insert an arc from terminal node : " << node)
195
196 // Check if associated modality is lower than node bound variable domain
197 // size
198 if (_functionGraph_->isInternalNode(node)
199 && modality > _functionGraph_->_internalNodeMap_[node]->nodeVar()->domainSize() - 1)
201 "Modality " << modality << "is higher than domain size "
202 << _functionGraph_->_internalNodeMap_[node]->nodeVar()->domainSize()
203 << "minus 1 of variable "
204 << _functionGraph_->_internalNodeMap_[node]->nodeVar()->name())
205
206 // Check if variable order is respected
207 if (_functionGraph_->isInternalNode(sonNode)
208 && _functionGraph_->variablesSequence().pos(
209 _functionGraph_->_internalNodeMap_[node]->nodeVar())
210 >= _functionGraph_->variablesSequence().pos(
211 _functionGraph_->_internalNodeMap_[sonNode]->nodeVar()))
213 "Variable " << _functionGraph_->_internalNodeMap_[node]->nodeVar()
214 << " is after variable "
215 << _functionGraph_->_internalNodeMap_[sonNode]->nodeVar()
216 << "in Function Graph order.")
217
218 _functionGraph_->_internalNodeMap_[node]->setSon(modality, sonNode);
219 if (sonNode && !_functionGraph_->isTerminalNode(sonNode))
220 _functionGraph_->_internalNodeMap_[sonNode]->addParent(node, modality);
221 }
222
223 // Changes var position in variable sequence
224 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
225 void MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy >::minimizeSize() {
226 // Ordering variables by number of nodes asssociated to them
230 = _functionGraph_->variablesSequence().beginSafe();
231 varIter != _functionGraph_->variablesSequence().endSafe();
232 ++varIter) {
233 const Link< NodeId >* curElem = _functionGraph_->_var2NodeIdMap_[*varIter]->list();
234 Idx nbElem = 0;
235 for (; curElem != nullptr; nbElem++, curElem = curElem->nextLink())
236 ;
237 varLvlSize.insert(*varIter, nbElem);
238 siftingSeq.insert(*varIter);
239 Idx pos = siftingSeq.pos(*varIter);
240 while (pos > 0 && varLvlSize[siftingSeq.atPos(pos - 1)] > nbElem) {
241 siftingSeq.swap(pos - 1, pos);
242 pos--;
243 }
244 }
245
246 // Sifting var par var
248 sifIter != siftingSeq.endSafe();
249 ++sifIter) {
250 // Initialization
251 Idx currentPos = _functionGraph_->variablesSequence().pos(*sifIter);
252 Idx bestSize = _functionGraph_->realSize();
253 Idx bestPos = currentPos;
254
255
256 // Sifting towards upper places
257 while (currentPos > 0) {
258 moveTo(*sifIter, currentPos - 1);
259 currentPos = _functionGraph_->variablesSequence().pos(*sifIter);
260 if (_functionGraph_->realSize() < bestSize) {
261 bestPos = currentPos;
262 bestSize = _functionGraph_->realSize();
263 }
264 }
265
266 // Sifting towards lower places
267 while (currentPos < _functionGraph_->variablesSequence().size() - 1) {
268 moveTo(*sifIter, currentPos + 1);
269 currentPos = _functionGraph_->variablesSequence().pos(*sifIter);
270 if (_functionGraph_->realSize() < bestSize) {
271 bestPos = currentPos;
272 bestSize = _functionGraph_->realSize();
273 }
274 }
275
276 moveTo(*sifIter, bestPos);
277 }
278 }
279
280 // Changes var position in variable sequence
281 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
283 const DiscreteVariable* movedVar,
284 Idx desiredPos) {
285 // First we determine the position of both variable
286 // We also determine which one precede the other
287 if (_functionGraph_->variablesSequence().pos(movedVar) > desiredPos)
288 for (Idx currentPos = _functionGraph_->variablesSequence().pos(movedVar);
289 currentPos != desiredPos;
290 currentPos--) {
291 const DiscreteVariable* preVar = _functionGraph_->variablesSequence().atPos(currentPos - 1);
292 if (_functionGraph_->_var2NodeIdMap_[preVar]->list()
293 && _functionGraph_->_var2NodeIdMap_[movedVar]->list())
294 _adjacentSwap_(preVar, movedVar);
295 _functionGraph_->invert_(currentPos - 1, currentPos);
296 }
297 else
298 for (Idx currentPos = _functionGraph_->variablesSequence().pos(movedVar);
299 currentPos != desiredPos;
300 currentPos++) {
301 const DiscreteVariable* suiVar = _functionGraph_->variablesSequence().atPos(currentPos + 1);
302 if (_functionGraph_->_var2NodeIdMap_[suiVar]->list()
303 && _functionGraph_->_var2NodeIdMap_[movedVar]->list())
304 _adjacentSwap_(movedVar, suiVar);
305 _functionGraph_->invert_(currentPos, currentPos + 1);
306 }
307 }
308
309 // Swap two adjacent variable.
310 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
312 const DiscreteVariable* x,
313 const DiscreteVariable* y) {
314 LinkedList< NodeId >* oldxNodes = _functionGraph_->_var2NodeIdMap_[x];
315 _functionGraph_->_var2NodeIdMap_[x] = new LinkedList< NodeId >();
316 LinkedList< NodeId >* oldyNodes = _functionGraph_->_var2NodeIdMap_[y];
317 _functionGraph_->_var2NodeIdMap_[y] = new LinkedList< NodeId >();
318
319
320 InternalNode* currentOldXNode = nullptr;
321 NodeId* currentNewXNodeSons = nullptr;
322 Idx indx = 0;
323
324 NodeId* currentNewYNodeSons = nullptr;
325 NodeId currentNewYNodeId = 0;
326 Idx indy = 0;
327
328 while (oldxNodes->list()) {
329 // Recuperating a node associated to variables x
330 currentOldXNode = _functionGraph_->_internalNodeMap_[oldxNodes->list()->element()];
331
332 // Creating a new node associated to variable y
333 currentNewYNodeSons = InternalNode::allocateNodeSons(y);
334
335 // Now the graph needs to be remap by inserting nodes bound to x
336 // for each values assumed by y
337 for (indy = 0; indy < y->domainSize(); ++indy) {
338 // Creating a new node bound to x that will be the son of the node
339 // tied to y for the current value assumed by y
340 currentNewXNodeSons = InternalNode::allocateNodeSons(x);
341
342 // Iterating on the different values taht x can assumed to do the remap
343 for (indx = 0; indx < x->domainSize(); ++indx) {
344 currentNewXNodeSons[indx] = currentOldXNode->son(indx);
345 if (!_functionGraph_->isTerminalNode(currentOldXNode->son(indx))
346 && _functionGraph_->node(currentOldXNode->son(indx))->nodeVar() == y)
347 currentNewXNodeSons[indx]
348 = _functionGraph_->node(currentOldXNode->son(indx))->son(indy);
349 }
350
351 // Inserting the new node bound to x
352 currentNewYNodeSons[indy] = nodeRedundancyCheck_(x, currentNewXNodeSons);
353 }
354
355 // Replacing old node x by new node y
356 currentNewYNodeId = currentNewYNodeSons[0];
357 if (_isRedundant_(y, currentNewYNodeSons)) {
358 migrateNode_(oldxNodes->list()->element(), currentNewYNodeId);
359 SOA_DEALLOCATE(currentNewYNodeSons, y->domainSize() * sizeof(NodeId));
360 } else {
361 currentNewYNodeId = _checkIsomorphism_(y, currentNewYNodeSons);
362 if (currentNewYNodeId != 0) {
363 migrateNode_(oldxNodes->list()->element(), currentNewYNodeId);
364 SOA_DEALLOCATE(currentNewYNodeSons, y->domainSize() * sizeof(NodeId));
365 } else {
366 // Updating the sons (they must not consider old x as their parent)
367 for (Idx i = 0; i < currentOldXNode->nodeVar()->domainSize(); ++i) {
368 if (_functionGraph_->_internalNodeMap_.exists(currentOldXNode->son(i))) {
369 _functionGraph_->_internalNodeMap_[currentOldXNode->son(i)]->removeParent(
370 oldxNodes->list()->element(),
371 i);
372 }
373 }
374 // Reaffecting old node x internal attributes to correct new one
375 currentOldXNode->setNode(y, currentNewYNodeSons);
376 // Updating new sons (they must consider the node as a parent)
377 for (Idx i = 0; i < currentOldXNode->nodeVar()->domainSize(); ++i) {
378 if (_functionGraph_->_internalNodeMap_.exists(currentNewYNodeSons[i])) {
379 _functionGraph_->_internalNodeMap_[currentNewYNodeSons[i]]->addParent(
380 oldxNodes->list()->element(),
381 i);
382 }
383 }
384
385 _functionGraph_->_var2NodeIdMap_[y]->addLink(oldxNodes->list()->element());
386 }
387 }
388
389 oldxNodes->searchAndRemoveLink(oldxNodes->list()->element());
390 }
391 delete oldxNodes;
392
393 while (oldyNodes->list()) {
394 NodeId curId = oldyNodes->list()->element();
395 if (_functionGraph_->_internalNodeMap_[curId]->parents() == nullptr) {
396 for (Idx i = 0; i < _functionGraph_->_internalNodeMap_[curId]->nodeVar()->domainSize(); ++i)
397 if (_functionGraph_->_internalNodeMap_.exists(
398 _functionGraph_->_internalNodeMap_[curId]->son(i)))
399 _functionGraph_->_internalNodeMap_[_functionGraph_->_internalNodeMap_[curId]->son(i)]
400 ->removeParent(curId, i);
401 delete _functionGraph_->_internalNodeMap_[curId];
402 _functionGraph_->_internalNodeMap_.erase(curId);
403 _functionGraph_->_model_.eraseNode(curId);
404 } else {
405 _functionGraph_->_var2NodeIdMap_[y]->addLink(curId);
406 }
407 oldyNodes->searchAndRemoveLink(curId);
408 }
409 delete oldyNodes;
410 }
411
412 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
414 const NodeId& origin,
415 const NodeId& destination) {
416 InternalNode* org = _functionGraph_->_internalNodeMap_[origin];
417 // Upating parents after the change
418 Link< Parent >* picle = org->parents();
419 while (picle != nullptr) {
420 setSon(picle->element().parentId, picle->element().modality, destination);
421 picle = picle->nextLink();
422 }
423
424 // Updating sons after the change
425 for (Idx i = 0; i < org->nbSons(); ++i)
426 if (_functionGraph_->_internalNodeMap_.exists(org->son(i)))
427 _functionGraph_->_internalNodeMap_[org->son(i)]->removeParent(origin, i);
428
429 delete org;
430 _functionGraph_->_internalNodeMap_.erase(origin);
431 _functionGraph_->_model_.eraseNode(origin);
432
433 if (_functionGraph_->root() == origin) this->setRootNode(destination);
434 }
435
436 // Checks if a similar node does not already exists in the graph or
437 // if it has the same child for every variable value.
438 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
439 INLINE NodeId
441 const DiscreteVariable* var,
442 NodeId* sonsIds) {
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 }
458
459 // Checks if a similar node does not already exists in the graph.
460 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
462 const DiscreteVariable* var,
463 NodeId* sons) {
464 const InternalNode* nody = nullptr;
465 Idx i = 0;
466
467 // Check abscence of identical node
468 Link< NodeId >* currentElem = _functionGraph_->_var2NodeIdMap_[var]->list();
469 while (currentElem != nullptr) {
470 nody = _functionGraph_->_internalNodeMap_[currentElem->element()];
471
472 // Check on the other sons
473 i = 0;
474 while (i < var->domainSize() && sons[i] == nody->son(i))
475 ++i;
476 if (i == var->domainSize()) return currentElem->element();
477
478 currentElem = currentElem->nextLink();
479 }
480 return 0;
481 }
482
483 // Checks if node has the same child for every variable value
484 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
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 >
496 Link< NodeId >* currentNodeId = nullptr;
497 Link< NodeId >* nextNodeId = nullptr;
498 InternalNode* currentNode = nullptr;
499 bool theSame = true;
500 Idx currentInd;
501
502 for (SequenceIterator< const DiscreteVariable* > varIter
503 = _functionGraph_->variablesSequence().rbegin();
504 varIter != _functionGraph_->variablesSequence().rend();
505 --varIter) {
506 currentNodeId = _functionGraph_->_var2NodeIdMap_[*varIter]->list();
507
508 while (currentNodeId != nullptr) {
509 nextNodeId = currentNodeId->nextLink();
510 currentNode = _functionGraph_->_internalNodeMap_[currentNodeId->element()];
511
512 // First isomorphism to handle is the one where all node children are
513 // the same
514 theSame = true;
515 for (currentInd = 1; currentInd < (*varIter)->domainSize(); currentInd++) {
516 if (currentNode->son(currentInd) != currentNode->son(0)) {
517 theSame = false;
518 break;
519 }
520 }
521
522 if (theSame == true) {
523 migrateNode_(currentNodeId->element(), currentNode->son(0));
524 _functionGraph_->_var2NodeIdMap_[*varIter]->searchAndRemoveLink(currentNodeId->element());
525 currentNodeId = nextNodeId;
526 continue;
527 }
528
529 // Second isomorphism to handle is the one where two nodes have same
530 // variable and same children
531 if (nextNodeId) {
532 Link< NodeId >* anotherNodeId = currentNodeId->nextLink();
533 InternalNode* anotherNode = nullptr;
534 Idx modality = 0;
535 while (anotherNodeId->nextLink() != nullptr) {
536 nextNodeId = anotherNodeId->nextLink();
537 anotherNode = _functionGraph_->_internalNodeMap_[anotherNodeId->element()];
538
539 // Check on the other sons
540 for (modality = 0; modality < (*varIter)->domainSize(); ++modality) {
541 if (anotherNode->son(modality) != currentNode->son(modality)) break;
542 if (modality == (*varIter)->domainSize() - 1) {
543 migrateNode_(anotherNodeId->element(), currentNodeId->element());
544 _functionGraph_->_var2NodeIdMap_[*varIter]->searchAndRemoveLink(
545 anotherNodeId->element());
546 }
547 }
548
549 anotherNodeId = nextNodeId;
550 }
551 }
552 currentNodeId = currentNodeId->nextLink();
553 }
554 }
555 }
556
557 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
559 Sequence< const DiscreteVariable* > oldSequence(_functionGraph_->variablesSequence());
560 for (SequenceIterator< const DiscreteVariable* > varIter = oldSequence.begin();
561 varIter != oldSequence.end();
562 ++varIter)
563 if (!_functionGraph_->varNodeListe(*varIter)->list()) _functionGraph_->erase(**varIter);
564 }
565
566 // ==========================================================================
567 // MultiDimFunctionGraphTreeManager
568 // ==========================================================================
569
570 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
577
578 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
581 GUM_DESTRUCTOR(MultiDimFunctionGraphTreeManager);
582 }
583
584 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
590
591 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
593
594 // ===========================================================================
595 // MultiDimFunctionGraphROManager
596 // ===========================================================================
597
598 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
604
605 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
607 TerminalNodePolicy >::~MultiDimFunctionGraphROManager() {
608 GUM_DESTRUCTOR(MultiDimFunctionGraphROManager);
609 }
610
611 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
617
618 template < typename GUM_SCALAR, template < class > class TerminalNodePolicy >
622
623} // namespace gum
Base class for discrete random variable.
virtual Size domainSize() const =0
The class for generic Hash Tables.
Definition hashTable.h:637
Structure used to represent a node internal structure.
void setNode(const DiscreteVariable *v, NodeId *sons)
Allows you to respecify the node, changing its attached variable as well as its son map.
const DiscreteVariable * nodeVar() const
Returns the node variable.
Idx nbSons() const
Returns the number of sons.
static NodeId * allocateNodeSons(const DiscreteVariable *v)
Allocates a table of nodeid of the size given in parameter.
NodeId son(Idx modality) const
Returns the son at a given index.
Link< Parent > * parents()
Returns the list of parents.
Exception: at least one argument passed to a function is not what was expected.
Exception : node does not exist.
void searchAndRemoveLink(const T &elem)
Removes a element from the list.
Definition link_tpl.h:163
const Link< T > * list() const
Returns the first link in the chained list.
Definition link_tpl.h:136
Class implementingting a function graph manager.
void eraseNode(NodeId id, NodeId replacingId=0, bool updateParents=true)
Erases a node from the diagram.
bool _isRedundant_(const DiscreteVariable *var, NodeId *sons)
Checks if node has the same child for every variable value.
NodeId addInternalNode_(const DiscreteVariable *var, NodeId *sons)
Adds an internal node.
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * _functionGraph_
The multidimdecisiongraph supposed to be edited.
void _adjacentSwap_(const DiscreteVariable *x, const DiscreteVariable *y)
void reduce_()
Ensures that every isomorphic subgraphs are merged together.
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...
void clean()
Removes var without nodes in the diagram.
void setRootNode(const NodeId &root)
Sets root node of decision diagram.
void minimizeSize()
Performs a sifting in search of a(local) minimal size.
NodeId addTerminalNode(const GUM_SCALAR &value)
Adds a value to the MultiDimFunctionGraph.
MultiDimFunctionGraphManager(MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > *master)
Default constructor.
NodeId addInternalNode(const DiscreteVariable *var)
Inserts a new non terminal node in graph.
NodeId _checkIsomorphism_(const DiscreteVariable *var, NodeId *sons)
Checks if a similar node does not already exists in the graph.
void setSon(const NodeId &node, const Idx &modality, const NodeId &sonNode)
Sets nodes son for given modality to designated son node.
NodeId nodeRedundancyCheck_(const DiscreteVariable *var, NodeId *sonsMap)
Check for redundancy.
MultiDimFunctionGraphROManager(MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > *master)
virtual void reduce()
Ensures that every isomorphic subgraphs are merged together.
virtual NodeId addInternalNode(const DiscreteVariable *var, NodeId *sons)
Inserts a new non terminal node in graph.
MultiDimFunctionGraphTreeManager(MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > *master)
Class constructor.
virtual NodeId addInternalNode(const DiscreteVariable *var, NodeId *sons)
Inserts a new non terminal node in graph.
virtual void reduce()
Ensures that every isomorphic subgraphs are merged together.
Exception : the element we looked for cannot be found.
Exception : operation not allowed.
const iterator & end() const noexcept
Returns the unsafe end iterator.
iterator_safe beginSafe() const
Returns a safe begin iterator.
iterator begin() const
Returns an unsafe begin iterator.
const iterator_safe & endSafe() const noexcept
Returns the safe end iterator.
Safe iterators for Sequence.
Definition sequence.h:1134
The generic class for storing (ordered) sequences of objects.
Definition sequence.h:972
#define GUM_ERROR(type, msg)
Definition exceptions.h:72
Size Idx
Type for indexes.
Definition types.h:79
Size NodeId
Type for node ids.
Headers of MultiDimFunctionGraphManager.
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
Header file of gum::Sequence, a class for storing (ordered) sequences of objects.
#define SOA_DEALLOCATE(x, y)