Source code for elbow_helper.multi_criteria

"""Phase M2: the subtractive-sign modified BIC for :func:`elbow_helper.robust_knees`.

Ported from the validated ``research/multiknee/criteria.py`` (see ``ELBOW-en.tex``
section 14 and ``research/multiknee/RESULTS.md`` for the derivation, the
sign-convention ambiguity, and why the subtractive form is the one shipped:
0.85 overall exact-k accuracy and a 0% false-positive rate on flat data,
versus 0.77 and 11% for the literal additive form).

Author
------
Warith Harchaoui, <warith.harchaoui@deraison.ai>
"""

from __future__ import annotations

import numpy as np

from .multi_segmentation import Segmentation

_EPS = 1e-12


[docs] def modified_bic(seg: Segmentation) -> float: """Zhang-Siegmund-inspired modified BIC, subtractive sign convention. ``mBIC = n*ln(sse/n) + 3*m*ln(n) - sum(ln(l_j / n))``, ``m = k`` the number of breakpoints and ``l_j`` the segment lengths. Lower is better. See ``ELBOW-en.tex`` section 18 for the derivation and why the segment-length term is subtracted rather than added. Parameters ---------- seg : Segmentation A candidate segmentation, carrying ``n``, ``sse``, ``k`` and ``segment_lengths``. Returns ------- float The subtractive-sign modified BIC score; lower is better. """ n = seg.n sse = max(seg.sse, _EPS) m = seg.k seg_len_term = sum(np.log(max(ell, 1) / n) for ell in seg.segment_lengths) return float(n * np.log(sse / n) + 3 * m * np.log(n) - seg_len_term)