パッケージの詳細

graphology-communities-louvain

graphology34.6kMIT2.0.2

Louvain community detection for graphology.

community, detection, graph, graphology

readme

Graphology Communities Louvain

Implementation of the Louvain algorihtm for community detection to be used with graphology.

References

M. E. J. Newman, « Modularity and community structure in networks », Proc. Natl. Acad. Sci. USA, vol. 103, no 23, 2006, p. 8577–8582 https://dx.doi.org/10.1073%2Fpnas.0601602103

Newman, M. E. J. « Community detection in networks: Modularity optimization and maximum likelihood are equivalent ». Physical Review E, vol. 94, no 5, novembre 2016, p. 052315. arXiv.org, doi:10.1103/PhysRevE.94.052315. https://arxiv.org/pdf/1606.02319.pdf

Blondel, Vincent D., et al. « Fast unfolding of communities in large networks ». Journal of Statistical Mechanics: Theory and Experiment, vol. 2008, no 10, octobre 2008, p. P10008. DOI.org (Crossref), doi:10.1088/1742-5468/2008/10/P10008. https://arxiv.org/pdf/0803.0476.pdf

Nicolas Dugué, Anthony Perez. Directed Louvain: maximizing modularity in directed networks. [Research Report] Université d’Orléans. 2015. hal-01231784 https://hal.archives-ouvertes.fr/hal-01231784

R. Lambiotte, J.-C. Delvenne and M. Barahona. Laplacian Dynamics and Multiscale Modular Structure in Networks, doi:10.1109/TNSE.2015.2391998. https://arxiv.org/abs/0812.1770

Traag, V. A., et al. « From Louvain to Leiden: Guaranteeing Well-Connected Communities ». Scientific Reports, vol. 9, no 1, décembre 2019, p. 5233. DOI.org (Crossref), doi:10.1038/s41598-019-41695-z. https://arxiv.org/abs/1810.08473

Installation

npm install graphology-communities-louvain

Usage

Runs the Louvain algorithm to detect communities in the given graph. It works both for undirected & directed graph by using the relevant modularity computations.

This function also works on multi graphs but won't work with mixed graph as it is not trivial to adapt modularity to this case. As such, if you need to process a true mixed graph (this function will correctly handle mixed graphs containing only directed or undirected edges), cast your graph as either directed or undirected using graphology-operators dedicated functions.

Note also that this algorithm's run time is bounded by the number of edges in your graph. As such, it might be preferable, in some cases, to cast your multi graph as a simple one using graphology-operators functions for better performance.

Note that the community labels are returned as an integer range from 0 to n.

import louvain from 'graphology-communities-louvain';

// To retrieve the partition
const communities = louvain(graph);

// To directly assign communities as a node attribute
louvain.assign(graph);

// If you need to pass custom options
louvain.assign(graph, {
  resolution: 0.8
});

// If you want to return some details about the algorithm's execution
var details = louvain.detailed(graph);

// If you want to ignore your graph's weights
louvain.assign(graph, {getEdgeWeight: null});

Arguments

  • graph Graph: target graph.
  • options ?object: options:
    • getEdgeWeight ?string|function [weight]: name of the edges' weight attribute or getter function.
    • nodeCommunityAttribute ?string [community]: name of the community attribute.
    • fastLocalMoves ?boolean [true]: whether to use a well-known optimization relying on a queue set to traverse the graph more efficiently.
    • randomWalk ?boolean [true]: whether to traverse the graph randomly.
    • resolution ?number [1]: resolution parameter. An increased resolution should produce more communities.
    • rng ?function [Math.random]: RNG function to use for randomWalk. Useful if you need to seed your rng using, for instance, seedrandom.

Detailed Output

  • communities [object]: partition of the graph.
  • count [number]: number of communities in the partition.
  • deltaComputations [number]: number of delta computations that were run to produce the partition.
  • dendrogram [array]: array of partitions.
  • modularity [number]: final modularity of the graph given the found partition.
  • moves [array]: array of array of number of moves if fastLocalMoves was false or array of number of moves if fastLocalMoves was true.
  • nodesVisited [number]: number of times nodes were visited.

Benchmark

To run the benchmark:

npm install --no-save ngraph.louvain.native
node benchmark/comparison.js
Clustered Undirected graph with 1000 nodes and 9724 edges.

graphology undirected1000: 52.732ms
Communities 8
Modularity 0.42944314393593924

jlouvain undirected1000: 2368.053ms
Communities 8
Modularity 0.4302331134880074

ngraph.louvain undirected1000: 71.108ms
Communities 8

ngraph.louvain.native undirected1000: 39.185ms
Communities 7

---

EuroSIS Directed graph with 1285 nodes and 7524 edges.

graphology euroSis: 30.809ms
Communities 19
Modularity 0.7375260763995757

jlouvain euroSis: 1310.008ms
Communities 23
Modularity 0.7376116434498033

ngraph euroSis: 38.262ms
Communities 16

ngraph.native euroSis: 20.018ms
Communities 16

---

Big Undirected graph with 50000 nodes and 994713 edges.

graphology bigGraph: 937.942ms
Communities 43
Modularity 0.481431448861252

jLouvain is too slow...

ngraph bigGraph: 7783.050ms
Communities 44

ngraph.native bigGraph: 8415.692ms
Communities 1

更新履歴

Changelog

0.25.4

  • Reverting to 0.25.1 package semantics to avoid partial ESM-first support issues.

0.25.3

  • Fixing missing types declaration in package's exports key.

0.25.2

  • Loosening plain object tests to avoid issues with objects coming from different JavaScript contexts.

0.25.1

  • Fixing #.hasEdge methods for multigraphs.
  • Fixing #.degreeWithoutSelfLoops methods for multigraphs.

0.25.0

  • Optimizing JSON serialization.
  • Shipping source maps with package.

0.24.1

  • Improving performance and memory usage of multigraphs.

0.24.0

  • Adding #.inboundDegree, #.outboundDegree, #.inboundDegreeWithoutSelfLoops, #.outboundDegreeWithoutSelfLoops.
  • Adding missing #.dropDirectedEdge & #.dropUndirectedEdge.
  • Adding possibility to pass upgrading options to #.copy.
  • Refactoring internal edge & neighbor iteration schemes.
  • Dropping undocumented #.upgradeToMixed & #.upgradeToMulti.
  • Refactoring internal indices.
  • Fixing edge iteration wrt. self loops.
  • Dropping some irrelevant arities for edge attribute updates.
  • Improving performance of edge iteration.
  • Improving performance of neighbor iteration.
  • Improving performance of node deletion.
  • Improving performance of edge attribute edition.
  • Improving performance of internal edge key generator.
  • Improving memory usage.
  • Improving performance of default degree methods.
  • Improving serialization performance.

0.23.2

  • Fixing a #.mergeUndirectedEdgeWithKey & #.updateUndirectedEdgeWithKey bug when source & target are given in the reverse order.

0.23.1

  • Fixing #.copy not copying the graph's attributes.
  • Improving performance of #.copy.

0.23.0

  • Adding #.updateAttributes.
  • Adding #.updateNodeAttributes.
  • Adding #.updateEdgeAttributes.
  • Adding #.getSourceAttribute, #.getTargetAttribute, #.getOppositeAttribute and friends.
  • Aligning #.updateEachEdgeAttributes callback arguments to #.forEachEdge.
  • Improving #.merge* and #.update* function by returning useful information.
  • Improving #.opposite performance.

Migration guide

This release should only affect you in the following cases:

  1. You were relying on the keys returned by #.mergeEdge, #.updateEdge etc. In which case those methods now return a useful tuple containing said key as its first element as well as additional information about whether target elements already existed in the graph or not.
  2. Some hidden adjacency iteration methods were mangled and are still hidden. This could only affect you if you were using #.forEach, #.find or #.adjacency (not to be confused with their node, edge & neighbor counterparts).

0.22.2

  • Fixing #.mergeEdge & #.updateEdge error messages.
  • Improving performance of #.addEdge etc. (less deopt).
  • Improving #.inspect output wrt undirected multi edges.

0.22.1

  • Fixing prepublishOnly script and shipped package.

0.22.0

  • Rolling back to robust generated ids for edges.
  • Adding #.mapNodes, #.filterNodes, #.reduceNodes, #.findNode #.someNode, #.everyNode.
  • Adding #.mapEdges, #.filterEdges, #.reduceEdges, #.findEdge #.someEdge, #.everyEdge.
  • Adding #.mapNeighbors, #.filterNeighbors, #.reduceNeighbors, #.findNeighbor #.someNeighbor, #.everyNeighbor.
  • Adding #.degreeWithoutSelfLoops.
  • Changing #.forEach*Until methods to #.find* methods.
  • Dropping #.hasGeneratedKey.
  • Dropping the generated last argument to edge & adjacency iterations.
  • Dropping the edgeKeyGenerator instantiation option.
  • Dropping second argument of #.degree.
  • Changing #.neighbors(source, target) to #.areNeighbors.
  • Changing iterator entries to objects rather than arrays.
  • #.exportEdge will now always return a key.
  • Fixing mutability bug with #.copy.
  • Fixing adjacency iterator items missing undirected.
  • Fixing edge iterator items missing undirected.
  • Fixing bug related to instance counters and #.clear, #.clearEdges.
  • Improving #.copy performance.
  • Improving #.areNeighbors performance.
  • Improving #.forEachNode performance.
  • Upgrading obliterator and improving iterator-based methods.

Migration guide

This release should only affect you in the following use-cases:

  1. You were using #.forEach*Until methods, in which case you should replace them by the relevant #.find* or #.some* method.
  2. You were using the boolean second argument to the #.degree methods. Replace those calls by #.degreeWithoutSelfLoops.
  3. You were using the (well-hidden) two-arguments polymorphism of #.neighbors. Replace those calls by #.areNeighbors.
  4. You were using iterators in which case the yielded entries are now objects rather than arrays and should be easier to destructure to access the parts you need.
  5. You were doing despicable things with automatically generated keys.

0.21.1

  • Fixing #.removeNodeAttribute error message.
  • Upgrading types to 0.20.0.

0.21.0

  • *Until methods now return whether they broke.
  • Fixing a bug with #.forEachNodeUntil.

0.20.0

  • Changing default edge key generator to simple incremental id.

0.19.3

  • Fixing issues related to rollup bundling.

0.19.2

  • Fixing #.dropNode bug.

0.19.1

  • Optimizing #.dropNode.

0.19.0

  • Adding #.forEachUntil.
  • Adding #.forEachNodeUntil.
  • Adding #.forEachEdgeUntil.
  • Adding #.forEachNeighborUntil.
  • Adding #.updateNode.
  • Adding #.updateEdge.
  • Adding attributes to attributesUpdated events.
  • Adding attributes to nodeAttributesUpdated events.
  • Adding attributes to edgeAttributesUpdated events.
  • Adding #.updateEachNodeAttributes.
  • Adding #.updateEachEdgeAttributes.
  • Passing undirected & generatedKey to #.forEachEdge callbacks.
  • Changing #.forEach & #.adjacency semantics to something actually useful.
  • Optimizing *AttributesUpdated events payload.
  • Optimizing #.edges(A, B).
  • Optimizing #.forEachEdge.
  • Optimizing #.mergeEdge.
  • Optimizing #.edges and #.nodes.
  • Optimizing #.import.
  • Fixing #.edges(A, B) with directed self loops.
  • Fixing #.mergeEdgeWithKey edge cases.
  • Fixing #.mergeAttributes event payload.
  • Fixing #.edgeEntries stack overflow with undirected edges.
  • Dropping before and after from replace events metadata.
  • Dropping value from set events metadata.
  • Dropping overkill toString method.
  • Correctly emitting nodeAttributesUpdated event when node is merged.
  • Correctly emitting edgeAttributesUpdated event when edge is merged.
  • graphology-types is now a peer dependency.

0.18.0

  • Adding #.implementation.
  • Adding #.hasExtremity.
  • Adding #.selfLoopCount, #.directedSelfLoopCount & #.undirectedSelfLoopCount.
  • Adding #.hasGeneratedKey.
  • Renaming #.directed & #.undirected to #.isDirected & #.isUndirected.
  • Renaming #.selfLoop to #.isSelfLoop.
  • Serializing options & accepting them with #.from static methods.
  • Improving performance of #.opposite.
  • Improving serialization performance.
  • Updating type declarations & adding generics.
  • Optimizing various degree methods.
  • Optimizing graph attributes methods.
  • Fixing edges & neighbors iteration regarding self loops in the directed case.

0.17.1

  • Optimizing #.forEachEdge methods.

0.17.0

  • Changing packaging system.
  • Fixing browser bundle.

0.16.1

  • Bundle fixes (@zakjan).

0.16.0

  • Proper #.nullCopy & #.emptyCopy methods.

0.15.2

  • More flexible dependency to graphology-types.

0.15.1

  • Adding missing MultiGraph export.
  • Adding missing error typings.

0.15.0

  • TypeScript support.
  • Adding possibility to merge options using #.emptyCopy.

0.14.1

  • Fixing #.mergeEdge for the self loop case.

0.14.0

  • Adding Symbol.iterator to the prototype.
  • Fixing custom inspection for node >= 10.

0.13.1

  • Fixing edge attributes methods with typed graphs.

0.13.0

  • Adding #.nodeEntries.
  • Adding #.edgeEntries.
  • Adding #.neighborEntries.
  • Adding #.forEach.
  • Adding #.adjacency.

0.12.0

  • Adding #.clearEdges.
  • Adding #.forEachEdge & alii.
  • Adding #.forEachNode & alii.
  • Adding #.forEachNeighbor & alii.
  • Adding #.inboundNeighbors & #.outboundNeighbors.
  • Adding #.inboundEdges & #.outboundEdges.
  • Dropping #.addNodesFrom.
  • Dropping #.dropNodes & #.dropEdges.
  • Dropping plural serialization methods.
  • Dropping defaultNodeAttributes & defaultEdgeAttributes.
  • Fixing semantics of #.inEdges & #.outEdges for arity 2.
  • Improving performance of edges-related methods.
  • Improving performance of internal indices.
  • Improving performance of #.mergeNode.
  • Fixing edge-case deopt for #.dropEdges.
  • Fixing bug related to multigraphs' neighbors.
  • Attribute copy is now done on serialization.
  • Completely reworking internal indices.

0.11.4

  • Improving performance of neighbors-related methods.
  • Improving performance of edges-related methods.

0.11.3

  • Fixing issues related to the obliterator dependencies.

0.11.2

  • Fixing an issue with #.mergeNode & string coercion.

0.11.1

  • Fixing the #.edges for undirected graphs.

0.11.0

  • Adding #.directedSize & #.undirectedSize.

0.10.2

  • Performance enhancements.

0.10.1

  • Performance enhancements.
  • Fixing a bug with #.mergeEdge & undirected edges.

0.10.0

  • Adding basic edges iterators.
  • Fixing #.inspect.

0.9.1

  • Fixing a bug concerning #.hasEdge & typed graphs.

0.9.0

  • Major write performance improvements.
  • Shifting the default edge key generation system.
  • Dropping index' laziness.

0.8.0

  • Adding the #.nodesIterator method.
  • Performance improvements.

0.7.1

  • Fixing a bug related to typed graphs' attributes.
  • Fixing a bug with the dropping methods.

0.7.0

  • Adding the #.edge & variants methods.
  • Adding the #.upgradeToMixed method.
  • Adding the #.upgradeToMulti method.
  • Refactoring indices methods.

0.6.0

  • Dropping inbound & outbound iteration methods.
  • Dropping useless counting iteration methods.
  • Dropping bunch consuming polymorphisms from iteration methods.
  • Refactoring internal indices for undirected graphs.
  • Improving performance.

0.5.4

  • Fixing degree methods for typed graphs.

0.5.3

  • Improving performance.

0.5.2

  • Node.js 0.12.x compatibility.
  • Fixing bug related to the graph's string coercion.
  • Improving performance.
  • Better error message when adding a self-loop when it's not authorized.

0.5.1

  • Better unit tests.
  • Internal refactoring.

0.5.0

  • Implementing the static #.from method & switching constructor paradigm.
  • Fixing bug related to the attributesUpdated event.
  • Adding more errors related to attributes' setters.
  • Adding typed edges attributes' getters/setters.
  • Rewrote internal indices.
  • Dropping #.getEdge & friends.
  • Dropping #.selfLoops.

0.4.2

  • Adding missing built files to the npm package.

0.4.1

  • Adding missing attributes in export.

0.4.0

  • Adding #.removeNodeAttribute & #.removeEdgeAttribute that was actually missing from earlier versions.
  • Adding graph attributes.
  • nodeUpdated & edgeUpdated changing to nodeAttributesUpdated & edgeAttributesUpdated respectively.

0.3.0

  • Adding merge flags to import methods.

0.2.0

  • Adding #.hasNodeAttribute & #.hasEdgeAttribute.
  • Adding #.removeNodeAttribute & #.removeEdgeAttribute.
  • Adding #.mergeNode.
  • Adding #.mergeEdge, #.mergeEdgeWithKey and friends.
  • Renaming #.relatedNode to #.opposite.
  • Dropping the onDuplicateNode & onDuplicateEdge options.

0.1.1

  • Fixing the argument passed to the edgeKeyGenerator function.
  • Fixing a bug where source & target of an edge were not internally coerced to strings.

0.1.0

Initial version compliant to the specs.