vtraag / louvain-igraph

Implementation of the Louvain algorithm for community detection with various methods for use with igraph in python.
GNU General Public License v3.0
246 stars 46 forks source link

How to exactly handle negative weights? #33

Closed tjiagoM closed 2 years ago

tjiagoM commented 6 years ago

I started using louvain-igraph because of the possibility of using negative weights in community detection. However, I think your documentation is not very clear in some points and if possible I would like some clarification. Maybe I just misunderstood some parts.

1) First, regarding the attribute consider_comms. From what I understood, I just needed to set this attribute (for example in ModularityVertexPartition) to ALL_COMMS, which I couldn't find how to do. How do I really setup this attribute?

2) Looking a bit further, I discovered that CPMVertexPartition is prepared for negative weights. Doing some quick tests it seems it does what I want. However, it's not clear whether it uses ALL_COMMS or ALL_NEIGH_COMMS. Which one it uses? And would it be possible to configure this?

3) Finally, in your pdf documentation you have a small section for negative weights. If I understood correctly, what you suggest there is to separate the graph in 2, where one has the positive weights, and the other the negative weights. So, this would create communities with many negative links which I think it's not what we want: we want negative weights to separate communities, not to have those weights inside one community, right? Did I understand something wrong? What would be the difference between the approach in CPMVertexPartition and the approach in this part of the documentation?

I hope you can clarify this, and maybe include the clarification in the documentation.

vtraag commented 6 years ago

I think there is some confusion regarding the use of ALL_COMMS. This is a property of the Optimiser not of a particular partition. You can look it up in the documentation. The reason you might want to use ALL_COMMS is because communities need no longer be connected in networks with negative weights. However, it is slower than ALL_NEIGH_COMMS, and that option may already provide you with good solutions.

Indeed, CPMVertexPartition works correctly with negative weights, unlike other partitions. If you do want to stick to other quality functions for detecting communities, you should do that as is documented here.

I'm not sure where the documentation is unclear exactly, but if you can pinpoint some specific parts that you found unclear or ambiguous, I'd be more than happy to update the documentation!

tjiagoM commented 6 years ago

Ok, I definitely made a confusion between Optimiser and the pre-defined partitions you have. I was understanding that under the hood CPMVertexPartition and others were using an Optimiser, when they are simply different things. Sorry about that.

With regards to the negative weights section, my point was twofold: 1) You present a way of handling negative weights by putting in the same community all nodes with negative links connecting them. However, this is not usually what we want (we want negative weights to separate communities, not to have those weights inside one community). So I was just questioning whether you actually meant this. 2) In the docs, it was not clear that CPMVertexPartition handles negative weights. I just discovered that because of that small section on negative weights in the optimisers where you say "Most methods (except CPM) only accept positive weights". It would be more clear if you say it handles negative links on the class definition itself (http://louvain-igraph.readthedocs.io/en/latest/reference.html?highlight=all_comms#louvain.CPMVertexPartition).

Many thanks for your quick response!

tjiagoM commented 6 years ago
vtraag commented 6 years ago

No problem, I'll try to see if I can clarify the distinction between the Optimiser and all the partitions classes.

Your second point shouldn't be any problem, I'll make sure to update it when I get a chance.

Regarding your first point, I'm not exactly sure what you mean. Indeed, I would typically also want negative weights between communities. I'm not sure how you got the idea that I would want to put all nodes in the same community if they have negative links between them?

tjiagoM commented 6 years ago

I got that idea from this sentence: "In order to deal with graphs that do have negative links, a solution is to separate the graph into two layers: one layer with positive links, the other with only negative links".

And also from the example code in which you create two graphs: one with positive weights, and the other with negative weigts (G_pos and G_neg)

vtraag commented 6 years ago

That indeed refers to separating the graph in two parts, but it does not state that communities should contain negative links within them, no?

The idea of the approach is that, whereas we ordinarily maximise the positive part (i.e. find as many positive links as possible within communities), we want the opposite of that for the negative part (i.e. find as few negative links as possible within communities). That is why the so-called layer_weight is set to -1 for the layer containing the negative links, so that the Optimiser actually minimises the negative part, but maximises the positive part.

tjiagoM commented 6 years ago

Ok, now that I re-read the docs it's pretty obvious, but for some reason I didn't get that before. I guess it was the fact that not explicitly explaining what layer_weight is for. In optimise_partition_multiplex you just define it very vaguely as "List of weights of layers", and in the notes saying "...weighted by the layer_weight". I guess you could improve documentation by just adding that explanation you just wrote for layer_weight, but I admit it's already quite obvious anyway.

Thank you very much for your attention, all my doubts are clear now!

vtraag commented 6 years ago

OK, good to hear! I'll try to re-read the documentation and improve it where I can.