aGrUM 3.1.1
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-2026 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-2026 *
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
41#pragma once
42
43
56
57namespace gum {
58
59 // Default constructor
60 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
66
67 // Destructor
68 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
72
74 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
79
80 // Inserts a new non terminal node in graph.
81 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
83 const DiscreteVariable* var,
84 NodeId nid) {
85 InternalNode* newNodeStruct = new InternalNode(var);
86
87 _functionGraph_->_internalNodeMap_.insert(nid, newNodeStruct);
88
89 _functionGraph_->_var2NodeIdMap_[var]->addLink(nid);
90
91 return nid;
92 }
93
94 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
96 const DiscreteVariable* var) {
97 InternalNode* newNodeStruct = new InternalNode(var);
98 NodeId nid = _functionGraph_->_model_.addNode();
99 _functionGraph_->_internalNodeMap_.insert(nid, newNodeStruct);
100 _functionGraph_->_var2NodeIdMap_[var]->addLink(nid);
101
102 return nid;
103 }
104
105 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
107 const DiscreteVariable* var,
108 NodeId* sons) {
109 InternalNode* newNodeStruct = new InternalNode(var, sons);
110 NodeId nid = _functionGraph_->_model_.addNode();
111 _functionGraph_->_internalNodeMap_.insert(nid, newNodeStruct);
112 _functionGraph_->_var2NodeIdMap_[var]->addLink(nid);
113 for (Idx i = 0; i < newNodeStruct->nbSons(); i++)
114 if (!_functionGraph_->isTerminalNode(sons[i]))
115 _functionGraph_->_internalNodeMap_[sons[i]]->addParent(nid, i);
116
117 return nid;
118 }
119
120 // Adds a value to the MultiDimFunctionGraph.
121 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
123 const GUM_ELEMENT& value) {
124 if (_functionGraph_->existsTerminalNodeWithValue(value))
125 return _functionGraph_->terminalNodeId(value);
126
127 NodeId node = _functionGraph_->_model_.addNode();
128 _functionGraph_->addTerminalNode(node, value);
129 return node;
130 }
131
132 // Erases a node from the diagram.
133 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
135 NodeId eraseId,
136 NodeId replacingId,
137 bool updateParents) {
138 if (!_functionGraph_->_model_.exists(eraseId))
139 GUM_ERROR(NotFound, "Node : " << eraseId << " doesn't exists in the graph")
140
141 if (_functionGraph_->isTerminalNode(eraseId)) {
142 for (auto iterVar = _functionGraph_->variablesSequence().begin();
143 iterVar != _functionGraph_->variablesSequence().end();
144 ++iterVar) {
145 Link< NodeId >* nodeIter = _functionGraph_->_var2NodeIdMap_[*iterVar]->list();
146 while (nodeIter != nullptr) {
147 for (Idx modality = 0; modality < (*iterVar)->domainSize(); ++modality)
148 if (_functionGraph_->node(nodeIter->element())->son(modality) == eraseId)
149 setSon(nodeIter->element(), modality, replacingId);
150
151 nodeIter = nodeIter->nextLink();
152 }
153 }
154 _functionGraph_->eraseTerminalNode(eraseId);
155
156 } else {
157 InternalNode* eraseNode = _functionGraph_->_internalNodeMap_[eraseId];
158
159 if (updateParents) {
160 Link< Parent >* picle = eraseNode->parents();
161 while (picle != nullptr) {
162 setSon(picle->element().parentId, picle->element().modality, replacingId);
163 picle = picle->nextLink();
164 }
165 }
166
167 _functionGraph_->_var2NodeIdMap_[_functionGraph_->_internalNodeMap_[eraseId]->nodeVar()]
168 ->searchAndRemoveLink(eraseId);
169
170 delete _functionGraph_->_internalNodeMap_[eraseId];
171 _functionGraph_->_internalNodeMap_.erase(eraseId);
172 }
174 _functionGraph_->_model_.eraseNode(eraseId);
175
176 if (_functionGraph_->_root_ == eraseId) _functionGraph_->_root_ = replacingId;
177 }
178
180 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
182 const NodeId& node,
183 const Idx& modality,
184 const NodeId& sonNode) {
185 // Ensuring that both nodes exists in the graph
186 if (!_functionGraph_->_model_.exists(node))
187 GUM_ERROR(NotFound, "Node : " << node << " doesn't exists in the graph")
188 if (!_functionGraph_->_model_.exists(sonNode))
189 GUM_ERROR(NotFound, "Node : " << sonNode << " doesn't exists in the graph")
190
191 // Check if starting node is not terminal
192 if (_functionGraph_->isTerminalNode(node))
193 GUM_ERROR(InvalidNode, "You cannot insert an arc from terminal node : " << node)
194
195 // Check if associated modality is lower than node bound variable domain
196 // size
197 if (_functionGraph_->isInternalNode(node)
198 && modality > _functionGraph_->_internalNodeMap_[node]->nodeVar()->domainSize() - 1)
200 "Modality " << modality << "is higher than domain size "
201 << _functionGraph_->_internalNodeMap_[node]->nodeVar()->domainSize()
202 << "minus 1 of variable "
203 << _functionGraph_->_internalNodeMap_[node]->nodeVar()->name())
204
205 // Check if variable order is respected
206 if (_functionGraph_->isInternalNode(sonNode)
207 && _functionGraph_->variablesSequence().pos(
208 _functionGraph_->_internalNodeMap_[node]->nodeVar())
209 >= _functionGraph_->variablesSequence().pos(
210 _functionGraph_->_internalNodeMap_[sonNode]->nodeVar()))
212 "Variable " << _functionGraph_->_internalNodeMap_[node]->nodeVar()
213 << " is after variable "
214 << _functionGraph_->_internalNodeMap_[sonNode]->nodeVar()
215 << "in Function Graph order.")
216
217 _functionGraph_->_internalNodeMap_[node]->setSon(modality, sonNode);
218 if (sonNode && !_functionGraph_->isTerminalNode(sonNode))
219 _functionGraph_->_internalNodeMap_[sonNode]->addParent(node, modality);
220 }
221
222 // Changes var position in variable sequence
223 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
224 void MultiDimFunctionGraphManager< GUM_ELEMENT, TerminalNodePolicy >::minimizeSize() {
225 // Ordering variables by number of nodes asssociated to them
229 = _functionGraph_->variablesSequence().beginSafe();
230 varIter != _functionGraph_->variablesSequence().endSafe();
231 ++varIter) {
232 const Link< NodeId >* curElem = _functionGraph_->_var2NodeIdMap_[*varIter]->list();
233 Idx nbElem = 0;
234 for (; curElem != nullptr; nbElem++, curElem = curElem->nextLink())
235 ;
236 varLvlSize.insert(*varIter, nbElem);
237 siftingSeq.insert(*varIter);
238 Idx pos = siftingSeq.pos(*varIter);
239 while (pos > 0 && varLvlSize[siftingSeq.atPos(pos - 1)] > nbElem) {
240 siftingSeq.swap(pos - 1, pos);
241 pos--;
242 }
243 }
244
245 // Sifting var par var
247 sifIter != siftingSeq.endSafe();
248 ++sifIter) {
249 // Initialization
250 Idx currentPos = _functionGraph_->variablesSequence().pos(*sifIter);
251 Idx bestSize = _functionGraph_->realSize();
252 Idx bestPos = currentPos;
253
254
255 // Sifting towards upper places
256 while (currentPos > 0) {
257 moveTo(*sifIter, currentPos - 1);
258 currentPos = _functionGraph_->variablesSequence().pos(*sifIter);
259 if (_functionGraph_->realSize() < bestSize) {
260 bestPos = currentPos;
261 bestSize = _functionGraph_->realSize();
263 }
264
265 // Sifting towards lower places
266 while (currentPos < _functionGraph_->variablesSequence().size() - 1) {
267 moveTo(*sifIter, currentPos + 1);
268 currentPos = _functionGraph_->variablesSequence().pos(*sifIter);
269 if (_functionGraph_->realSize() < bestSize) {
270 bestPos = currentPos;
271 bestSize = _functionGraph_->realSize();
272 }
273 }
274
275 moveTo(*sifIter, bestPos);
276 }
277 }
278
279 // Changes var position in variable sequence
280 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
282 const DiscreteVariable* movedVar,
283 Idx desiredPos) {
284 // First we determine the position of both variable
285 // We also determine which one precede the other
286 if (_functionGraph_->variablesSequence().pos(movedVar) > desiredPos)
287 for (Idx currentPos = _functionGraph_->variablesSequence().pos(movedVar);
288 currentPos != desiredPos;
289 currentPos--) {
290 const DiscreteVariable* preVar = _functionGraph_->variablesSequence().atPos(currentPos - 1);
291 if (_functionGraph_->_var2NodeIdMap_[preVar]->list()
292 && _functionGraph_->_var2NodeIdMap_[movedVar]->list())
293 _adjacentSwap_(preVar, movedVar);
294 _functionGraph_->invert_(currentPos - 1, currentPos);
295 }
296 else
297 for (Idx currentPos = _functionGraph_->variablesSequence().pos(movedVar);
298 currentPos != desiredPos;
299 currentPos++) {
300 const DiscreteVariable* suiVar = _functionGraph_->variablesSequence().atPos(currentPos + 1);
301 if (_functionGraph_->_var2NodeIdMap_[suiVar]->list()
302 && _functionGraph_->_var2NodeIdMap_[movedVar]->list())
303 _adjacentSwap_(movedVar, suiVar);
304 _functionGraph_->invert_(currentPos, currentPos + 1);
305 }
306 }
307
308 // Swap two adjacent variable.
309 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
311 const DiscreteVariable* x,
312 const DiscreteVariable* y) {
313 LinkedList< NodeId >* oldxNodes = _functionGraph_->_var2NodeIdMap_[x];
314 _functionGraph_->_var2NodeIdMap_[x] = new LinkedList< NodeId >();
315 LinkedList< NodeId >* oldyNodes = _functionGraph_->_var2NodeIdMap_[y];
316 _functionGraph_->_var2NodeIdMap_[y] = new LinkedList< NodeId >();
317
318
319 InternalNode* currentOldXNode = nullptr;
320 NodeId* currentNewXNodeSons = nullptr;
321 Idx indx = 0;
323 NodeId* currentNewYNodeSons = nullptr;
324 NodeId currentNewYNodeId = 0;
325 Idx indy = 0;
326
327 while (oldxNodes->list()) {
328 // Recuperating a node associated to variables x
329 currentOldXNode = _functionGraph_->_internalNodeMap_[oldxNodes->list()->element()];
331 // Creating a new node associated to variable y
332 currentNewYNodeSons = InternalNode::allocateNodeSons(y);
333
334 // Now the graph needs to be remap by inserting nodes bound to x
335 // for each values assumed by y
336 for (indy = 0; indy < y->domainSize(); ++indy) {
337 // Creating a new node bound to x that will be the son of the node
338 // tied to y for the current value assumed by y
339 currentNewXNodeSons = InternalNode::allocateNodeSons(x);
340
341 // Iterating on the different values taht x can assumed to do the remap
342 for (indx = 0; indx < x->domainSize(); ++indx) {
343 currentNewXNodeSons[indx] = currentOldXNode->son(indx);
344 if (!_functionGraph_->isTerminalNode(currentOldXNode->son(indx))
345 && _functionGraph_->node(currentOldXNode->son(indx))->nodeVar() == y)
346 currentNewXNodeSons[indx]
347 = _functionGraph_->node(currentOldXNode->son(indx))->son(indy);
348 }
349
350 // Inserting the new node bound to x
351 currentNewYNodeSons[indy] = nodeRedundancyCheck_(x, currentNewXNodeSons);
352 }
353
354 // Replacing old node x by new node y
355 currentNewYNodeId = currentNewYNodeSons[0];
356 if (_isRedundant_(y, currentNewYNodeSons)) {
357 migrateNode_(oldxNodes->list()->element(), currentNewYNodeId);
358 SOA_DEALLOCATE(currentNewYNodeSons, y->domainSize() * sizeof(NodeId));
359 } else {
360 currentNewYNodeId = _checkIsomorphism_(y, currentNewYNodeSons);
361 if (currentNewYNodeId != 0) {
362 migrateNode_(oldxNodes->list()->element(), currentNewYNodeId);
363 SOA_DEALLOCATE(currentNewYNodeSons, y->domainSize() * sizeof(NodeId));
364 } else {
365 // Updating the sons (they must not consider old x as their parent)
366 for (Idx i = 0; i < currentOldXNode->nodeVar()->domainSize(); ++i) {
367 if (_functionGraph_->_internalNodeMap_.exists(currentOldXNode->son(i))) {
368 _functionGraph_->_internalNodeMap_[currentOldXNode->son(i)]->removeParent(
369 oldxNodes->list()->element(),
370 i);
371 }
372 }
373 // Reaffecting old node x internal attributes to correct new one
374 currentOldXNode->setNode(y, currentNewYNodeSons);
375 // Updating new sons (they must consider the node as a parent)
376 for (Idx i = 0; i < currentOldXNode->nodeVar()->domainSize(); ++i) {
377 if (_functionGraph_->_internalNodeMap_.exists(currentNewYNodeSons[i])) {
378 _functionGraph_->_internalNodeMap_[currentNewYNodeSons[i]]->addParent(
379 oldxNodes->list()->element(),
380 i);
381 }
382 }
383
384 _functionGraph_->_var2NodeIdMap_[y]->addLink(oldxNodes->list()->element());
385 }
386 }
387
388 oldxNodes->searchAndRemoveLink(oldxNodes->list()->element());
389 }
390 delete oldxNodes;
391
392 while (oldyNodes->list()) {
393 NodeId curId = oldyNodes->list()->element();
394 if (_functionGraph_->_internalNodeMap_[curId]->parents() == nullptr) {
395 for (Idx i = 0; i < _functionGraph_->_internalNodeMap_[curId]->nodeVar()->domainSize(); ++i)
396 if (_functionGraph_->_internalNodeMap_.exists(
397 _functionGraph_->_internalNodeMap_[curId]->son(i)))
398 _functionGraph_->_internalNodeMap_[_functionGraph_->_internalNodeMap_[curId]->son(i)]
399 ->removeParent(curId, i);
400 delete _functionGraph_->_internalNodeMap_[curId];
401 _functionGraph_->_internalNodeMap_.erase(curId);
402 _functionGraph_->_model_.eraseNode(curId);
403 } else {
404 _functionGraph_->_var2NodeIdMap_[y]->addLink(curId);
405 }
406 oldyNodes->searchAndRemoveLink(curId);
407 }
408 delete oldyNodes;
409 }
410
411 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
413 const NodeId& origin,
414 const NodeId& destination) {
415 InternalNode* org = _functionGraph_->_internalNodeMap_[origin];
416 // Upating parents after the change
417 Link< Parent >* picle = org->parents();
418 while (picle != nullptr) {
419 setSon(picle->element().parentId, picle->element().modality, destination);
420 picle = picle->nextLink();
421 }
422
423 // Updating sons after the change
424 for (Idx i = 0; i < org->nbSons(); ++i)
425 if (_functionGraph_->_internalNodeMap_.exists(org->son(i)))
426 _functionGraph_->_internalNodeMap_[org->son(i)]->removeParent(origin, i);
427
428 delete org;
429 _functionGraph_->_internalNodeMap_.erase(origin);
430 _functionGraph_->_model_.eraseNode(origin);
431
432 if (_functionGraph_->root() == origin) this->setRootNode(destination);
433 }
434
435 // Checks if a similar node does not already exists in the graph or
436 // if it has the same child for every variable value.
437 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
439 const DiscreteVariable* var,
440 NodeId* sonsIds) {
441 NodeId newNode = sonsIds[0];
442
443 if (_isRedundant_(var, sonsIds)) {
444 SOA_DEALLOCATE(sonsIds, sizeof(NodeId) * var->domainSize());
445 } else {
446 newNode = _checkIsomorphism_(var, sonsIds);
447 if (newNode == 0) {
448 newNode = addInternalNode_(var, sonsIds);
449 } else {
450 SOA_DEALLOCATE(sonsIds, sizeof(NodeId) * var->domainSize());
451 }
452 }
453
454 return newNode;
455 }
456
457 // Checks if a similar node does not already exists in the graph.
458 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
460 const DiscreteVariable* var,
461 NodeId* sons) {
462 const InternalNode* nody = nullptr;
463 Idx i = 0;
464
465 // Check abscence of identical node
466 Link< NodeId >* currentElem = _functionGraph_->_var2NodeIdMap_[var]->list();
467 while (currentElem != nullptr) {
468 nody = _functionGraph_->_internalNodeMap_[currentElem->element()];
469
470 // Check on the other sons
471 i = 0;
472 while (i < var->domainSize() && sons[i] == nody->son(i))
473 ++i;
474 if (i == var->domainSize()) return currentElem->element();
475
476 currentElem = currentElem->nextLink();
477 }
478 return 0;
479 }
480
481 // Checks if node has the same child for every variable value
482 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
484 const DiscreteVariable* var,
485 NodeId* sons) {
486 for (Idx m = 1; m < var->domainSize(); m++)
487 if (sons[m] != sons[0]) return false;
488 return true;
489 }
490
491 // Ensures that every isomorphic subgraphs are merged together.
492 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
494 Link< NodeId >* currentNodeId = nullptr;
495 Link< NodeId >* nextNodeId = nullptr;
496 InternalNode* currentNode = nullptr;
497 bool theSame = true;
498 Idx currentInd;
499
500 for (SequenceIterator< const DiscreteVariable* > varIter
501 = _functionGraph_->variablesSequence().rbegin();
502 varIter != _functionGraph_->variablesSequence().rend();
503 --varIter) {
504 currentNodeId = _functionGraph_->_var2NodeIdMap_[*varIter]->list();
505
506 while (currentNodeId != nullptr) {
507 nextNodeId = currentNodeId->nextLink();
508 currentNode = _functionGraph_->_internalNodeMap_[currentNodeId->element()];
509
510 // First isomorphism to handle is the one where all node children are
511 // the same
512 theSame = true;
513 for (currentInd = 1; currentInd < (*varIter)->domainSize(); currentInd++) {
514 if (currentNode->son(currentInd) != currentNode->son(0)) {
515 theSame = false;
516 break;
517 }
518 }
519
520 if (theSame == true) {
521 migrateNode_(currentNodeId->element(), currentNode->son(0));
522 _functionGraph_->_var2NodeIdMap_[*varIter]->searchAndRemoveLink(currentNodeId->element());
523 currentNodeId = nextNodeId;
524 continue;
525 }
526
527 // Second isomorphism to handle is the one where two nodes have same
528 // variable and same children
529 if (nextNodeId) {
530 Link< NodeId >* anotherNodeId = currentNodeId->nextLink();
531 InternalNode* anotherNode = nullptr;
532 Idx modality = 0;
533 while (anotherNodeId->nextLink() != nullptr) {
534 nextNodeId = anotherNodeId->nextLink();
535 anotherNode = _functionGraph_->_internalNodeMap_[anotherNodeId->element()];
536
537 // Check on the other sons
538 for (modality = 0; modality < (*varIter)->domainSize(); ++modality) {
539 if (anotherNode->son(modality) != currentNode->son(modality)) break;
540 if (modality == (*varIter)->domainSize() - 1) {
541 migrateNode_(anotherNodeId->element(), currentNodeId->element());
542 _functionGraph_->_var2NodeIdMap_[*varIter]->searchAndRemoveLink(
543 anotherNodeId->element());
544 }
545 }
546
547 anotherNodeId = nextNodeId;
548 }
549 }
550 currentNodeId = currentNodeId->nextLink();
551 }
552 }
553 }
554
555 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
557 Sequence< const DiscreteVariable* > oldSequence(_functionGraph_->variablesSequence());
558 for (SequenceIterator< const DiscreteVariable* > varIter = oldSequence.begin();
559 varIter != oldSequence.end();
560 ++varIter)
561 if (!_functionGraph_->varNodeListe(*varIter)->list()) _functionGraph_->erase(**varIter);
562 }
563
564 // ==========================================================================
565 // MultiDimFunctionGraphTreeManager
566 // ==========================================================================
567
568 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
575
576 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
579 GUM_DESTRUCTOR(MultiDimFunctionGraphTreeManager);
580 }
581
582 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
588
589 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
591
592 // ===========================================================================
593 // MultiDimFunctionGraphROManager
594 // ===========================================================================
595
596 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
602
603 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
605 TerminalNodePolicy >::~MultiDimFunctionGraphROManager() {
606 GUM_DESTRUCTOR(MultiDimFunctionGraphROManager);
607 }
608
609 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
615
616 template < typename GUM_ELEMENT, template < class > class TerminalNodePolicy >
620
621} // namespace gum
Base class for discrete random variable.
virtual Size domainSize() const =0
The class for generic Hash Tables.
Definition hashTable.h:640
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.
const Link< T > * list() const
Returns the first link in the chained list.
Definition link_tpl.h:136
void searchAndRemoveLink(const T &elem)
Removes a element from the list.
Definition link_tpl.h:163
void eraseNode(NodeId id, NodeId replacingId=0, bool updateParents=true)
Erases a node from the diagram.
NodeId addInternalNode(const DiscreteVariable *var)
Inserts a new non terminal node in graph.
void clean()
Removes var without nodes in the diagram.
NodeId nodeRedundancyCheck_(const DiscreteVariable *var, NodeId *sonsMap)
Check for redundancy.
bool _isRedundant_(const DiscreteVariable *var, NodeId *sons)
Checks if node has the same child for every variable value.
void _adjacentSwap_(const DiscreteVariable *x, const DiscreteVariable *y)
void reduce_()
Ensures that every isomorphic subgraphs are merged together.
void setRootNode(const NodeId &root)
Sets root node of decision diagram.
NodeId addTerminalNode(const GUM_ELEMENT &value)
Adds a value to the MultiDimFunctionGraph.
void minimizeSize()
Performs a sifting in search of a(local) minimal size.
NodeId addInternalNode_(const DiscreteVariable *var, NodeId *sons)
Adds an internal node.
MultiDimFunctionGraphManager(MultiDimFunctionGraph< GUM_ELEMENT, TerminalNodePolicy > *master)
Default constructor.
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 _checkIsomorphism_(const DiscreteVariable *var, NodeId *sons)
Checks if a similar node does not already exists in the graph.
MultiDimFunctionGraph< GUM_ELEMENT, TerminalNodePolicy > * _functionGraph_
The multidimdecisiongraph supposed to be edited.
void setSon(const NodeId &node, const Idx &modality, const NodeId &sonNode)
Sets nodes son for given modality to designated son node.
MultiDimFunctionGraphROManager(MultiDimFunctionGraph< GUM_ELEMENT, TerminalNodePolicy > *master)
void reduce() override
Ensures that every isomorphic subgraphs are merged together.
NodeId addInternalNode(const DiscreteVariable *var, NodeId *sons) override
Inserts a new non terminal node in graph.
NodeId addInternalNode(const DiscreteVariable *var, NodeId *sons) override
Inserts a new non terminal node in graph.
void reduce() override
Ensures that every isomorphic subgraphs are merged together.
MultiDimFunctionGraphTreeManager(MultiDimFunctionGraph< GUM_ELEMENT, TerminalNodePolicy > *master)
Class constructor.
Exception : the element we looked for cannot be found.
Exception : operation not allowed.
iterator begin() const
Returns an unsafe begin iterator.
const iterator & end() const noexcept
Returns the unsafe end iterator.
iterator_safe beginSafe() const
Returns a safe begin iterator.
const iterator_safe & endSafe() const noexcept
Returns the safe end iterator.
Safe iterators for Sequence.
Definition sequence.h:1148
The generic class for storing (ordered) sequences of objects.
Definition sequence.h:994
#define GUM_ERROR(type, msg)
Definition exceptions.h:76
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)