OpenWalnut  1.5.0dev
WHtreePartition.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 //---------------------------------------------------------------------------
26 //
27 // Project: hClustering
28 //
29 // Whole-Brain Connectivity-Based Hierarchical Parcellation Project
30 // David Moreno-Dominguez
31 // d.mor.dom@gmail.com
32 // moreno@cbs.mpg.de
33 // www.cbs.mpg.de/~moreno//
34 // This file is also part of OpenWalnut ( http://www.openwalnut.org ).
35 //
36 // hClustering is free software: you can redistribute it and/or modify
37 // it under the terms of the GNU Lesser General Public License as published by
38 // the Free Software Foundation, either version 3 of the License, or
39 // (at your option) any later version.
40 // http://creativecommons.org/licenses/by-nc/3.0
41 //
42 // hClustering is distributed in the hope that it will be useful,
43 // but WITHOUT ANY WARRANTY; without even the implied warranty of
44 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45 // GNU Lesser General Public License for more details.
46 //
47 //---------------------------------------------------------------------------
48 
49 #include <vector>
50 #include <list>
51 #include <string>
52 #include <utility>
53 #include <map>
54 #include <algorithm>
55 #include <limits>
56 
57 
58 #include "core/common/WStringUtils.h"
59 
60 #include "WHtreePartition.h"
61 
62 
63 
64 WHtreePartition::WHtreePartition( WHtree* const tree ) : m_tree( *tree )
65 {
66 }
67 
69 {
70  //Cleanup
71 }
72 
73 // === PUBLIC MEMBER FUNCTIONS ===
74 
75 void WHtreePartition::scanOptimalPartitions( const size_t levelDepth, std::vector< float >* partitionValuesPointer,
76  std::vector< std::vector< size_t> >* partitionVectorPointer, const bool verbose )
77 {
78  std::vector< float >& partitionValues = *partitionValuesPointer;
79  std::vector< std::vector< size_t> >& partitionVector = *partitionVectorPointer;
80 
81  partitionValues.clear();
82  partitionVector.clear();
83 
84  size_t match250( 0 ), mismatch250( 0 ), match500( 0 ), mismatch500( 0 ), match1000( 0 ), mismatch1000( 0 );
85  size_t match2000( 0 ), mismatch2000( 0 ), match5000( 0 ), mismatch5000( 0 );
86 
87 
88  std::vector< size_t > currentPartition, lastPartition;
89  float currentValue;
90 
91  // do first step
92  {
93  const WHnode treeRoot( m_tree.getRoot() );
94  std::vector< nodeID_t > firstKids( treeRoot.getChildren() );
95  for( size_t i = 0; i < firstKids.size(); ++i )
96  {
97  // get kids of root as first partition set
98  if( firstKids[i].first )
99  {
100  currentPartition.push_back( firstKids[i].second );
101  }
102  }
103 
104  currentValue = evalPartOptimal( currentPartition );
105 
106  partitionValues.push_back( currentValue );
107  partitionVector.push_back( currentPartition );
108  } // end first step
109 
110  lastPartition = currentPartition;
111  if( verbose )
112  {
113  std::cout << "Step: " << 0 << ". Current partition size: " << currentPartition.size() << ". Current value: " << currentValue << std::flush;
114  }
115 
116  size_t stepNr( 0 );
117 
118  while( true )
119  {
120  ++stepNr;
121  std::cout << "\rStep: " << stepNr << ". Current partition size: ";
122  std::cout << currentPartition.size() << ". Current value: ";
123  std::cout << currentValue << " " << std::flush;
124 
125  std::vector<float> currentLevels;
126  currentLevels.reserve( currentPartition.size() );
127  size_t highestLevelindex( 0 );
128  for( size_t i = 0; i < currentPartition.size(); ++i )
129  {
130  currentLevels.push_back( m_tree.getNode( currentPartition[i] ).getDistLevel() );
131  if( currentLevels[i] > currentLevels[highestLevelindex] )
132  {
133  highestLevelindex = i;
134  }
135  }
136 
137  lastPartition = currentPartition;
138 
139  std::vector< std::vector< size_t > > derivedPartitionSet;
140  std::vector< std::vector< unsigned int > > derivedIndexes( m_tree.getBranching( currentPartition, levelDepth, &derivedPartitionSet ) );
141 
142  std::vector< double > derivedPartitionValues( derivedPartitionSet.size(), -1 );
143  bool stopLoop( true );
144 
145  // get the partitions and values for all possible branchings
146  #pragma omp parallel for schedule( guided )
147  for( size_t i = 0; i < derivedPartitionSet.size(); ++i )
148  {
149  // if there are possible branchings continue looping
150  #pragma omp critical
151  stopLoop = false;
152 
153  //get the value for this partition
154  derivedPartitionValues[i] = evalPartOptimal( derivedPartitionSet[i] );
155  } // endFor
156 
157  //if there are no more possible branchings stop the loop
158  if( stopLoop )
159  {
160  break;
161  }
162 
163 
164  size_t bestPartitionIndex( 0 );
165  float bestValue( -1 );
166  for( size_t j = 0; j < derivedPartitionValues.size(); ++j )
167  {
168  //if value is better than previous ones, keep partition and matrix
169  if( derivedPartitionValues[j] > bestValue )
170  {
171  bestValue = derivedPartitionValues[j];
172  bestPartitionIndex = j;
173  }
174  }
175 
176  unsigned int firstBranchIndex( derivedIndexes[bestPartitionIndex].front() );
177 
178  // find the first branching partition corresponding to the best partition found
179  if( derivedIndexes[bestPartitionIndex].size() == 1 )
180  {
181  // it was a first branch partition
182  currentPartition = derivedPartitionSet[bestPartitionIndex];
183  }
184  else
185  {
186  size_t nextBestIndex( 0 );
187  bool notFound( true );
188 
189  for( size_t j = 0; j < derivedIndexes.size(); ++j )
190  {
191  if( ( derivedIndexes[j].size() == 1 ) && ( derivedIndexes[j].front() == firstBranchIndex ) )
192  {
193  nextBestIndex = j;
194  notFound = false;
195  }
196  }
197 
198  if( notFound )
199  {
200  throw std::runtime_error( "ERROR @ partitionMatcher::findMatchingPartitions(): best match index not found" );
201  }
202 
203  currentPartition = derivedPartitionSet[nextBestIndex];
204  currentValue = derivedPartitionValues[nextBestIndex];
205  }
206 
207  //introduce best partition on the vector and update current vector and matrix
208  partitionValues.push_back( currentValue );
209  partitionVector.push_back( currentPartition );
210 
211 
212  std::vector< nodeID_t > partHozFullID;
213  partitionClassic( currentPartition.size(), &partHozFullID, HTP_HOZ, HTC_CNUM, true, m_tree.getRoot().getID() );
214  std::vector< size_t > partHoz;
215  partHoz.reserve( partHozFullID.size() );
216  for( size_t i = 0; i < partHozFullID.size(); ++i )
217  {
218  if( partHozFullID[i].first )
219  {
220  partHoz.push_back( partHozFullID[i].second );
221  }
222  }
223 
224  std::vector< size_t > currentCopy( currentPartition );
225  std::sort( partHoz.begin(), partHoz.end() );
226  std::sort( currentCopy.begin(), currentCopy.end() );
227 
228 
229  //bool matchcondition( firstBranchIndex == highestLevelindex );
230  bool matchcondition( partHoz == currentCopy );
231 
232 
233  if( currentPartition.size() <= 250 )
234  {
235  if( matchcondition )
236  {
237  ++match250;
238  }
239  else
240  {
241  ++mismatch250;
242  }
243  }
244  if( currentPartition.size() <= 500 )
245  {
246  if( matchcondition )
247  {
248  ++match500;
249  }
250  else
251  {
252  ++mismatch500;
253  }
254  }
255  if( currentPartition.size() <= 1000 )
256  {
257  if( matchcondition )
258  {
259  ++match1000;
260  }
261  else
262  {
263  ++mismatch1000;
264  }
265  }
266  if( currentPartition.size() <= 2000 )
267  {
268  if( matchcondition )
269  {
270  ++match2000;
271  }
272  else
273  {
274  ++mismatch2000;
275  }
276  }
277  if( currentPartition.size() <= 5000 )
278  {
279  if( matchcondition )
280  {
281  ++match5000;
282  }
283  else
284  {
285  ++mismatch5000;
286  }
287  }
288  } // end infinite loop
289 
290  if( verbose )
291  {
292  std::cout << std::endl;
293  }
294 
295 
296  ///////////printout
297  std::cout << "Are partition decisions the same as in horizontal partitioning???" << std::endl;
298  std::cout << "250 % match: " << ( match250*100.0 )/( match250+mismatch250 );
299  std::cout << ". Total matches: " << match250 << ". fails: " << mismatch250 << std::endl;
300  std::cout << "500 % match: " << ( match500*100.0 )/( match500+mismatch500 );
301  std::cout << ". Total matches: " << match500 << ". fails: " << mismatch500 << std::endl;
302  std::cout << "1000 % match: " << ( match1000*100.0 )/( match1000+mismatch1000 );
303  std::cout << ". Total matches: " << match1000 << ". fails: " << mismatch1000 << std::endl;
304  std::cout << "2000 % match: " << ( match2000*100.0 )/( match2000+mismatch2000 );
305  std::cout << ". Total matches: " << match2000 << ". fails: " << mismatch2000 << std::endl;
306  std::cout << "5000 % match: " << ( match5000*100.0 )/( match5000+mismatch5000 );
307  std::cout << ". Total matches: " << match5000 << ". fails: " << mismatch5000 << std::endl;
308 
309 
310 
311 
312  return;
313 } // end scanOptimalPartitions() -------------------------------------------------------------------------------------
314 
315 
316 void WHtreePartition::scanHozPartitions( std::vector< float >* partitionValuesPointer,
317  std::vector< std::vector< size_t> >* partitionVectorPointer,
318  const bool verbose )
319 {
320  std::vector< float >& partitionValues = *partitionValuesPointer;
321  std::vector< std::vector< size_t> >& partitionVector = *partitionVectorPointer;
322 
323  partitionValues.clear();
324  partitionVector.clear();
325 
326  std::vector< size_t > currentPartition, lastPartition;
327  float currentValue;
328 
329  // do first step
330  {
331  const WHnode treeRoot( m_tree.getRoot() );
332  std::vector< nodeID_t > firstKids( treeRoot.getChildren() );
333  for( size_t i = 0; i < firstKids.size(); ++i )
334  {
335  // get kids of root as first partition set
336  if( firstKids[i].first )
337  {
338  currentPartition.push_back( firstKids[i].second );
339  }
340  }
341 
342  currentValue = evalPartOptimal( currentPartition );
343 
344  partitionValues.push_back( currentValue );
345  partitionVector.push_back( currentPartition );
346  } // end first step
347 
348  lastPartition = currentPartition;
349  if( verbose )
350  {
351  std::cout << "Step: " << 0 << ". Current partition size: " << currentPartition.size() << ". Current value: " << currentValue << std::flush;
352  }
353 
354  size_t stepNr( 0 );
355  size_t partSizeCounter( currentPartition.size() );
356  size_t lastSize( currentPartition.size() );
357 
358  while( partSizeCounter <= 5000 )
359  {
360  ++stepNr;
361  ++partSizeCounter;
362  std::cout << "\rStep: " << stepNr << ". Current partition size: ";
363  std::cout << currentPartition.size() << ". Current value: ";
364  std::cout << currentValue << " " << std::flush;
365 
366  std::vector<nodeID_t> partHozFullID;
367  partitionClassic( partSizeCounter, &partHozFullID, HTP_HOZ, HTC_CNUM, true, m_tree.getRoot().getID() );
368  currentPartition.clear();
369  currentPartition.reserve( partHozFullID.size() );
370  for( size_t i = 0; i < partHozFullID.size(); ++i )
371  {
372  if( partHozFullID[i].first )
373  {
374  currentPartition.push_back( partHozFullID[i].second );
375  }
376  }
377 
378  currentValue = evalPartOptimal( currentPartition );
379  partitionValues.push_back( currentValue );
380  partitionVector.push_back( currentPartition );
381  partSizeCounter = currentPartition.size();
382 
383  if( lastSize == partSizeCounter )
384  {
385  break;
386  }
387 
388  lastSize = partSizeCounter;
389  } // end infinite loop
390 
391  if( verbose )
392  {
393  std::cout << std::endl;
394  }
395 
396 
397  return;
398 } // end scanHozPartitions() -------------------------------------------------------------------------------------
399 
400 
401 
402 size_t WHtreePartition::filterMaxPartitions( const unsigned int filterRadius,
403  std::vector< float > *partValPoint,
404  std::vector< std::vector< size_t> > *partVectorPoint )
405 {
406  std::vector< float > &partValues( *partValPoint );
407  std::vector< std::vector< size_t> > &partVector( *partVectorPoint );
408 
409  std::vector< float > filteredValues;
410  std::vector< std::vector< size_t> > filteredPartitions;
411 
412  size_t partCount( 0 ), bestIndex( 0 );
413  float bestValue( -1 );
414 
415  for( size_t i = 0; i < partValues.size(); ++i )
416  {
417  // get in a vector the allements within the filter raidzs, centre element is always first entry
418  std::vector< float > currentValues;
419  currentValues.reserve( 1+ ( 2*filterRadius ) );
420  size_t jDownLimit( ( i > filterRadius ) ? ( i - filterRadius ) : 0 );
421  size_t jUpLimit( std::min( i + filterRadius + 1, partValues.size() ) );
422 
423 
424  size_t centreIndex( 0 );
425  for( size_t j = jDownLimit; j < jUpLimit; ++j )
426  {
427  if( j == i )
428  {
429  centreIndex = currentValues.size();
430  }
431  currentValues.push_back( partValues[j] );
432  }
433 
434  // centre element is the biggest
435  if( std::max_element( currentValues.begin(), currentValues.end() ) == ( currentValues.begin() + centreIndex ) )
436  {
437  filteredValues.push_back( partValues[i] );
438  filteredPartitions.push_back( partVector[i] );
439 
440  if( partValues[i] > bestValue )
441  {
442  bestValue = partValues[i];
443  bestIndex = partCount;
444  }
445 
446  ++partCount;
447  }
448  }
449 
450  partValues.swap( filteredValues );
451  partVector.swap( filteredPartitions );
452 
453  return bestIndex;
454 } // end filterMaxPartitions() -------------------------------------------------------------------------------------
455 
456 
457 
458 void WHtreePartition::writePartitionSet( std::string partFileName,
459  const std::vector< float > &partitionValues,
460  const std::vector< std::vector< size_t> > &patitionVector )
461 {
462  std::ofstream partFile( partFileName.c_str() );
463  if( !partFile )
464  {
465  std::cerr << "ERROR: unable to open out file: \"" << partFileName << "\"" << std::endl;
466  exit( -1 );
467  }
468 
469 
470 
471  partFile << "#value size" << std::endl;
472 
473  for( size_t i = 0; i < partitionValues.size(); ++i )
474  {
475  partFile << partitionValues[i] << " " << patitionVector[i].size() << std::endl;
476  }
477 
478  return;
479 } // end writePartitionSet() -------------------------------------------------------------------------------------
480 
481 
482 // === PRIVATE MEMBER FUNCTIONS ===
483 
484 
485 float WHtreePartition::evalPartOptimal( const std::vector<size_t> &partition ) const
486 {
487  std::vector<nodeID_t> partFullID;
488  partFullID.reserve( partition.size() );
489  for( size_t i = 0; i < partition.size(); ++i )
490  {
491  partFullID.push_back( std::make_pair( true, partition[i] ) );
492  }
493  return evalPartOptimal( partFullID );
494 } // end evalPartOptimal() -------------------------------------------------------------------------------------
495 float WHtreePartition::evalPartOptimal( const std::vector<nodeID_t> &partition ) const
496 {
497 // float intraDvalue( evalPartIntraDistWeighted( partition ) );
498 // float interDvalue( evalPartBranchDist ( partition ) );
499 // return interDvalue / intraDvalue;
500 
501  return evalSSindex( partition );
502 } // end evalPartOptimal() -------------------------------------------------------------------------------------
503 
504 
505 
506 float WHtreePartition::evalSSindex( const std::vector<size_t> &partition ) const
507 {
508  std::vector<nodeID_t> partFullID;
509  partFullID.reserve( partition.size() );
510  for( size_t i = 0; i < partition.size(); ++i )
511  {
512  partFullID.push_back( std::make_pair( true, partition[i] ) );
513  }
514  return evalSSindex( partFullID );
515 } // end evalSSindex() -------------------------------------------------------------------------------------
516 float WHtreePartition::evalSSindex( const std::vector<nodeID_t> &partition ) const
517 {
518 // double ssSum( 0 );
519 // double sizeSum( 0 );
520 
521  double spreadSum( 0 );
522  double sepSum( 0 );
523  double sizeSum( 0 );
524  for( size_t i = 0; i < partition.size(); ++i )
525  {
526  const WHnode &thisNode( m_tree.getNode( partition[i] ) );
527  const WHnode &parentNode( m_tree.getNode( thisNode.getParent() ) );
528 
529 // ssSum += ( parentNode.getDistLevel() * thisNode.getSize() ) / thisNode.getDistLevel() ;
530 // sizeSum += thisNode.getSize();
531 
532  spreadSum += thisNode.getSize() *thisNode.getDistLevel();
533  sepSum += parentNode.getDistLevel();
534  sizeSum += thisNode.getSize();
535  }
536 // return ssSum / sizeSum ;
537 
538  double part1( sizeSum/partition.size() );
539  double part2( sepSum/spreadSum );
540 
541  return ( part1*part2 );
542 } // end evalSSindex() -------------------------------------------------------------------------------------
543 
544 
545 std::pair< float, float > WHtreePartition::evalPartClustSizeDiff( const std::vector<size_t> &partition ) const
546 {
547  std::vector<nodeID_t> partFullID;
548  partFullID.reserve( partition.size() );
549  for( size_t i = 0; i < partition.size(); ++i )
550  {
551  partFullID.push_back( std::make_pair( true, partition[i] ) );
552  }
553  return evalPartClustSizeDiff( partFullID );
554 } // end evalPartitClustSizeD() -------------------------------------------------------------------------------------
555 std::pair< float, float > WHtreePartition::evalPartClustSizeDiff( const std::vector<nodeID_t> &partition ) const
556 {
557  double diffSqSum( 0 ), sizeSum( 0 );
558  for( size_t i = 0; i < partition.size() - 1; ++i )
559  {
560  double size1( m_tree.getNode( partition[i] ).getSize() );
561  for( size_t j = i+1; j < partition.size(); ++j )
562  {
563  double size2( m_tree.getNode( partition[j] ).getSize() );
564  double sizeDif( size1 - size2 );
565  diffSqSum += sizeDif*sizeDif;
566  }
567  sizeSum += size1;
568  }
569  sizeSum += m_tree.getNode( partition.back() ).getSize();
570  double M( partition.size() * ( partition.size() -1 ) / 2.0 );
571  return std::make_pair( sizeSum/partition.size(), diffSqSum/M );
572 } // end evalPartitClustSizeD() -------------------------------------------------------------------------------------
573 
574 float WHtreePartition::evalPartIntraDist( const std::vector<size_t> &partition ) const
575 {
576  std::vector<nodeID_t> partFullID;
577  partFullID.reserve( partition.size() );
578  for( size_t i = 0; i < partition.size(); ++i )
579  {
580  partFullID.push_back( std::make_pair( true, partition[i] ) );
581  }
582  return evalPartIntraDist( partFullID );
583 } // end evalPartitWintraD() -------------------------------------------------------------------------------------
584 
585 float WHtreePartition::evalPartIntraDist( const std::vector<nodeID_t> &partition ) const
586 {
587  double iaDistSum( 0 );
588  for( size_t i = 0; i < partition.size(); ++i )
589  {
590  const WHnode &thisNode( m_tree.getNode( partition[i] ) );
591  iaDistSum += thisNode.getDistLevel();
592  }
593  return iaDistSum/partition.size();
594 } // end evalPartitWintraD() -------------------------------------------------------------------------------------
595 
596 
597 float WHtreePartition::evalPartIntraDistWeighted( const std::vector<size_t> &partition ) const
598 {
599  std::vector<nodeID_t> partFullID;
600  partFullID.reserve( partition.size() );
601  for( size_t i = 0; i < partition.size(); ++i )
602  {
603  partFullID.push_back( std::make_pair( true, partition[i] ) );
604  }
605  return evalPartIntraDistWeighted( partFullID );
606 } // end evalPartitIntraDweighted() -------------------------------------------------------------------------------------
607 float WHtreePartition::evalPartIntraDistWeighted( const std::vector<nodeID_t> &partition ) const
608 {
609  double iaWDistSum( 0 );
610  size_t sizeSum( 0 );
611  for( size_t i = 0; i < partition.size(); ++i )
612  {
613  const WHnode &thisNode( m_tree.getNode( partition[i] ) );
614  iaWDistSum += thisNode.getDistLevel()*thisNode.getSize();
615  sizeSum += thisNode.getSize();
616  }
617  return iaWDistSum/sizeSum;
618 } // end evalPartitIntraDweighted() -------------------------------------------------------------------------------------
619 
620 float WHtreePartition::evalPartBranchDist( const std::vector<size_t> &partition ) const
621 {
622  std::vector<nodeID_t> partFullID;
623  partFullID.reserve( partition.size() );
624  for( size_t i = 0; i < partition.size(); ++i )
625  {
626  partFullID.push_back( std::make_pair( true, partition[i] ) );
627  }
628  return evalPartBranchDist( partFullID );
629 } // end evalPartitDnb() -------------------------------------------------------------------------------------
630 
631 float WHtreePartition::evalPartBranchDist( const std::vector<nodeID_t> &partition ) const
632 {
633  double iaDistSum( 0 );
634  for( size_t i = 0; i < partition.size(); ++i )
635  {
636  const WHnode &thisNode( m_tree.getNode( partition[i] ) );
637  const WHnode &parentNode( m_tree.getNode( thisNode.getParent() ) );
638  iaDistSum += parentNode.getDistLevel();
639  }
640  return iaDistSum/partition.size();
641 } // end evalPartitDnb() -------------------------------------------------------------------------------------
642 
643 
644 float WHtreePartition::evalPartBranchDistWeighted( const std::vector<size_t> &partition ) const
645 {
646  std::vector<nodeID_t> partFullID;
647  partFullID.reserve( partition.size() );
648  for( size_t i = 0; i < partition.size(); ++i )
649  {
650  partFullID.push_back( std::make_pair( true, partition[i] ) );
651  }
652  return evalPartBranchDistWeighted( partFullID );
653 } // end evalPartitDnb() -------------------------------------------------------------------------------------
654 float WHtreePartition::evalPartBranchDistWeighted( const std::vector<nodeID_t> &partition ) const
655 {
656  double iaDistSum( 0 ), sizeSum( 0 );
657  for( size_t i = 0; i < partition.size(); ++i )
658  {
659  const WHnode &thisNode( m_tree.getNode( partition[i] ) );
660  size_t thisSize( thisNode.getSize() );
661  const WHnode &parentNode( m_tree.getNode( thisNode.getParent() ) );
662  iaDistSum += parentNode.getDistLevel() * thisSize;
663  sizeSum += thisSize;
664  }
665  return iaDistSum/sizeSum;
666 } // end evalPartitDnb() -------------------------------------------------------------------------------------
667 
668 
669 
670 
671 
672 float WHtreePartition::partitionClassic( float compValue, std::vector<nodeID_t> * partition, const HT_PARTMODE mode, const HT_CONDITION condition,
673  const bool excludeLeaves, const size_t root ) const
674 {
675  partition->clear();
676  if( root > m_tree.getRoot().getID() )
677  {
678  std::cerr << "ERROR @ WHtree::partitionClassic(): branch root ID is out of boundaries (ID: "
679  << root << ", # nodes: " << m_tree.getNumNodes() << " )." << std::endl;
680  return 0;
681  }
682 
683  std::list<nodeID_t> worklist;
684  std::list<nodeID_t> storelist;
685  worklist.push_back( std::make_pair( true, root ) );
686  float currentValue( 0 );
687  WHnode currentNode( m_tree.getNode( root ) );
688  bool loopCondition( true );
689 
690  switch( mode )
691  {
692  case HTP_HOZ:
693  currentValue = m_tree.getNode( root ).getDistLevel();
694  if( condition == HTC_CNUM )
695  {
696  compValue = static_cast<int>( compValue );
697  }
698  break;
699  case HTP_SIZE:
700  currentValue = m_tree.getNode( root ).getSize();
701  compValue = static_cast<int>( compValue );
702  break;
703  case HTP_HLEVEL:
704  currentValue = m_tree.getNode( root ).getHLevel();
705  compValue = static_cast<int>( compValue );
706  break;
707  default:
708  std::cerr << "ERROR @ WHtree::partitionClassic(): mode not recognized " << std::endl;
709  return 0;
710  break;
711  }
712 
713  switch( condition )
714  {
715  case HTC_VALUE:
716  loopCondition = ( currentValue > compValue );
717  break;
718  case HTC_CNUM:
719  loopCondition = ( worklist.size() + storelist.size() < compValue );
720  break;
721  default:
722  std::cerr << "ERROR @ WHtree::partitionClassic(): condition not recognized " << std::endl;
723  return 0;
724  break;
725  }
726 
727  while( loopCondition )
728  {
729  const WHnode current( m_tree.getNode( worklist.front() ) );
730  worklist.pop_front();
731  std::vector<nodeID_t> kids( current.getChildren() );
732  for( size_t i = 0; i < kids.size(); ++i )
733  {
734  const WHnode thisKid( m_tree.getNode( kids[i] ) );
735  if( thisKid.isLeaf() )
736  {
737  storelist.push_back( thisKid.getFullID() );
738  }
739  else if( thisKid.getHLevel() == 1 && excludeLeaves )
740  {
741  storelist.push_back( thisKid.getFullID() );
742  }
743  else
744  {
745  worklist.push_back( thisKid.getFullID() );
746  }
747  }
748 
749  if( worklist.empty() )
750  {
751  break;
752  }
753 
754  switch( mode )
755  {
756  case HTP_HOZ:
757  worklist.sort();
758  worklist.reverse();
759  currentNode = m_tree.getNode( worklist.front() );
760  currentValue = currentNode.getDistLevel();
761  break;
762  case HTP_SIZE:
763  m_tree.sortBySize( &worklist );
764  worklist.reverse();
765  currentNode = m_tree.getNode( worklist.front() );
766  currentValue = currentNode.getSize();
767  break;
768  case HTP_HLEVEL:
769  m_tree.sortByHLevel( &worklist );
770  worklist.reverse();
771  currentNode = m_tree.getNode( worklist.front() );
772  currentValue = currentNode.getHLevel();
773  break;
774  default:
775  break;
776  }
777 
778  switch( condition )
779  {
780  case HTC_VALUE:
781  loopCondition = ( currentValue > compValue );
782  break;
783  case HTC_CNUM:
784  loopCondition = ( worklist.size() + storelist.size() < compValue );
785  break;
786  default:
787  break;
788  }
789  }
790 
791  storelist.insert( storelist.end(), worklist.begin(), worklist.end() );
792  worklist.clear();
793 
794  // assign output current value
795  float output( 0 );
796  switch( mode )
797  {
798  case HTP_HOZ:
799  if( !currentNode.isRoot() )
800  {
801  output = ( currentNode.getDistLevel() + m_tree.getNode( currentNode.getID()+1 ).getDistLevel() ) * 0.5;
802  }
803  else
804  {
805  output = ( 1+currentNode.getDistLevel() )*0.5;
806  }
807  break;
808  case HTP_SIZE:
809  output = currentValue;
810  break;
811  case HTP_HLEVEL:
812  output = currentValue;
813  break;
814  default:
815  break;
816  }
817 
818  storelist.sort();
819  partition->reserve( storelist.size() );
820  for( std::list<nodeID_t>::iterator it( storelist.begin() ); it != storelist.end(); ++it )
821  {
822  partition->push_back( *it );
823  }
824  return output;
825 } // end partitionClassic() -------------------------------------------------------------------------------------
826 
827 
828 float WHtreePartition::partitionOptimized( float compValue, std::vector<nodeID_t> * partition, const HT_PARTMODE2 mode, const HT_CONDITION condition,
829  const bool excludeLeaves, const size_t root, const size_t levelDepth ) const
830 {
831  std::cout << "DEBUG. level depth: " << levelDepth << std::endl;
832 
833 
834  size_t OPTPARTLIMIT = 500;
835 
836  partition->clear();
837  if( root > m_tree.getRoot().getID() )
838  {
839  std::cerr << "ERROR @ WHtree::partitionOptimized(): branch root ID is out of boundaries (ID: "
840  << root << ", # nodes: " << m_tree.getNumNodes() << " )." << std::endl;
841  return 0;
842  }
843 
844  std::vector< nodeID_t > bestPartition;
845  float condValue( 0 );
846  const WHnode currentNode( m_tree.getNode( root ) );
847  bestPartition.push_back( currentNode.getFullID() );
848 
849  bool loopCondition( true );
850 
851  switch( mode )
852  {
853  case HTP2_CSD:
854  condValue = m_tree.getNode( root ).getSize();
855  compValue = static_cast<int>( compValue );
856  break;
857  case HTP2_MIAD:
858  case HTP2_WIAD:
859  condValue = 1;
860  if( condition == HTC_CNUM )
861  {
862  compValue = static_cast<int>( compValue );
863  }
864  break;
865  case HTP2_MIRD:
866  case HTP2_WIRD:
867  case HTP2_OPT:
868  std::cout << "DEBUG: Spread-Separation" << std::endl;
869 
870  condValue = 0;
871  if( condition == HTC_CNUM )
872  {
873  compValue = static_cast<int>( compValue );
874  }
875  else
876  {
877  partition->push_back( currentNode.getFullID() );
878  return currentNode.getDistLevel();
879  }
880  break;
881  default:
882  return 0;
883  break;
884  }
885 
886  switch( condition )
887  {
888  case HTC_VALUE:
889  loopCondition = ( condValue > compValue );
890  break;
891  case HTC_CNUM:
892  std::cout << "DEBUG: by clust num" << std::endl;
893  loopCondition = ( bestPartition.size() < compValue );
894  break;
895  default:
896  break;
897  }
898 
899  while( loopCondition )
900  {
901  std::vector< std::vector< nodeID_t > > derivedPartitionSet;
902  std::vector< std::vector< unsigned int > > derivedIndexes( m_tree.getBranching( bestPartition,
903  levelDepth,
904  &derivedPartitionSet,
905  excludeLeaves ) );
906  std::vector< float > derivedPartitionValues;
907  float bestValue( 0 );
908 
909 
910  // initialize values
911  switch( mode )
912  {
913  case HTP2_CSD:
914  case HTP2_MIAD:
915  case HTP2_WIAD:
916  derivedPartitionValues.assign( derivedPartitionSet.size(), std::numeric_limits< double >::max() );
917  bestValue = std::numeric_limits< double >::max();
918  break;
919  case HTP2_MIRD:
920  case HTP2_WIRD:
921  case HTP2_OPT:
922  derivedPartitionValues.assign( derivedPartitionSet.size(), -1 );
923  bestValue = -1;
924  break;
925  default:
926  break;
927  }
928 
929  bool stopLoop( true );
930 
931  // get the partitions and values for all possible branchings
932 #pragma omp parallel for schedule( guided )
933  for( size_t i = 0; i < derivedPartitionSet.size(); ++i )
934  {
935  // if there are possible branchings continue looping
936 #pragma omp critical
937  stopLoop = false;
938 
939  derivedPartitionValues[i] = evalPartOptimal( derivedPartitionSet[i] );
940  switch( mode )
941  {
942  case HTP2_CSD:
943  derivedPartitionValues[i]=evalPartClustSizeDiff( derivedPartitionSet[i] ).second;
944  break;
945  case HTP2_MIAD:
946  derivedPartitionValues[i]=evalPartIntraDist( derivedPartitionSet[i] );
947  break;
948  case HTP2_WIAD:
949  derivedPartitionValues[i]=evalPartIntraDistWeighted( derivedPartitionSet[i] );
950  break;
951  case HTP2_MIRD:
952  derivedPartitionValues[i] = ( evalPartBranchDist( derivedPartitionSet[i] ) );
953  break;
954  case HTP2_WIRD:
955  derivedPartitionValues[i] = ( evalPartBranchDistWeighted( derivedPartitionSet[i] ) );
956  break;
957  case HTP2_OPT:
958  derivedPartitionValues[i] = ( evalPartOptimal( derivedPartitionSet[i] ) );
959  break;
960  default:
961  break;
962  }
963  } // endFor
964 
965  //if there are no more possible branchings stop the loop
966  if( stopLoop )
967  {
968  break;
969  }
970 
971  // search for the best partition
972  size_t bestPartIndex( 0 );
973  for( size_t i = 0; i < derivedPartitionValues.size(); ++i )
974  {
975  switch( mode )
976  {
977  case HTP2_CSD:
978  case HTP2_MIAD:
979  case HTP2_WIAD:
980  if( derivedPartitionValues[i] < bestValue )
981  {
982  bestValue = derivedPartitionValues[i];
983  bestPartIndex = i;
984  }
985  break;
986  case HTP2_MIRD:
987  case HTP2_WIRD:
988  case HTP2_OPT:
989  if( derivedPartitionValues[i] > bestValue )
990  {
991  bestValue = derivedPartitionValues[i];
992  bestPartIndex = i;
993  }
994  break;
995  default:
996  break;
997  }
998  }
999 
1000  // find the first branching partition corresponding to the best partition found
1001  if( derivedIndexes[bestPartIndex].size() == 1 )
1002  {
1003  // it was a first branch partition
1004  bestPartition = derivedPartitionSet[bestPartIndex];
1005  }
1006  else
1007  {
1008  unsigned int firstBranchIndex( derivedIndexes[bestPartIndex].front() );
1009 
1010  size_t nextBestIndex( 0 );
1011  bool notFound( true );
1012 
1013  for( size_t j = 0; j < derivedIndexes.size(); ++j )
1014  {
1015  if( ( derivedIndexes[j].size() == 1 ) && ( derivedIndexes[j].front() == firstBranchIndex ) )
1016  {
1017  nextBestIndex = j;
1018  notFound = false;
1019  }
1020  }
1021 
1022  if( notFound )
1023  {
1024  throw std::runtime_error( "ERROR @ partitionMatcher::findMatchingPartitions(): best match index not found" );
1025  }
1026 
1027  bestPartition = derivedPartitionSet[nextBestIndex];
1028  bestValue = derivedPartitionValues[nextBestIndex];
1029  }
1030 
1031  // update condition value
1032  switch( mode )
1033  {
1034  case HTP2_CSD:
1035  condValue = evalPartClustSizeDiff( bestPartition ).first;
1036  break;
1037  case HTP2_MIAD:
1038  case HTP2_WIAD:
1039  case HTP2_MIRD:
1040  case HTP2_WIRD:
1041  case HTP2_OPT:
1042  condValue = bestValue;
1043  break;
1044  default:
1045  break;
1046  }
1047 
1048  // test condition
1049  switch( condition )
1050  {
1051  case HTC_VALUE:
1052  if( bestPartition.size() > OPTPARTLIMIT )
1053  {
1054  loopCondition = false;
1055  }
1056 
1057  switch( mode )
1058  {
1059  case HTP2_CSD:
1060  case HTP2_MIAD:
1061  case HTP2_WIAD:
1062  case HTP2_MIRD:
1063  case HTP2_WIRD:
1064  loopCondition = ( condValue < compValue );
1065  break;
1066  case HTP2_OPT:
1067  loopCondition = ( condValue > compValue );
1068  break;
1069  default:
1070  break;
1071  }
1072 
1073  break;
1074  case HTC_CNUM:
1075  loopCondition = ( bestPartition.size() < compValue );
1076  break;
1077  default:
1078  break;
1079  }
1080  } // end while loop
1081 
1082 
1083  // assign output current value
1084  std::sort( bestPartition.begin(), bestPartition.end() );
1085  *partition = bestPartition;
1086  return condValue;
1087 } // end partitionOptimized() -------------------------------------------------------------------------------------
1088 
1089 
1091  std::vector<nodeID_t>* partition,
1092  const bool excludeLeaves,
1093  const size_t root,
1094  const bool normalized ) const
1095 {
1096  partition->clear();
1097  float longestBranch( 0 );
1098 
1099  if( root > m_tree.getRoot().getID() )
1100  {
1101  std::cerr << "ERROR @ WHtree::partitionSharp(): branch root ID is out of boundaries (ID: "
1102  << root << ", # nodes: " << m_tree.getNumNodes() << " )." << std::endl;
1103  return 0;
1104  }
1105 
1106  std::list<nodeID_t> worklist;
1107  std::list<nodeID_t> storelist;
1108 
1109  worklist.push_back( std::make_pair( true, root ) );
1110  while( !worklist.empty() )
1111  {
1112  const WHnode& current( m_tree.getNode( worklist.front() ) );
1113  worklist.pop_front();
1114  std::vector<nodeID_t> kids( current.getChildren() );
1115  for( size_t i = 0; i < kids.size(); ++i )
1116  {
1117  const WHnode& thisKid( m_tree.getNode( kids[i] ) );
1118  float branchValue( ( current.getDistLevel()-thisKid.getDistLevel() ) );
1119  if( normalized )
1120  {
1121  branchValue = branchValue / thisKid.getDistLevel();
1122  }
1123  if( branchValue >= compValue )
1124  {
1125  storelist.push_back( thisKid.getFullID() );
1126  if( branchValue > longestBranch )
1127  {
1128  longestBranch = branchValue;
1129  }
1130  }
1131  if( thisKid.isLeaf() )
1132  {
1133  continue;
1134  }
1135  else if( thisKid.getHLevel() == 1 && excludeLeaves )
1136  {
1137  continue;
1138  }
1139  else
1140  {
1141  worklist.push_back( thisKid.getFullID() );
1142  }
1143  }
1144  }
1145  storelist.sort();
1146 
1147  partition->reserve( storelist.size() );
1148  for( std::list<nodeID_t>::iterator it( storelist.begin() ); it != storelist.end(); ++it )
1149  {
1150  partition->push_back( *it );
1151  }
1152  return longestBranch;
1153 } // end partitionSharp() -------------------------------------------------------------------------------------
1154 
1155 
1156 float WHtreePartition::partitionSmooth( const float compValue, std::vector<nodeID_t>* partition, const bool excludeLeaves, const size_t root ) const
1157 {
1158  partition->clear();
1159  float longestGap( 0 );
1160 
1161  if( root > m_tree.getRoot().getID() )
1162  {
1163  std::cerr << "ERROR @ WHtree::partitionSmooth(): branch root ID is out of boundaries (ID: "
1164  << root << ", # nodes: " << m_tree.getNumNodes() << " )." << std::endl;
1165  return 0;
1166  }
1167 
1168  std::vector<unsigned int> conditionMet( m_tree.getNumNodes(), 0 );
1169 
1170  // if base nodes are always included flag them
1171  if( excludeLeaves )
1172  {
1173  std::vector<size_t> bases( m_tree.getBaseNodes( root ) );
1174  for( size_t i = 0; i < bases.size(); ++i )
1175  {
1176  conditionMet[bases[i]] = 1;
1177  }
1178  }
1179  else
1180  {
1181  // mark all base nodes that fit condition
1182  for( size_t i = 0; i < m_tree.getNumLeaves(); ++i )
1183  {
1184  const WHnode& dad( m_tree.getNode( m_tree.getLeaf( i ).getParent() ) );
1185  if( dad.getDistLevel() <= compValue )
1186  {
1187  conditionMet[dad.getID()] = 1;
1188  if( dad.getDistLevel() > longestGap )
1189  {
1190  longestGap = dad.getDistLevel();
1191  }
1192  }
1193  }
1194  }
1195 
1196  for( size_t i = 0; i < conditionMet.size(); ++i )
1197  {
1198  float level = m_tree.getNode( i ).getDistLevel();
1199 
1200  if( conditionMet[i] == 1 )
1201  {
1202  if( m_tree.getNode( i ).isRoot() )
1203  {
1204  partition->push_back( m_tree.getRoot().getFullID() );
1205  return longestGap;
1206  }
1207  const WHnode& dad( m_tree.getNode( m_tree.getNode( i ).getParent() ) );
1208  dist_t gap( dad.getDistLevel()-level );
1209  if( gap <= compValue )
1210  {
1211  if( gap > longestGap )
1212  {
1213  longestGap = gap;
1214  }
1215  conditionMet[dad.getID()] = 1;
1216  }
1217  }
1218  else if( conditionMet[i] == 0 )
1219  {
1220  std::vector<nodeID_t> kids( m_tree.getNode( i ).getChildren() );
1221  for( size_t j = 0; j < kids.size(); ++j )
1222  {
1223  if( kids[j].first )
1224  {
1225  if( conditionMet[kids[j].second] == 1 )
1226  {
1227  conditionMet[kids[j].second] = 2;
1228  }
1229  }
1230  }
1231  }
1232  else
1233  {
1234  std::cerr << "ERROR @ WHtree::partitionSmooth()" << std::endl;
1235  }
1236  }
1237 
1238  for( size_t i = 0; i < conditionMet.size(); ++i )
1239  {
1240  if( conditionMet[i] == 2 )
1241  {
1242  partition->push_back( m_tree.getNode( i ).getFullID() );
1243  }
1244  }
1245  std::sort( partition->begin(), partition->end() );
1246  return longestGap;
1247 } // end partitionSmooth() -------------------------------------------------------------------------------------
1248 
1249 
1250 // DEPRECATED FUNCTIONS
1251 
1252 std::vector< std::vector< dist_t > > WHtreePartition::getICDmatrix( const std::vector<size_t> &oldPartition,
1253  size_t branchPos, std::vector<size_t> branch,
1254  std::vector< std::vector< dist_t > > oldMatrix )
1255 {
1256  std::vector< std::vector< dist_t > >newMatrix;
1257  newMatrix.reserve( oldPartition.size() + branch.size() );
1258 
1259  // do whole matrix new
1260  if( oldMatrix.empty() )
1261  {
1262  for( size_t i = 0; i < oldPartition.size(); ++i )
1263  {
1264  std::vector< dist_t > newLine;
1265  newLine.reserve( i );
1266  for( size_t j = 0; j < i; ++j )
1267  {
1268  newLine.push_back( m_tree.getNode( m_tree.getCommonAncestor( oldPartition[i], oldPartition[j] ) ).getDistLevel() );
1269  }
1270  newMatrix.push_back( newLine );
1271  }
1272  }
1273  else
1274  {
1275  for( size_t i = 0; i < oldPartition.size(); ++i )
1276  {
1277  // if i<branchPos the line is the same as in the old matrix
1278  if( i < branchPos )
1279  {
1280  newMatrix.push_back( oldMatrix[i] );
1281  }
1282  // if i == i the old line has to be replaced by as many lines as new nodesi in the branching
1283  else if( i == branchPos )
1284  {
1285  for( size_t j = 0; j < branch.size(); ++j )
1286  {
1287  std::vector< float > newLine( oldMatrix[branchPos] );
1288  std::vector< float > extra( j, m_tree.getNode( branch[j] ).getDistLevel() );
1289  newLine.insert( newLine.end(), extra.begin(), extra.end() );
1290  newMatrix.push_back( newLine );
1291  }
1292  }
1293  else
1294  {
1295  std::vector< float > newLine( oldMatrix[i] );
1296  std::vector< float >::iterator insertPoint( newLine.begin() + branchPos );
1297  std::vector< float > extra( branch.size()-1, *insertPoint );
1298  newLine.insert( insertPoint, extra.begin(), extra.end() );
1299  newMatrix.push_back( newLine );
1300  }
1301  }
1302  }
1303  return newMatrix;
1304 } // end getICDmatrix() -------------------------------------------------------------------------------------
1305 
1306 
1307 float WHtreePartition::evalPartInterDist( const std::vector<size_t> &partition, const std::vector< std::vector < dist_t > > &icdMatrix ) const
1308 {
1309  if( partition.size() != icdMatrix.size() )
1310  {
1311  std::cerr << "ERROR: matrix size: " << icdMatrix.size() << ". PArtition size: " << partition.size() << std::endl;
1312  throw std::runtime_error( " ERROR @ WHtreePartition::evalPartitInterD(): partition and icd matrix dimensions dont match" );
1313  }
1314 
1315  double irDistSum( 0 );
1316 
1317  for( size_t i = 0; i < partition.size(); ++i )
1318  {
1319  if( icdMatrix[i].size() != i )
1320  {
1321  std::cerr << "ERROR: matrix row " << i << " size: " << icdMatrix[i].size() << std::endl;
1322  throw std::runtime_error( " ERROR @ WHtreePartition::evalPartitInterD(): matrix has wrong dimensions" );
1323  }
1324  for( size_t j = 0; j < i; ++j )
1325  {
1326  dist_t ieDist( icdMatrix[i][j] );
1327  irDistSum += ieDist;
1328  }
1329  }
1330  double M( partition.size() * ( partition.size() -1 ) / 2.0 );
1331 
1332  return irDistSum/M;
1333 } // end evalPartitInter() -------------------------------------------------------------------------------------
1334 
1335 float WHtreePartition::evalPartInterDistWeighted( const std::vector<size_t> &partition, const std::vector< std::vector < dist_t > > &icdMatrix ) const
1336 {
1337  if( partition.size() != icdMatrix.size() )
1338  {
1339  std::cerr << "ERROR: matrix size: " << icdMatrix.size() << ". PArtition size: " << partition.size() << std::endl;
1340  throw std::runtime_error( " ERROR @ WHtreePartition::evalPartitInterD(): partition and icd matrix dimensions dont match" );
1341  }
1342 
1343  double irDistSum( 0 ), sizeSum( 0 );
1344 
1345  for( size_t i = 0; i < partition.size(); ++i )
1346  {
1347  const WHnode nodeI( m_tree.getNode( partition[i] ) );
1348  size_t sizeI( nodeI.getSize() );
1349  if( icdMatrix[i].size() != i )
1350  {
1351  std::cerr << "ERROR: matrix row " << i << " size: " << icdMatrix[i].size() << std::endl;
1352  throw std::runtime_error( " ERROR @ WHtreePartition::evalPartitInterD(): matrix has wrong dimensions" );
1353  }
1354  for( size_t j = 0; j < i; ++j )
1355  {
1356  const WHnode nodeJ( m_tree.getNode( partition[j] ) );
1357  size_t sizeJ( nodeJ.getSize() );
1358  dist_t ieDist( icdMatrix[i][j] );
1359  irDistSum += ieDist * ( sizeI+sizeJ );
1360  sizeSum += sizeI+sizeJ;
1361  }
1362  }
1363 
1364  return irDistSum/sizeSum;
1365 } // end evalPartitInterDweighted() -------------------------------------------------------------------------------------
1366 
1367 
1368 void WHtreePartition::level2granularity( std::vector<nodeID_t>* partitionPointer ) const
1369 {
1370  std::vector<nodeID_t>& partition( *partitionPointer );
1371  partition.clear();
1372  std::vector<size_t> partitionst;
1373  level2granularity( &partitionst );
1374  partition.reserve( partitionst.size() );
1375 
1376  for( size_t i = 0; i < partitionst.size(); ++i )
1377  {
1378  partition.push_back( std::make_pair( true, partitionst[i] ) );
1379  }
1380  return;
1381 } // end level2granularity() -------------------------------------------------------------------------------------
1382 
1383 void WHtreePartition::level2granularity( std::vector<size_t>* partitionPointer ) const
1384 {
1385  std::vector<size_t>& partition( *partitionPointer );
1386  partition.clear();
1387 
1388  std::vector<size_t> baseNodes( m_tree.getRootBaseNodes() );
1389  std::vector<bool> checkvector( m_tree.getNumNodes(), false );
1390 
1391  for( size_t i = 0; i < baseNodes.size(); ++i )
1392  {
1393  if( checkvector[ baseNodes[i] ] )
1394  {
1395  continue;
1396  }
1397 
1398  size_t parent( m_tree.getNode( baseNodes[i] ).getParent().second );
1399  if( m_tree.getNode( parent ).getHLevel() > 2 )
1400  {
1401  partition.push_back( baseNodes[i] );
1402  checkvector[ baseNodes[i] ] = true;
1403  }
1404  else
1405  {
1406  partition.push_back( parent );
1407  checkvector[ parent ] = true;
1408 
1409  std::vector<nodeID_t> kids( m_tree.getNode( parent ).getChildren() );
1410  for( size_t j = 0; j < kids.size(); ++j )
1411  {
1412  if( kids[j].first )
1413  {
1414  checkvector[ kids[j].second ] = true;
1415  }
1416  }
1417  }
1418  }
1419  return;
1420 } // end level2granularity() -------------------------------------------------------------------------------------
this class implements a hierarchical tree node with several relevant attributes
Definition: WHnode.h:69
size_t getSize() const
returns number of elements contained by the node
Definition: WHnode.h:257
bool isLeaf() const
returns true if object is a leaf
Definition: WHnode.h:232
size_t getHLevel() const
returns maximum number of nodes between the node and a leaf element
Definition: WHnode.h:267
bool isRoot() const
returns true if object is the root of the tree
Definition: WHnode.cpp:77
size_t getID() const
returns node/leaf ID
Definition: WHnode.h:242
dist_t getDistLevel() const
returns distance level at which the element was formed
Definition: WHnode.h:262
nodeID_t getFullID() const
returns full ID
Definition: WHnode.h:247
nodeID_t getParent() const
returns parent ID
Definition: WHnode.h:252
std::vector< nodeID_t > getChildren() const
returns a vector with the ids of the children of that node
Definition: WHnode.h:272
std::pair< float, float > evalPartClustSizeDiff(const std::vector< size_t > &partition) const
Evaluate partition cluster size difference (using only non-leaf node ID)
void writePartitionSet(std::string partFileName, const std::vector< float > &partitionValues, const std::vector< std::vector< size_t > > &patitionVector)
write a set of partitions and their quality values to a text file
WHtreePartition(WHtree *const tree)
Constructor.
float evalSSindex(const std::vector< size_t > &partition) const
Evaluate spread-separation index for selected partition (using only non-leaf node ID)
float evalPartInterDist(const std::vector< size_t > &partition, const std::vector< std::vector< dist_t > > &icdMatrix) const
Evaluate full inter cluster distance factor for selected partition (DEPRECATED)
void scanOptimalPartitions(const size_t levelDepth, std::vector< float > *partitionValuesPointer, std::vector< std::vector< size_t > > *patitionVectorPointer, const bool verbose=false)
Obtain the partition quality values for the optimized (inter vs weighted intra cluster distance) part...
size_t filterMaxPartitions(const unsigned int filterRadius, std::vector< float > *partValPoint, std::vector< std::vector< size_t > > *partVectorPoint)
Filter a set of partitions across granularity levels in orther to keep only local maxima within a cer...
float evalPartOptimal(const std::vector< size_t > &partition) const
Evaluate partition quality: spread-separation index (using only non-leaf node ID)
float evalPartIntraDist(const std::vector< size_t > &partition) const
Evaluate intra cluster distance factor for selected partition (using only non-leaf node ID)
float evalPartIntraDistWeighted(const std::vector< size_t > &partition) const
Evaluate weighted intra cluster distance factor for selected partition (using only non-leaf node ID)
std::vector< std::vector< dist_t > > getICDmatrix(const std::vector< size_t > &oldPartition, size_t branchPos=0, std::vector< size_t > branch=std::vector< size_t >(), std::vector< std::vector< dist_t > > oldMatrix=std::vector< std::vector< dist_t > >())
Obtain pairwise intercluster distance matrix for the selected partition, or derive new icd matrix fro...
float evalPartInterDistWeighted(const std::vector< size_t > &partition, const std::vector< std::vector< dist_t > > &icdMatrix) const
Evaluate full weighted inter cluster distance factor for selected partition (DEPRECATED)
float partitionClassic(float compValue, std::vector< nodeID_t > *const partition, const HT_PARTMODE mode, const HT_CONDITION condition, const bool excludeLeaves, const size_t root) const
Gets a classic partition for the tree (those where clusters are further subdivided until a condition ...
void level2granularity(std::vector< nodeID_t > *partition) const
obtain the partition corresponding to the second lowest level of granularity of a tree (using full bo...
float evalPartBranchDistWeighted(const std::vector< size_t > &partition) const
Evaluate approximated weighted inter cluster distance factor for selected partition (using only non-l...
float partitionSharp(const float compValue, std::vector< nodeID_t > *const partition, const bool excludeLeaves, const size_t root, const bool normalized) const
Finds clusters with sharp boundaries (long branches) the tree.
float evalPartBranchDist(const std::vector< size_t > &partition) const
Evaluate approximated inter cluster distance factor for selected partition (using only non-leaf node ...
WHtree & m_tree
tree object
float partitionOptimized(float compValue, std::vector< nodeID_t > *const partition, const HT_PARTMODE2 mode, const HT_CONDITION condition, const bool excludeLeaves, const size_t root, const size_t levelDepth) const
Gets an optimized partition for the tree (those where a partition characteristic must be cosnidered f...
float partitionSmooth(const float compValue, std::vector< nodeID_t > *const partition, const bool excludeLeaves, const size_t root) const
Finds regions without sharp inner boundaries the tree.
~WHtreePartition()
Destructor.
void scanHozPartitions(std::vector< float > *partitionValuesPointer, std::vector< std::vector< size_t > > *patitionVectorPointer, const bool verbose=false)
Obtain the partition quality values for the classic partitions at each granulairty of the tree.
this class implements a hierarchical tree and provides functions for creation, partitioning,...
Definition: WHtree.h:81
std::vector< size_t > getRootBaseNodes() const
returns a vector with all the nodes that have direct link to leaves from the main root
Definition: WHtree.cpp:706
const WHnode & getRoot() const
returns a const reference to the root node
Definition: WHtree.cpp:348
size_t getCommonAncestor(const size_t nodeID1, const size_t nodeID2) const
retrieves the the first common ancestor node of two given nodes
Definition: WHtree.cpp:535
std::vector< size_t > getBaseNodes(const size_t root) const
returns a vector with all the nodes that have direct link to leaves fro the indicated subtree
Definition: WHtree.cpp:642
size_t getNumNodes() const
Returns the number of nodes of the tree.
Definition: WHtree.h:836
const WHnode & getNode(const nodeID_t &thisNode) const
returns a const pointer to the node indicated by the ID
Definition: WHtree.cpp:307
const WHnode & getLeaf(const size_t thisLeaf) const
returns a const pointer to the leaf indicated by the ID
Definition: WHtree.cpp:333
void sortByHLevel(std::vector< size_t > *const nodeVector) const
Reorders the nodes in the vector according to their hierarchical level.
Definition: WHtree.cpp:817
void sortBySize(std::vector< size_t > *const nodeVector) const
Reorders the nodes in the vector according to their size.
Definition: WHtree.cpp:755
size_t getNumLeaves() const
Returns the number of leaves of the tree.
Definition: WHtree.h:831
std::vector< std::vector< unsigned int > > getBranching(const std::vector< nodeID_t > &thisPartition, size_t depthLevel, std::vector< std::vector< nodeID_t > > *partitionSet, const bool excludeLeaves)
gets all possble sets of sub-partitions in a tree given an initial partition and a depth level (where...
Definition: WHtree.cpp:1552
implements a compare operator for clusters, depending on custom value of the cluster