38 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
43 __functionGraph = mddg;
47 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
54 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
58 __functionGraph->__root = root;
62 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
67 __functionGraph->__internalNodeMap.insert(nid, newNodeStruct);
69 __functionGraph->__var2NodeIdMap[var]->addLink(nid);
74 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
78 NodeId nid = __functionGraph->__model.addNode();
79 __functionGraph->__internalNodeMap.insert(nid, newNodeStruct);
80 __functionGraph->__var2NodeIdMap[var]->addLink(nid);
85 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
89 NodeId nid = __functionGraph->__model.addNode();
90 __functionGraph->__internalNodeMap.insert(nid, newNodeStruct);
91 __functionGraph->__var2NodeIdMap[var]->addLink(nid);
92 for (
Idx i = 0; i < newNodeStruct->
nbSons(); i++)
93 if (!__functionGraph->isTerminalNode(sons[i]))
94 __functionGraph->__internalNodeMap[sons[i]]->addParent(nid, i);
100 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
103 if (__functionGraph->existsTerminalNodeWithValue(value))
104 return __functionGraph->terminalNodeId(value);
106 NodeId node = __functionGraph->__model.addNode();
107 __functionGraph->addTerminalNode(node, value);
112 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
114 NodeId eraseId,
NodeId replacingId,
bool updateParents) {
115 if (!__functionGraph->__model.exists(eraseId))
118 if (__functionGraph->isTerminalNode(eraseId)) {
119 for (
auto iterVar = __functionGraph->variablesSequence().begin();
120 iterVar != __functionGraph->variablesSequence().end();
123 __functionGraph->__var2NodeIdMap[*iterVar]->list();
124 while (nodeIter !=
nullptr) {
125 for (
Idx modality = 0; modality < (*iterVar)->domainSize(); ++modality)
126 if (__functionGraph->node(nodeIter->
element())->son(modality)
128 setSon(nodeIter->
element(), modality, replacingId);
133 __functionGraph->eraseTerminalNode(eraseId);
136 InternalNode* eraseNode = __functionGraph->__internalNodeMap[eraseId];
140 while (picle !=
nullptr) {
148 ->__var2NodeIdMap[__functionGraph->__internalNodeMap[eraseId]->nodeVar()]
149 ->searchAndRemoveLink(eraseId);
151 delete __functionGraph->__internalNodeMap[eraseId];
152 __functionGraph->__internalNodeMap.erase(eraseId);
155 __functionGraph->__model.eraseNode(eraseId);
157 if (__functionGraph->__root == eraseId) __functionGraph->__root = replacingId;
161 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
166 if (!__functionGraph->__model.exists(node))
168 if (!__functionGraph->__model.exists(sonNode))
172 if (__functionGraph->isTerminalNode(node))
174 "You cannot insert an arc from terminal node : " << node)
178 if (__functionGraph->isInternalNode(node)
180 > __functionGraph->__internalNodeMap[node]->nodeVar()->domainSize()
185 << modality <<
"is higher than domain size " 186 << __functionGraph->__internalNodeMap[node]->nodeVar()->domainSize()
187 <<
"minus 1 of variable " 188 << __functionGraph->__internalNodeMap[node]->nodeVar()->name())
191 if (__functionGraph->isInternalNode(sonNode)
192 && __functionGraph->variablesSequence().pos(
193 __functionGraph->__internalNodeMap[node]->nodeVar())
194 >= __functionGraph->variablesSequence().pos(
195 __functionGraph->__internalNodeMap[sonNode]->nodeVar()))
198 "Variable " << __functionGraph->__internalNodeMap[node]->nodeVar()
199 <<
" is after variable " 200 << __functionGraph->__internalNodeMap[sonNode]->nodeVar()
201 <<
"in Function Graph order.")
203 __functionGraph->__internalNodeMap[node]->setSon(modality, sonNode);
204 if (sonNode && !__functionGraph->isTerminalNode(sonNode))
205 __functionGraph->__internalNodeMap[sonNode]->addParent(node, modality);
209 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
211 TerminalNodePolicy >::minimizeSize() {
216 __functionGraph->variablesSequence().beginSafe();
217 varIter != __functionGraph->variablesSequence().endSafe();
220 __functionGraph->__var2NodeIdMap[*varIter]->list();
222 for (; curElem !=
nullptr; nbElem++, curElem = curElem->
nextLink())
224 varLvlSize.
insert(*varIter, nbElem);
225 siftingSeq.
insert(*varIter);
226 Idx pos = siftingSeq.
pos(*varIter);
227 while (pos > 0 && varLvlSize[siftingSeq.
atPos(pos - 1)] > nbElem) {
228 siftingSeq.
swap(pos - 1, pos);
236 sifIter != siftingSeq.
endSafe();
239 Idx currentPos = __functionGraph->variablesSequence().pos(*sifIter);
240 Idx bestSize = __functionGraph->realSize();
241 Idx bestPos = currentPos;
245 while (currentPos > 0) {
246 moveTo(*sifIter, currentPos - 1);
247 currentPos = __functionGraph->variablesSequence().pos(*sifIter);
248 if (__functionGraph->realSize() < bestSize) {
249 bestPos = currentPos;
250 bestSize = __functionGraph->realSize();
255 while (currentPos < __functionGraph->variablesSequence().size() - 1) {
256 moveTo(*sifIter, currentPos + 1);
257 currentPos = __functionGraph->variablesSequence().pos(*sifIter);
258 if (__functionGraph->realSize() < bestSize) {
259 bestPos = currentPos;
260 bestSize = __functionGraph->realSize();
264 moveTo(*sifIter, bestPos);
269 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
274 if (__functionGraph->variablesSequence().pos(movedVar) > desiredPos)
275 for (
Idx currentPos = __functionGraph->variablesSequence().pos(movedVar);
276 currentPos != desiredPos;
279 __functionGraph->variablesSequence().atPos(currentPos - 1);
280 if (__functionGraph->__var2NodeIdMap[preVar]->list()
281 && __functionGraph->__var2NodeIdMap[movedVar]->list())
282 __adjacentSwap(preVar, movedVar);
283 __functionGraph->_invert(currentPos - 1, currentPos);
286 for (
Idx currentPos = __functionGraph->variablesSequence().pos(movedVar);
287 currentPos != desiredPos;
290 __functionGraph->variablesSequence().atPos(currentPos + 1);
291 if (__functionGraph->__var2NodeIdMap[suiVar]->list()
292 && __functionGraph->__var2NodeIdMap[movedVar]->list())
293 __adjacentSwap(movedVar, suiVar);
294 __functionGraph->_invert(currentPos, currentPos + 1);
299 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
309 NodeId* currentNewXNodeSons =
nullptr;
312 NodeId* currentNewYNodeSons =
nullptr;
313 NodeId currentNewYNodeId = 0;
316 while (oldxNodes->
list()) {
319 __functionGraph->__internalNodeMap[oldxNodes->
list()->element()];
326 for (indy = 0; indy < y->
domainSize(); ++indy) {
332 for (indx = 0; indx < x->
domainSize(); ++indx) {
333 currentNewXNodeSons[indx] = currentOldXNode->son(indx);
334 if (!__functionGraph->isTerminalNode(currentOldXNode->son(indx))
335 && __functionGraph->node(currentOldXNode->son(indx))->nodeVar() == y)
336 currentNewXNodeSons[indx] =
337 __functionGraph->node(currentOldXNode->son(indx))->son(indy);
341 currentNewYNodeSons[indy] = _nodeRedundancyCheck(x, currentNewXNodeSons);
345 currentNewYNodeId = currentNewYNodeSons[0];
346 if (__isRedundant(y, currentNewYNodeSons)) {
347 _migrateNode(oldxNodes->
list()->element(), currentNewYNodeId);
350 currentNewYNodeId = __checkIsomorphism(y, currentNewYNodeSons);
351 if (currentNewYNodeId != 0) {
352 _migrateNode(oldxNodes->
list()->element(), currentNewYNodeId);
356 for (
Idx i = 0; i < currentOldXNode->nodeVar()->domainSize(); ++i) {
357 if (__functionGraph->__internalNodeMap.exists(
358 currentOldXNode->son(i))) {
359 __functionGraph->__internalNodeMap[currentOldXNode->son(i)]
360 ->removeParent(oldxNodes->
list()->element(), i);
364 currentOldXNode->setNode(y, currentNewYNodeSons);
366 for (
Idx i = 0; i < currentOldXNode->nodeVar()->domainSize(); ++i) {
367 if (__functionGraph->__internalNodeMap.exists(
368 currentNewYNodeSons[i])) {
369 __functionGraph->__internalNodeMap[currentNewYNodeSons[i]]
370 ->addParent(oldxNodes->
list()->element(), i);
374 __functionGraph->__var2NodeIdMap[y]->
addLink(
375 oldxNodes->
list()->element());
383 while (oldyNodes->
list()) {
385 if (__functionGraph->__internalNodeMap[curId]->parents() ==
nullptr) {
388 < __functionGraph->__internalNodeMap[curId]->nodeVar()->domainSize();
390 if (__functionGraph->__internalNodeMap.exists(
391 __functionGraph->__internalNodeMap[curId]->son(i)))
393 ->__internalNodeMap[__functionGraph->__internalNodeMap[curId]->son(
395 ->removeParent(curId, i);
396 delete __functionGraph->__internalNodeMap[curId];
397 __functionGraph->__internalNodeMap.erase(curId);
398 __functionGraph->__model.eraseNode(curId);
400 __functionGraph->__var2NodeIdMap[y]->addLink(curId);
407 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
411 InternalNode* org = __functionGraph->__internalNodeMap[origin];
414 while (picle !=
nullptr) {
421 if (__functionGraph->__internalNodeMap.exists(org->
son(i)))
422 __functionGraph->__internalNodeMap[org->
son(i)]->removeParent(origin, i);
425 __functionGraph->__internalNodeMap.erase(origin);
426 __functionGraph->__model.eraseNode(origin);
428 if (__functionGraph->root() == origin) this->setRootNode(destination);
433 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
436 NodeId newNode = sonsIds[0];
438 if (__isRedundant(var, sonsIds)) {
441 newNode = __checkIsomorphism(var, sonsIds);
443 newNode = _addInternalNode(var, sonsIds);
453 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
460 Link< NodeId >* currentElem = __functionGraph->__var2NodeIdMap[var]->list();
461 while (currentElem !=
nullptr) {
462 nody = __functionGraph->__internalNodeMap[currentElem->
element()];
466 while (i < var->domainSize() && sons[i] == nody->
son(i))
470 currentElem = currentElem->
nextLink();
476 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
481 if (sons[m] != sons[0])
return false;
486 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
495 for (SequenceIterator< const DiscreteVariable* > varIter =
496 __functionGraph->variablesSequence().rbegin();
497 varIter != __functionGraph->variablesSequence().rend();
499 currentNodeId = __functionGraph->__var2NodeIdMap[*varIter]->list();
501 while (currentNodeId !=
nullptr) {
502 nextNodeId = currentNodeId->
nextLink();
503 currentNode = __functionGraph->__internalNodeMap[currentNodeId->
element()];
508 for (currentInd = 1; currentInd < (*varIter)->domainSize(); currentInd++) {
509 if (currentNode->
son(currentInd) != currentNode->
son(0)) {
515 if (theSame ==
true) {
516 _migrateNode(currentNodeId->
element(), currentNode->
son(0));
517 __functionGraph->__var2NodeIdMap[*varIter]->searchAndRemoveLink(
529 while (anotherNodeId->
nextLink() !=
nullptr) {
530 nextNodeId = anotherNodeId->
nextLink();
532 __functionGraph->__internalNodeMap[anotherNodeId->
element()];
535 for (modality = 0; modality < (*varIter)->domainSize(); ++modality) {
536 if (anotherNode->
son(modality) != currentNode->
son(modality))
break;
537 if (modality == (*varIter)->domainSize() - 1) {
539 __functionGraph->__var2NodeIdMap[*varIter]->searchAndRemoveLink(
547 currentNodeId = currentNodeId->
nextLink();
552 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
556 __functionGraph->variablesSequence());
557 for (SequenceIterator< const DiscreteVariable* > varIter = oldSequence.begin();
558 varIter != oldSequence.end();
560 if (!__functionGraph->varNodeListe(*varIter)->list())
561 __functionGraph->
erase(**varIter);
568 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
576 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
582 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
588 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
597 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
605 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
611 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
617 template <
typename GUM_SCALAR,
template <
class >
class TerminalNodePolicy >
virtual void reduce()
Ensures that every isomorphic subgraphs are merged together.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
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.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
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.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
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.
Copyright 2005-2019 Pierre-Henri WUILLEMIN et Christophe GONZALES (LIP6) {prenom.nom}_at_lip6.fr.
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.