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::ConnectomicsSyntheticNetworkGenerator::GenerateSyntheticRandomNetwork(
  mitk::ConnectomicsNetwork::Pointer network, int numberOfPoints, double threshold )
{
  // as the surface is proportional to the square of the radius the density stays the same
  double radius = 5 * std::sqrt( (float) numberOfPoints );

  //the random number generators
  unsigned int randomOne = (unsigned int) rand();
  unsigned int randomTwo = (unsigned int) rand();

  vnl_random rng( (unsigned int) rand() );
  vnl_random rng2( (unsigned int) rand() );

  // map for storing the conversion from indices to vertex descriptor
  std::map< int, mitk::ConnectomicsNetwork::VertexDescriptorType > idToVertexMap;

  //add vertices on sphere surface
  for( int loopID( 0 ); loopID < numberOfPoints; loopID++  )
  {

    std::vector< float > position;
    std::string label;
    std::stringstream labelStream;
    labelStream << loopID;
    label = labelStream.str();

    //generate random, uniformly distributed points on a sphere surface
    const double uVariable = rng.drand64( 0.0 , 1.0);
    const double vVariable = rng.drand64( 0.0 , 1.0);
    const double phi = 2 * vnl_math::pi * uVariable;
    const double theta = std::acos( 2 * vVariable - 1 );

    double xpos = radius * std::cos( phi ) * std::sin( theta );
    double ypos = radius * std::sin( phi ) * std::sin( theta );
    double zpos = radius * std::cos( theta );

    position.push_back( xpos );
    position.push_back( ypos );
    position.push_back( zpos );

    mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = network->AddVertex( loopID );
    network->SetLabel( newVertex, label );
    network->SetCoordinates( newVertex, position );

    if ( idToVertexMap.count( loopID ) > 0 )
    {
      MITK_ERROR << "Aborting network creation, duplicate vertex ID generated.";
      m_LastGenerationWasSuccess = false;
      return;
    }
    idToVertexMap.insert( std::pair< int, mitk::ConnectomicsNetwork::VertexDescriptorType >( loopID, newVertex) );
  }

  int edgeID(0);
  // uniform weight of one
  int edgeWeight(1);

  mitk::ConnectomicsNetwork::VertexDescriptorType source;
  mitk::ConnectomicsNetwork::VertexDescriptorType target;

  for( int loopID( 0 ); loopID < numberOfPoints; loopID++  )
  {
    // to avoid creating an edge twice (this being an undirected graph) we only
    // potentially generate edges with all nodes with a bigger ID
    for( int innerLoopID( loopID ); innerLoopID < numberOfPoints; innerLoopID++  )
    {
      if( rng.drand64( 0.0 , 1.0) > threshold)
      {
        // do nothing
      }
      else
      {
        source = idToVertexMap.find( loopID )->second;
        target = idToVertexMap.find( innerLoopID )->second;
        network->AddEdge( source, target, loopID, innerLoopID, edgeWeight);

        edgeID++;
      }
    } // end for( int innerLoopID( loopID ); innerLoopID < numberOfPoints; innerLoopID++  )
  } // end for( int loopID( 0 ); loopID < numberOfPoints; loopID++  )
  m_LastGenerationWasSuccess = true;
}
void mitk::ConnectomicsSyntheticNetworkGenerator::GenerateSyntheticCenterToSurfaceNetwork(
  mitk::ConnectomicsNetwork::Pointer network, int numberOfPoints, double radius )
{
  //the random number generators
  unsigned int randomOne = (unsigned int) rand();
  unsigned int randomTwo = (unsigned int) rand();

  vnl_random rng( (unsigned int) rand() );
  vnl_random rng2( (unsigned int) rand() );

  mitk::ConnectomicsNetwork::VertexDescriptorType centerVertex;
  int vertexID(0);
  { //add center vertex
    std::vector< float > position;
    std::string label;
    std::stringstream labelStream;
    labelStream << vertexID;
    label = labelStream.str();

    position.push_back( 0 );
    position.push_back( 0 );
    position.push_back( 0 );

    centerVertex = network->AddVertex( vertexID );
    network->SetLabel( centerVertex, label );
    network->SetCoordinates( centerVertex, position );
  }//end add center vertex

  // uniform weight of one
  int edgeWeight(1);

  mitk::ConnectomicsNetwork::VertexDescriptorType source;
  mitk::ConnectomicsNetwork::VertexDescriptorType target;

  //add vertices on sphere surface
  for( int loopID( 1 ); loopID < numberOfPoints; loopID++  )
  {

    std::vector< float > position;
    std::string label;
    std::stringstream labelStream;
    labelStream << loopID;
    label = labelStream.str();

    //generate random, uniformly distributed points on a sphere surface
    const double uVariable = rng.drand64( 0.0 , 1.0);
    const double vVariable = rng.drand64( 0.0 , 1.0);
    const double phi = 2 * vnl_math::pi * uVariable;
    const double theta = std::acos( 2 * vVariable - 1 );

    double xpos = radius * std::cos( phi ) * std::sin( theta );
    double ypos = radius * std::sin( phi ) * std::sin( theta );
    double zpos = radius * std::cos( theta );

    position.push_back( xpos );
    position.push_back( ypos );
    position.push_back( zpos );

    mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = network->AddVertex( loopID );
    network->SetLabel( newVertex, label );
    network->SetCoordinates( newVertex, position );

    network->AddEdge( newVertex, centerVertex, loopID, 0, edgeWeight);
  }
  m_LastGenerationWasSuccess = true;
}
void mitk::ConnectomicsSyntheticNetworkGenerator::GenerateSyntheticCubeNetwork(
  mitk::ConnectomicsNetwork::Pointer network, int cubeExtent, double distance )
{
  // map for storing the conversion from indices to vertex descriptor
  std::map< int, mitk::ConnectomicsNetwork::VertexDescriptorType > idToVertexMap;

  int vertexID(0);
  for( int loopX( 0 ); loopX < cubeExtent; loopX++  )
  {
    for( int loopY( 0 ); loopY < cubeExtent; loopY++  )
    {
      for( int loopZ( 0 ); loopZ < cubeExtent; loopZ++  )
      {
        std::vector< float > position;
        std::string label;
        std::stringstream labelStream;
        labelStream << vertexID;
        label = labelStream.str();

        position.push_back( loopX * distance );
        position.push_back( loopY * distance );
        position.push_back( loopZ * distance );

        mitk::ConnectomicsNetwork::VertexDescriptorType newVertex = network->AddVertex( vertexID );
        network->SetLabel( newVertex, label );
        network->SetCoordinates( newVertex, position );

        if ( idToVertexMap.count( vertexID ) > 0 )
        {
          MITK_ERROR << "Aborting network creation, duplicate vertex ID generated.";
          m_LastGenerationWasSuccess = false;
          return;
        }
        idToVertexMap.insert( std::pair< int, mitk::ConnectomicsNetwork::VertexDescriptorType >( vertexID, newVertex) );

        vertexID++;
      }
    }
  }

  int edgeID(0), edgeSourceID(0), edgeTargetID(0);
  // uniform weight of one
  int edgeWeight(1);

  mitk::ConnectomicsNetwork::VertexDescriptorType source;
  mitk::ConnectomicsNetwork::VertexDescriptorType target;

  for( int loopX( 0 ); loopX < cubeExtent; loopX++  )
  {
    for( int loopY( 0 ); loopY < cubeExtent; loopY++  )
    {
      for( int loopZ( 0 ); loopZ < cubeExtent; loopZ++  )
      {
        // to avoid creating an edge twice (this being an undirected graph) we only generate
        // edges in three directions, the others will be supplied by the corresponding nodes
        if( loopX != 0 )
        {
          edgeTargetID = edgeSourceID - cubeExtent * cubeExtent;

          source = idToVertexMap.find( edgeSourceID )->second;
          target = idToVertexMap.find( edgeTargetID )->second;
          network->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight);

          edgeID++;
        }
        if( loopY != 0 )
        {
          edgeTargetID = edgeSourceID - cubeExtent;

          source = idToVertexMap.find( edgeSourceID )->second;
          target = idToVertexMap.find( edgeTargetID )->second;
          network->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight);

          edgeID++;
        }
        if( loopZ != 0 )
        {
          edgeTargetID = edgeSourceID - 1;

          source = idToVertexMap.find( edgeSourceID )->second;
          target = idToVertexMap.find( edgeTargetID )->second;
          network->AddEdge( source, target, edgeSourceID, edgeTargetID, edgeWeight);

          edgeID++;
        }

        edgeSourceID++;
      } // end for( int loopZ( 0 ); loopZ < cubeExtent; loopZ++  )
    } // end for( int loopY( 0 ); loopY < cubeExtent; loopY++  )
  } // end for( int loopX( 0 ); loopX < cubeExtent; loopX++  )
  m_LastGenerationWasSuccess = true;
}
void mitk::ConnectomicsSimulatedAnnealingPermutationModularity::extractModuleSubgraph(
  ToModuleMapType *vertexToModuleMap,
  mitk::ConnectomicsNetwork::Pointer network,
  int moduleToSplit,
  mitk::ConnectomicsNetwork::Pointer subNetwork,
  VertexToVertexMapType* graphToSubgraphVertexMap,
  VertexToVertexMapType* subgraphToGraphVertexMap )
{
  const std::vector< VertexDescriptorType > allNodesVector = network->GetVectorOfAllVertexDescriptors();

  // add vertices to subgraph
  for( unsigned int nodeNumber( 0 ); nodeNumber < allNodesVector.size() ; nodeNumber++)
  {

    if( moduleToSplit == vertexToModuleMap->find( allNodesVector[ nodeNumber ] )->second )
    {
      int id = network->GetNode( allNodesVector[ nodeNumber ] ).id;
      VertexDescriptorType newVertex = subNetwork->AddVertex( id );

      graphToSubgraphVertexMap->insert(
        std::pair<VertexDescriptorType, VertexDescriptorType>(
        allNodesVector[ nodeNumber ], newVertex
        )
        );
      subgraphToGraphVertexMap->insert(
        std::pair<VertexDescriptorType, VertexDescriptorType>(
        newVertex, allNodesVector[ nodeNumber ]
      )
        );
    }
  }

  // add edges to subgraph
  VertexToVertexMapType::iterator iter = graphToSubgraphVertexMap->begin();
  VertexToVertexMapType::iterator end =  graphToSubgraphVertexMap->end();

  while( iter != end )
  {
    const std::vector< VertexDescriptorType > adjacentNodexVector
      = network->GetVectorOfAdjacentNodes( iter->first );

    for( unsigned int adjacentNodeNumber( 0 ); adjacentNodeNumber < adjacentNodexVector.size() ; adjacentNodeNumber++)
    {
      // if the adjacent vertex is part of the subgraph,
      // add edge, if it does not exist yet, else do nothing

      VertexDescriptorType adjacentVertex = adjacentNodexVector[ adjacentNodeNumber ];
      if( graphToSubgraphVertexMap->count( adjacentVertex ) > 0 )
      {
        if( !subNetwork->EdgeExists( iter->second, graphToSubgraphVertexMap->find( adjacentVertex )->second ) )
        { //edge exists in parent network, but not yet in sub network
          const VertexDescriptorType vertexA = iter->second;
          const VertexDescriptorType vertexB = graphToSubgraphVertexMap->find( adjacentVertex )->second;
          const int sourceID = network->GetNode( vertexA ).id;
          const int targetID = network->GetNode( vertexB ).id;
          const int weight = network->GetEdge( iter->first, graphToSubgraphVertexMap->find( adjacentVertex )->first ).weight;
          subNetwork->AddEdge( vertexA , vertexB, sourceID, targetID, weight );
        }
      }
    }
    iter++;
  }// end while( iter != end )
}
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;
}