aGrUM  0.14.2
leafAggregator.cpp
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  *********************************************************************************/
26 // =======================================================
27 #include <agrum/core/math/math.h>
29 // =======================================================
30 
31 namespace gum {
32 
33  // ############################################################################
34  // Constructors / Destructors
35  // ############################################################################
36 
37  // ============================================================================
38  // Default constructor.
39  // ============================================================================
41  double similarityThreshold) :
42  __leavesCpt(idSource),
43  __similarityThreshold(similarityThreshold) {
44  GUM_CONSTRUCTOR(LeafAggregator);
46  __needsUpdate = false;
47  }
48 
49  // ============================================================================
50  // Default constructor.
51  // ============================================================================
53  __removeContext(0);
54 
55  delete __initialContext;
56 
58  __leaf2Pair.beginSafe();
59  leafIter != __leaf2Pair.endSafe();
60  ++leafIter) {
61  for (SetIteratorSafe< LeafPair* > pairIter = leafIter.val()->beginSafe();
62  pairIter != leafIter.val()->endSafe();
63  ++pairIter) {
64  LeafPair* curPair = *pairIter;
65  __leaf2Pair[curPair->otherLeaf(leafIter.key())]->erase(*pairIter);
66  leafIter.val()->erase(curPair);
67  delete curPair;
68  }
69  delete leafIter.val();
70  }
71 
72 
73  GUM_DESTRUCTOR(LeafAggregator);
74  }
75 
76  // ############################################################################
77  //
78  // ############################################################################
79 
80  // ============================================================================
81  //
82  // ============================================================================
84  Set< LeafPair* >* leafPairSet = new Set< LeafPair* >();
85  Set< LeafPair* > bag;
86 
87  // ****************************************************************************************
88  // Création et ajout des pairs de base (Feuille de base + nouvelle Feuille)
90  __leaf2Pair.cbeginSafe();
91  leafIter != __leaf2Pair.cendSafe();
92  ++leafIter) {
93  // Création de la pair et ajout dans les listes de pair des feuilles de
94  // base
95  LeafPair* p = new LeafPair(l, leafIter.key());
96  p->updateLikelyhood();
97  leafPairSet->insert(p);
98  (leafIter.val())->insert(p);
99 
100  // Ajout de la nouvelle pair au tas initial
101  __addInitialPair(p);
102 
103  bag.insert(p);
104  }
105 
106  // ****************************************************************************************
107  // Enregistrement de la nouvelle Feuille en tant que feuille de base
108  __leaf2Pair.insert(l, leafPairSet);
109 
110  // ****************************************************************************************
111  // Ajout de la feuille aux FusionContext
112 
114  __fusionSeq.beginSafe();
115  fusIter != __fusionSeq.endSafe();
116  ++fusIter) {
117  // Ajout de la nouvelle pair composée de la feuille de FusIter et de la
118  // nouvelle feuille aux FusionContext suivant
119  for (SetIteratorSafe< LeafPair* > pairIter = bag.beginSafe();
120  pairIter != bag.endSafe();
121  ++pairIter) {
122  if ((*fusIter)->leaf()->contains((*pairIter)->secondLeaf()->id())) {
123  bag >> *pairIter;
124  continue;
125  }
126 
127  if ((*fusIter)->addPair(*pairIter)) __removeContext(fusIter.pos() + 1);
128  }
129 
130  if ((*fusIter)->associateLeaf(l)) __removeContext(fusIter.pos() + 1);
131 
132  bag << (*fusIter)->leafAssociatedPair(l);
133  }
134 
135  __needsUpdate = true;
136  }
137 
138 
139  // ============================================================================
140  //
141  // ============================================================================
143  // ***********************************************************************************
144  // First we update every base pair linked to that leaf
145  Set< LeafPair* > bag(*(__leaf2Pair[l]));
146  for (SetIteratorSafe< LeafPair* > pairIter = bag.beginSafe();
147  pairIter != bag.endSafe();
148  ++pairIter) {
149  (*pairIter)->updateLikelyhood();
150  __updateInitialPair(*pairIter);
151  }
152 
153  // **********************************************************************************
154  // The we have top update FusionContext pairs associated to that leaf
155  AbstractLeaf* curLeaf = l;
157  __fusionSeq.beginSafe();
158  fusIter != __fusionSeq.endSafe();
159  ++fusIter) {
160  if ((*fusIter)->leaf()->contains(curLeaf->id())) {
161  bag.clear();
162  if ((*fusIter)->updateAllAssociatedLeaves())
163  __removeContext(fusIter.pos() + 1);
164  bag = (*fusIter)->associatedPairs();
165  curLeaf = (*fusIter)->leaf();
166  continue;
167  }
168 
169  for (SetIteratorSafe< LeafPair* > pairIter = bag.beginSafe();
170  pairIter != bag.endSafe();
171  ++pairIter) {
172  if ((*fusIter)->leaf()->contains((*pairIter)->secondLeaf()->id())
173  || (*fusIter)->leaf()->contains((*pairIter)->firstLeaf()->id())) {
174  bag >> *pairIter;
175  continue;
176  }
177 
178  if ((*fusIter)->updatePair(*pairIter)) __removeContext(fusIter.pos() + 1);
179  }
180  if ((*fusIter)->updateAssociatedLeaf(curLeaf))
181  __removeContext(fusIter.pos() + 1);
182  bag << (*fusIter)->leafAssociatedPair(curLeaf);
183  }
184 
185  return __needsUpdate;
186  }
187 
188 
189  // ============================================================================
190  //
191  // ============================================================================
193  // ***********************************************************************************
194  // First we update every base pair linked to that leaf
195  Set< LeafPair* > bag(*(__leaf2Pair[l]));
196  for (SetIteratorSafe< LeafPair* > pairIter = bag.beginSafe();
197  pairIter != bag.endSafe();
198  ++pairIter) {
199  __removeInitialPair(*pairIter);
200  (*__leaf2Pair[(*pairIter)->otherLeaf(l)]) >> *pairIter;
201  }
202 
203  // **********************************************************************************
204  // The we have top update FusionContext pairs associated to that leaf
205  Set< LeafPair* > toBeDeleted;
207  __fusionSeq.beginSafe();
208  fusIter != __fusionSeq.endSafe();
209  ++fusIter) {
210  for (SetIteratorSafe< LeafPair* > pairIter = bag.beginSafe();
211  pairIter != bag.endSafe();
212  ++pairIter) {
213  if ((*fusIter)->leaf()->contains((*pairIter)->secondLeaf()->id())
214  || (*fusIter)->leaf()->contains((*pairIter)->firstLeaf()->id())) {
215  bag >> *pairIter;
216  continue;
217  }
218 
219  if ((*fusIter)->removePair(*pairIter)) {
220  __removeContext(fusIter.pos() + 1);
221  }
222  }
223 
224  bag << (*fusIter)->leafAssociatedPair(l);
225  toBeDeleted << (*fusIter)->leafAssociatedPair(l);
226 
227  if ((*fusIter)->deassociateLeaf(l)) { __removeContext(fusIter.pos() + 1); }
228  }
229 
230  for (SetIteratorSafe< LeafPair* > pairIter = toBeDeleted.beginSafe();
231  pairIter != toBeDeleted.endSafe();
232  ++pairIter)
233  delete *pairIter;
234 
235  for (SetIteratorSafe< LeafPair* > pairIter = __leaf2Pair[l]->beginSafe();
236  pairIter != __leaf2Pair[l]->endSafe();
237  ++pairIter)
238  delete *pairIter;
239  delete __leaf2Pair[l];
240  __leaf2Pair.erase(l);
241 
242  __needsUpdate = true;
243  }
244 
245 
246  // ============================================================================
247  //
248  // ============================================================================
250  LeafPair* nextPair = __initialContext->top();
253  if (!__fusionSeq.empty()) {
254  nextPair = __fusionSeq.back()->top();
255  pb = __fusionSeq.back()->beginPairs();
256  pe = __fusionSeq.back()->endPairs();
257  }
258 
259 
260  while (nextPair && nextPair->likelyhood() < __similarityThreshold) {
261  AbstractLeaf* newLeaf = nextPair->convert2Leaf(__leavesCpt->addNode());
262  FusionContext< false >* newContext = new FusionContext< false >(newLeaf);
263 
264  for (pair_iterator pairIter = pb; pairIter != pe; ++pairIter) {
265  if (!newLeaf->contains(pairIter.key()->firstLeaf()->id())
266  && !newLeaf->contains(pairIter.key()->secondLeaf()->id()))
267  newContext->addPair(pairIter.key());
268  if (!newLeaf->contains(pairIter.key()->firstLeaf()->id())
269  && !newContext->containsAssociatedLeaf(pairIter.key()->firstLeaf()))
270  newContext->associateLeaf(pairIter.key()->firstLeaf());
271  if (!newLeaf->contains(pairIter.key()->secondLeaf()->id())
272  && !newContext->containsAssociatedLeaf(pairIter.key()->secondLeaf()))
273  newContext->associateLeaf(pairIter.key()->secondLeaf());
274  }
275 
276  __fusionSeq.insert(newContext);
277  nextPair = __fusionSeq.back()->top();
278  pb = __fusionSeq.back()->beginPairs();
279  pe = __fusionSeq.back()->endPairs();
280  }
281  __needsUpdate = false;
282  }
283 
284 
288  __fusionSeq.rbeginSafe();
289  fusIter != __fusionSeq.rendSafe();
290  --fusIter) {
291  bool alreadyIn = false;
293  retMap.beginSafe();
294  mapIter != retMap.endSafe();
295  ++mapIter)
296  if (mapIter.val()->contains((*fusIter)->leaf()->id())) {
297  alreadyIn = true;
298  break;
299  }
300  if (!alreadyIn) retMap.insert((*fusIter)->leaf()->id(), (*fusIter)->leaf());
301  }
302 
304  __leaf2Pair.beginSafe();
305  leafIter != __leaf2Pair.endSafe();
306  ++leafIter) {
308  retMap.beginSafe();
309  mapIter != retMap.endSafe();
310  ++mapIter)
311  if (mapIter.val()->contains(leafIter.key()->id())) {
312  retMap.insert(leafIter.key()->id(), mapIter.val());
313  break;
314  }
315  if (!retMap.exists(leafIter.key()->id()))
316  retMap.insert(leafIter.key()->id(), leafIter.key());
317  }
318 
319  return retMap;
320  }
321 
322 
323  std::string LeafAggregator::toString() {
324  std::stringstream ss;
325  ss << "################\nTas Initial : " << std::endl
326  << __initialContext->toString() << std::endl;
327 
328  for (auto fusIter = __fusionSeq.beginSafe(); fusIter != __fusionSeq.endSafe();
329  ++fusIter) {
330  ss << "################\nTas " << fusIter.pos() << " : " << std::endl
331  << (*fusIter)->toString();
332  }
333 
334  return ss.str();
335  }
336 
337  // ############################################################################
338  //
339  // ############################################################################
340 
341  // ============================================================================
342  //
343  // ============================================================================
345  for (Idx i = __fusionSeq.size() - 1; !__fusionSeq.empty() && i >= startingPos;
346  --i) {
347  __leavesCpt->eraseNode(__fusionSeq.atPos(i)->leaf()->id());
348  delete __fusionSeq.atPos(i);
349  __fusionSeq.erase(__fusionSeq.atPos(i));
350  }
351 
352  __needsUpdate = true;
353  }
354 
355 
356  // ============================================================================
357  //
358  // ============================================================================
360  bool res = __initialContext->addPair(p);
361  if (res) __removeContext(0);
362  }
363 
364 
365  // ============================================================================
366  //
367  // ============================================================================
369  bool res = __initialContext->updatePair(p);
370  if (res) __removeContext(0);
371  }
372 
373  // ============================================================================
374  //
375  // ============================================================================
377  bool res = __initialContext->removePair(p);
378  if (res) __removeContext(0);
379  }
380 
381 } // namespace gum
Useful macros for maths.
virtual bool contains(NodeId testedId) const
Returns true if abstractleaf has leaf in it.
Definition: abstractLeaf.h:90
Safe iterators for Sequence.
Definition: sequence.h:1203
void __removeInitialPair(LeafPair *)
AbstractLeaf * convert2Leaf(NodeId leafId) const
Returns a leaf matching data and having given id as id.
Definition: leafPair.h:112
const iterator_safe & endSafe() noexcept
Returns the safe iterator pointing to the end of the hashtable.
Safe iterators for the Set classDevelopers may consider using Set<x>::iterator_safe instead of SetIte...
Definition: set.h:808
std::string toString()
<agrum/FMDP/learning/FunctionGraph/leafAggregator.h>
bool removePair(LeafPair *p)
pair_iterator endPairs()
<agrum/FMDP/learning/datastructure/leaves/abstractLeaf.h>
Definition: abstractLeaf.h:50
Safe Const Iterators for hashtables.
Definition: hashTable.h:1915
<agrum/FMDP/learning/datastructure/leaves/leafPair.h>
Definition: leafPair.h:48
bool exists(const Key &key) const
Checks whether there exists an element with a given key in the hashtable.
NodeGraphPart * __leavesCpt
void __addInitialPair(LeafPair *)
Safe Iterators for hashtables.
Definition: hashTable.h:2217
gum is the global namespace for all aGrUM entities
Definition: agrum.h:25
virtual NodeId addNode()
insert a new node and return its id
The class for generic Hash Tables.
Definition: hashTable.h:676
Representation of a setA Set is a structure that contains arbitrary elements.
Definition: set.h:162
const iterator_safe & endSafe() const noexcept
The usual safe end iterator to parse the set.
Definition: set_tpl.h:499
~LeafAggregator()
Default destructor.
Sequence< FusionContext< false > *> __fusionSeq
AbstractLeaf * otherLeaf(AbstractLeaf *l) const
Definition: leafPair.h:116
LeafAggregator(NodeGraphPart *idSource, double similarityThreshold)
Default constructor.
Class for node sets in graph.
bool addPair(LeafPair *p)
HashTable< NodeId, AbstractLeaf *> leavesMap()
FusionContext< true > * __initialContext
HashTable< AbstractLeaf *, Set< LeafPair *> *> __leaf2Pair
iterator_safe beginSafe()
Returns the safe iterator pointing to the beginning of the hashtable.
iterator_safe beginSafe() const
The usual safe begin iterator to parse the set.
Definition: set_tpl.h:485
bool containsAssociatedLeaf(AbstractLeaf *l)
Definition: fusionContext.h:93
LeafPair * top()
Size Idx
Type for indexes.
Definition: types.h:50
void removeLeaf(AbstractLeaf *)
void clear()
Removes all the elements, if any, from the set.
Definition: set_tpl.h:372
bool associateLeaf(AbstractLeaf *l)
std::string toString()
value_type & insert(const Key &key, const Val &val)
Adds a new element (actually a copy of this element) into the hash table.
bool updateLeaf(AbstractLeaf *)
double likelyhood()
Updates GStatistic.
Definition: leafPair.cpp:74
void addLeaf(AbstractLeaf *)
void insert(const Key &k)
Inserts a new element into the set.
Definition: set_tpl.h:610
Headers of the Leaf Aggregator class.
bool updatePair(LeafPair *p)
void updateLikelyhood()
Updates GStatistic.
Definition: leafPair.cpp:39
pair_iterator beginPairs()
virtual void eraseNode(const NodeId id)
erase the node with the given id
void __updateInitialPair(LeafPair *)