aGrUM  0.14.2
multiDimFunctionGraphOperator_tpl.h
Go to the documentation of this file.
1 /****************************************************************************
2  * Copyright (C) 2005 by Pierre-Henri WUILLEMIN et Christophe GONZALES *
3  * {prenom.nom}_at_lip6.fr *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the GNU General Public License as published by *
7  * the Free Software Foundation; either version 2 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the GNU General Public License *
16  * along with this program; if not, write to the *
17  * Free Software Foundation, Inc., *
18  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19  ****************************************************************************/
29 
30 namespace gum {
31 
32  template < typename GUM_SCALAR,
33  template < typename >
34  class FUNCTOR,
35  template < typename >
36  class TerminalNodePolicy >
41  __DG1(DG1),
42  __DG2(DG2), __function(),
43  __DG1InstantiationNeeded(DG1->realSize(), true, false),
44  __DG2InstantiationNeeded(DG2->realSize(), true, false) {
45  GUM_CONSTRUCTOR(MultiDimFunctionGraphOperator);
46  __rd =
47  MultiDimFunctionGraph< GUM_SCALAR,
48  TerminalNodePolicy >::getReducedAndOrderedInstance();
49  __nbVar = 0;
50  __default = nullptr;
51 
52  __nbCall = 0;
53  __nbVar = 0;
54  __sizeVarRetro = 1;
55  }
56 
57  template < typename GUM_SCALAR,
58  template < typename >
59  class FUNCTOR,
60  template < typename >
61  class TerminalNodePolicy >
64  GUM_DESTRUCTOR(MultiDimFunctionGraphOperator);
65 
66 
67  for (auto instIter = __DG1InstantiationNeeded.beginSafe();
68  instIter != __DG1InstantiationNeeded.endSafe();
69  ++instIter)
70  SOA_DEALLOCATE(instIter.val(), sizeof(short int) * __nbVar);
71 
72  for (auto instIter = __DG2InstantiationNeeded.beginSafe();
73  instIter != __DG2InstantiationNeeded.endSafe();
74  ++instIter)
75  SOA_DEALLOCATE(instIter.val(), sizeof(short int) * __nbVar);
76 
77  if (__nbVar != 0) SOA_DEALLOCATE(__default, sizeof(short int) * __nbVar);
78  }
79 
80 
81  // This function is the main function. To be call every time an operation
82  // between the two given Function Graphs is required
83  template < typename GUM_SCALAR,
84  template < typename >
85  class FUNCTOR,
86  template < typename >
87  class TerminalNodePolicy >
94 
95  Idx* varInst = nullptr;
96  if (__nbVar != 0) {
97  varInst = static_cast< Idx* >(SOA_ALLOCATE(sizeof(Idx) * __nbVar));
98  for (Idx i = 0; i < __nbVar; i++)
99  varInst[i] = (Idx)0;
100  }
101 
102  O4DGContext conti(varInst, __nbVar);
103  conti.setDG1Node(__DG1->root());
104  conti.setDG2Node(__DG2->root());
105 
106  NodeId root = __compute(conti, (Idx)0 - 1);
107  __rd->manager()->setRootNode(root);
108 
109  if (__nbVar != 0) SOA_DEALLOCATE(varInst, sizeof(Idx) * __nbVar);
110 
111  return __rd;
112  }
113 
114  // This function computes an efficient order for the final decision diagrams.
115  // Its main criterion to do so is the number of re-exploration to be done.
116  template < typename GUM_SCALAR,
117  template < typename >
118  class FUNCTOR,
119  template < typename >
120  class TerminalNodePolicy >
124  __DG1->variablesSequence().beginSafe();
126  __DG2->variablesSequence().beginSafe();
127 
128  while (fite != __DG1->variablesSequence().endSafe()
129  && site != __DG2->variablesSequence().endSafe()) {
130  // Test : if var from first order is already in final order
131  // we move onto the next one
132  if (__rd->variablesSequence().exists(*fite)) {
133  ++fite;
134  continue;
135  }
136 
137  // Test : if var from second order is already in final order
138  // we move onto the next one
139  if (__rd->variablesSequence().exists(*site)) {
140  ++site;
141  continue;
142  }
143 
144  // Test : is current var of the first order present in the second order.
145  // if not we add it to final order
146  if (!__DG2->variablesSequence().exists(*fite)) {
147  __rd->add(**fite);
148  ++fite;
149  continue;
150  }
151 
152  // Test : is current var of the second order present in the first order.
153  // if not we add it to final order
154  if (!__DG1->variablesSequence().exists(*site)) {
155  __rd->add(**site);
156  ++site;
157  continue;
158  }
159 
160  // Test : is current var of the second order present in the first order.
161  // if not we add it to final order
162  if (*fite == *site) {
163  __rd->add(**fite);
164  ++fite;
165  ++site;
166  continue;
167  }
168 
169  // Test : the current tested situation is when two retrograde variables
170  // are detected.
171  // Chosen solution here is to find compute domainSize in between
172  // and chose the one with the smallest
173  __nbVarRetro++;
174  if (__distance(__DG1, *fite, *site) < __distance(__DG2, *site, *fite)) {
175  __rd->add(**fite);
176  __sizeVarRetro *= (*fite)->domainSize();
177  ++fite;
178  continue;
179  } else {
180  __rd->add(**site);
181  __sizeVarRetro *= (*site)->domainSize();
182  ++site;
183  continue;
184  }
185  }
186 
187  // Whenever an iterator has finished its sequence,
188  // the other may still be in the middle of its one.
189  // Hence, this part ensures that any variables remaining
190  // will be added to the final sequence if needed.
191  if (fite == __DG1->variablesSequence().endSafe()) {
192  for (; site != __DG2->variablesSequence().endSafe(); ++site)
193  if (!__rd->variablesSequence().exists(*site)) __rd->add(**site);
194  } else {
195  for (; fite != __DG1->variablesSequence().endSafe(); ++fite)
196  if (!__rd->variablesSequence().exists(*fite)) __rd->add(**fite);
197  }
198 
199 
200  // Various initialization needed now that we have a bigger picture
201  __nbVar = __rd->variablesSequence().size();
202 
203  if (__nbVar != 0) {
204  __default =
205  static_cast< short int* >(SOA_ALLOCATE(sizeof(short int) * __nbVar));
206  for (Idx i = 0; i < __nbVar; i++)
207  __default[i] = (short int)0;
208  }
209  }
210 
211  // This function computes the number of re-exploration needed whenever to
212  // retrograde variables collides
213  template < typename GUM_SCALAR,
214  template < typename >
215  class FUNCTOR,
216  template < typename >
217  class TerminalNodePolicy >
218  INLINE Idx
222  const DiscreteVariable* from,
223  const DiscreteVariable* to) {
224  Idx posi = d->variablesSequence().pos(from);
225  Idx dist = 1;
226 
227  while (d->variablesSequence().atPos(posi) != to) {
228  dist *= (*(d->variablesSequence().atPos(posi))).domainSize();
229  posi++;
230  }
231 
232  return dist;
233  }
234 
235 
236  // This function computes for every nodes if any retrograde variable is
237  // present below
238  template < typename GUM_SCALAR,
239  template < typename >
240  class FUNCTOR,
241  template < typename >
242  class TerminalNodePolicy >
243  INLINE void
247  HashTable< NodeId, short int* >& dgInstNeed) {
248  HashTable< NodeId, short int* > nodesVarDescendant;
249  Size tableSize = Size(__nbVar * sizeof(short int));
250 
251  for (auto varIter = dg->variablesSequence().rbeginSafe();
252  varIter != dg->variablesSequence().rendSafe();
253  --varIter) {
254  Idx varPos = __rd->variablesSequence().pos(*varIter);
255  const Link< NodeId >* nodeIter = dg->varNodeListe(*varIter)->list();
256  while (nodeIter != nullptr) {
257  short int* instantiationNeeded =
258  static_cast< short int* >(SOA_ALLOCATE(tableSize));
259  dgInstNeed.insert(nodeIter->element(), instantiationNeeded);
260 
261  short int* varDescendant =
262  static_cast< short int* >(SOA_ALLOCATE(tableSize));
263  nodesVarDescendant.insert(nodeIter->element(), varDescendant);
264  for (Idx j = 0; j < __nbVar; j++) {
265  instantiationNeeded[j] = (short int)0;
266  varDescendant[j] = (short int)0;
267  }
268 
269  varDescendant[varPos] = (short int)1;
270  for (Idx modality = 0; modality < dg->node(nodeIter->element())->nbSons();
271  ++modality) {
272  if (!dg->isTerminalNode(dg->node(nodeIter->element())->son(modality))) {
273  short int* sonVarDescendant =
274  nodesVarDescendant[dg->node(nodeIter->element())->son(modality)];
275  for (Idx varIdx = 0; varIdx < __nbVar; varIdx++) {
276  varDescendant[varIdx] += sonVarDescendant[varIdx];
277  if (varDescendant[varIdx] && varIdx < varPos)
278  instantiationNeeded[varIdx] = (short int)1;
279  }
280  }
281  }
282  nodeIter = nodeIter->nextLink();
283  }
284  }
285 
286  for (auto varIter = dg->variablesSequence().beginSafe();
287  varIter != dg->variablesSequence().endSafe();
288  ++varIter) {
289  const Link< NodeId >* nodeIter = dg->varNodeListe(*varIter)->list();
290  while (nodeIter != nullptr) {
291  for (Idx modality = 0; modality < dg->node(nodeIter->element())->nbSons();
292  ++modality) {
293  NodeId sonId = dg->node(nodeIter->element())->son(modality);
294  if (!dg->isTerminalNode(sonId)) {
295  for (Idx varIdx = 0; varIdx < __nbVar; ++varIdx) {
296  if (dgInstNeed[nodeIter->element()][varIdx]
297  && nodesVarDescendant[sonId][varIdx]) {
298  dgInstNeed[sonId][varIdx] = (short int)1;
299  }
300  }
301  }
302  }
303  nodeIter = nodeIter->nextLink();
304  }
305  }
306 
307  for (HashTableIterator< NodeId, short int* > it = nodesVarDescendant.begin();
308  it != nodesVarDescendant.end();
309  ++it) {
310  SOA_DEALLOCATE(it.val(), tableSize);
311  }
312  nodesVarDescendant.clear();
313  }
314 
315 
318 
319  // A key is used for prunning uneccesary operations since once a node has been
320  // visited in a given context, there's no use to revisit him,
321  // the result will be the same node, so we just have to do an association
322  // context - node.
323  // The context consists in :
324  // _ Leader node we are visiting.
325  // _ Follower node we are visiting.
326  // _ For all retrograde variables, if it has been instanciated
327  // before, current modality instanciated, meaning :
328  // _ 0 means the variable hasn't be instanciated yet,
329  // _ From 1 to domainSize + 1 means that current modality
330  // index of variable is value - 1,
331  // _ domainSize + 2 means variable is on default mode.
332  // A key - node association is made each time we create a node in resulting
333  // diagram.
334  // Since GUM_MULTI_DIM_DECISION_DIAGRAM_RECUR_FUNCTION is a corner step in
335  // algorithm ( meaning each time we explore a node we go trought
336  // this function ), check only have to be at the beginning of that function.
337  template < typename GUM_SCALAR,
338  template < typename >
339  class FUNCTOR,
340  template < typename >
341  class TerminalNodePolicy >
343  __compute(O4DGContext& currentSituation, Idx lastInstVarPos) {
344  __nbCall += 1;
345 
346  NodeId newNode = 0;
347 
348 
349  // If both current nodes are terminal,
350  // we only have to compute the resulting value
351  if (__DG1->isTerminalNode(currentSituation.DG1Node())
352  && __DG2->isTerminalNode(currentSituation.DG2Node())) {
353  // We have to compute new valueand we insert a new node in diagram with
354  // this value, ...
355  return __rd->manager()->addTerminalNode(
356  __function(__DG1->terminalNodeValue(currentSituation.DG1Node()),
357  __DG2->terminalNodeValue(currentSituation.DG2Node())));
358  }
359 
360  // If not,
361  // we'll have to do some exploration
362 
363  // First we ensure that we hadn't already visit this pair of node under hte
364  // same circumstances
365 
366  short int* dg1NeededVar =
367  __DG1InstantiationNeeded.exists(currentSituation.DG1Node())
368  ? __DG1InstantiationNeeded[currentSituation.DG1Node()]
369  : __default;
370  Idx dg1CurrentVarPos =
371  __DG1->isTerminalNode(currentSituation.DG1Node())
372  ? __nbVar
373  : __rd->variablesSequence().pos(
374  __DG1->node(currentSituation.DG1Node())->nodeVar());
375  short int* dg2NeededVar =
376  __DG2InstantiationNeeded.exists(currentSituation.DG2Node())
377  ? __DG2InstantiationNeeded[currentSituation.DG2Node()]
378  : __default;
379  Idx dg2CurrentVarPos =
380  __DG2->isTerminalNode(currentSituation.DG2Node())
381  ? __nbVar
382  : __rd->variablesSequence().pos(
383  __DG2->node(currentSituation.DG2Node())->nodeVar());
384 
385  short int* instNeeded =
386  static_cast< short int* >(SOA_ALLOCATE(sizeof(short int) * __nbVar));
387  for (Idx i = 0; i < __nbVar; i++)
388  instNeeded[i] = dg1NeededVar[i] + dg2NeededVar[i];
389 
390  double curSitKey = currentSituation.key(instNeeded);
391 
392  if (__explorationTable.exists(curSitKey)) {
393  SOA_DEALLOCATE(instNeeded, sizeof(short int) * __nbVar);
394  return __explorationTable[curSitKey];
395  }
396 
397  // ====================================================
398 
399  NodeId origDG1 = currentSituation.DG1Node(),
400  origDG2 = currentSituation.DG2Node();
401 
403  nullptr;
404  NodeId leadNodeId = 0;
405  Idx leadVarPos = __rd->variablesSequence().size();
406  typedef void (O4DGContext::*SetNodeFunction)(const NodeId&);
407  SetNodeFunction leadFunction = nullptr;
408 
409  bool sameVar = false;
410 
411  if (!__DG1->isTerminalNode(currentSituation.DG1Node())) {
412  if (currentSituation.varModality(dg1CurrentVarPos) != 0) {
413  currentSituation.setDG1Node(
414  __DG1->node(currentSituation.DG1Node())
415  ->son(currentSituation.varModality(dg1CurrentVarPos) - 1));
416 
417  newNode = __compute(currentSituation, lastInstVarPos);
418  __explorationTable.insert(curSitKey, newNode);
419  currentSituation.setDG1Node(origDG1);
420  currentSituation.setDG2Node(origDG2);
421 
422  SOA_DEALLOCATE(instNeeded, sizeof(short int) * __nbVar);
423 
424  return newNode;
425  }
426 
427  leaddg = __DG1;
428  leadNodeId = currentSituation.DG1Node();
429  leadVarPos = dg1CurrentVarPos;
430  leadFunction = &O4DGContext::setDG1Node;
431  }
432 
433  if (!__DG2->isTerminalNode(currentSituation.DG2Node())) {
434  if (currentSituation.varModality(dg2CurrentVarPos) != 0) {
435  currentSituation.setDG2Node(
436  __DG2->node(currentSituation.DG2Node())
437  ->son(currentSituation.varModality(dg2CurrentVarPos) - 1));
438 
439  newNode = __compute(currentSituation, lastInstVarPos);
440  __explorationTable.insert(curSitKey, newNode);
441  currentSituation.setDG1Node(origDG1);
442  currentSituation.setDG2Node(origDG2);
443 
444  SOA_DEALLOCATE(instNeeded, sizeof(short int) * __nbVar);
445 
446  return newNode;
447  }
448 
449  if (leadVarPos == dg2CurrentVarPos) { sameVar = true; }
450 
451  if (leadVarPos > dg2CurrentVarPos) {
452  leaddg = __DG2;
453  leadNodeId = currentSituation.DG2Node();
454  leadVarPos = dg2CurrentVarPos;
455  leadFunction = &O4DGContext::setDG2Node;
456  }
457  }
458 
459  // ====================================================
460 
461  // Before exploring nodes, we have to ensure that every anticipated
462  // exploration is done
463  for (Idx varPos = lastInstVarPos + 1; varPos < leadVarPos; ++varPos) {
464  if (instNeeded[varPos]) {
465  const DiscreteVariable* curVar = __rd->variablesSequence().atPos(varPos);
466  NodeId* sonsIds = static_cast< NodeId* >(
467  SOA_ALLOCATE(sizeof(NodeId) * curVar->domainSize()));
468 
469  for (Idx modality = 0; modality < curVar->domainSize(); modality++) {
470  currentSituation.chgVarModality(varPos, modality + 1);
471 
472  sonsIds[modality] = __compute(currentSituation, varPos);
473  }
474 
475  newNode = __rd->manager()->addInternalNode(curVar, sonsIds);
476 
477  __explorationTable.insert(curSitKey, newNode);
478  currentSituation.chgVarModality(varPos, 0);
479  currentSituation.setDG1Node(origDG1);
480  currentSituation.setDG2Node(origDG2);
481 
482  SOA_DEALLOCATE(instNeeded, sizeof(short int) * __nbVar);
483 
484  return newNode;
485  }
486  }
487 
488  // ====================================================
489 
490  // If only one of the current node is terminal,
491  // we have to pursue deeper on the other diagram
492  if (sameVar) {
493  // If so - meaning it's the same variable - we have to go
494  // down on both
495  const InternalNode* dg1Node = __DG1->node(origDG1);
496  const InternalNode* dg2Node = __DG2->node(origDG2);
497 
498  const DiscreteVariable* curVar = dg1Node->nodeVar();
499  Idx varPos = __rd->variablesSequence().pos(curVar);
500 
501  NodeId* sonsIds = static_cast< NodeId* >(
502  SOA_ALLOCATE(sizeof(NodeId) * curVar->domainSize()));
503 
504  for (Idx modality = 0; modality < curVar->domainSize(); modality++) {
505  currentSituation.chgVarModality(varPos, modality + 1);
506  currentSituation.setDG1Node(dg1Node->son(modality));
507  currentSituation.setDG2Node(dg2Node->son(modality));
508 
509  sonsIds[modality] = __compute(currentSituation, varPos);
510  }
511 
512  newNode = __rd->manager()->addInternalNode(curVar, sonsIds);
513 
514  __explorationTable.insert(curSitKey, newNode);
515  currentSituation.chgVarModality(varPos, 0);
516  currentSituation.setDG1Node(origDG1);
517  currentSituation.setDG2Node(origDG2);
518 
519  SOA_DEALLOCATE(instNeeded, sizeof(short int) * __nbVar);
520 
521  return newNode;
522  }
523  // ====================================================
524  else {
525  const InternalNode* leaddgNode = leaddg->node(leadNodeId);
526 
527  const DiscreteVariable* curVar = leaddgNode->nodeVar();
528  NodeId* sonsIds = static_cast< NodeId* >(
529  SOA_ALLOCATE(sizeof(NodeId) * curVar->domainSize()));
530 
531  for (Idx modality = 0; modality < curVar->domainSize(); modality++) {
532  currentSituation.chgVarModality(leadVarPos, modality + 1);
533  (currentSituation.*leadFunction)(leaddgNode->son(modality));
534 
535  sonsIds[modality] = __compute(currentSituation, leadVarPos);
536  }
537 
538  newNode = __rd->manager()->addInternalNode(curVar, sonsIds);
539 
540  __explorationTable.insert(curSitKey, newNode);
541  currentSituation.chgVarModality(leadVarPos, 0);
542  currentSituation.setDG1Node(origDG1);
543  currentSituation.setDG2Node(origDG2);
544 
545  SOA_DEALLOCATE(instNeeded, sizeof(short int) * __nbVar);
546 
547  return newNode;
548  }
549  }
550 
551  template < typename GUM_SCALAR,
552  template < typename >
553  class FUNCTOR,
554  template < typename >
555  class TerminalNodePolicy >
556  INLINE Idx MultiDimFunctionGraphOperator< GUM_SCALAR,
557  FUNCTOR,
558  TerminalNodePolicy >::nbCall() {
559  return __nbCall;
560  }
561 
562  template < typename GUM_SCALAR,
563  template < typename >
564  class FUNCTOR,
565  template < typename >
566  class TerminalNodePolicy >
567  INLINE Idx MultiDimFunctionGraphOperator< GUM_SCALAR,
568  FUNCTOR,
569  TerminalNodePolicy >::nbVarRetro() {
570  return __nbVarRetro;
571  }
572 
573  template < typename GUM_SCALAR,
574  template < typename >
575  class FUNCTOR,
576  template < typename >
577  class TerminalNodePolicy >
578  INLINE Idx
581  return __sizeVarRetro;
582  }
583 
584 } // namespace gum
iterator begin()
Returns an unsafe iterator pointing to the beginning of the hashtable.
const NodeId & DG2Node() const
Get DG2 diagram current explored Node.
Definition: o4DGContext.h:89
Safe iterators for Sequence.
Definition: sequence.h:1203
const iterator & end() noexcept
Returns the unsafe iterator pointing to the end of the hashtable.
const iterator_safe & endSafe() noexcept
Returns the safe iterator pointing to the end of the hashtable.
const DiscreteVariable * nodeVar() const
Returns the node variable.
void __findRetrogradeVariables(const MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > *dg, HashTable< NodeId, short int * > &dgInstNeed)
Establish for each node in both function graph if it has retrograde variables beneath it...
Unsafe Iterators for hashtablesHashTableIterator provides a fast but unsafe way to parse HashTables...
Definition: hashTable.h:2747
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * compute()
Computes and builds the Function Graph that is the result of the operation.
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * __rd
The resulting function graph.
#define SOA_DEALLOCATE(x, y)
NodeId son(Idx modality) const
Returns the son at a given index.
short int * __default
Just a comptuationnal trick.
Headers of the InternalNode class.
HashTable< NodeId, short int *> __DG1InstantiationNeeded
Table uses to know if a given node of first function graph has retrograde vrariables.
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
const double & key(short int *instNeeded)
Returns o4DGContext key.
Idx __nbVar
The total number of variable implied in the operation.
void chgVarModality(Idx, Idx)
Changes given variable modality.
Base class for discrete random variable.
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
virtual Size domainSize() const =0
Idx __distance(const MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > *, const DiscreteVariable *, const DiscreteVariable *)
Heuristic methods to decide which of two retrograde variables should come first.
const NodeId & DG1Node() const
Get DG1 diagram current explored Node.
Definition: o4DGContext.h:83
HashTable< double, NodeId > __explorationTable
The hashtable used to know if two pair of nodes have already been visited.
void setDG1Node(const NodeId &)
Set DG1 diagram current explored Node.
HashTable< NodeId, short int *> __DG2InstantiationNeeded
Table uses to know if a given node of second function graph has retrograde vrariables.
Structure used to represent a node internal structure.
Definition: internalNode.h:100
Class used to compute the operation between two decision diagrams.
Class implementingting a function graph.
Class used to perform Function Graph Operations.
const FUNCTOR< GUM_SCALAR > __function
The function to be performed on the leaves.
void setDG2Node(const NodeId &)
Set DG2 diagram current explored Node.
const MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * __DG1
One of the two function graphs used for the operation.
void clear()
Removes all the elements in the hash table.
iterator_safe beginSafe()
Returns the safe iterator pointing to the beginning of the hashtable.
MultiDimFunctionGraphOperator(const MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > *DG1, const MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > *DG2)
Default constructor.
Size Idx
Type for indexes.
Definition: types.h:50
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition: types.h:45
Class used to manipulate context during Function Graph Operations.
Definition: o4DGContext.h:46
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
void __establishVarOrder()
Computes an order for the final Decision graph that will minimize the number of re exploration...
Size NodeId
Type for node ids.
Definition: graphElements.h:97
Idx varModality(Idx)
Changes given variable modality.
NodeId __compute(O4DGContext &currentSituation, Idx lastInstVarPos)
The main recursion function.
const MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * __DG2
The other one.
#define SOA_ALLOCATE(x)