Commit 650f4d77 authored by pmla's avatar pmla

modularity optimization: vertices considered in RMSD order

parent 577bc667
Pipeline #24550644 canceled with stage
......@@ -27,14 +27,6 @@
#include <ptm/ptm_functions.h>
#include <ptm/qcprot/quat.hpp>
#include <boost/range/algorithm/fill.hpp>
#include <boost/range/algorithm/replace.hpp>
#include <boost/range/algorithm/count.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/range/algorithm_ext/iota.hpp>
#include <boost/functional/hash.hpp>
#include "louvain.h"
......@@ -485,7 +477,7 @@ bool GrainSegmentationEngine::randomizeClusterIDs()
int numClusters = _numClusters;
std::vector<size_t> clusterRandomMapping(numClusters+1);
boost::iota(clusterRandomMapping, 0);
std::iota(clusterRandomMapping.begin(), clusterRandomMapping.end(), 0);
std::mt19937 rng(1);
std::shuffle(clusterRandomMapping.begin() + 1, clusterRandomMapping.end(), rng);
......@@ -511,6 +503,7 @@ bool GrainSegmentationEngine::modularitySegmentation()
std::vector<size_t> particleToVertexId(numAtoms);
std::vector<size_t> vertexToParticleId(numAtoms);
std::vector<size_t> atomCumulative(_numSuperclusters);
std::vector<double> orderedRMSD(numAtoms);
atomCumulative[0] = 0;
std::partial_sum(_superclusterSizes.begin(), _superclusterSizes.end() - 1, atomCumulative.begin() + 1);
......@@ -519,6 +512,8 @@ bool GrainSegmentationEngine::modularitySegmentation()
size_t numVertices = vIndex[scIndex];
particleToVertexId[particleIndex] = numVertices;
vertexToParticleId[atomCumulative[scIndex] + numVertices] = particleIndex;
orderedRMSD[atomCumulative[scIndex] + numVertices] = _results->rmsd()->getFloat(particleIndex);
vIndex[scIndex]++;
}
......@@ -590,7 +585,11 @@ bool GrainSegmentationEngine::modularitySegmentation()
adjweight[c2] = weight;
}
if(!parallelFor(_numSuperclusters, *this, [this, &atomCumulative, &vIndex, &particleToVertexId, &vertexToParticleId, &numEdges, &numSuperclusterEdges, &adjlist, &edgeCumulative, &adjweight, numAtoms, totalWeight](size_t scIndex) {
//totalWeight *= 8;
clock_t startTime = clock();
if(!parallelFor(_numSuperclusters, *this, [this, &atomCumulative, &vIndex, &particleToVertexId, &vertexToParticleId, &numEdges, &numSuperclusterEdges, &adjlist, &edgeCumulative, &adjweight, numAtoms, totalWeight, &orderedRMSD](size_t scIndex) {
// Nothing to do for supercluster 0.
if(scIndex == 0) return;
......@@ -598,11 +597,11 @@ bool GrainSegmentationEngine::modularitySegmentation()
size_t numVertices = vIndex[scIndex];
std::vector<int> community(numVertices);
int numCommunities = assign_communities_halfedge( numVertices, numEdges.begin() + atomCumulative[scIndex],
numSuperclusterEdges[scIndex],
adjlist.begin() + edgeCumulative[atomCumulative[scIndex]],
adjweight.begin() + edgeCumulative[atomCumulative[scIndex]],
totalWeight, community);
assign_communities_halfedge( numVertices, numEdges.begin() + atomCumulative[scIndex], orderedRMSD.begin() + atomCumulative[scIndex],
numSuperclusterEdges[scIndex],
adjlist.begin() + edgeCumulative[atomCumulative[scIndex]],
adjweight.begin() + edgeCumulative[atomCumulative[scIndex]],
totalWeight, community);
for(size_t i = 0; i < numVertices; i++) {
int clusterId = community[i] + atomCumulative[scIndex] + 1;
......@@ -613,6 +612,11 @@ bool GrainSegmentationEngine::modularitySegmentation()
return false;
}
clock_t endTime = clock();
clock_t clockTicksTaken = endTime - startTime;
double timeInSeconds = clockTicksTaken / (double) CLOCKS_PER_SEC;
printf("time taken: %f\n", timeInSeconds);
_clusterSizes.resize(numAtoms + 1, 0);
for(size_t particleIndex = 0; particleIndex < numAtoms; particleIndex++) {
qlonglong c = _results->atomClusters()->getInt64(particleIndex);
......
......@@ -33,11 +33,10 @@
// Modified for grain segmentation by PM Larsen, June 2018
//-----------------------------------------------------------------------------
#include <algorithm>
#include <cassert>
#include <map>
#include <vector>
#include <cassert>
#include <algorithm>
class Graph {
......@@ -47,16 +46,21 @@ public:
std::vector<int> degrees;
std::vector<int> edges;
std::vector<double> weights;
std::vector<double> rmsds;
Graph(int _num_nodes, std::vector<int>& comm_size) {
Graph(int _num_nodes, std::vector<int>& comm_size, std::vector<double>& comm_rmsd) {
num_nodes = _num_nodes;
degrees.resize(_num_nodes);
for (auto c: comm_size)
node_size.push_back(c);
for (auto c: comm_rmsd)
rmsds.push_back(c);
};
Graph(size_t num_vertices, std::vector<size_t>::iterator adjdegrees, size_t num_edges, std::vector<size_t>::iterator adjlist, std::vector<double>::iterator adjweight)
Graph( size_t num_vertices, std::vector<size_t>::iterator adjdegrees, std::vector<double>::iterator _rmsds,
size_t num_edges, std::vector<size_t>::iterator adjlist, std::vector<double>::iterator adjweight)
{
num_nodes = num_vertices;
......@@ -69,6 +73,8 @@ public:
for (int i=0;i<num_nodes;i++) {
tot += adjdegrees[i];
degrees.push_back(tot);
rmsds.push_back(_rmsds[i]);
}
node_size.assign(num_nodes, 1);
......@@ -179,20 +185,33 @@ static void neigh_comm(Graph* g, int node, int& neigh_last, std::vector<int>& n2
}
}
static std::vector<int> shuffled_order(std::mt19937_64& mt_rand, int n)
#if 0
static std::vector<int> random_order(std::mt19937_64& mt_rand, int n)
{
std::vector<int> random_order(n);
for (int i=0;i<n;i++)
random_order[i] = i;
std::vector<int> node_order(n);
std::iota(node_order.begin(), node_order.end(), 0);
for (int i=0;i<n-1;i++) {
int rand_pos = mt_rand() % (n - i) + i;
int tmp = random_order[i];
random_order[i] = random_order[rand_pos];
random_order[rand_pos] = tmp;
int tmp = node_order[i];
node_order[i] = node_order[rand_pos];
node_order[rand_pos] = tmp;
}
return random_order;
return node_order;
}
#endif
static std::vector<std::pair<int, double>> rmsd_order(size_t num_nodes, std::vector<double>& rmsds, std::vector<int> node_size)
{
std::vector<std::pair<int, double>> node_order(num_nodes);
for (int i=0;i<num_nodes;i++) {
node_order[i].first = i;
node_order[i].second = rmsds[i] / node_size[i];
}
sort(node_order.begin(), node_order.end(), [](std::pair<int, double> a, std::pair<int, double> b) {return a.second < b.second;} );
return node_order;
}
static Graph one_level(std::mt19937_64& mt_rand, Graph* g, std::vector< int > &prev_n2c, double total_weight, bool& improvement) {
......@@ -216,7 +235,8 @@ static Graph one_level(std::mt19937_64& mt_rand, Graph* g, std::vector< int > &p
int nb_moves = 0;
double new_qual = quality(total_weight, g, in, tot);
double cur_qual = new_qual;
std::vector<int> random_order = shuffled_order(mt_rand, num_nodes);
//std::vector<int> node_order = random_order(mt_rand, num_nodes);
std::vector<std::pair<int, double>> node_order = rmsd_order(num_nodes, g->rmsds, g->node_size);
// repeat while
// there is an improvement of quality
......@@ -229,7 +249,7 @@ static Graph one_level(std::mt19937_64& mt_rand, Graph* g, std::vector< int > &p
// for each node: remove the node from its community and insert it in the
// best community
for (int i=0;i<num_nodes;i++) {
int node = random_order[i];
int node = node_order[i].first;
int node_comm = n2c[node];
double w_degree = g->weighted_degree(node);
......@@ -288,14 +308,18 @@ static Graph one_level(std::mt19937_64& mt_rand, Graph* g, std::vector< int > &p
// Compute communities
std::vector< std::vector< int > > comm_nodes(num_reduced_nodes);
std::vector<int> comm_size(num_reduced_nodes, 0);
std::vector<double> comm_rmsd(num_reduced_nodes, 0);
for (int i=0;i<num_nodes;i++) {
comm_nodes[renumber[n2c[i]]].push_back(i);
comm_size[renumber[n2c[i]]] += g->node_size[i];
int rc = renumber[n2c[i]];
comm_nodes[rc].push_back(i);
comm_size[rc] += g->node_size[i];
comm_rmsd[rc] += g->rmsds[i];
}
// Compute weighted graph
Graph g2(num_reduced_nodes, comm_size);
Graph g2(num_reduced_nodes, comm_size, comm_rmsd);
for (int comm = 0; comm < num_reduced_nodes; comm++) {
......@@ -330,17 +354,19 @@ static Graph one_level(std::mt19937_64& mt_rand, Graph* g, std::vector< int > &p
return g2;
}
int assign_communities_halfedge(size_t num_vertices, std::vector<size_t>::iterator adjdegrees, size_t num_edges, std::vector<size_t>::iterator adjlist, std::vector<double>::iterator adjweight, double total_weight, std::vector< int > &n2c)
int assign_communities_halfedge(size_t num_vertices, std::vector<size_t>::iterator adjdegrees, std::vector<double>::iterator rmsds,
size_t num_edges, std::vector<size_t>::iterator adjlist, std::vector<double>::iterator adjweight, double total_weight, std::vector< int > &n2c)
{
//thread-safe random number generation
std::mt19937_64 mt_rand(0);
Graph g(num_vertices, adjdegrees, num_edges, adjlist, adjweight);
Graph g(num_vertices, adjdegrees, rmsds, num_edges, adjlist, adjweight);
for (int i=0;i<num_vertices;i++)
n2c[i] = i;
int numc = g.num_nodes;
bool improvement = true;
do {
g = one_level(mt_rand, &g, n2c, total_weight, improvement);
numc = g.num_nodes;
......
......@@ -35,7 +35,8 @@
#include <vector>
int assign_communities_halfedge(size_t numVertices, std::vector<size_t>::iterator adjdegrees, size_t numEdges, std::vector<size_t>::iterator adjlist, std::vector<double>::iterator adjweight, double total_weight, std::vector< int > &n2c);
int assign_communities_halfedge(size_t numVertices, std::vector<size_t>::iterator adjdegrees, std::vector<double>::iterator rmsds,
size_t numEdges, std::vector<size_t>::iterator adjlist, std::vector<double>::iterator adjweight, double total_weight, std::vector< int > &n2c);
#endif // LOUVAIN_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment