aGrUM 3.1.1
a C++ library for (probabilistic) graphical models
regress_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
52
55
56#define ALLOCATE(x) SmallObjectAllocator::instance().allocate(x)
57#define DEALLOCATE(x, y) SmallObjectAllocator::instance().deallocate(x, y)
58
59namespace gum {
60
61 template < typename GUM_ELEMENT,
62 template < typename > class COMBINEOPERATOR,
63 template < typename > class PROJECTOPERATOR,
64 template < typename > class TerminalNodePolicy >
68 const gum::VariableSet* primedVars,
69 const DiscreteVariable* targetVar,
70 const GUM_ELEMENT neutral) :
71 _DG1_(DG1), _DG2_(DG2), _neutral_(neutral), _combine_(), _project_(),
72 _DG1InstantiationNeeded_(DG1->realSize(), true, false),
73 _DG2InstantiationNeeded_(DG2->realSize(), true, false) {
74 GUM_CONSTRUCTOR(Regress);
76 _nbVar_ = 0;
77 _default_ = nullptr;
78 _primedVars_ = primedVars;
79 _targetVar_ = targetVar;
80 }
81
82 template < typename GUM_ELEMENT,
83 template < typename > class COMBINEOPERATOR,
84 template < typename > class PROJECTOPERATOR,
85 template < typename > class TerminalNodePolicy >
87 GUM_DESTRUCTOR(Regress);
88
89 for (auto instIter = _DG1InstantiationNeeded_.beginSafe();
90 instIter != _DG1InstantiationNeeded_.endSafe();
91 ++instIter)
92 DEALLOCATE(instIter.val(), sizeof(short int) * _nbVar_);
93
94 for (auto instIter = _DG2InstantiationNeeded_.beginSafe();
95 instIter != _DG2InstantiationNeeded_.endSafe();
96 ++instIter)
97 DEALLOCATE(instIter.val(), sizeof(short int) * _nbVar_);
98
99 if (_nbVar_ != 0) DEALLOCATE(_default_, sizeof(short int) * _nbVar_);
100 }
101
102 // This function is the main function. To be call every time an operation
103 // between the two given Function Graphs is required
104 template < typename GUM_ELEMENT,
105 template < typename > class COMBINEOPERATOR,
106 template < typename > class PROJECTOPERATOR,
107 template < typename > class TerminalNodePolicy >
113
114 Idx* varInst = nullptr;
115 if (_nbVar_ != 0) {
116 varInst = static_cast< Idx* >(ALLOCATE(sizeof(Idx) * _nbVar_));
117 for (Idx i = 0; i < _nbVar_; i++)
118 varInst[i] = (Idx)0;
119 }
120
121 O4DGContext conti(varInst, _nbVar_);
122 conti.setDG1Node(_DG1_->root());
123 conti.setDG2Node(_DG2_->root());
124
125 NodeId root = _compute_(conti, (Idx)0 - 1);
126 _rd_->manager()->setRootNode(root);
127
128 if (_nbVar_ != 0) DEALLOCATE(varInst, sizeof(Idx) * _nbVar_);
129
130 _rd_->erase(*_targetVar_);
131
132 return _rd_;
133 }
134
135 // This function computes an efficient order for the final decision diagrams.
136 // Its main criterion to do so is the number of
137 // re-exploration to be done
138 template < typename GUM_ELEMENT,
139 template < typename > class COMBINEOPERATOR,
140 template < typename > class PROJECTOPERATOR,
141 template < typename > class TerminalNodePolicy >
144 SequenceIteratorSafe< const DiscreteVariable* > fite = _DG1_->variablesSequence().beginSafe();
145 SequenceIteratorSafe< const DiscreteVariable* > site = _DG2_->variablesSequence().beginSafe();
146
147 while (fite != _DG1_->variablesSequence().endSafe()
148 && site != _DG2_->variablesSequence().endSafe()) {
149 // Test : if var from first order is already in final order
150 // we move onto the next one
151 if (_rd_->variablesSequence().exists(*fite)) {
152 ++fite;
153 continue;
154 }
155
156 // Test : if var from second order is already in final order
157 // we move onto the next one
158 if (_rd_->variablesSequence().exists(*site)) {
159 ++site;
160 continue;
161 }
162
163 // Test : is current var of the first order present in the second order.
164 // if not we add it to final order
165 if (!_DG2_->variablesSequence().exists(*fite) && !_primedVars_->exists(*fite)) {
166 _rd_->add(**fite);
167 ++fite;
168 continue;
169 }
170
171 // Test : is current var of the second order present in the first order.
172 // if not we add it to final order
173 if (!_DG1_->variablesSequence().exists(*site) && !_primedVars_->exists(*site)) {
174 _rd_->add(**site);
175 ++site;
176 continue;
177 }
178
179 // Test : is current var of the second order present in the first order.
180 // if not we add it to final order
181 if (*fite == *site) {
182 _rd_->add(**fite);
183 ++fite;
184 ++site;
185 continue;
186 }
187
188 // Test : if chosing first order var cost less in terms or re exploration,
189 // we chose it
190 _rd_->add(**fite);
191 ++fite;
192 }
193
194 // Whenever an iterator has finished its sequence,
195 // the other may still be in the middle of its one.
196 // Hence, this part ensures that any variables remaining
197 // will be added to the final sequence if needed.
198 if (fite == _DG1_->variablesSequence().endSafe()) {
199 for (; site != _DG2_->variablesSequence().endSafe(); ++site)
200 if (!_rd_->variablesSequence().exists(*site)) _rd_->add(**site);
201 } else {
202 for (; fite != _DG1_->variablesSequence().endSafe(); ++fite)
203 if (!_rd_->variablesSequence().exists(*fite)) _rd_->add(**fite);
204 }
205
206 // Various initialization needed now that we have a bigger picture
207 _nbVar_ = _rd_->variablesSequence().size();
208
209 if (_nbVar_ != 0) {
210 _default_ = static_cast< short int* >(ALLOCATE(sizeof(short int) * _nbVar_));
211 for (Idx i = 0; i < _nbVar_; i++)
212 _default_[i] = (short int)0;
213 }
214 }
215
216 // This function computes for every nodes if any retrograde variable is
217 // present below
218 template < typename GUM_ELEMENT,
219 template < typename > class COMBINEOPERATOR,
220 template < typename > class PROJECTOPERATOR,
221 template < typename > class TerminalNodePolicy >
225 HashTable< NodeId, short int* > nodesVarDescendant;
226 Size tableSize = Size(_nbVar_ * sizeof(short int));
227
228 for (auto varIter = dg->variablesSequence().rbeginSafe();
229 varIter != dg->variablesSequence().rendSafe();
230 --varIter) {
231 Idx varPos = _rd_->variablesSequence().pos(*varIter);
232
233 const Link< NodeId >* nodeIter = dg->varNodeListe(*varIter)->list();
234 while (nodeIter != nullptr) {
235 short int* instantiationNeeded = static_cast< short int* >(ALLOCATE(tableSize));
236 dgInstNeed.insert(nodeIter->element(), instantiationNeeded);
237 short int* varDescendant = static_cast< short int* >(ALLOCATE(tableSize));
238 nodesVarDescendant.insert(nodeIter->element(), varDescendant);
239 for (Idx j = 0; j < _nbVar_; j++) {
240 instantiationNeeded[j] = (short int)0;
241 varDescendant[j] = (short int)0;
242 }
243
244
245 varDescendant[varPos] = (short int)1;
246 for (Idx modality = 0; modality < dg->node(nodeIter->element())->nbSons(); ++modality) {
247 if (!dg->isTerminalNode(dg->node(nodeIter->element())->son(modality))) {
248 short int* sonVarDescendant
249 = nodesVarDescendant[dg->node(nodeIter->element())->son(modality)];
250 for (Idx varIdx = 0; varIdx < _nbVar_; varIdx++) {
251 varDescendant[varIdx] += sonVarDescendant[varIdx];
252 if (varDescendant[varIdx] && varIdx < varPos)
253 instantiationNeeded[varIdx] = (short int)1;
254 }
255 }
256 }
257 nodeIter = nodeIter->nextLink();
258 }
259 }
260
261 for (auto varIter = dg->variablesSequence().beginSafe();
262 varIter != dg->variablesSequence().endSafe();
263 ++varIter) {
264 const Link< NodeId >* nodeIter = dg->varNodeListe(*varIter)->list();
265 while (nodeIter != nullptr) {
266 for (Idx modality = 0; modality < dg->node(nodeIter->element())->nbSons(); ++modality) {
267 NodeId sonId = dg->node(nodeIter->element())->son(modality);
268 if (!dg->isTerminalNode(sonId)) {
269 for (Idx varIdx = 0; varIdx < _nbVar_; ++varIdx) {
270 if (dgInstNeed[nodeIter->element()][varIdx] && nodesVarDescendant[sonId][varIdx]) {
271 dgInstNeed[sonId][varIdx] = (short int)1;
272 }
273 }
274 }
275 }
276 nodeIter = nodeIter->nextLink();
277 }
278 }
279
280 for (HashTableIterator< NodeId, short int* > it = nodesVarDescendant.begin();
281 it != nodesVarDescendant.end();
282 ++it) {
283 DEALLOCATE(it.val(), tableSize);
284 }
285
286 nodesVarDescendant.clear();
287 }
288
289 // A key is used for prunning uneccesary operations since once a node has been
290 // visited in a given context, there's no use to revisit him,
291 // the result will be the same node, so we just have to do an association
292 // context - node.
293 // The context consists in :
294 // _ Leader node we are visiting.
295 // _ Follower node we are visiting.
296 // _ For all retrograde variables, if it has been instanciated
297 // before, current modality instanciated, meaning :
298 // _ 0 means the variable hasn't be instanciated yet,
299 // _ From 1 to domainSize + 1 means that current modality
300 // index of variable is value - 1,
301 // _ domainSize + 2 means variable is on default mode.
302 // A key - node association is made each time we create a node in resulting
303 // diagram.
304 // Since GUM_MULTI_DIM_DECISION_DIAGRAM_RECUR_FUNCTION is a corner step in
305 // algorithm ( meaning each time we explore a node we go trought
306 // this function ), check only have to be at the beginning of that function.
307 template < typename GUM_ELEMENT,
308 template < typename > class COMBINEOPERATOR,
309 template < typename > class PROJECTOPERATOR,
310 template < typename > class TerminalNodePolicy >
312 O4DGContext& currentSituation,
313 Idx lastInstVarPos) {
314 NodeId newNode = 0;
315
316 // If both current nodes are terminal,
317 // we only have to compute the resulting value
318 if (_DG1_->isTerminalNode(currentSituation.DG1Node())
319 && _DG2_->isTerminalNode(currentSituation.DG2Node())) {
320 // We have to compute new valueand we insert a new node in diagram with
321 // this value, ...
322 GUM_ELEMENT newVal = _neutral_;
323 GUM_ELEMENT tempVal = _combine_(_DG1_->nodeValue(currentSituation.DG1Node()),
324 _DG2_->nodeValue(currentSituation.DG2Node()));
325 for (Idx targetModa = 0; targetModa < _targetVar_->domainSize(); ++targetModa)
326 newVal = _project_(newVal, tempVal);
327 return _rd_->manager()->addTerminalNode(newVal);
328 }
329
330 // If not,
331 // we'll have to do some exploration
332
333 // First we ensure that we hadn't already visit this pair of node under hte
334 // same circumstances
335 short int* dg1NeededVar = _DG1InstantiationNeeded_.exists(currentSituation.DG1Node())
336 ? _DG1InstantiationNeeded_[currentSituation.DG1Node()]
337 : _default_;
338 Idx dg1CurrentVarPos
339 = _DG1_->isTerminalNode(currentSituation.DG1Node())
340 ? _nbVar_
341 : _rd_->variablesSequence().pos(_DG1_->node(currentSituation.DG1Node())->nodeVar());
342 short int* dg2NeededVar = _DG2InstantiationNeeded_.exists(currentSituation.DG2Node())
343 ? _DG2InstantiationNeeded_[currentSituation.DG2Node()]
344 : _default_;
345 Idx dg2CurrentVarPos
346 = _DG2_->isTerminalNode(currentSituation.DG2Node())
347 ? _nbVar_
348 : _rd_->variablesSequence().pos(_DG2_->node(currentSituation.DG2Node())->nodeVar());
349
350 short int* instNeeded = static_cast< short int* >(ALLOCATE(sizeof(short int) * _nbVar_));
351
352 for (Idx i = 0; i < _nbVar_; i++) {
353 instNeeded[i] = dg1NeededVar[i] + dg2NeededVar[i];
354 }
355
356 double curSitKey = currentSituation.key(instNeeded);
357
358 if (_explorationTable_.exists(curSitKey)) {
359 DEALLOCATE(instNeeded, sizeof(short int) * _nbVar_);
360
361 return _explorationTable_[curSitKey];
362 }
363
364 // ====================================================
365
366 NodeId origDG1 = currentSituation.DG1Node(), origDG2 = currentSituation.DG2Node();
367
369 NodeId leadNodeId = 0;
370 Idx leadVarPos = _rd_->variablesSequence().size();
371 using SetNodeFunction = void (O4DGContext::*)(const NodeId&);
372 SetNodeFunction leadFunction = nullptr;
373
374 bool sameVar = false;
375
376 if (!_DG1_->isTerminalNode(currentSituation.DG1Node())) {
377 if (currentSituation.varModality(dg1CurrentVarPos) != 0) {
378 // If var associated to current node has already been instanciated, we
379 // have to jump it
380 currentSituation.setDG1Node(_DG1_->node(currentSituation.DG1Node())
381 ->son(currentSituation.varModality(dg1CurrentVarPos) - 1));
382
383 newNode = _compute_(currentSituation, lastInstVarPos);
384 _explorationTable_.insert(curSitKey, newNode);
385 currentSituation.setDG1Node(origDG1);
386 currentSituation.setDG2Node(origDG2);
387
388 DEALLOCATE(instNeeded, sizeof(short int) * _nbVar_);
389
390 return newNode;
391 }
392
393 leaddg = _DG1_;
394 leadNodeId = currentSituation.DG1Node();
395 leadVarPos = dg1CurrentVarPos;
396 leadFunction = &O4DGContext::setDG1Node;
397 }
398
399 if (!_DG2_->isTerminalNode(currentSituation.DG2Node())) {
400 if (currentSituation.varModality(dg2CurrentVarPos) != 0) {
401 // If var associated to current node has already been instanciated, we
402 // have to jump it
403 currentSituation.setDG2Node(_DG2_->node(currentSituation.DG2Node())
404 ->son(currentSituation.varModality(dg2CurrentVarPos) - 1));
405
406 newNode = _compute_(currentSituation, lastInstVarPos);
407 _explorationTable_.insert(curSitKey, newNode);
408 currentSituation.setDG1Node(origDG1);
409 currentSituation.setDG2Node(origDG2);
410
411 DEALLOCATE(instNeeded, sizeof(short int) * _nbVar_);
412
413 return newNode;
414 }
415
416 if (leadVarPos == dg2CurrentVarPos) { sameVar = true; }
417
418 if (leadVarPos > dg2CurrentVarPos) {
419 leaddg = _DG2_;
420 leadNodeId = currentSituation.DG2Node();
421 leadVarPos = dg2CurrentVarPos;
422 leadFunction = &O4DGContext::setDG2Node;
423 }
424 }
425
426 // ====================================================
427 // Anticipated Exploration
428
429 // Before exploring nodes, we have to ensure that every anticipated
430 // exploration is done
431 for (Idx varPos = lastInstVarPos + 1; varPos < leadVarPos; ++varPos) {
432 if (instNeeded[varPos]) {
433 const DiscreteVariable* curVar = _rd_->variablesSequence().atPos(varPos);
434 NodeId* sonsIds = static_cast< NodeId* >(ALLOCATE(sizeof(NodeId) * curVar->domainSize()));
435
436 for (Idx modality = 0; modality < curVar->domainSize(); modality++) {
437 currentSituation.chgVarModality(varPos, modality + 1);
438
439 sonsIds[modality] = _compute_(currentSituation, varPos);
440 }
441
442 newNode = _rd_->manager()->addInternalNode(curVar, sonsIds);
443
444 _explorationTable_.insert(curSitKey, newNode);
445 currentSituation.chgVarModality(varPos, 0);
446 currentSituation.setDG1Node(origDG1);
447 currentSituation.setDG2Node(origDG2);
448
449 DEALLOCATE(instNeeded, sizeof(short int) * _nbVar_);
450
451 return newNode;
452 }
453 }
454
455 // ====================================================
456 // Terminal Exploration
457 if (sameVar && _DG1_->node(origDG1)->nodeVar() == _targetVar_) {
458 GUM_ELEMENT newVal = _neutral_;
459 for (Idx targetModa = 0; targetModa < _targetVar_->domainSize(); ++targetModa)
460 newVal = _project_(newVal,
461 _combine_(_DG1_->nodeValue(_DG1_->node(origDG1)->son(targetModa)),
462 _DG2_->nodeValue(_DG2_->node(origDG2)->son(targetModa))));
463 newNode = _rd_->manager()->addTerminalNode(newVal);
464 _explorationTable_.insert(curSitKey, newNode);
465 DEALLOCATE(instNeeded, sizeof(short int) * _nbVar_);
466 return newNode;
467 }
468 if (_DG1_->isTerminalNode(origDG1)) {
469 if (_DG2_->node(origDG2)->nodeVar() == _targetVar_) {
470 GUM_ELEMENT newVal = _neutral_;
471 for (Idx targetModa = 0; targetModa < _targetVar_->domainSize(); ++targetModa)
472 newVal = _project_(newVal,
473 _combine_(_DG1_->nodeValue(origDG1),
474 _DG2_->nodeValue(_DG2_->node(origDG2)->son(targetModa))));
475 newNode = _rd_->manager()->addTerminalNode(newVal);
476 _explorationTable_.insert(curSitKey, newNode);
477 DEALLOCATE(instNeeded, sizeof(short int) * _nbVar_);
478 return newNode;
479 }
480 } else {
481 if (_DG1_->node(origDG1)->nodeVar() == _targetVar_ && _DG2_->isTerminalNode(origDG2)) {
482 GUM_ELEMENT newVal = _neutral_;
483 for (Idx targetModa = 0; targetModa < _targetVar_->domainSize(); ++targetModa)
484 newVal = _project_(newVal,
485 _combine_(_DG1_->nodeValue(_DG1_->node(origDG1)->son(targetModa)),
486 _DG2_->nodeValue(origDG2)));
487 newNode = _rd_->manager()->addTerminalNode(newVal);
488 _explorationTable_.insert(curSitKey, newNode);
489 DEALLOCATE(instNeeded, sizeof(short int) * _nbVar_);
490 return newNode;
491 }
492 }
493
494 // ====================================================
495 // Normal Exploration
496
497 // If only one of the current node is terminal,
498 // we have to pursue deeper on the other diagram
499 if (sameVar) {
500 // If so - meaning it's the same variable - we have to go
501 // down on both
502 const InternalNode* dg1Node = _DG1_->node(origDG1);
503 const InternalNode* dg2Node = _DG2_->node(origDG2);
504
505 const DiscreteVariable* curVar = dg1Node->nodeVar();
506 Idx varPos = _rd_->variablesSequence().pos(curVar);
507 NodeId* sonsIds = static_cast< NodeId* >(ALLOCATE(sizeof(NodeId) * curVar->domainSize()));
508
509 for (Idx modality = 0; modality < curVar->domainSize(); modality++) {
510 currentSituation.chgVarModality(varPos, modality + 1);
511 currentSituation.setDG1Node(dg1Node->son(modality));
512 currentSituation.setDG2Node(dg2Node->son(modality));
513
514 sonsIds[modality] = _compute_(currentSituation, varPos);
515 }
516
517 newNode = _rd_->manager()->addInternalNode(curVar, sonsIds);
518
519 _explorationTable_.insert(curSitKey, newNode);
520 currentSituation.chgVarModality(varPos, 0);
521 currentSituation.setDG1Node(origDG1);
522 currentSituation.setDG2Node(origDG2);
523
524 DEALLOCATE(instNeeded, sizeof(short int) * _nbVar_);
525
526 return newNode;
527 }
528 // ====================================================
529 else {
530 const InternalNode* leaddgNode = leaddg->node(leadNodeId);
531
532 const DiscreteVariable* curVar = leaddgNode->nodeVar();
533 NodeId* sonsIds = static_cast< NodeId* >(ALLOCATE(sizeof(NodeId) * curVar->domainSize()));
534
535 for (Idx modality = 0; modality < curVar->domainSize(); modality++) {
536 currentSituation.chgVarModality(leadVarPos, modality + 1);
537 (currentSituation.*leadFunction)(leaddgNode->son(modality));
538
539 sonsIds[modality] = _compute_(currentSituation, leadVarPos);
540 }
541
542 newNode = _rd_->manager()->addInternalNode(curVar, sonsIds);
543
544 _explorationTable_.insert(curSitKey, newNode);
545 currentSituation.chgVarModality(leadVarPos, 0);
546 currentSituation.setDG1Node(origDG1);
547 currentSituation.setDG2Node(origDG2);
548
549 DEALLOCATE(instNeeded, sizeof(short int) * _nbVar_);
550
551 return newNode;
552 }
553 }
554
555} // namespace gum
Unsafe Iterators for hashtables.
Definition hashTable.h:2465
Base class for discrete random variable.
virtual Size domainSize() const =0
The class for generic Hash Tables.
Definition hashTable.h:640
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
void clear()
Removes all the elements in the hash table.
iterator begin()
Returns an unsafe iterator pointing to the beginning of the hashtable.
const iterator & end() noexcept
Returns the unsafe iterator pointing to the end of the hashtable.
Structure used to represent a node internal structure.
const DiscreteVariable * nodeVar() const
Returns the node variable.
NodeId son(Idx modality) const
Returns the son at a given index.
static MultiDimFunctionGraph< GUM_ELEMENT, TerminalNodePolicy > * getReducedAndOrderedInstance()
Returns a reduced and ordered instance.
const Sequence< const DiscreteVariable * > & variablesSequence() const override
Returns a const ref to the sequence of DiscreteVariable*.
Class used to manipulate context during Function Graph Operations.
Definition o4DGContext.h:70
const NodeId & DG2Node() const
Get DG2 diagram current explored Node.
void setDG2Node(const NodeId &)
Set DG2 diagram current explored Node.
void chgVarModality(Idx, Idx)
Changes given variable modality.
void setDG1Node(const NodeId &)
Set DG1 diagram current explored Node.
const double & key(short int *instNeeded)
Returns o4DGContext key.
Idx varModality(Idx)
Changes given variable modality.
const NodeId & DG1Node() const
Get DG1 diagram current explored Node.
void _establishVarOrder_()
Computes an order for the final Decision graph that will minimize the number of re exploration.
HashTable< NodeId, short int * > _DG2InstantiationNeeded_
Definition regress.h:147
const MultiDimFunctionGraph< GUM_ELEMENT, TerminalNodePolicy > * _DG1_
One of the two function graphs used for the operation.
Definition regress.h:116
const gum::VariableSet * _primedVars_
The set of variables we want to keep at the end.
Definition regress.h:125
~Regress()
Default destructor.
Definition regress_tpl.h:86
MultiDimFunctionGraph< GUM_ELEMENT, TerminalNodePolicy > * _rd_
The resulting function graph.
Definition regress.h:122
HashTable< double, NodeId > _explorationTable_
The hashtable used to know if two pair of nodes have already been visited.
Definition regress.h:142
const DiscreteVariable * _targetVar_
The variable we work on to eleminate.
Definition regress.h:128
const GUM_ELEMENT _neutral_
The function to be performed on the leaves.
Definition regress.h:131
short int * _default_
Just a computationnal trick.
Definition regress.h:150
HashTable< NodeId, short int * > _DG1InstantiationNeeded_
Table uses to know if a given node of given function graph has retrograde variables.
Definition regress.h:146
MultiDimFunctionGraph< GUM_ELEMENT, TerminalNodePolicy > * compute()
Computes and builds the Function Graph that is the result of the operation.
NodeId _compute_(O4DGContext &currentSituation, Idx lastInstVarPos)
The main recursion function.
void _findRetrogradeVariables_(const MultiDimFunctionGraph< GUM_ELEMENT, TerminalNodePolicy > *dg, HashTable< NodeId, short int * > &dgInstNeed)
Establish for each node in both function graph if it has retrograde variables beneath it.
Regress(const MultiDimFunctionGraph< GUM_ELEMENT, TerminalNodePolicy > *vfunction, const MultiDimFunctionGraph< GUM_ELEMENT, TerminalNodePolicy > *probDist, const gum::VariableSet *primedVars, const DiscreteVariable *targetVar, const GUM_ELEMENT neutral)
Default constructor.
Definition regress_tpl.h:65
const MultiDimFunctionGraph< GUM_ELEMENT, TerminalNodePolicy > * _DG2_
The other one.
Definition regress.h:119
const PROJECTOPERATOR< GUM_ELEMENT > _project_
Definition regress.h:138
const COMBINEOPERATOR< GUM_ELEMENT > _combine_
The functions to be performed on the leaves.
Definition regress.h:137
Idx _nbVar_
The total number of variable implied in the operation.
Definition regress.h:134
Safe iterators for Sequence.
Definition sequence.h:1148
std::size_t Size
In aGrUM, hashed values are unsigned long int.
Definition types.h:74
Size Idx
Type for indexes.
Definition types.h:79
Size NodeId
Type for node ids.
#define DEALLOCATE(x, y)
#define ALLOCATE(x)
Headers of the InternalNode class.
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
Set< const DiscreteVariable * > VariableSet
Class used to compute the operation between two decision diagrams.