#pragma once
#include <vector>
#include <utility>

/**
 * Louvain-style Surprise maximizer.
 *
 * Key improvements over the pure-Python refine/anneal:
 *   1. Log-factorial precomputation  → O(1) logC evaluation (vs O(n) sumRange)
 *   2. Incremental ΔM / Δp updates  → no full partition scan per move
 *   3. Neighbor-restricted proposals → O(degree) candidates (vs O(k) communities)
 *   4. Community merge pass          → escapes node-level local optima
 *   5. Pre_CS initialization         → common-neighbor seeding (tang2019)
 *   6. Multi-restart                 → global coverage
 *
 * Parameters
 * ----------
 * edges      : undirected edge list (0-based integer node ids)
 * n_nodes    : total number of nodes
 * n_restarts : number of independent optimisation runs (best is returned)
 * seed       : RNG seed (<0 → random device)
 *
 * Returns    : partition vector where partition[i] = community of node i
 */
std::vector<int> louvain_surprise(
    const std::vector<std::pair<int, int>>& edges,
    int n_nodes,
    int n_restarts = 8,
    int seed       = 42
);
