| 7108 | } |
| 7109 | |
| 7110 | int cbm_leiden(const int64_t *nodes, int node_count, const cbm_louvain_edge_t *edges, |
| 7111 | int edge_count, double resolution, cbm_louvain_result_t **out, int *out_count) { |
| 7112 | if (node_count <= 0) { |
| 7113 | *out = NULL; |
| 7114 | *out_count = 0; |
| 7115 | return CBM_STORE_OK; |
| 7116 | } |
| 7117 | int n = node_count; |
| 7118 | double gamma = resolution > 0.0 ? resolution : 1.0; |
| 7119 | |
| 7120 | cbm_louvain_result_t *result = malloc((size_t)n * sizeof(*result)); |
| 7121 | if (!result) { |
| 7122 | return CBM_NOT_FOUND; |
| 7123 | } |
| 7124 | for (int i = 0; i < n; i++) { |
| 7125 | result[i].node_id = nodes[i]; |
| 7126 | result[i].community = i; |
| 7127 | } |
| 7128 | |
| 7129 | /* Build deduplicated undirected edge weights, then a CSR graph. */ |
| 7130 | int *wsi; |
| 7131 | int *wdi; |
| 7132 | double *ww; |
| 7133 | int wn; |
| 7134 | louvain_build_weights(nodes, n, edges, edge_count, &wsi, &wdi, &ww, &wn); |
| 7135 | cbm_lg_t g; |
| 7136 | int built = (wn > 0) ? lg_build(n, wsi, wdi, ww, wn, &g) : CBM_NOT_FOUND; |
| 7137 | free(wsi); |
| 7138 | free(wdi); |
| 7139 | free(ww); |
| 7140 | if (built != CBM_STORE_OK) { |
| 7141 | /* No edges (or allocation failure): every node is its own community. */ |
| 7142 | *out = result; |
| 7143 | *out_count = n; |
| 7144 | return CBM_STORE_OK; |
| 7145 | } |
| 7146 | |
| 7147 | double twom = 0.0; |
| 7148 | for (int i = 0; i < n; i++) { |
| 7149 | twom += g.k[i]; |
| 7150 | } |
| 7151 | |
| 7152 | int *orig = malloc((size_t)n * sizeof(int)); /* original node -> current graph node */ |
| 7153 | int *comm = malloc((size_t)n * sizeof(int)); |
| 7154 | if (twom <= 0.0 || !orig || !comm) { |
| 7155 | free(orig); |
| 7156 | free(comm); |
| 7157 | lg_free(&g); |
| 7158 | *out = result; |
| 7159 | *out_count = n; |
| 7160 | return CBM_STORE_OK; |
| 7161 | } |
| 7162 | for (int i = 0; i < n; i++) { |
| 7163 | orig[i] = i; |
| 7164 | comm[i] = i; |
| 7165 | } |
| 7166 | |
| 7167 | for (int level = 0; level < LEIDEN_MAX_LEVELS; level++) { |
no test coverage detected