In testing the clustering given by the louvain_communities algorithm I found that the resolution parameter worked counter to literature behaviour and also stated documentation behaviour.
As the resolution increases we expect the size of the communities to get smaller, but as implemented we see precisely the inverse behaviour. A brief look at louvain.rs I think reveals the error, specifically in the function Modularity::q calculating the change in modularity when an isolated vertex $v$ is added to a community $C$ with resolution $\gamma$.
$$2m Q_{isolated} = Q_{other} + (\ell_{\text{v loop weight}} - \gamma \cdot \frac{d_v^2}{2m} ) + (C_{\text{internal edge weights}} - \gamma \cdot \frac{d_C^2}{2m})$$
$$2m Q_{merged} = Q_{other} + ( C_{\text{internal edge wights}} + |{\text{weights of edges from $v$ to $C$}}| - \gamma \frac{(d_C + d_v)^2}{2m})$$
$$2m \Delta_Q = 2m(Q_{merged} - Q_{isolated}) = |{\text{weights of edges from $v$ to $C$}}| - \ell_{\text{v loop weight}} - \gamma \cdot \frac{2d_cd_v}{2m}$$
You include the scaling factor of $2m$ (I think erroneously as $0.5m$) but as comparisons are relative this can be ignored. Also, the above equations are working under the context that a vertex may represent an entire community due to how louvain's stages works, and so loops need to be checked. Looking at your code I don't see that behaviour but that's a separate issue.
Note that $\gamma$ is in front of the second term, but in your code $\Delta_Q$ is calculated:
self.resolution_over_m * d_ij - (d_i * d_j) / (self.m_half * self.m)
The resolution is in front of the first term. This is a problem because there's no way for us to try fix it from the outside. This is a trivial fix to simply move the resolution parameter over (and presumably change some cached values) but I'm unfamiliar with pull requests and the like so didn't want to mess anything up.
In testing the clustering given by the
louvain_communitiesalgorithm I found that the resolution parameter worked counter to literature behaviour and also stated documentation behaviour.As the resolution increases we expect the size of the communities to get smaller, but as implemented we see precisely the inverse behaviour. A brief look at$v$ is added to a community $C$ with resolution $\gamma$ .
louvain.rsI think reveals the error, specifically in the functionModularity::qcalculating the change in modularity when an isolated vertexYou include the scaling factor of$2m$ (I think erroneously as $0.5m$ ) but as comparisons are relative this can be ignored. Also, the above equations are working under the context that a vertex may represent an entire community due to how louvain's stages works, and so loops need to be checked. Looking at your code I don't see that behaviour but that's a separate issue.
Note that$\gamma$ is in front of the second term, but in your code $\Delta_Q$ is calculated:
self.resolution_over_m * d_ij - (d_i * d_j) / (self.m_half * self.m)The resolution is in front of the first term. This is a problem because there's no way for us to try fix it from the outside. This is a trivial fix to simply move the resolution parameter over (and presumably change some cached values) but I'm unfamiliar with pull requests and the like so didn't want to mess anything up.