Skip to content
This repository has been archived by the owner on Apr 26, 2019. It is now read-only.

community: new package implement Louvain graph modularisation #133

Merged
merged 3 commits into from
Oct 28, 2015

Conversation

kortschak
Copy link
Member

This adds the measure used for modularity optimisation. The Louvain, LouvainMultilevel and SLM algorithms will come later.

I'm not sure about the API - the optimisation algorithms may demand a change, but what exists here looks OK for public use with the exception that community memberships must be disjoint and we don't check for that here.

https://en.wikipedia.org/wiki/Louvain_Modularity#Algorithm and http://arxiv.org/abs/cond-mat/0603718 for reference - the latter only for the resolution parameter.

@vladimir-ch Please take a look.

@kortschak kortschak force-pushed the community branch 23 times, most recently from 4b7d90d to f487514 Compare October 20, 2015 05:55
@kortschak
Copy link
Member Author

I'm a fair way into Louvain, so hold off on this and I'll submit as Q+Louvain (possibly others depending on how much additional work is needed for them).

@kortschak kortschak force-pushed the community branch 6 times, most recently from 4b1ca7b to ff00885 Compare October 21, 2015 02:16
@kortschak kortschak force-pushed the community branch 9 times, most recently from 1191bec to 5a57447 Compare October 27, 2015 19:35
@kortschak kortschak changed the title network: add community Q modularity function community: new package implement Louvain graph modularisation Oct 27, 2015
@kortschak
Copy link
Member Author

For reference, the benchmark for the optimised code altered to use 1e4 or 1e5 node graphs gives the following results:

BenchmarkLouvain-8         1    1682792460 ns/op
BenchmarkLouvain-8         1    49984771994 ns/op

I think that is adequate.

@kortschak
Copy link
Member Author

@vladimir-ch This is now ready for review.

PTAL

@kortschak
Copy link
Member Author

Two questions:

  1. I think we should add a Qnull and LouvainNull which use the \gamma instead of the \gamma k_i k_j/2m term used here. That covers most the cases in doi:10.1103/PhysRevE.74.016110 if we allow users to provide the graph's density, which they can calculate, as \gamma.
  2. Probably at some stage we should add directed graph handling. There is enough difference in the code (efficiencies gained in the undirected case) that code duplication is warranted. The divergence of the copies can either be hidden to the user and we type switch on the graph type or we provide Louvain and LouvainDirected (the undirected case being the canonical instance because of history). I think the API duplication is the better approach. If we do this, I should probably get the API for the current state correct. This would be to rename ReducedGraph to ReducedUndirected.

What do you think? The upshot of the non-type switched approach in conjunction with the two Q measures would be we have 4 Louvains and 4 Qs.

// reduce returns a reduced graph constructed from g divided
// into the given communities. The communities value is mutated
// by the call to reduce. If communities is nil and g is a
// ReducedGraph, it is returned unaltered.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*ReducedGraph or leave it be?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The English is nicer without sigils.

@vladimir-ch
Copy link
Member

LGTM

Re 1. If you think that the \gamma case is useful, then having two Qs seems like the only option (unless we add a bool argument but ...). QNull or LouvainNull do not sound like great names but I can't think of anything better.

Re 2. Agreed on usefulness of modularity for directed graphs and on api duplication although I wish there were a third way.

@kortschak
Copy link
Member Author

  1. Can happen later, so we have time to think of better names. An alternative is for Louvain to take a Metric interface that is the Q func and has Q⁺ and Q¯ methods. While this is elegant, it doesn't give the expected performance payback that you would expect for the null cases since the deltaQ won't know that the edge statistics aren't needed.
  2. So I should update ReducedGraph => ReducedUndirected. I'll also add a note pointing to louvain.tex which has just been merged.

name     old time/op  new time/op  delta
Louvain   7.18s ± 1%   0.12s ± 1%  -98.26%  (p=0.000 n=10+9)
name     old time/op  new time/op  delta
Louvain   119ms ± 1%   102ms ± 4%  -14.31%  (p=0.000 n=94+97)

benchmark              old allocs     new allocs     delta
BenchmarkLouvain-8     509657         420228         -17.55%

benchmark              old bytes     new bytes     delta
BenchmarkLouvain-8     26689475      20862968      -21.83%
@kortschak
Copy link
Member Author

I wish there were a third way.

Lyron has pointed out a section of Reichardt and Bornholdt that says this is possible, He's going to make an addition to louvain.tex showing its correctness. And I have an implementation of it ready - 140 lines of trivial Go. I just need to add some simple tests.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants