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