| 7007 | } |
| 7008 | |
| 7009 | int cbm_leiden(const int64_t *nodes, int node_count, const cbm_louvain_edge_t *edges, |
| 7010 | int edge_count, double resolution, cbm_louvain_result_t **out, int *out_count) { |
| 7011 | if (node_count <= 0) { |
| 7012 | *out = NULL; |
| 7013 | *out_count = 0; |
| 7014 | return CBM_STORE_OK; |
| 7015 | } |
| 7016 | int n = node_count; |
| 7017 | double gamma = resolution > 0.0 ? resolution : 1.0; |
| 7018 | |
| 7019 | cbm_louvain_result_t *result = malloc((size_t)n * sizeof(*result)); |
| 7020 | if (!result) { |
| 7021 | return CBM_NOT_FOUND; |
| 7022 | } |
| 7023 | for (int i = 0; i < n; i++) { |
| 7024 | result[i].node_id = nodes[i]; |
| 7025 | result[i].community = i; |
| 7026 | } |
| 7027 | |
| 7028 | /* Build deduplicated undirected edge weights, then a CSR graph. */ |
| 7029 | int *wsi; |
| 7030 | int *wdi; |
| 7031 | double *ww; |
| 7032 | int wn; |
| 7033 | louvain_build_weights(nodes, n, edges, edge_count, &wsi, &wdi, &ww, &wn); |
| 7034 | cbm_lg_t g; |
| 7035 | int built = (wn > 0) ? lg_build(n, wsi, wdi, ww, wn, &g) : CBM_NOT_FOUND; |
| 7036 | free(wsi); |
| 7037 | free(wdi); |
| 7038 | free(ww); |
| 7039 | if (built != CBM_STORE_OK) { |
| 7040 | /* No edges (or allocation failure): every node is its own community. */ |
| 7041 | *out = result; |
| 7042 | *out_count = n; |
| 7043 | return CBM_STORE_OK; |
| 7044 | } |
| 7045 | |
| 7046 | double twom = 0.0; |
| 7047 | for (int i = 0; i < n; i++) { |
| 7048 | twom += g.k[i]; |
| 7049 | } |
| 7050 | |
| 7051 | int *orig = malloc((size_t)n * sizeof(int)); /* original node -> current graph node */ |
| 7052 | int *comm = malloc((size_t)n * sizeof(int)); |
| 7053 | if (twom <= 0.0 || !orig || !comm) { |
| 7054 | free(orig); |
| 7055 | free(comm); |
| 7056 | lg_free(&g); |
| 7057 | *out = result; |
| 7058 | *out_count = n; |
| 7059 | return CBM_STORE_OK; |
| 7060 | } |
| 7061 | for (int i = 0; i < n; i++) { |
| 7062 | orig[i] = i; |
| 7063 | comm[i] = i; |
| 7064 | } |
| 7065 | |
| 7066 | for (int level = 0; level < LEIDEN_MAX_LEVELS; level++) { |
no test coverage detected