Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkConnectomicsSimulatedAnnealingPermutationModularity.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
20 
21 //for random number generation
22 #include "vnl/vnl_random.h"
23 #include "vnl/vnl_math.h"
24 
26 {
27 }
28 
30 {
31 }
32 
35 {
36  m_Network = theNetwork;
37 }
38 
40 {
41  // create entry for every vertex
42  std::vector< VertexDescriptorType > vertexVector = m_Network->GetVectorOfAllVertexDescriptors();
43  const int vectorSize = vertexVector.size();
44 
45  for( int index( 0 ); index < vectorSize; index++)
46  {
47  m_BestSolution.insert( std::pair<VertexDescriptorType, int>( vertexVector[ index ], 0 ) );
48  }
49 
50  // initialize with random distribution of n modules
51  int n( 5 );
52  randomlyAssignNodesToModules( &m_BestSolution, n );
53 
54 }
55 
57 {
58 
59  ToModuleMapType currentSolution = m_BestSolution;
60  ToModuleMapType currentBestSolution = m_BestSolution;
61 
62  int factor = 1;
63  int numberOfVertices = m_BestSolution.size();
64  int singleNodeMaxNumber = factor * numberOfVertices * numberOfVertices;
65  int moduleMaxNumber = factor * numberOfVertices;
66  double currentBestCost = Evaluate( &currentBestSolution );
67 
68  // do singleNodeMaxNumber node permutations and evaluate
69  for(int loop( 0 ); loop < singleNodeMaxNumber; loop++)
70  {
71  permutateMappingSingleNodeShift( &currentSolution, m_Network );
72  if( AcceptChange( currentBestCost, Evaluate( &currentSolution ), temperature ) )
73  {
74  currentBestSolution = currentSolution;
75  currentBestCost = Evaluate( &currentBestSolution );
76  }
77  }
78 
79  // do moduleMaxNumber module permutations
80  for(int loop( 0 ); loop < moduleMaxNumber; loop++)
81  {
82  permutateMappingModuleChange( &currentSolution, temperature, m_Network );
83  if( AcceptChange( currentBestCost, Evaluate( &currentSolution ), temperature ) )
84  {
85  currentBestSolution = currentSolution;
86  currentBestCost = Evaluate( &currentBestSolution );
87  }
88  }
89 
90  // store the best solution after the run
91  m_BestSolution = currentBestSolution;
92 }
93 
95 {
96  // delete empty modules, if any
97  for( int loop( 0 ); loop < getNumberOfModules( &m_BestSolution ) ; loop++ )
98  {
99  if( getNumberOfVerticesInModule( &m_BestSolution, loop ) < 1 )
100  {
101  removeModule( &m_BestSolution, loop );
102  }
103  }
104 }
105 
107  ToModuleMapType *vertexToModuleMap, mitk::ConnectomicsNetwork::Pointer network )
108 {
109 
110  const int nodeCount = vertexToModuleMap->size();
111  const int moduleCount = getNumberOfModules( vertexToModuleMap );
112 
113  // the random number generators
114  vnl_random rng( (unsigned int) rand() );
115  unsigned long randomNode = rng.lrand32( nodeCount - 1 );
116  // move the node either to any existing module, or to its own
117  //unsigned long randomModule = rng.lrand32( moduleCount );
118  unsigned long randomModule = rng.lrand32( moduleCount - 1 );
119 
120  // do some sanity checks
121 
122  if ( nodeCount < 2 )
123  {
124  // no sense in doing anything
125  return;
126  }
127 
128  const std::vector< VertexDescriptorType > allNodesVector
129  = network->GetVectorOfAllVertexDescriptors();
130 
131  auto iter = vertexToModuleMap->find( allNodesVector[ randomNode ] );
132  const int previousModuleNumber = iter->second;
133 
134  // if we move the node to its own module, do nothing
135  if( previousModuleNumber == (long)randomModule )
136  {
137  return;
138  }
139 
140  iter->second = randomModule;
141 
142  if( getNumberOfVerticesInModule( vertexToModuleMap, previousModuleNumber ) < 1 )
143  {
144  removeModule( vertexToModuleMap, previousModuleNumber );
145  }
146 }
147 
149  ToModuleMapType *vertexToModuleMap, double currentTemperature, mitk::ConnectomicsNetwork::Pointer network )
150 {
151  //the random number generators
152  vnl_random rng( (unsigned int) rand() );
153 
154  //randomly generate threshold
155  const double threshold = rng.drand64( 0.0 , 1.0);
156 
157  //for deciding whether to join two modules or split one
158  double splitThreshold = 0.5;
159 
160  //stores whether to join or two split
161  bool joinModules( false );
162 
163  //select random module
164  int numberOfModules = getNumberOfModules( vertexToModuleMap );
165  unsigned long randomModuleA = rng.lrand32( numberOfModules - 1 );
166 
167  //select the second module to join, if joining
168  unsigned long randomModuleB = rng.lrand32( numberOfModules - 1 );
169 
170  if( ( threshold < splitThreshold ) && ( randomModuleA != randomModuleB ) )
171  {
172  joinModules = true;
173  }
174 
175  if( joinModules )
176  {
177  // this being an kommutative operation, we will always join B to A
178  joinTwoModules( vertexToModuleMap, randomModuleA, randomModuleB );
179  //eliminate the empty module
180  removeModule( vertexToModuleMap, randomModuleB );
181 
182  }
183  else
184  {
185  //split module
186  splitModule( vertexToModuleMap, currentTemperature, network, randomModuleA );
187  }
188 
189 
190 }
191 
193  ToModuleMapType *vertexToModuleMap, int moduleA, int moduleB )
194 {
195 
196  auto iter = vertexToModuleMap->begin();
197  auto end = vertexToModuleMap->end();
198 
199  while( iter != end )
200  {
201  // if vertex belongs to module B move it to A
202  if( iter->second == moduleB )
203  {
204  iter->second = moduleA;
205  }
206 
207  iter++;
208  }// end while( iter != end )
209 }
210 
212  ToModuleMapType *vertexToModuleMap, double currentTemperature, mitk::ConnectomicsNetwork::Pointer network, int moduleToSplit )
213 {
214 
215  if( m_Depth == 0 )
216  {
217  // do nothing
218  return;
219  }
220 
221  // if the module contains only one node, no more division is sensible
222  if( getNumberOfVerticesInModule( vertexToModuleMap, moduleToSplit ) < 2 )
223  {
224  // do nothing
225  return;
226  }
227 
228  // create subgraph of the module, that is to be splitted
229 
231  VertexToVertexMapType graphToSubgraphVertexMap;
232  VertexToVertexMapType subgraphToGraphVertexMap;
233 
234 
235  extractModuleSubgraph( vertexToModuleMap, network, moduleToSplit, subNetwork, &graphToSubgraphVertexMap, &subgraphToGraphVertexMap );
236 
237 
238  // The submap
239  ToModuleMapType vertexToModuleSubMap;
240 
241  // run simulated annealing on the subgraph to determine how the module should be split
242  if( m_Depth > 0 && m_StepSize > 0 )
243  {
247 
248  permutation->SetCostFunction( costFunction.GetPointer() );
249  permutation->SetNetwork( subNetwork );
250  permutation->SetDepth( m_Depth - 1 );
251  permutation->SetStepSize( m_StepSize * 2 );
252 
253  manager->SetPermutation( permutation.GetPointer() );
254 
255  manager->RunSimulatedAnnealing( currentTemperature, m_StepSize * 2 );
256 
257  vertexToModuleSubMap = permutation->GetMapping();
258  }
259 
260  // now carry the information over to the original map
261  std::vector< int > moduleTranslationVector;
262  moduleTranslationVector.resize( getNumberOfModules( &vertexToModuleSubMap ), 0 );
263  int originalNumber = getNumberOfModules( vertexToModuleMap );
264 
265  // the new parts are added at the end
266  for(unsigned int index( 0 ); index < moduleTranslationVector.size() ; index++)
267  {
268  moduleTranslationVector[ index ] = originalNumber + index;
269  }
270 
271  auto iter2 = vertexToModuleSubMap.begin();
272  auto end2 = vertexToModuleSubMap.end();
273 
274  while( iter2 != end2 )
275  {
276  // translate vertex descriptor from subgraph to graph
277  VertexDescriptorType key = subgraphToGraphVertexMap.find( iter2->first )->second;
278  // translate module number from subgraph to graph
279  int value = moduleTranslationVector[ iter2->second ];
280  // change the corresponding entry
281  vertexToModuleMap->find( key )->second = value;
282 
283  iter2++;
284  }
285 
286  // remove the now empty module, that was splitted
287  removeModule( vertexToModuleMap, moduleToSplit );
288 
289 }
290 
292  ToModuleMapType *vertexToModuleMap,
294  int moduleToSplit,
296  VertexToVertexMapType* graphToSubgraphVertexMap,
297  VertexToVertexMapType* subgraphToGraphVertexMap )
298 {
299  const std::vector< VertexDescriptorType > allNodesVector = network->GetVectorOfAllVertexDescriptors();
300 
301  // add vertices to subgraph
302  for( unsigned int nodeNumber( 0 ); nodeNumber < allNodesVector.size() ; nodeNumber++)
303  {
304 
305  if( moduleToSplit == vertexToModuleMap->find( allNodesVector[ nodeNumber ] )->second )
306  {
307  int id = network->GetNode( allNodesVector[ nodeNumber ] ).id;
308  VertexDescriptorType newVertex = subNetwork->AddVertex( id );
309 
310  graphToSubgraphVertexMap->insert(
311  std::pair<VertexDescriptorType, VertexDescriptorType>(
312  allNodesVector[ nodeNumber ], newVertex
313  )
314  );
315  subgraphToGraphVertexMap->insert(
316  std::pair<VertexDescriptorType, VertexDescriptorType>(
317  newVertex, allNodesVector[ nodeNumber ]
318  )
319  );
320  }
321  }
322 
323  // add edges to subgraph
324  auto iter = graphToSubgraphVertexMap->begin();
325  auto end = graphToSubgraphVertexMap->end();
326 
327  while( iter != end )
328  {
329  const std::vector< VertexDescriptorType > adjacentNodexVector
330  = network->GetVectorOfAdjacentNodes( iter->first );
331 
332  for( unsigned int adjacentNodeNumber( 0 ); adjacentNodeNumber < adjacentNodexVector.size() ; adjacentNodeNumber++)
333  {
334  // if the adjacent vertex is part of the subgraph,
335  // add edge, if it does not exist yet, else do nothing
336 
337  VertexDescriptorType adjacentVertex = adjacentNodexVector[ adjacentNodeNumber ];
338  if( graphToSubgraphVertexMap->count( adjacentVertex ) > 0 )
339  {
340  if( !subNetwork->EdgeExists( iter->second, graphToSubgraphVertexMap->find( adjacentVertex )->second ) )
341  { //edge exists in parent network, but not yet in sub network
342  const VertexDescriptorType vertexA = iter->second;
343  const VertexDescriptorType vertexB = graphToSubgraphVertexMap->find( adjacentVertex )->second;
344  const int sourceID = network->GetNode( vertexA ).id;
345  const int targetID = network->GetNode( vertexB ).id;
346  const int weight = network->GetEdge( iter->first, graphToSubgraphVertexMap->find( adjacentVertex )->first ).weight;
347  subNetwork->AddEdge( vertexA , vertexB, sourceID, targetID, weight );
348  }
349  }
350  }
351  iter++;
352  }// end while( iter != end )
353 }
354 
356  ToModuleMapType *vertexToModuleMap ) const
357 {
358  int maxModule( 0 );
359  auto iter = vertexToModuleMap->begin();
360  auto end = vertexToModuleMap->end();
361  while( iter != end )
362  {
363  if( iter->second > maxModule )
364  {
365  maxModule = iter->second;
366  }
367 
368  iter++;
369  }
370 
371  return maxModule + 1;
372 }
373 
375  ToModuleMapType *vertexToModuleMap, int module ) const
376 {
377  int number( 0 );
378  auto iter = vertexToModuleMap->begin();
379  auto end = vertexToModuleMap->end();
380  while( iter != end )
381  {
382  if( iter->second == module )
383  {
384  number++;
385  }
386 
387  iter++;
388  }
389 
390  return number;
391 }
392 
394  ToModuleMapType *vertexToModuleMap, int module )
395 {
396  int lastModuleNumber = getNumberOfModules( vertexToModuleMap ) - 1;
397  if( module == lastModuleNumber )
398  {
399  // no need to do anything, the last module is deleted "automatically"
400  return;
401  }
402 
403  if( getNumberOfVerticesInModule( vertexToModuleMap, module ) > 0 )
404  {
405  MBI_WARN << "Trying to remove non-empty module";
406  return;
407  }
408 
409  auto iter = vertexToModuleMap->begin();
410  auto end = vertexToModuleMap->end();
411  while( iter != end )
412  {
413  if( iter->second == lastModuleNumber )
414  {
415  // renumber last module to to-be-deleted module
416  iter->second = module;
417  }
418 
419  iter++;
420  }
421 }
422 
424  ToModuleMapType *vertexToModuleMap, int numberOfIntendedModules )
425 {
426  // we make sure that each intended module contains *at least* one node
427  // thus if more modules are asked for than node exists we will only generate
428  // as many modules as there are nodes
429  if( numberOfIntendedModules > 0 &&
430  (unsigned int)numberOfIntendedModules > vertexToModuleMap->size() )
431  {
432  MBI_ERROR << "Tried to generate more modules than vertices were provided";
433  numberOfIntendedModules = vertexToModuleMap->size();
434  }
435 
436  //the random number generators
437  vnl_random rng( (unsigned int) rand() );
438 
439  std::vector< int > histogram;
440  std::vector< int > nodeList;
441 
442  histogram.resize( numberOfIntendedModules, 0 );
443  nodeList.resize( vertexToModuleMap->size(), 0 );
444 
445  int numberOfVertices = vertexToModuleMap->size();
446 
447  //randomly distribute nodes to modules
448  for( unsigned int nodeIndex( 0 ); nodeIndex < nodeList.size(); nodeIndex++ )
449  {
450  //select random module
451  nodeList[ nodeIndex ] = rng.lrand32( numberOfIntendedModules - 1 );
452 
453  histogram[ nodeList[ nodeIndex ] ]++;
454 
455  }
456 
457  // make sure no module contains no node, if one does assign it one of a random module
458  // that does contain at least two
459  for( unsigned int moduleIndex( 0 ); moduleIndex < histogram.size(); moduleIndex++ )
460  {
461  while( histogram[ moduleIndex ] == 0 )
462  {
463  int randomNodeIndex = rng.lrand32( numberOfVertices - 1 );
464  if( histogram[ nodeList[ randomNodeIndex ] ] > 1 )
465  {
466  histogram[ moduleIndex ]++;
467  histogram[ nodeList[ randomNodeIndex ] ]--;
468  nodeList[ randomNodeIndex ] = moduleIndex;
469  }
470  }
471  }
472 
473  auto iter = vertexToModuleMap->begin();
474  auto end = vertexToModuleMap->end();
475 
476  for( unsigned int index( 0 ); ( iter != end ) && ( index < nodeList.size() ); index++, iter++ )
477  {
478  iter->second = nodeList[ index ] ;
479  }
480 }
481 
483 {
484  m_BestSolution = mapping;
485 }
486 
489 {
490  return m_BestSolution;
491 }
492 
494 {
496  dynamic_cast<mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity*>( m_CostFunction.GetPointer() );
497  if( costMapping )
498  {
499  return costMapping->Evaluate( m_Network, mapping );
500  }
501  else
502  {
503  return 0;
504  }
505 }
506 
507 bool mitk::ConnectomicsSimulatedAnnealingPermutationModularity::AcceptChange( double costBefore, double costAfter, double temperature ) const
508 {
509  if( costAfter <= costBefore )
510  {// if cost is lower after
511  return true;
512  }
513 
514  //the random number generators
515  vnl_random rng( (unsigned int) rand() );
516 
517  //randomly generate threshold
518  const double threshold = rng.drand64( 0.0 , 1.0);
519 
520  //the likelihood of acceptance
521  double likelihood = std::exp( - ( costAfter - costBefore ) / temperature );
522 
523  if( threshold < likelihood )
524  {
525  return true;
526  }
527 
528  return false;
529 }
530 
531 
533 {
534  m_Depth = depth;
535 }
536 
538 {
539  m_StepSize = size;
540 }
itk::SmartPointer< Self > Pointer
void extractModuleSubgraph(ToModuleMapType *vertexToModuleMap, mitk::ConnectomicsNetwork::Pointer network, int moduleToSplit, mitk::ConnectomicsNetwork::Pointer subNetwork, VertexToVertexMapType *graphToSubgraphVertexMap, VertexToVertexMapType *subgraphToGraphVertexMap)
void permutateMappingModuleChange(ToModuleMapType *vertexToModuleMap, double currentTemperature, mitk::ConnectomicsNetwork::Pointer network)
static Pointer New()
void joinTwoModules(ToModuleMapType *vertexToModuleMap, int moduleA, int moduleB)
double Evaluate(mitk::ConnectomicsNetwork::Pointer network, ToModuleMapType *vertexToModuleMap) const
void randomlyAssignNodesToModules(ToModuleMapType *vertexToModuleMap, int numberOfIntendedModules)
bool AcceptChange(double costBefore, double costAfter, double temperature) const
void permutateMappingSingleNodeShift(ToModuleMapType *vertexToModuleMap, mitk::ConnectomicsNetwork::Pointer network)
void splitModule(ToModuleMapType *vertexToModuleMap, double currentTemperature, mitk::ConnectomicsNetwork::Pointer network, int moduleToSplit)
#define MBI_ERROR
Definition: mbilog.h:223
#define MBI_WARN
Definition: mbilog.h:222