uint32_t InitializeSimplePartition(const CGraph* graph, CommunityPartition* partition, const double64_t alfa) { //Computing the clustering coefficient of each node of the graph. NodeClustering* nC = new NodeClustering[graph->GetNumNodes()]; if (!nC) { printf("Error allocating node clustering array."); return 1; } for (uint32_t i = 0; i < graph->GetNumNodes(); i++) { nC[i].m_NodeId = i; nC[i].m_Degree = graph->GetDegree(i); nC[i].m_CC = graph->GetTotalTriangles(i) / (double64_t) (nC[i].m_Degree * (nC[i].m_Degree - 1)); } qsort(nC, graph->GetNumNodes(), sizeof (NodeClustering), Compare_NodeClusterings); //Creating a vector to track which nodes have already been visited. bool * visited = new bool[graph->GetNumNodes()]; if (!visited) { printf("Error allocating visited array."); return 1; } memset(visited, false, graph->GetNumNodes() ); uint32_t* communities = new uint32_t[graph->GetNumNodes()]; if (!communities) { printf("Error allocating communities array.\n"); return 1; } uint32_t nextLabel = 0; for (uint32_t i = 0; i < graph->GetNumNodes(); i++) { NodeClustering* nodeClustering = &nC[i]; // printf("%f\n", nodeClustering->m_CC); if (!visited[nodeClustering->m_NodeId]) { visited[nodeClustering->m_NodeId] = true; communities[nodeClustering->m_NodeId] = nextLabel; const uint32_t* adjacencies1 = graph->GetNeighbors(nodeClustering->m_NodeId); uint32_t degree = graph->GetDegree(nodeClustering->m_NodeId); for (uint32_t j = 0; j < degree; j++) { if (!visited[adjacencies1[j]]) { visited[adjacencies1[j]] = true; communities[adjacencies1[j]] = nextLabel; } } nextLabel++; } } delete [] visited; delete [] nC; InitializeFromLabelsArray(graph, partition, communities, alfa); delete [] communities; return 0; }
uint32_t LoadPartition( const CGraph* graph, CommunityPartition* partition, const char_t* partitionFileName, const double64_t alfa ) { std::map<uint32_t, uint32_t> oldToNew; const uint32_t* newToOld = graph->GetMap(); for( uint32_t i = 0; i < graph->GetNumNodes(); ++i ) { oldToNew.insert(std::pair<uint32_t, uint32_t>(newToOld[i],i)); } uint32_t* communities = new uint32_t[graph->GetNumNodes()]; memset(communities,0xff,sizeof(uint32_t)*graph->GetNumNodes()); if (!communities) { printf("Unable to allocate partition\n"); return 1; } std::ifstream partitionFile; partitionFile.open(partitionFileName); if(!partitionFile.is_open()) { printf("Unable to load partition file.\n"); return 1; } std::string line; uint32_t nextLabel = 0; while(std::getline(partitionFile,line)) { std::istringstream stream(line); uint32_t node; while( stream >> node ) { communities[oldToNew[node]] = nextLabel; } ++nextLabel; } for( uint32_t i=0; i<graph->GetNumNodes(); ++i) { if( communities[i] == 0xffffffff ) { communities[i] = nextLabel++; } } partitionFile.close(); InitializeFromLabelsArray(graph,partition,communities, alfa); delete [] communities; return 0; }
/** @brief Performs an improvement step, that is, checks for movements for all the nodes and and computes the new partitions. @param[in] graph The graph. @param[out] partition The current partition. It will be modified with the new partition. @param[in] alfa The alfa parameter controlling the cohesivness of the communities.*/ static uint32_t PerformImprovementStep(const CGraph* graph, CommunityPartition* partition, const double64_t alfa) { std::vector<Movement>* movements = new std::vector<Movement>[num_threads]; uint32_t N = graph->GetNumNodes(); #pragma omp parallel for schedule(SCD_SCHEDULING,SCD_THREAD_BLOCK_SIZE) for (uint32_t i = 0; i < N; i++) { int thread = omp_get_thread_num(); if (i % 100000 == 0) { printf("Thread %d: Checked movements of %d nodes.\n", thread, i); } Movement movement; movement = CheckForBestMovement(graph, i, partition, alfa); if (movement.m_MovementType != E_NO_MOVEMENT) { movements[thread].push_back(movement); } } printf("All movements checked\n"); uint32_t* tempNodeLabels = new uint32_t[partition->m_NumNodes]; memcpy(&tempNodeLabels[0], &partition->m_NodeLabels[0], sizeof (uint32_t) * partition->m_NumNodes); uint32_t totalMovements = 0; //uint32_t nextLabel = partition->m_NumCommunities; uint32_t removeMovements = 0; uint32_t removeAndInsertMovements = 0; uint32_t insertMovements = 0; #pragma omp parallel for schedule(static,1) for (uint32_t thread = 0; thread < num_threads; thread++) { uint32_t numMovements = movements[thread].size(); totalMovements += numMovements; uint32_t nextLabelThread = partition->m_NumCommunities + numMovements * thread; for (uint32_t i = 0; i < numMovements; i++) { Movement movement = (movements[thread])[i]; switch (movement.m_MovementType) { case E_REMOVE: tempNodeLabels[movement.m_NodeId] = nextLabelThread; removeMovements++; nextLabelThread++; break; case E_REMOVE_AND_INSERT: tempNodeLabels[movement.m_NodeId] = movement.m_Community; if (partition->m_Communities[partition->m_CommunityIndices[partition->m_NodeLabels[movement.m_NodeId]]] == 1) { insertMovements++; } else { removeAndInsertMovements++; } break; } } } delete [] movements; printf(" Number of removes performed: %d\n", removeMovements); printf(" Number of remove and insert performed: %d\n", removeAndInsertMovements); printf(" Number of insert performed: %d\n", insertMovements); FreeResources(partition); if (InitializeFromLabelsArray(graph, partition, tempNodeLabels, alfa)) { printf("Error initializing from label array.\n"); return 1; } delete [] tempNodeLabels; return 0; }
static uint32_t MergeCommunities(const CGraph* graph, CommunityPartition* partition, const double64_t alfa) { // Look for community interactions. InteractionsSet candidateMerges(CompareById); uint32_t N = graph->GetNumNodes(); for( uint32_t i = 0; i < N; ++i ) { uint32_t communityLabel1 = partition->m_NodeLabels[i]; uint32_t degree = graph->GetDegree(i); const uint32_t* adjacencies = graph->GetNeighbors(i); for( uint32_t j = 0; j < degree; ++j ) { uint32_t communityLabel2 = partition->m_NodeLabels[adjacencies[j]]; if( communityLabel1 != communityLabel2 ) { CommunityInteraction cI; cI.degree = 0; if( communityLabel1 < communityLabel2 ) { cI.m_CommunityId1 = communityLabel1; cI.m_CommunityId2 = communityLabel2; } else { cI.m_CommunityId2 = communityLabel1; cI.m_CommunityId1 = communityLabel2; } candidateMerges.insert(cI); } } } std::vector<CommunityInteraction> filteredInteractions; uint32_t earlyFilter = 0; // Test each community interaction and rank it. for( InteractionsSet::iterator it = candidateMerges.begin(); it != candidateMerges.end(); ++it ) { CommunityInteraction cI = *it; if( partition->m_Communities[partition->m_CommunityIndices[cI.m_CommunityId1]] > 2 && partition->m_Communities[partition->m_CommunityIndices[cI.m_CommunityId2]] > 2 ) { earlyFilter++; double64_t improvement = TestMerge(graph, partition, alfa, cI); if( improvement > 0.0 ) { cI.m_Improvement = improvement; filteredInteractions.push_back(cI); } } } std::cout << earlyFilter << " " << filteredInteractions.size() << " " << candidateMerges.size() << std::endl; // Sort community interactions by improvement. uint32_t* tempNodeLabels = new uint32_t[partition->m_NumNodes]; memcpy(tempNodeLabels, partition->m_NodeLabels, sizeof(uint32_t)*partition->m_NumNodes); std::sort(filteredInteractions.begin(), filteredInteractions.end(), CompareByImprovement); std::set<uint32_t> touched; uint32_t numInteractions = filteredInteractions.size(); for( uint32_t i = 0; i < numInteractions; ++i ) { if( (touched.find(filteredInteractions[i].m_CommunityId1) == touched.end()) && (touched.find(filteredInteractions[i].m_CommunityId2) == touched.end()) ) { uint32_t communitySize = partition->m_Communities[partition->m_CommunityIndices[filteredInteractions[i].m_CommunityId1]]; const uint32_t* community = &partition->m_Communities[partition->m_CommunityIndices[filteredInteractions[i].m_CommunityId1]+1]; for( uint32_t j = 0; j < communitySize; ++j ) { tempNodeLabels[community[j]] = filteredInteractions[i].m_CommunityId2; } touched.insert(filteredInteractions[i].m_CommunityId1); touched.insert(filteredInteractions[i].m_CommunityId2); } } // Perform interactions constrained by independence and create a new labels array to create a partition from. FreeResources(partition); if (InitializeFromLabelsArray(graph, partition, tempNodeLabels, alfa)) { printf("Error initializing from label array.\n"); return 1; } delete [] tempNodeLabels; return 0; }