35 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
40 __functionGraph = mddg;
44 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
51 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
55 __functionGraph->__root = root;
59 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
64 __functionGraph->__internalNodeMap.insert(nid, newNodeStruct);
66 __functionGraph->__var2NodeIdMap[var]->addLink(nid);
71 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
75 NodeId nid = __functionGraph->__model.addNode();
76 __functionGraph->__internalNodeMap.insert(nid, newNodeStruct);
77 __functionGraph->__var2NodeIdMap[var]->addLink(nid);
82 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
86 NodeId nid = __functionGraph->__model.addNode();
87 __functionGraph->__internalNodeMap.insert(nid, newNodeStruct);
88 __functionGraph->__var2NodeIdMap[var]->addLink(nid);
89 for (
Idx i = 0; i < newNodeStruct->
nbSons(); i++)
90 if (!__functionGraph->isTerminalNode(sons[i]))
91 __functionGraph->__internalNodeMap[sons[i]]->addParent(nid, i);
97 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
100 if (__functionGraph->existsTerminalNodeWithValue(value))
101 return __functionGraph->terminalNodeId(value);
103 NodeId node = __functionGraph->__model.addNode();
104 __functionGraph->addTerminalNode(node, value);
109 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
111 NodeId eraseId,
NodeId replacingId,
bool updateParents) {
112 if (!__functionGraph->__model.exists(eraseId))
115 if (__functionGraph->isTerminalNode(eraseId)) {
116 for (
auto iterVar = __functionGraph->variablesSequence().begin();
117 iterVar != __functionGraph->variablesSequence().end();
120 __functionGraph->__var2NodeIdMap[*iterVar]->list();
121 while (nodeIter !=
nullptr) {
122 for (
Idx modality = 0; modality < (*iterVar)->domainSize(); ++modality)
123 if (__functionGraph->node(nodeIter->
element())->son(modality)
125 setSon(nodeIter->
element(), modality, replacingId);
130 __functionGraph->eraseTerminalNode(eraseId);
133 InternalNode* eraseNode = __functionGraph->__internalNodeMap[eraseId];
137 while (picle !=
nullptr) {
145 ->__var2NodeIdMap[__functionGraph->__internalNodeMap[eraseId]->nodeVar()]
146 ->searchAndRemoveLink(eraseId);
148 delete __functionGraph->__internalNodeMap[eraseId];
149 __functionGraph->__internalNodeMap.erase(eraseId);
152 __functionGraph->__model.eraseNode(eraseId);
154 if (__functionGraph->__root == eraseId) __functionGraph->__root = replacingId;
158 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
163 if (!__functionGraph->__model.exists(node))
165 if (!__functionGraph->__model.exists(sonNode))
169 if (__functionGraph->isTerminalNode(node))
171 "You cannot insert an arc from terminal node : " << node)
175 if (__functionGraph->isInternalNode(node)
177 > __functionGraph->__internalNodeMap[node]->nodeVar()->domainSize()
182 << modality <<
"is higher than domain size " 183 << __functionGraph->__internalNodeMap[node]->nodeVar()->domainSize()
184 <<
"minus 1 of variable " 185 << __functionGraph->__internalNodeMap[node]->nodeVar()->name())
188 if (__functionGraph->isInternalNode(sonNode)
189 && __functionGraph->variablesSequence().pos(
190 __functionGraph->__internalNodeMap[node]->nodeVar())
191 >= __functionGraph->variablesSequence().pos(
192 __functionGraph->__internalNodeMap[sonNode]->nodeVar()))
195 "Variable " << __functionGraph->__internalNodeMap[node]->nodeVar()
196 <<
" is after variable " 197 << __functionGraph->__internalNodeMap[sonNode]->nodeVar()
198 <<
"in Function Graph order.")
200 __functionGraph->__internalNodeMap[node]->setSon(modality, sonNode);
201 if (sonNode && !__functionGraph->isTerminalNode(sonNode))
202 __functionGraph->__internalNodeMap[sonNode]->addParent(node, modality);
206 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
208 TerminalNodePolicy >::minimizeSize() {
213 __functionGraph->variablesSequence().beginSafe();
214 varIter != __functionGraph->variablesSequence().endSafe();
217 __functionGraph->__var2NodeIdMap[*varIter]->list();
219 for (; curElem !=
nullptr; nbElem++, curElem = curElem->
nextLink())
221 varLvlSize.
insert(*varIter, nbElem);
222 siftingSeq.
insert(*varIter);
223 Idx pos = siftingSeq.
pos(*varIter);
224 while (pos > 0 && varLvlSize[siftingSeq.
atPos(pos - 1)] > nbElem) {
225 siftingSeq.
swap(pos - 1, pos);
233 sifIter != siftingSeq.
endSafe();
236 Idx currentPos = __functionGraph->variablesSequence().pos(*sifIter);
237 Idx bestSize = __functionGraph->realSize();
238 Idx bestPos = currentPos;
242 while (currentPos > 0) {
243 moveTo(*sifIter, currentPos - 1);
244 currentPos = __functionGraph->variablesSequence().pos(*sifIter);
245 if (__functionGraph->realSize() < bestSize) {
246 bestPos = currentPos;
247 bestSize = __functionGraph->realSize();
252 while (currentPos < __functionGraph->variablesSequence().size() - 1) {
253 moveTo(*sifIter, currentPos + 1);
254 currentPos = __functionGraph->variablesSequence().pos(*sifIter);
255 if (__functionGraph->realSize() < bestSize) {
256 bestPos = currentPos;
257 bestSize = __functionGraph->realSize();
261 moveTo(*sifIter, bestPos);
266 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
271 if (__functionGraph->variablesSequence().pos(movedVar) > desiredPos)
272 for (
Idx currentPos = __functionGraph->variablesSequence().pos(movedVar);
273 currentPos != desiredPos;
276 __functionGraph->variablesSequence().atPos(currentPos - 1);
277 if (__functionGraph->__var2NodeIdMap[preVar]->list()
278 && __functionGraph->__var2NodeIdMap[movedVar]->list())
279 __adjacentSwap(preVar, movedVar);
280 __functionGraph->_invert(currentPos - 1, currentPos);
283 for (
Idx currentPos = __functionGraph->variablesSequence().pos(movedVar);
284 currentPos != desiredPos;
287 __functionGraph->variablesSequence().atPos(currentPos + 1);
288 if (__functionGraph->__var2NodeIdMap[suiVar]->list()
289 && __functionGraph->__var2NodeIdMap[movedVar]->list())
290 __adjacentSwap(movedVar, suiVar);
291 __functionGraph->_invert(currentPos, currentPos + 1);
296 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
306 NodeId* currentNewXNodeSons =
nullptr;
309 NodeId* currentNewYNodeSons =
nullptr;
310 NodeId currentNewYNodeId = 0;
313 while (oldxNodes->
list()) {
316 __functionGraph->__internalNodeMap[oldxNodes->
list()->element()];
323 for (indy = 0; indy < y->
domainSize(); ++indy) {
329 for (indx = 0; indx < x->
domainSize(); ++indx) {
330 currentNewXNodeSons[indx] = currentOldXNode->son(indx);
331 if (!__functionGraph->isTerminalNode(currentOldXNode->son(indx))
332 && __functionGraph->node(currentOldXNode->son(indx))->nodeVar() == y)
333 currentNewXNodeSons[indx] =
334 __functionGraph->node(currentOldXNode->son(indx))->son(indy);
338 currentNewYNodeSons[indy] = _nodeRedundancyCheck(x, currentNewXNodeSons);
342 currentNewYNodeId = currentNewYNodeSons[0];
343 if (__isRedundant(y, currentNewYNodeSons)) {
344 _migrateNode(oldxNodes->
list()->element(), currentNewYNodeId);
347 currentNewYNodeId = __checkIsomorphism(y, currentNewYNodeSons);
348 if (currentNewYNodeId != 0) {
349 _migrateNode(oldxNodes->
list()->element(), currentNewYNodeId);
353 for (
Idx i = 0; i < currentOldXNode->nodeVar()->domainSize(); ++i) {
354 if (__functionGraph->__internalNodeMap.exists(
355 currentOldXNode->son(i))) {
356 __functionGraph->__internalNodeMap[currentOldXNode->son(i)]
357 ->removeParent(oldxNodes->
list()->element(), i);
361 currentOldXNode->setNode(y, currentNewYNodeSons);
363 for (
Idx i = 0; i < currentOldXNode->nodeVar()->domainSize(); ++i) {
364 if (__functionGraph->__internalNodeMap.exists(
365 currentNewYNodeSons[i])) {
366 __functionGraph->__internalNodeMap[currentNewYNodeSons[i]]
367 ->addParent(oldxNodes->
list()->element(), i);
371 __functionGraph->__var2NodeIdMap[y]->
addLink(
372 oldxNodes->
list()->element());
380 while (oldyNodes->
list()) {
382 if (__functionGraph->__internalNodeMap[curId]->parents() ==
nullptr) {
385 < __functionGraph->__internalNodeMap[curId]->nodeVar()->domainSize();
387 if (__functionGraph->__internalNodeMap.exists(
388 __functionGraph->__internalNodeMap[curId]->son(i)))
390 ->__internalNodeMap[__functionGraph->__internalNodeMap[curId]->son(
392 ->removeParent(curId, i);
393 delete __functionGraph->__internalNodeMap[curId];
394 __functionGraph->__internalNodeMap.erase(curId);
395 __functionGraph->__model.eraseNode(curId);
397 __functionGraph->__var2NodeIdMap[y]->addLink(curId);
404 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
408 InternalNode* org = __functionGraph->__internalNodeMap[origin];
411 while (picle !=
nullptr) {
418 if (__functionGraph->__internalNodeMap.exists(org->
son(i)))
419 __functionGraph->__internalNodeMap[org->
son(i)]->removeParent(origin, i);
422 __functionGraph->__internalNodeMap.erase(origin);
423 __functionGraph->__model.eraseNode(origin);
425 if (__functionGraph->root() == origin) this->setRootNode(destination);
430 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
433 NodeId newNode = sonsIds[0];
435 if (__isRedundant(var, sonsIds)) {
438 newNode = __checkIsomorphism(var, sonsIds);
440 newNode = _addInternalNode(var, sonsIds);
450 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
457 Link< NodeId >* currentElem = __functionGraph->__var2NodeIdMap[var]->list();
458 while (currentElem !=
nullptr) {
459 nody = __functionGraph->__internalNodeMap[currentElem->
element()];
463 while (i < var->domainSize() && sons[i] == nody->
son(i))
467 currentElem = currentElem->
nextLink();
473 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
478 if (sons[m] != sons[0])
return false;
483 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
492 for (SequenceIterator< const DiscreteVariable* > varIter =
493 __functionGraph->variablesSequence().rbegin();
494 varIter != __functionGraph->variablesSequence().rend();
496 currentNodeId = __functionGraph->__var2NodeIdMap[*varIter]->list();
498 while (currentNodeId !=
nullptr) {
499 nextNodeId = currentNodeId->
nextLink();
500 currentNode = __functionGraph->__internalNodeMap[currentNodeId->
element()];
505 for (currentInd = 1; currentInd < (*varIter)->domainSize(); currentInd++) {
506 if (currentNode->
son(currentInd) != currentNode->
son(0)) {
512 if (theSame ==
true) {
513 _migrateNode(currentNodeId->
element(), currentNode->
son(0));
514 __functionGraph->__var2NodeIdMap[*varIter]->searchAndRemoveLink(
526 while (anotherNodeId->
nextLink() !=
nullptr) {
527 nextNodeId = anotherNodeId->
nextLink();
529 __functionGraph->__internalNodeMap[anotherNodeId->
element()];
532 for (modality = 0; modality < (*varIter)->domainSize(); ++modality) {
533 if (anotherNode->
son(modality) != currentNode->
son(modality))
break;
534 if (modality == (*varIter)->domainSize() - 1) {
536 __functionGraph->__var2NodeIdMap[*varIter]->searchAndRemoveLink(
544 currentNodeId = currentNodeId->
nextLink();
549 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
553 __functionGraph->variablesSequence());
554 for (SequenceIterator< const DiscreteVariable* > varIter = oldSequence.begin();
555 varIter != oldSequence.end();
557 if (!__functionGraph->varNodeListe(*varIter)->list())
558 __functionGraph->
erase(**varIter);
565 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
573 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
579 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
585 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
594 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
602 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
608 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
614 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
virtual void reduce()
Ensures that every isomorphic subgraphs are merged together.
Headers of MultiDimFunctionGraphManager.
Safe iterators for Sequence.
Idx pos(const Key &key) const
Returns the position of the object passed in argument (if it exists).
void setSon(const NodeId &node, const Idx &modality, const NodeId &sonNode)
Sets nodes son for given modality to designated son node.
void clean()
Removes var without nodes in the diagram.
void __adjacentSwap(const DiscreteVariable *x, const DiscreteVariable *y)
Swap two adjacent variable.
~MultiDimFunctionGraphTreeManager()
Class destructor.
void setRootNode(const NodeId &root)
Sets root node of decision diagram.
const iterator_safe & endSafe() const noexcept
Returns the safe end iterator.
Header file of gum::Sequence, a class for storing (ordered) sequences of objects. ...
Idx nbSons() const
Returns the number of sons.
The generic class for storing (ordered) sequences of objects.
static NodeId * allocateNodeSons(const DiscreteVariable *v)
Allocates a table of nodeid of the size given in parameter.
#define SOA_DEALLOCATE(x, y)
NodeId son(Idx modality) const
Returns the son at a given index.
NodeId addInternalNode(const DiscreteVariable *var)
Inserts a new non terminal node in graph.
Link< Parent > * parents()
Returns the list of parents.
Base class for discrete random variable.
gum is the global namespace for all aGrUM entities
void moveTo(const DiscreteVariable *x, Idx desiredPos)
Changes var position in variable sequence.
The class for generic Hash Tables.
void searchAndRemoveLink(const T &elem)
Removes a element from the list.
void eraseNode(NodeId id, NodeId replacingId=0, bool updateParents=true)
Erases a node from the diagram.
iterator_safe beginSafe() const
Returns a safe begin iterator.
const T & element() const
Returns the element stored in this link.
virtual Size domainSize() const =0
virtual NodeId addInternalNode(const DiscreteVariable *var, NodeId *sons)
Inserts a new non terminal node in graph.
Class implementingting a function graph manager.
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...
MultiDimFunctionGraphManager(MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > *master)
Default constructor.
virtual void reduce()
Ensures that every isomorphic subgraphs are merged together.
Structure used to represent a node internal structure.
Link of a chain list allocated using the SmallObjectAllocator.
Class implementingting a function graph.
~MultiDimFunctionGraphROManager()
void _reduce()
Ensures that every isomorphic subgraphs are merged together.
MultiDimFunctionGraphROManager(MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > *master)
NodeId nextNodeId()
Returns the next value of an unique counter for PRM's node id.
MultiDimFunctionGraphTreeManager(MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > *master)
Class constructor.
void erase(const Key &k)
Remove an element from the sequence.
Chain list allocated using the SmallObjectAllocator.
void swap(Idx i, Idx j)
Swap index.
const Link< T > * list() const
Returns the first link in the chained list.
NodeId addTerminalNode(const GUM_SCALAR &value)
Adds a value to the MultiDimFunctionGraph.
Size Idx
Type for indexes.
Headers of the Link and LinkedList classes.
bool __isRedundant(const DiscreteVariable *var, NodeId *sons)
Checks if node has the same child for every variable value.
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
NodeId _nodeRedundancyCheck(const DiscreteVariable *var, NodeId *sonsMap)
Check for redundancy.
const Link< T > * nextLink() const
Returns next link.
NodeId _addInternalNode(const DiscreteVariable *var, NodeId *sons)
Adds an internal node.
virtual ~MultiDimFunctionGraphManager()
Class destructor.
Size NodeId
Type for node ids.
void addLink(const T &elem)
Adds a link.
#define GUM_ERROR(type, msg)
NodeId __checkIsomorphism(const DiscreteVariable *var, NodeId *sons)
Checks if a similar node does not already exists in the graph.
const Key & atPos(Idx i) const
Returns the object at the pos i.
virtual NodeId addInternalNode(const DiscreteVariable *var, NodeId *sons)
Inserts a new non terminal node in graph.
void insert(const Key &k)
Insert an element at the end of the sequence.