• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

graphty-org / graphty-element / 20514590651

26 Dec 2025 02:37AM UTC coverage: 70.559% (-0.3%) from 70.836%
20514590651

push

github

apowers313
ci: fix npm ci

9591 of 13363 branches covered (71.77%)

Branch coverage included in aggregate %.

25136 of 35854 relevant lines covered (70.11%)

6233.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.04
/src/algorithms/LeidenAlgorithm.ts
1
import {leiden} from "@graphty/algorithms";
15✔
2
import {z} from "zod/v4";
15✔
3

4
import {defineOptions, type OptionsSchema as ZodOptionsSchema, type SuggestedStylesConfig} from "../config";
15✔
5
import {Algorithm} from "./Algorithm";
15✔
6
import type {OptionsSchema} from "./types/OptionSchema";
7
import {countUniqueCommunities} from "./utils/communityUtils";
15✔
8
import {toAlgorithmGraph} from "./utils/graphConverter";
15✔
9

10
/**
11
 * Zod-based options schema for Leiden algorithm
12
 */
13
export const leidenOptionsSchema = defineOptions({
15✔
14
    resolution: {
15✔
15
        schema: z.number().min(0.1).max(5.0).default(1.0),
15✔
16
        meta: {
15✔
17
            label: "Resolution",
15✔
18
            description: "Controls community granularity",
15✔
19
            step: 0.1,
15✔
20
        },
15✔
21
    },
15✔
22
    randomSeed: {
15✔
23
        schema: z.number().int().min(0).max(2147483647).default(42),
15✔
24
        meta: {
15✔
25
            label: "Random Seed",
15✔
26
            description: "Seed for reproducible results",
15✔
27
            advanced: true,
15✔
28
        },
15✔
29
    },
15✔
30
    maxIterations: {
15✔
31
        schema: z.number().int().min(1).max(500).default(100),
15✔
32
        meta: {
15✔
33
            label: "Max Iterations",
15✔
34
            description: "Maximum refinement iterations",
15✔
35
            advanced: true,
15✔
36
        },
15✔
37
    },
15✔
38
    threshold: {
15✔
39
        schema: z.number().min(1e-10).max(0.01).default(1e-6),
15✔
40
        meta: {
15✔
41
            label: "Threshold",
15✔
42
            description: "Convergence threshold",
15✔
43
            advanced: true,
15✔
44
        },
15✔
45
    },
15✔
46
});
15✔
47

48
/**
49
 * Options for the Leiden community detection algorithm
50
 */
51
export interface LeidenOptions extends Record<string, unknown> {
52
    /** Controls community granularity */
53
    resolution: number;
54
    /** Seed for reproducible results */
55
    randomSeed: number;
56
    /** Maximum refinement iterations */
57
    maxIterations: number;
58
    /** Convergence threshold */
59
    threshold: number;
60
}
61

62
/**
63
 *
64
 */
65
export class LeidenAlgorithm extends Algorithm<LeidenOptions> {
15✔
66
    static namespace = "graphty";
19✔
67
    static type = "leiden";
120✔
68

69
    static zodOptionsSchema: ZodOptionsSchema = leidenOptionsSchema;
120✔
70

71
    static optionsSchema: OptionsSchema = {
120✔
72
        resolution: {
120✔
73
            type: "number",
120✔
74
            default: 1.0,
120✔
75
            label: "Resolution",
120✔
76
            description: "Controls community granularity",
120✔
77
            min: 0.1,
120✔
78
            max: 5.0,
120✔
79
            step: 0.1,
120✔
80
        },
120✔
81
        randomSeed: {
120✔
82
            type: "integer",
120✔
83
            default: 42,
120✔
84
            label: "Random Seed",
120✔
85
            description: "Seed for reproducible results",
120✔
86
            min: 0,
120✔
87
            max: 2147483647,
120✔
88
            advanced: true,
120✔
89
        },
120✔
90
        maxIterations: {
120✔
91
            type: "integer",
120✔
92
            default: 100,
120✔
93
            label: "Max Iterations",
120✔
94
            description: "Maximum refinement iterations",
120✔
95
            min: 1,
120✔
96
            max: 500,
120✔
97
            advanced: true,
120✔
98
        },
120✔
99
        threshold: {
120✔
100
            type: "number",
120✔
101
            default: 1e-6,
120✔
102
            label: "Threshold",
120✔
103
            description: "Convergence threshold",
120✔
104
            min: 1e-10,
120✔
105
            max: 0.01,
120✔
106
            advanced: true,
120✔
107
        },
120✔
108
    };
120✔
109

110
    static suggestedStyles = (): SuggestedStylesConfig => ({
120✔
111
        layers: [
11✔
112
            {
11✔
113
                node: {
11✔
114
                    selector: "",
11✔
115
                    style: {
11✔
116
                        enabled: true,
11✔
117
                    },
11✔
118
                    calculatedStyle: {
11✔
119
                        inputs: ["algorithmResults.graphty.leiden.communityId"],
11✔
120
                        output: "style.texture.color",
11✔
121
                        expr: "{ return StyleHelpers.color.categorical.tolMuted(arguments[0] ?? 0) }",
11✔
122
                    },
11✔
123
                },
11✔
124
                metadata: {
11✔
125
                    name: "Leiden - Muted Colors",
11✔
126
                    description: "7 subdued professional community colors",
11✔
127
                },
11✔
128
            },
11✔
129
        ],
11✔
130
        description: "Visualizes communities detected via Leiden algorithm (improved Louvain)",
11✔
131
        category: "grouping",
11✔
132
    });
11✔
133

134
    /**
135
     * Executes the Leiden algorithm on the graph
136
     *
137
     * Detects communities using an improved modularity optimization method.
138
     */
139
    async run(): Promise<void> {
19✔
140
        const g = this.graph;
3✔
141
        const nodes = Array.from(g.getDataManager().nodes.keys());
3✔
142

143
        if (nodes.length === 0) {
3!
144
            return;
×
145
        }
×
146

147
        // Get options from schema
148
        const {resolution, maxIterations, threshold} = this.schemaOptions;
3✔
149

150
        // Convert to @graphty/algorithms Graph format (undirected for community detection)
151
        const graphData = toAlgorithmGraph(g, {addReverseEdges: false});
3✔
152

153
        // Run Leiden algorithm - returns {communities: Map<string, number>, modularity, iterations}
154
        const result = leiden(graphData, {
3✔
155
            resolution,
3✔
156
            maxIterations,
3✔
157
            threshold,
3✔
158
        });
3✔
159

160
        // Store results on nodes
161
        for (const nodeId of nodes) {
3✔
162
            const communityId = result.communities.get(String(nodeId)) ?? 0;
43!
163
            this.addNodeResult(nodeId, "communityId", communityId);
43✔
164
        }
43✔
165

166
        // Store graph-level results
167
        this.addGraphResult("modularity", result.modularity);
3✔
168
        this.addGraphResult("communityCount", countUniqueCommunities(result.communities));
3✔
169
        this.addGraphResult("iterations", result.iterations);
3✔
170
    }
3✔
171
}
19✔
172

173
// Auto-register this algorithm when the module is imported
174
Algorithm.register(LeidenAlgorithm);
15✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc