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

/**
 * M² (Marin Squared) — fast hybrid Surprise maximizer.
 *
 * Combines three key ideas for speed + quality:
 *
 *   1. FAGSO warm-start        — Jaccard-ranked merging gives a good O(m·log m)
 *                                 initial partition (replaces slow Pre_CS on r=0).
 *   2. Asymptotic Louvain      — Node movements scored with KL-divergence
 *                                 approximation (O(1) per candidate) instead of
 *                                 exact surprise_fast.  Super-node aggregation
 *                                 (from SP4) compresses the graph after each
 *                                 convergence.  NO merge_pass (the main bottleneck
 *                                 of Louvain S v1).
 *   3. Exact refinement        — One final node pass on the original graph using
 *                                 exact surprise_fast to correct any approximation
 *                                 errors from the asymptotic phase.
 *
 * References
 * ----------
 *   - Traag, Aldecoa & Delvenne (2015) — asymptotic Surprise ≈ m·D(q‖⟨q⟩)
 *   - Tang et al. (2019)               — SP4: Pre_CS + aggregation + Post_CS
 *   - Jiang et al. (2014)              — FAGSO: Jaccard-ranked greedy merging
 *
 * 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> m2_surprise(
    const std::vector<std::pair<int, int>>& edges,
    int n_nodes,
    int n_restarts = 4,
    int seed       = 42
);
