double64_t TestMerge(const CGraph* graph, const CommunityPartition* partition, const double64_t alfa, const CommunityInteraction& interaction) { // printf("Testing merge %d - %d\n", interaction.m_CommunityId1, interaction.m_CommunityId2); // PrintCommunity(partition, interaction.m_CommunityId1); // PrintCommunity(partition, interaction.m_CommunityId2); std::set<uint32_t> community; const uint32_t* nodes = &partition->m_Communities[partition->m_CommunityIndices[interaction.m_CommunityId1]+1]; uint32_t size = partition->m_Communities[partition->m_CommunityIndices[interaction.m_CommunityId1]]; double64_t before = 0.0; for( uint32_t i = 0; i < size; ++i ) { community.insert(nodes[i]); before += partition->m_NodeWCC[nodes[i]]; } nodes = &partition->m_Communities[partition->m_CommunityIndices[interaction.m_CommunityId2]+1]; size = partition->m_Communities[partition->m_CommunityIndices[interaction.m_CommunityId2]]; for( uint32_t i = 0; i < size; ++i ) { community.insert(nodes[i]); before += partition->m_NodeWCC[nodes[i]]; } /* for( std::set<uint32_t>::iterator it = community.begin(); it != community.end(); ++it){ printf("%d ",*it); } printf("\n");*/ double64_t after = ComputeWCC(graph,alfa,community); // printf("after: %f, before: %f\n", after, before); return (after - before); }
double64_t ComputeWCC(const CGraph * graph, const uint32_t * communities, const uint32_t numCommunities, const uint32_t* labelsIndices, const uint32_t * communitiesInvIndex, double64_t* wccs) { double64_t globalWCC = 0; #pragma omp parallel for schedule(static, 8) reduction(+:globalWCC) for (uint32_t i = 0; i < graph->GetNumNodes(); i++) { uint32_t communitySize = communitiesInvIndex[labelsIndices[communities[i]]]; wccs[i] = ComputeWCC(graph, i, communities[i], communities, communitySize); globalWCC += wccs[i]; } return globalWCC; }
/** @brief Initializes a partition structure from a labels to communities array. * @param[in] graph The graph where the partition belongs. * @param[out] partition The partition structure where the partition will be stored. * @param[in] communities The array of nodes to community labels from which the partition is initialized. * @param[in] alfa The alfa parameter controlling the cohesivness of the communities.*/ static uint32_t InitializeFromLabelsArray(const CGraph* graph, CommunityPartition* partition, const uint32_t* communities, const double64_t alfa) { //Initializing default values partition->m_NodeLabels = NULL; partition->m_CommunityIndices = NULL; partition->m_Communities = NULL; partition->m_InternalEdges = NULL; partition->m_ExternalEdges = NULL; partition->m_NodeWCC = NULL; partition->m_NumCommunities = 0; partition->m_ConnectedInsert = NULL; partition->m_ConnectedRemove = NULL; partition->m_NotConnectedInsert = NULL; partition->m_NotConnectedRemove = NULL; partition->m_WCC = 0; partition->m_NumNodes = graph->GetNumNodes(); partition->m_NodeLabels = new uint32_t[graph->GetNumNodes()]; if (!partition->m_NodeLabels) { printf("Error allocating node labels %u.\n", graph->GetNumNodes()); return 1; } uint32_t maxNumCommunities = 0; for (uint32_t i = 0; i < graph->GetNumNodes(); i++) { if (communities[i] > maxNumCommunities) { maxNumCommunities = communities[i]; } } maxNumCommunities++; partition->m_NumCommunities = CompressCommunityLabels(graph, communities, partition->m_NodeLabels); //Allocating space to store the communities partition->m_CommunityIndices = new uint32_t[partition->m_NumCommunities]; if (!partition->m_CommunityIndices) { printf("Error allocating labels indices.\n"); return 1; } partition->m_Communities = new uint32_t[partition->m_NumCommunities + graph->GetNumNodes()]; if (!partition->m_Communities) { printf("Error allocating inverted index.\n"); return 1; } partition->m_NodeWCC = new double64_t[graph->GetNumNodes()]; if (!partition->m_NodeWCC) { printf("Error allocating node labels %u.\n", graph->GetNumNodes()); return 1; } partition->m_ConnectedInsert = new double64_t[graph->GetNumNodes()]; if (!partition->m_ConnectedInsert) { printf("Error allocating connected insert.\n"); return 1; } partition->m_ConnectedRemove = new double64_t[graph->GetNumNodes()]; if (!partition->m_ConnectedRemove) { printf("Error allocating connected insert.\n"); return 1; } partition->m_NotConnectedInsert = new double64_t[graph->GetNumNodes()]; if (!partition->m_NotConnectedInsert) { printf("Error allocating connected insert.\n"); return 1; } partition->m_NotConnectedRemove = new double64_t[graph->GetNumNodes()]; if (!partition->m_NotConnectedRemove) { printf("Error allocating connected insert.\n"); return 1; } //Creating the counters the creation of the inverted index uint32_t* counters = new uint32_t[partition->m_NumCommunities]; if (!counters) { printf("Error allocating counters: %u\n", partition->m_NumCommunities); return 1; } #pragma omp parallel for schedule(SCD_SCHEDULING, SCD_THREAD_BLOCK_SIZE) for (uint32_t i = 0; i < partition->m_NumCommunities; i++) { counters[i] = 0; } //Computing community sizes; for (uint32_t i = 0; i < graph->GetNumNodes(); i++) { counters[partition->m_NodeLabels[i]]++; } //Initializing labels indices. uint32_t currentIndex = 0; for (uint32_t i = 0; i < partition->m_NumCommunities; i++) { if (counters[i] > 0) { partition->m_CommunityIndices[i] = currentIndex; partition->m_Communities[currentIndex] = counters[i]; currentIndex += counters[i] + 1; } else { partition->m_CommunityIndices[i] = SCD_INVALID_COMMUNITY; } counters[i] = 0; } //Initializing the inverted index. for (uint32_t i = 0; i < graph->GetNumNodes(); i++) { uint32_t lIndex = partition->m_CommunityIndices[partition->m_NodeLabels[i]]; assert(lIndex != SCD_INVALID_COMMUNITY); assert(counters[partition->m_NodeLabels[i]] < partition->m_Communities[lIndex]); partition->m_Communities[lIndex + counters[partition->m_NodeLabels[i]] + 1] = i; counters[partition->m_NodeLabels[i]]++; } for (uint32_t i = 0; i < partition->m_NumCommunities; i++) { if (partition->m_CommunityIndices[i] != SCD_INVALID_COMMUNITY) { uint32_t lIndex = partition->m_CommunityIndices[i]; qsort(&(partition->m_Communities[lIndex + 1]), partition->m_Communities[lIndex], sizeof (uint32_t), Compare_Ids); } } delete[] counters; partition->m_InternalEdges = new uint32_t[partition->m_NumCommunities]; if (!partition->m_InternalEdges) { printf("Error while allocating internal edges.\n"); return 1; } partition->m_ExternalEdges = new uint32_t[partition->m_NumCommunities]; if (!partition->m_ExternalEdges) { printf("Error while allocating external edges.\n"); return 1; } #pragma omp parallel for schedule(SCD_SCHEDULING, SCD_THREAD_BLOCK_SIZE) for (uint32_t i = 0; i < partition->m_NumCommunities; i++) { partition->m_InternalEdges[i] = 0; partition->m_ExternalEdges[i] = 0; } for (uint32_t i = 0; i < graph->GetNumNodes(); i++) { const uint32_t* adjacencies = graph->GetNeighbors(i); uint32_t degree = graph->GetDegree(i); for (uint32_t j = 0; j < degree; j++) { if (i < adjacencies[j]) { if (partition->m_NodeLabels[i] == partition->m_NodeLabels[adjacencies[j]]) { partition->m_InternalEdges[partition->m_NodeLabels[i]]++; } else { partition->m_ExternalEdges[partition->m_NodeLabels[i]]++; partition->m_ExternalEdges[partition->m_NodeLabels[adjacencies[j]]]++; } } } } partition->m_WCC = ComputeWCC(graph, alfa, partition->m_NodeLabels, partition->m_NumCommunities, partition->m_CommunityIndices, partition->m_Communities, partition->m_NodeWCC); for (uint32_t i = 0; i < graph->GetNumNodes(); i++) { uint32_t communityLabel = partition->m_NodeLabels[i]; uint32_t degree = graph->GetDegree(i); const uint32_t* adjacencies = graph->GetNeighbors(i); uint32_t kin = 0; for(uint32_t j = 0; j < degree; ++j){ uint32_t neighbor = adjacencies[j]; if( partition->m_NodeLabels[neighbor] == communityLabel ) kin++; } uint32_t r = partition->m_Communities[partition->m_CommunityIndices[communityLabel]]; double64_t denom = (double64_t)(degree+alfa*(r-kin-1)); partition->m_ConnectedInsert[i] = denom > 0.0 ? (kin+1) / denom : 0.0 ; partition->m_ConnectedInsert[i]-=partition->m_NodeWCC[i]; denom = (double64_t)(degree+alfa*(r-1-kin)); partition->m_ConnectedRemove[i] = denom > 0.0 ? (kin-1) / denom : 0.0 ; partition->m_ConnectedRemove[i] -= partition->m_NodeWCC[i]; denom = (degree+alfa*(r-kin)); partition->m_NotConnectedInsert[i] = denom > 0.0 ? kin / denom : 0.0; partition->m_NotConnectedInsert[i] -= partition->m_NodeWCC[i]; denom = (degree+alfa*(r-1-1-kin)); partition->m_NotConnectedRemove[i] = denom > 0.0 ? kin / denom : 0.0; partition->m_NotConnectedRemove[i] -= partition->m_NodeWCC[i]; } return 0; }