aGrUM 2.3.2
a C++ library for (probabilistic) graphical models
multiDimFunctionGraphGenerator.cpp
Go to the documentation of this file.
1/****************************************************************************
2 * This file is part of the aGrUM/pyAgrum library. *
3 * *
4 * Copyright (c) 2005-2025 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-2025 *
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
51
52#include <cstdlib>
53
56
58
59namespace gum {
60 // Constructor
69
70 // Destructor
74
76 MultiDimFunctionGraph< double >* generatedFunctionGraph
78
80 varIter != _varSeq_.endSafe();
81 ++varIter) {
82 generatedFunctionGraph->add(**varIter);
83 }
84
85 HashTable< NodeId, Idx > node2MinVar;
86
87 std::vector< NodeId > filo;
88
89 generatedFunctionGraph->manager()->setRootNode(
90 generatedFunctionGraph->manager()->addInternalNode(_varSeq_.atPos(0)));
91 node2MinVar.insert(generatedFunctionGraph->root(), 0);
92 filo.push_back(generatedFunctionGraph->root());
93
94 while (!filo.empty()) {
95 NodeId currentNodeId = filo.back();
96 filo.pop_back();
97 Idx cvp = node2MinVar[currentNodeId];
98 const InternalNode* currentNode = generatedFunctionGraph->node(currentNodeId);
99
100 LinkedList< NodeId > tensorSons;
101 Idx nbTensorSons = 0;
102 for (Idx varPos = 0; varPos < generatedFunctionGraph->variablesSequence().size(); varPos++) {
103 const DiscreteVariable* var = generatedFunctionGraph->variablesSequence().atPos(varPos);
104
105 Idx vsp = _varSeq_.pos(var);
106 if (vsp > cvp) {
107 const Link< NodeId >* nicleIter = generatedFunctionGraph->varNodeListe(var)->list();
108 while (nicleIter) {
109 nbTensorSons++;
110 tensorSons.addLink(nicleIter->element());
111 nicleIter = nicleIter->nextLink();
112 }
113 }
114 }
115
116 for (Idx modality = 0; modality < currentNode->nodeVar()->domainSize(); modality++) {
117 if (!tensorSons.list() || randomProba() > (1.0 / (1.0 + 3.0 / nbTensorSons))) {
118 if (_createLeaf_(currentNodeId, node2MinVar)) {
119 generatedFunctionGraph->manager()->setSon(
120 currentNodeId,
121 modality,
122 generatedFunctionGraph->manager()->addTerminalNode(100.0 * randomProba()));
123 } else {
124 Idx sonVarPos = _generateVarPos_(node2MinVar[currentNodeId] + 1,
125 _nbTotalVar_ - node2MinVar[currentNodeId] - 2);
126 generatedFunctionGraph->manager()->setSon(
127 currentNodeId,
128 modality,
129 generatedFunctionGraph->manager()->addInternalNode(_varSeq_.atPos(sonVarPos)));
130 filo.push_back(currentNode->son(modality));
131 node2MinVar.insert(currentNode->son(modality), sonVarPos);
132 }
133 } else {
134 Idx sonPos = randomValue(nbTensorSons);
135 sonPos = sonPos == nbTensorSons ? nbTensorSons - 1 : sonPos;
136 Link< NodeId >* nicleIter = tensorSons.list();
137 while (sonPos) {
138 nicleIter = nicleIter->nextLink();
139 sonPos--;
140 }
141 generatedFunctionGraph->manager()->setSon(currentNodeId, modality, nicleIter->element());
142 }
143 }
144 }
145
146 generatedFunctionGraph->manager()->reduce();
147 generatedFunctionGraph->manager()->clean();
148
149 return generatedFunctionGraph;
150 }
151
153 HashTable< NodeId, Idx >& node2MinVar) {
154 return !(currentNodeId == 1
155 || (randomProba() < 0.9
156 + 0.01
157 * (float(_nbTotalVar_ - node2MinVar[currentNodeId])
158 / float(_nbTotalVar_))
159 && node2MinVar[currentNodeId] < _nbTotalVar_ - 1));
160 }
161
163 Idx randOut = 0;
164
165 if (span != 0) {
166 std::weibull_distribution< double > distribution(double(span), 1.0);
167 randOut = (Idx)(distribution(gum::randomGenerator()) * span / 2);
168 if (randOut > span) randOut = span;
169 }
170
171 return offset + randOut;
172 }
173
174} // namespace gum
Base class for discrete random variable.
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
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.
const Link< T > * list() const
Returns the first link in the chained list.
Definition link_tpl.h:136
void addLink(const T &elem)
Adds a link.
Definition link_tpl.h:157
MultiDimFunctionGraphGenerator(Idx maxVar, Idx minVar, const Sequence< const DiscreteVariable * > &varSeq)
Default constructor.
Idx _generateVarPos_(Idx offset, Idx span)
Generate a variable position.
Idx _nbTotalVar_
The total number of variables.
const Sequence< const DiscreteVariable * > _varSeq_
The variables.
MultiDimFunctionGraph< double > * generate()
Generates a MultiDimFunctionGraph.
bool _createLeaf_(NodeId currentNodeId, HashTable< NodeId, Idx > &node2MinVar)
Creates a leaf.
void clean()
Removes var without nodes in the diagram.
void setRootNode(const NodeId &root)
Sets root node of decision diagram.
NodeId addTerminalNode(const GUM_SCALAR &value)
Adds a value to the MultiDimFunctionGraph.
virtual void reduce()=0
Ensures that every isomorphic subgraphs are merged together.
NodeId addInternalNode(const DiscreteVariable *var)
Inserts a new non terminal node in graph.
void setSon(const NodeId &node, const Idx &modality, const NodeId &sonNode)
Sets nodes son for given modality to designated son node.
MultiDimFunctionGraphManager< GUM_SCALAR, TerminalNodePolicy > * manager()
Returns a const reference to the manager of this diagram.
const NodeId & root() const
Returns the id of the root node from the diagram.
static MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * getReducedAndOrderedInstance()
Returns a reduced and ordered instance.
const InternalNode * node(NodeId n) const
Returns internalNode structure associated to that nodeId.
const LinkedList< NodeId > * varNodeListe(const DiscreteVariable *var) const
Returns the list of node associated to given variable.
virtual void add(const DiscreteVariable &v)
Adds a new var to the variables of the multidimensional matrix.
virtual const Sequence< const DiscreteVariable * > & variablesSequence() const override
Returns a const ref to the sequence of DiscreteVariable*.
Safe iterators for Sequence.
Definition sequence.h:1134
The generic class for storing (ordered) sequences of objects.
Definition sequence.h:972
Size Idx
Type for indexes.
Definition types.h:79
Size NodeId
Type for node ids.
Idx randomValue(const Size max=2)
Returns a random Idx between 0 and max-1 included.
std::mt19937 & randomGenerator()
define a random_engine with correct seed
double randomProba()
Returns a random double between 0 and 1 included (i.e.
Headers of gum::MultiDimFunctionGraphGenerator.
gum is the global namespace for all aGrUM entities
Definition agrum.h:46
priority queues (in which an element cannot appear more than once)
Contains useful methods for random stuff.