Packages

A pure Elixir implementation of the Leiden algorithm for community detection in networks. The Leiden algorithm improves upon the Louvain method by addressing resolution limits and ensuring well-connected communities. Supports both modularity and CPM quality functions.

Current section

Files

Jump to
ex_leiden lib ex_leiden.ex
Raw

lib/ex_leiden.ex

defmodule ExLeiden do
@moduledoc """
A pure Elixir implementation of the Leiden algorithm for community detection in networks.
The main entry point is `call/2`, which accepts graph data as `{vertices, edges}` tuples and returns community detection results using the Leiden algorithm.
See the [README](README.md) for detailed documentation, usage examples, and algorithm overview.
"""
# Type definitions for the public API
@type vertex() :: term()
@type edge() :: {vertex(), vertex()} | {vertex(), vertex(), number()}
@type vertices() :: list(vertex())
@type edges() :: list(edge())
@type graph_input() :: {vertices(), edges()}
@type opts() :: [
resolution: float(),
quality_function: :modularity | :cpm,
max_level: pos_integer(),
theta: float(),
gamma: float(),
flatten?: boolean()
]
@type community_id() :: term()
@type level() :: non_neg_integer()
@type graph_level() :: %{
level: level(),
communities: %{community_id() => list(vertex())},
bridges: list({community_id(), community_id(), number()}),
modularity: float(),
cpm_score: float() | nil
}
@type result() :: %{
levels: list(graph_level()),
metadata: %{
total_levels: pos_integer(),
iterations: pos_integer(),
processing_time_ms: pos_integer()
}
}
@doc """
Detects communities in a graph using the Leiden algorithm.
This is the main entry point for the ExLeiden library. It accepts graph data as a tuple
of vertices and edges, with optional configuration to customize algorithm behavior.
## Parameters
- `data` - Graph data in one of these formats:
- `%Graph{}` - Graph struct (from libgraph library)
- `[{source, target}, ...]` - List of edges (unweighted)
- `[{source, target, weight}, ...]` - List of weighted edges
- `{vertices, edges}` - Tuple of vertex list and edge list
- `opts` - Keyword list of configuration options (see README.md for details)
## Options
* `:quality_function` - Quality function to optimize (`:modularity` or `:cpm`).
Defaults to `:modularity`.
* `:resolution` - Resolution parameter γ controlling community granularity.
Higher values favor smaller communities. Defaults to `1.0`.
* `:max_level` - Maximum hierarchical levels to create.
Algorithm may stop early if no improvements possible. Defaults to `5`.
## Returns
- `{:ok, result}` - Success with community detection results and metadata
- `{:error, reason}` - Invalid options or input validation error
"""
@spec call(graph_input(), opts()) :: {:ok, result()} | {:error, map()}
def call(input, opts \\ [])
# Catch-all pattern for invalid input types
# Returns validation error for unsupported input formats.
def call(%Graph{} = _graph, _opts) do
{:error, %{implementation: "graph input pattern not yet implemented"}}
end
def call(edges, _opts) when is_list(edges) do
# TODO: Implement tuple input processing
# 1. Validate edges list
# 2. Create graph structure from raw data
# 3. Process with algorithm
{:error, %{implemtation: "tuple input pattern not yet implemented"}}
end
def call({[], edges}, opts) when is_list(edges) do
call(edges, opts)
end
def call({vertices, edges}, _opts) when is_list(vertices) and is_list(edges) do
# TODO: Implement tuple input processing
# 1. Validate vertices and edges lists
# 2. Create graph structure from raw data
# 3. Process with algorithm
{:error, %{implemtation: "tuple input pattern not yet implemented"}}
end
end