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; }