OpenWalnut  1.5.0dev
WDendrogram.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 #include <algorithm>
26 #include <fstream>
27 #include <iterator>
28 #include <map>
29 #include <memory>
30 #include <set>
31 #include <sstream>
32 #include <string>
33 #include <vector>
34 
35 #include "../WAssert.h"
36 #include "../WLogger.h"
37 #include "../WStringUtils.h"
38 #include "../exceptions/WOutOfBounds.h"
39 #include "WDendrogram.h"
40 
41 // init _static_ member variable and provide a linker reference to it
42 std::shared_ptr< WPrototyped > WDendrogram::m_prototype = std::shared_ptr< WPrototyped >();
43 
44 std::shared_ptr< WPrototyped > WDendrogram::getPrototype()
45 {
46  if( !m_prototype )
47  {
48  m_prototype = std::shared_ptr< WPrototyped >( new WDendrogram() );
49  }
50  return m_prototype;
51 }
52 
54  : WTransferable(),
55  m_parents( 0 ),
56  m_heights( 0 )
57 {
58 }
59 
61  : WTransferable()
62 {
63  reset( n );
64 }
65 
66 void WDendrogram::reset( size_t n )
67 {
68  WAssert( n > 0, "A Dendrogram for an empty set of objects was created which makes no sence, if your really need it implement it!" );
69  m_heights.resize( n - 1, 0.0 );
70  m_parents.reserve( 2 * n - 1 );
71  m_parents.resize( n, 0 );
72 }
73 
75 {
76  if( m_parents.empty() )
77  {
78  throw WOutOfBounds( "Accessed an empty WDendrogam via a call to a memeber function: " + caller + " which needs access to elements." );
79  }
80 }
81 
82 size_t WDendrogram::merge( size_t i, size_t j, double height )
83 {
85 
86 #ifdef DEBUG
87  std::stringstream errMsg;
88  errMsg << "Bug: n=" << m_heights.size() << " many leafs can lead maximal to 2n-1 many nodes in a tree but this was violated now!" << std::endl;
89  WAssert( m_parents.size() != 2 * m_heights.size() + 1, errMsg.str() );
90 #endif
91 
92  m_parents.push_back( m_parents.size() ); // the root s always self referencing
93 
94  m_heights[ m_parents.size() - 2 - m_heights.size() ] = height;
95  m_parents[i] = m_parents.back();
96  m_parents[j] = m_parents.back();
97 
98  return m_parents.size() - 1;
99 }
100 
101 std::string WDendrogram::toString() const
102 {
104 
105  std::stringstream result;
106  std::map< size_t, std::vector< size_t > > childsOfInnerNodes;
107  std::map< size_t, std::vector< size_t > > preds;
108  std::vector< size_t > level( 2 * m_heights.size() + 1, 0 );
109 
110  // For very insane debugging only:
111  // wlog::debug( "WDendrogram" ) << "nodes size: " << m_parents.size() << " and expeceted: " << 2 * m_heights.size() + 1;
112  // wlog::debug( "WDendrogram" ) << "Parents-ARRAY:";
113  // wlog::debug( "WDendrogram" ) << m_parents;
114  // wlog::debug( "WDendrogram" ) << "Heights-ARRAY:";
115  // wlog::debug( "WDendrogram" ) << m_heights;
116 
117  // first write out all fibers
118  for( size_t i = 0; i < m_heights.size() + 1; ++i )
119  {
120  result << "(0, (" << i << ",))" << std::endl;
121  childsOfInnerNodes[ m_parents[i] ].push_back( i );
122  preds[ m_parents[i] ].push_back( i );
123  }
124  for( size_t i = m_heights.size() + 1; i < 2 * m_heights.size() + 1; ++i )
125  {
126  // using string_utils::operator<<;
127  // wlog::debug( "WDendrogram" ) << "i: " << i;
128  // wlog::debug( "WDendrogram" ) << "pred[i]: " << preds[i];
129  // wlog::debug( "WDendrogram" ) << "childs[i]: " << childsOfInnerNodes[i];
130  // wlog::debug( "WDendrogram" ) << "parentchilds: " << childsOfInnerNodes[ m_parents[ i ] ];
131 
132  size_t left = *( preds[ i ].begin() );
133  size_t right = *( preds[ i ].rbegin() );
134  level[i] = std::max( level[left], level[right] ) + 1;
135  if( i != m_parents[i] )
136  {
137  preds[ m_parents[ i ] ].push_back( i );
138  childsOfInnerNodes[ m_parents[i] ].reserve( childsOfInnerNodes[ m_parents[i] ].size() + childsOfInnerNodes[i].size() );
139  childsOfInnerNodes[ m_parents[i] ].insert( childsOfInnerNodes[ m_parents[i] ].end(), childsOfInnerNodes[i].begin(),
140  childsOfInnerNodes[i].end() );
141  }
142  result << "(" << level[i] << ", (";
143  size_t numElements = childsOfInnerNodes[i].size();
144  for( std::vector< size_t >::const_iterator cit = childsOfInnerNodes[i].begin(); cit != childsOfInnerNodes[i].end(); ++cit )
145  {
146  if( numElements == 1 )
147  {
148  result << *cit << "), ";
149  }
150  else
151  {
152  result << *cit << ", ";
153  }
154  numElements -= 1;
155  }
156  // wlog::debug( "WDendrogram" ) << "i: " << i;
157  // wlog::debug( "WDendrogram" ) << "pred[i]: " << preds[i];
158  // wlog::debug( "WDendrogram" ) << "childs[i]: " << childsOfInnerNodes[i];
159  // wlog::debug( "WDendrogram" ) << "parentchilds: " << childsOfInnerNodes[ m_parents[ i ] ];
160  result << "(" << left << ", " << right << "), " << m_heights[ i - m_heights.size() - 1 ] << ")" << std::endl;
161  }
162 
163  return result.str();
164 }
165 
166 const std::vector< size_t >& WDendrogram::getParents() const
167 {
168  return m_parents;
169 }
170 
171 const std::vector< double >& WDendrogram::getHeights() const
172 {
173  return m_heights;
174 }
void checkAndThrowExceptionIfUsedUninitialized(std::string caller) const
Checks if this instance is initialized.
Definition: WDendrogram.cpp:74
std::vector< double > m_heights
Stores only for the inner nodes their heights.
Definition: WDendrogram.h:161
std::vector< size_t > m_parents
Stores the parents of leafs as well as of inner nodes.
Definition: WDendrogram.h:156
size_t merge(size_t i, size_t j, double height)
Merges two elements (either inner nodes or leafs) given via the indices i and j.
Definition: WDendrogram.cpp:82
void reset(size_t n)
Resets the whole dendrogram to the number of elements it should be used for.
Definition: WDendrogram.cpp:66
static std::shared_ptr< WPrototyped > m_prototype
The prototype as singleton.
Definition: WDendrogram.h:134
static std::shared_ptr< WPrototyped > getPrototype()
Returns a prototype instantiated with the true type of the deriving class.
Definition: WDendrogram.cpp:44
const std::vector< size_t > & getParents() const
Returns const reference to the internal parents array.
std::string toString() const
Transform this dendrogram into a string, where each leaf or inner node is mapped to a special string.
const std::vector< double > & getHeights() const
Const reference to the heights array.
WDendrogram()
Default constructs an empty dendrogram.
Definition: WDendrogram.cpp:53
Indicates invalid element access of a container.
Definition: WOutOfBounds.h:37
Class building the interface for classes that might be transferred using WModuleConnector.
Definition: WTransferable.h:38