yog/community

Community detection and clustering algorithms.

Provides types and utility functions for working with community structures in graphs. Community detection algorithms identify groups of nodes that are more densely connected internally than with the rest of the graph.

Algorithms

AlgorithmModuleBest For
Louvainyog/community/louvainLarge graphs, modularity optimization
Leidenyog/community/leidenQuality guarantee, well-connected communities
Label Propagationyog/community/label_propagationSpeed, near-linear time
Girvan-Newmanyog/community/girvan_newmanHierarchical structure, edge betweenness
Infomapyog/community/infomapInformation-theoretic, flow-based
Clique Percolationyog/community/clique_percolationOverlapping communities
Walktrapyog/community/walktrapRandom walk-based distances
Local Communityyog/community/local_communityMassive graphs, seed expansion
Fluid Communitiesyog/community/fluid_communitiesExact k partitions, fast

Core Types

Example

import yog
import yog/community
import yog/community/louvain

let graph = // ... build your graph

// Detect communities
let communities = louvain.detect(graph)
io.debug(communities.num_communities)  // => 4

// Get nodes in each community
let communities_dict = community.communities_to_dict(communities)
// => dict.from_list([#(0, set.from_list([1, 2, 3])), #(1, set.from_list([4, 5]))])

// Find largest community
case community.largest_community(communities) {
  Some(community_id) -> io.debug(community_id)
  None -> io.println("No communities found")
}

Choosing an Algorithm

Types

Represents a community partition of a graph.

Fields

  • assignments: Dictionary mapping each node ID to its community ID
  • num_communities: Total number of distinct communities

Example

Communities(
  assignments: dict.from_list([#(1, 0), #(2, 0), #(3, 1)]),
  num_communities: 2
)
// Node 1 and 2 are in community 0, node 3 is in community 1
pub type Communities {
  Communities(
    assignments: dict.Dict(Int, Int),
    num_communities: Int,
  )
}

Constructors

  • Communities(
      assignments: dict.Dict(Int, Int),
      num_communities: Int,
    )

Community assignment for nodes

pub type CommunityId =
  Int

Hierarchical community structure with multiple levels of granularity.

Fields

  • levels: List of community partitions from finest to coarsest
  • merge_order: Order in which communities were merged (for dendrogram reconstruction)

Example

A dendrogram might have 3 levels:

  • Level 0: Each node in its own community (finest)
  • Level 1: Communities merged based on similarity
  • Level 2: All nodes in one community (coarsest)
pub type Dendrogram {
  Dendrogram(
    levels: List(Communities),
    merge_order: List(#(Int, Int)),
  )
}

Constructors

  • Dendrogram(
      levels: List(Communities),
      merge_order: List(#(Int, Int)),
    )

Values

pub fn communities_to_dict(
  communities: Communities,
) -> dict.Dict(Int, set.Set(Int))

Converts community assignments to a dictionary mapping community IDs to sets of node IDs.

This is useful when you need to iterate over all nodes in each community rather than looking up the community for each node.

Example

let communities = Communities(
  assignments: dict.from_list([#(1, 0), #(2, 0), #(3, 1)]),
  num_communities: 2
)

community.communities_to_dict(communities)
// => dict.from_list([
//      #(0, set.from_list([1, 2])),
//      #(1, set.from_list([3]))
//    ])
pub fn community_sizes(
  communities: Communities,
) -> dict.Dict(Int, Int)

Returns a dictionary mapping community IDs to their sizes (number of nodes).

Example

let communities = Communities(
  assignments: dict.from_list([#(1, 0), #(2, 0), #(3, 1), #(4, 1), #(5, 1)]),
  num_communities: 2
)

community.community_sizes(communities)
// => dict.from_list([#(0, 2), #(1, 3)])
pub fn largest_community(
  communities: Communities,
) -> option.Option(Int)

Returns the community ID with the largest number of nodes.

Returns None if there are no communities (empty graph or no assignments).

Example

let communities = Communities(
  assignments: dict.from_list([#(1, 0), #(2, 0), #(3, 0), #(4, 1)]),
  num_communities: 2
)

community.largest_community(communities)
// => Some(0)  // Community 0 has 3 nodes vs 1 for community 1
pub fn merge_communities(
  communities: Communities,
  source: Int,
  target: Int,
) -> Communities

Merges two communities into one.

All nodes from the source community are reassigned to the target community. The source community ID is effectively removed.

Parameters

  • communities: The current community partition
  • source: The community ID to merge from (will be removed)
  • target: The community ID to merge into (will be kept)

Example

let communities = Communities(
  assignments: dict.from_list([#(1, 0), #(2, 0), #(3, 1), #(4, 1)]),
  num_communities: 2
)

// Merge community 1 into community 0
let merged = community.merge_communities(communities, source: 1, target: 0)
// merged.assignments => dict.from_list([#(1, 0), #(2, 0), #(3, 0), #(4, 0)])
// merged.num_communities => 1
Search Document