void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::removeModule(
  ToModuleMapType *vertexToModuleMap, int module )
{
  int lastModuleNumber = getNumberOfModules( vertexToModuleMap ) - 1;
  if( module == lastModuleNumber )
  {
    // no need to do anything, the last module is deleted "automatically"
    return;
  }

  if( getNumberOfVerticesInModule( vertexToModuleMap, module ) > 0 )
  {
    MBI_WARN << "Trying to remove non-empty module";
    return;
  }

  ToModuleMapType::iterator iter = vertexToModuleMap->begin();
  ToModuleMapType::iterator end =  vertexToModuleMap->end();
  while( iter != end )
  {
    if( iter->second == lastModuleNumber )
    {
      // renumber last module to to-be-deleted module
      iter->second = module;
    }

    iter++;
  }
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::CleanUp()
{
  // delete empty modules, if any
  for( int loop( 0 ); loop < getNumberOfModules( &m_BestSolution ) ; loop++ )
  {
    if( getNumberOfVerticesInModule( &m_BestSolution, loop ) < 1 )
    {
      removeModule( &m_BestSolution, loop );
    }
  }
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::permutateMappingModuleChange(
  ToModuleMapType *vertexToModuleMap, double currentTemperature, mitk::ConnectomicsNetwork::Pointer network )
{
  //the random number generators
  vnl_random rng( (unsigned int) rand() );

  //randomly generate threshold
  const double threshold = rng.drand64( 0.0 , 1.0);

  //for deciding whether to join two modules or split one
  double splitThreshold = 0.5;

  //stores whether to join or two split
  bool joinModules( false );

  //select random module
  int numberOfModules = getNumberOfModules( vertexToModuleMap );
  unsigned long randomModuleA = rng.lrand32( numberOfModules - 1 );

  //select the second module to join, if joining
  unsigned long randomModuleB = rng.lrand32( numberOfModules - 1 );

  if( ( threshold < splitThreshold ) && ( randomModuleA != randomModuleB )  )
  {
    joinModules = true;
  }

  if( joinModules )
  {
    // this being an kommutative operation, we will always join B to A
    joinTwoModules( vertexToModuleMap, randomModuleA, randomModuleB );
    //eliminate the empty module
    removeModule( vertexToModuleMap, randomModuleB );

  }
  else
  {
    //split module
    splitModule( vertexToModuleMap, currentTemperature, network, randomModuleA );
  }


}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::permutateMappingSingleNodeShift(
  ToModuleMapType *vertexToModuleMap, mitk::ConnectomicsNetwork::Pointer network )
{

  const int nodeCount = vertexToModuleMap->size();
  const int moduleCount = getNumberOfModules( vertexToModuleMap );

  // the random number generators
  vnl_random rng( (unsigned int) rand() );
  unsigned long randomNode = rng.lrand32( nodeCount - 1 );
  // move the node either to any existing module, or to its own
  //unsigned long randomModule = rng.lrand32( moduleCount );
  unsigned long randomModule = rng.lrand32( moduleCount - 1 );

  // do some sanity checks

  if ( nodeCount < 2 )
  {
    // no sense in doing anything
    return;
  }

  const std::vector< VertexDescriptorType > allNodesVector
    = network->GetVectorOfAllVertexDescriptors();

  ToModuleMapType::iterator iter = vertexToModuleMap->find( allNodesVector[ randomNode ] );
  const int previousModuleNumber = iter->second;

  // if we move the node to its own module, do nothing
  if( previousModuleNumber == (long)randomModule )
  {
    return;
  }

  iter->second = randomModule;

  if( getNumberOfVerticesInModule( vertexToModuleMap, previousModuleNumber ) < 1 )
  {
    removeModule( vertexToModuleMap, previousModuleNumber );
  }
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::splitModule(
  ToModuleMapType *vertexToModuleMap, double currentTemperature, mitk::ConnectomicsNetwork::Pointer network, int moduleToSplit )
{

  if( m_Depth == 0 )
  {
    // do nothing
    return;
  }

  // if the module contains only one node, no more division is sensible
  if( getNumberOfVerticesInModule( vertexToModuleMap, moduleToSplit ) < 2 )
  {
    // do nothing
    return;
  }

  // create subgraph of the module, that is to be splitted

  mitk::ConnectomicsNetwork::Pointer subNetwork = mitk::ConnectomicsNetwork::New();
  VertexToVertexMapType graphToSubgraphVertexMap;
  VertexToVertexMapType subgraphToGraphVertexMap;


  extractModuleSubgraph( vertexToModuleMap, network, moduleToSplit, subNetwork, &graphToSubgraphVertexMap, &subgraphToGraphVertexMap );


  // The submap
  ToModuleMapType vertexToModuleSubMap;

  // run simulated annealing on the subgraph to determine how the module should be split
  if( m_Depth > 0 && m_StepSize > 0 )
  {
    mitk::ConnectomicsSimulatedAnnealingManager::Pointer manager = mitk::ConnectomicsSimulatedAnnealingManager::New();
    mitk::ConnectomicsSimulatedAnnealingPermutationModularity::Pointer permutation = mitk::ConnectomicsSimulatedAnnealingPermutationModularity::New();
    mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::Pointer costFunction = mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::New();

    permutation->SetCostFunction( costFunction.GetPointer() );
    permutation->SetNetwork( subNetwork );
    permutation->SetDepth( m_Depth - 1 );
    permutation->SetStepSize( m_StepSize * 2 );

    manager->SetPermutation( permutation.GetPointer() );

    manager->RunSimulatedAnnealing( currentTemperature, m_StepSize * 2 );

    vertexToModuleSubMap = permutation->GetMapping();
  }

  // now carry the information over to the original map
  std::vector< int > moduleTranslationVector;
  moduleTranslationVector.resize( getNumberOfModules( &vertexToModuleSubMap ), 0 );
  int originalNumber = getNumberOfModules( vertexToModuleMap );

  // the new parts are added at the end
  for(unsigned int index( 0 ); index < moduleTranslationVector.size()  ; index++)
  {
    moduleTranslationVector[ index ] = originalNumber + index;
  }

  ToModuleMapType::iterator iter2 = vertexToModuleSubMap.begin();
  ToModuleMapType::iterator end2 =  vertexToModuleSubMap.end();

  while( iter2 != end2 )
  {
    // translate vertex descriptor from subgraph to graph
    VertexDescriptorType key = subgraphToGraphVertexMap.find( iter2->first )->second;
    // translate module number from subgraph to graph
    int value = moduleTranslationVector[ iter2->second ];
    // change the corresponding entry
    vertexToModuleMap->find( key )->second = value;

    iter2++;
  }

  // remove the now empty module, that was splitted
  removeModule( vertexToModuleMap, moduleToSplit );

}
double mitk::ConnectomicsSimulatedAnnealingCostFunctionModularity::CalculateModularity( mitk::ConnectomicsNetwork::Pointer network, ToModuleMapType* vertexToModuleMap ) const
{
  double modularity( 0.0 );
  int numberOfModules = getNumberOfModules( vertexToModuleMap );

  if( network->GetNumberOfVertices() != vertexToModuleMap->size() )
  {
    MBI_ERROR << "Number of vertices and vertex to module map size do not match!";
    return modularity;
  }

  int numberOfLinksInNetwork( 0 );
  std::vector< int > numberOfLinksInModule, sumOfDegreesInModule;
  numberOfLinksInModule.resize( numberOfModules, 0 );
  sumOfDegreesInModule.resize( numberOfModules, 0 );
  // get vector of all vertex descriptors in the network

  const std::vector< VertexDescriptorType > allNodesVector 
    = network->GetVectorOfAllVertexDescriptors();

  for( int nodeNumber( 0 ); nodeNumber < allNodesVector.size() ; nodeNumber++)
  {
    int correspondingModule = vertexToModuleMap->find( allNodesVector[ nodeNumber ] )->second;
    const std::vector< VertexDescriptorType > adjacentNodexVector 
      = network->GetVectorOfAdjacentNodes( allNodesVector[ nodeNumber ] );
    numberOfLinksInNetwork += adjacentNodexVector.size();
    sumOfDegreesInModule[ correspondingModule ] += adjacentNodexVector.size();

    for( int adjacentNodeNumber( 0 ); adjacentNodeNumber < adjacentNodexVector.size() ; adjacentNodeNumber++)
    {
      if( correspondingModule == vertexToModuleMap->find( adjacentNodexVector[ adjacentNodeNumber ] )->second )
      {
        numberOfLinksInModule[ correspondingModule ]++;
      }
    }
  }

  // the numbers for links have to be halved, as each edge was counted twice
  numberOfLinksInNetwork = numberOfLinksInNetwork / 2;

  // if the network contains no links return 0
  if( numberOfLinksInNetwork < 1)
  {
    return 0;
  }

  for( int index( 0 ); index < numberOfModules ; index++)
  {
    numberOfLinksInModule[ index ] = numberOfLinksInModule[ index ] / 2;
  }

  //Calculate modularity M:
  //M = sum_{s=1}^{N_{M}} [ (l_{s} / L) - (d_{s} / ( 2L ))^2 ]
  //where N_{M} is the number of modules
  //L is the number of links in the network
  //l_{s} is the number of links between nodes in the module
  //s is the module
  //d_{s} is the sum of degrees of the nodes in the module
  //( taken from Guimera, R. AND Amaral, L. A. N.
  // Cartography of complex networks: modules and universal roles
  // Journal of Statistical Mechanics: Theory and Experiment, 2005, 2005, P02001 )

  for( int moduleID( 0 ); moduleID < numberOfModules; moduleID++ )
  {
    modularity += (((double) numberOfLinksInModule[ moduleID ]) / ((double) numberOfLinksInNetwork)) -
      (
      (((double) sumOfDegreesInModule[ moduleID ]) / ((double) 2 * numberOfLinksInNetwork) ) * 
      (((double) sumOfDegreesInModule[ moduleID ]) / ((double) 2 * numberOfLinksInNetwork) ) 
      );
  }

  return modularity;
}