aGrUM  0.14.2
multiDimFunctionGraphProjector_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  ****************************************************************************/
31 
32 namespace gum {
33 
34  // CONSTRUCTOR
35  template < typename GUM_SCALAR,
36  template < typename >
37  class FUNCTOR,
38  template < typename >
39  class TerminalNodePolicy >
43  const Set< const DiscreteVariable* >& delVars,
44  const GUM_SCALAR neutral) :
45  __src(src),
46  __delVars(delVars), __function(), __neutral(neutral) {
47  GUM_CONSTRUCTOR(MultiDimFunctionGraphProjector);
49  }
50 
51 
52  // DESTRUCTOR
53  template < typename GUM_SCALAR,
54  template < typename >
55  class FUNCTOR,
56  template < typename >
57  class TerminalNodePolicy >
60  GUM_DESTRUCTOR(MultiDimFunctionGraphProjector);
61  }
62 
63 
64  // This function is the main function. To be call every time an Projection
65  // between the two given Function Graphs is required
66  template < typename GUM_SCALAR,
67  template < typename >
68  class FUNCTOR,
69  template < typename >
70  class TerminalNodePolicy >
74  __rd->copy(*__src);
75 
77  __delVars.beginSafe();
78  varIter != __delVars.endSafe();
79  ++varIter) {
80  const DiscreteVariable* curVar = *varIter;
81 
82  // Tout d'abord, on déplace la variable à projeter en fin de séquence afin
83  // de simplifier la projection
84  if (__rd->variablesSequence().exists(curVar))
85  __rd->manager()->moveTo(curVar, __rd->variablesSequence().size() - 1);
86 
87  // 1er cas spécial : le diagramme est un un simple noeud terminal
88  if (__rd->isTerminalNode(__rd->root())) {
89  GUM_SCALAR newVal = __neutral, oldVal = __rd->nodeValue(__rd->root());
90  for (Idx curVarModality = 0; curVarModality < curVar->domainSize();
91  ++curVarModality)
92  newVal = __function(newVal, oldVal);
93 
94  NodeId newSonId = __rd->manager()->addTerminalNode(newVal);
95  __rd->manager()->setRootNode(newSonId);
96 
97  if (__rd->variablesSequence().exists(curVar)) __rd->erase(*curVar);
98  continue;
99  }
100 
101  // 2ème cas spécial : la racine du diagramme est associée à la variable
102  // projetée
103  if (__rd->node(__rd->root())->nodeVar() == curVar) {
104  const InternalNode* curVarNode = __rd->node(__rd->root());
105  GUM_SCALAR newVal = __neutral;
106  for (Idx curVarModality = 0; curVarModality < curVar->domainSize();
107  ++curVarModality)
108  newVal =
109  __function(newVal, __rd->nodeValue(curVarNode->son(curVarModality)));
110 
111  NodeId newSonId = __rd->manager()->addTerminalNode(newVal);
112 
113  __rd->manager()->eraseNode(__rd->root(), newSonId, false);
114 
115  if (__rd->variablesSequence().exists(curVar)) __rd->erase(*curVar);
116  continue;
117  }
118 
119  // Cas général
120  HashTable< NodeId, NodeId > visitedNode(2 * __rd->realSize(), true, false);
121  std::vector< NodeId > filo;
122  filo.push_back(__rd->root());
123 
124  while (!filo.empty()) {
125  NodeId curNodeId = filo.back();
126  filo.pop_back();
127 
128  const InternalNode* curNode = __rd->node(curNodeId);
129 
130  for (Idx modality = 0; modality < curNode->nodeVar()->domainSize();
131  ++modality) {
132  NodeId oldSonId = curNode->son(modality);
133 
134  if (!visitedNode.exists(oldSonId)) {
135  NodeId newSonId = oldSonId;
136 
137  if (!__rd->isTerminalNode(oldSonId)) {
138  if (__rd->node(oldSonId)->nodeVar() != curVar) {
139  filo.push_back(oldSonId);
140  } else {
141  const InternalNode* curVarNode = __rd->node(oldSonId);
142  GUM_SCALAR newVal = __neutral;
143  for (Idx curVarModality = 0; curVarModality < curVar->domainSize();
144  ++curVarModality)
145  newVal = __function(
146  newVal, __rd->nodeValue(curVarNode->son(curVarModality)));
147 
148  newSonId = __rd->manager()->addTerminalNode(newVal);
149 
150  __rd->manager()->eraseNode(oldSonId, newSonId, false);
151  __rd->manager()->setSon(curNodeId, modality, newSonId);
152  }
153 
154  } else {
155  GUM_SCALAR newVal = __neutral, oldVal = __rd->nodeValue(oldSonId);
156  for (Idx curVarModality = 0; curVarModality < curVar->domainSize();
157  ++curVarModality)
158  newVal = __function(newVal, oldVal);
159 
160  newSonId = __rd->manager()->addTerminalNode(newVal);
161  __rd->manager()->setSon(curNodeId, modality, newSonId);
162  }
163 
164  visitedNode.insert(oldSonId, newSonId);
165 
166  } else {
167  if (__rd->node(curNodeId)->son(modality) != visitedNode[oldSonId])
168  __rd->manager()->setSon(curNodeId, modality, visitedNode[oldSonId]);
169  }
170  }
171  }
172 
173  if (__rd->variablesSequence().exists(curVar)) __rd->erase(*curVar);
174  }
175 
176  return __rd;
177  }
178 
179 } // namespace gum
Base class for discrete random variable.
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * __rd
The resulting function graph.
Safe iterators for the Set classDevelopers may consider using Set<x>::iterator_safe instead of SetIte...
Definition: set.h:808
const DiscreteVariable * nodeVar() const
Returns the node variable.
const MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * __src
One of the two function graphs used for the Projection.
NodeId son(Idx modality) const
Returns the son at a given index.
Headers of the InternalNode class.
Base class for discrete random variable.
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
const FUNCTOR< GUM_SCALAR > __function
The function to be performed on the leaves.
Representation of a setA Set is a structure that contains arbitrary elements.
Definition: set.h:162
virtual Size domainSize() const =0
MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * project()
Computes and builds the Function Graph that is the result of the Projection.
const GUM_SCALAR __neutral
The function to be performed on the leaves.
Structure used to represent a node internal structure.
Definition: internalNode.h:100
Class implementingting a function graph.
Class used to compute the projection of a function graph.
const Set< const DiscreteVariable *> & __delVars
The list of variables on which the projection is performed.
Size Idx
Type for indexes.
Definition: types.h:50
MultiDimFunctionGraphProjector(const MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > *src, const Set< const DiscreteVariable * > &delVars, const GUM_SCALAR neutral)
Default constructor.
bool empty() const noexcept
Indicates whether the hash table is empty.
Size NodeId
Type for node ids.
Definition: graphElements.h:97
static MultiDimFunctionGraph< GUM_SCALAR, TerminalNodePolicy > * getReducedAndOrderedInstance()
Returns a reduced and ordered instance.
Class used to perform Function Graph projections.