Explosive-Synchronisation Early-Warning Monitor¶
The monitor.explosive_sync module raises an early warning before a
first-order (explosive) synchronisation transition — the abrupt,
hysteretic collapse to coherence behind power-grid blackouts and seizure
onset. It is the detection layer built on the ordinal-pattern transition
entropy primitive in monitor.opt_entropy.
The monitor is passive: it reads node observables and emits a warning record. It never actuates — consistent with SPO's review-only posture.
1. Why ordinal transition entropy is the right signal¶
Classic critical-slowing-down early-warning signals (rising variance, rising lag-1 autocorrelation; Scheffer et al. 2009) are tuned to continuous (second-order) bifurcations. A first-order synchronisation transition is abrupt and need not slow down before it fires, so variance/autocorrelation react late or not at all.
Ahead of explosive locking, each oscillator's local dynamics instead become
more predictable: the diversity of its ordinal-pattern transitions
contracts. That contraction is visible in the transition entropy H_T (see
monitor.opt_entropy §1.4) well before the
macroscopic order parameter jumps. The monitor watches H_T per node and
fires when it drops a robust margin below its leading baseline.
2. Algorithm¶
Given a node-by-time signal array signals of shape (N, T):
- Slide. Window starts at
0, step, 2·step, …while a fullwindowfits; each yields one analysis window. - Local entropy field. For every window and node, compute
transition_entropy(signals[node, start:start+window], dimension, delay), giving a(W, N)fieldper_node_entropy. The window must be long enough to admit two ordinal transitions:window ≥ (D − 1)·τ + 3. - Aggregate index. Average across nodes to the headline
coherence-regularisation index
entropy_indexof shape(W,). - Baseline fit. Use the leading
n_baseline = max(min_baseline_windows, ⌈baseline_fraction · W⌉)windows. The baseline is summarised by its medianm_0and robust scales_0 = 1.4826 · MAD(a normal-consistent standard-deviation estimate). The scale is floored at1e-12so a perfectly flat baseline does not divide by zero. - Robust drop score. Per window,
robust_z = (entropy_index − m_0) / max(s_0, 1e-12)andrelative_drop = (m_0 − entropy_index) / m_0(zero whenm_0 = 0). - Alarm. A window past the baseline breaches when both
robust_z ≤ −z_thresholdandrelative_drop ≥ drop_threshold. The alarm fires at the first run ofpersistenceconsecutive breaching windows;warning_windowis the start of that run andwarning_sampleits sample index. Requiring two gates (a robust z-score and an absolute fractional drop) and a sustained run suppresses single-window noise.
3. Python API¶
from scpn_phase_orchestrator.monitor.explosive_sync import (
explosive_sync_warning,
ExplosiveSyncWarning,
)
result = explosive_sync_warning(
signals, # (N, T) float array; (T,) is treated as one node
dimension=3,
delay=1,
window=128,
step=16,
baseline_fraction=0.25,
min_baseline_windows=3,
z_threshold=3.0,
drop_threshold=0.1,
persistence=2,
)
if result.warning_triggered:
print("explosive-sync warning at sample", result.warning_sample)
print(result.summary())
ExplosiveSyncWarning is a frozen dataclass carrying the full diagnostic
record: window_starts, entropy_index, the per_node_entropy field,
robust_z, relative_drop, the baseline fit (baseline_median,
baseline_scale, n_baseline_windows), the alarm decision
(warning_triggered, warning_window, warning_sample), and the echoed
parameters. summary() returns a flat scalar dictionary suitable for logging
or metric export. Construction replays the per-node mean, baseline median/MAD,
derived z/drop vectors, window grid, and first sustained threshold breach.
Every array is copied and made read-only before the record is published.
3.1 Input validation¶
signals must be a non-empty finite real one- or two-dimensional array.
Boolean, complex, text-coercible, malformed, and non-finite inputs are rejected
before window arithmetic, while legitimate real numeric-object arrays are
normalised to contiguous float64. window, step, min_baseline_windows,
and persistence must be positive integers;
baseline_fraction must lie in the open interval (0, 1); z_threshold and
drop_threshold must be finite and non-negative; window must fit the series
and admit two ordinal transitions.
4. Choosing parameters¶
| Parameter | Effect | Guidance |
|---|---|---|
window |
Samples per entropy estimate | Long enough for a stable H_T (hundreds of samples for D = 3); shorter reacts faster but is noisier. |
step |
Hop between windows | Smaller step sharpens the lead time at more compute. |
baseline_fraction |
Reference span | Large enough to capture normal variability before any transition. |
z_threshold |
Robust-drop sensitivity | Higher rejects more noise; 3.0 is a conventional 3-σ-equivalent. |
drop_threshold |
Minimum fractional drop | Guards against tiny but statistically sharp drops on a quiet baseline. |
persistence |
Sustained-breach length | ≥ 2 rejects single-window flickers. |
The two gates are complementary: z_threshold catches drops that are large
relative to baseline noise, while drop_threshold requires the drop to be
absolutely meaningful — necessary because a very flat baseline makes the
robust z-score explode on negligible movement.
5. Behaviour (tested)¶
- Fires on a noise→lock transition in the neighbourhood of the switch and
stays silent on stationary noise
(
test_fires_on_regularisation_transition,test_silent_on_stationary_noise). persistencesuppresses flickers — a longer required run never fires earlier than a shorter one (test_persistence_requires_sustained_breach).- A high
drop_thresholdsuppresses the warning even on a real transition (test_high_drop_threshold_suppresses_warning). - The entropy index equals the per-node mean and is bounded in
[0, 1](test_entropy_index_is_node_mean,test_entropy_index_bounded). - A flat baseline does not divide by zero — the scale floor keeps
robust_zfinite (test_zero_scale_does_not_divide_by_zero).
6. Pipeline position¶
signals (N, T) ──▶ explosive_sync_warning ──▶ ExplosiveSyncWarning
│ │ │
│ ▼ ▼
│ transition_entropy warning_triggered
│ (per node, per window) warning_sample
▼ entropy_index / per_node field
any scalar node observable
(phase velocity, sin θ, …)
The monitor consumes any per-node scalar observable (phase velocity, sin θ,
power-injection deviation, …) and emits a warning record for a supervisory or
alerting layer. It has no actuation path of its own.
7. Implementation cross-reference¶
| File | Role |
|---|---|
src/scpn_phase_orchestrator/monitor/explosive_sync.py |
Monitor + ExplosiveSyncWarning |
src/scpn_phase_orchestrator/monitor/opt_entropy.py |
Transition-entropy compute primitive |
tests/test_explosive_sync.py |
Detection, structure, validation, and guard tests |
8. References¶
- Scheffer, M. et al. 2009, Nature 461, 53 — "Early-warning signals for critical transitions" (the slowing-down framework this complements).
- Bandt, C. & Pompe, B. 2002, Phys. Rev. Lett. 88, 174102 — permutation entropy.
- Gómez-Gardeñes, J., Gómez, S., Arenas, A. & Moreno, Y. 2011, Phys. Rev. Lett. 106, 128701 — explosive synchronisation as a first-order transition.
9. API reference¶
explosive_sync ¶
Ordinal-pattern transition-entropy early warning for explosive sync.
A first-order (explosive) synchronisation transition — the abrupt, hysteretic collapse to coherence behind power-grid blackouts and seizure onset — is preceded by a regularisation of each oscillator's local dynamics. That regularisation shows up as a drop in the ordinal-pattern transition entropy of the node's observable before the macroscopic order parameter jumps, where variance / autocorrelation critical-slowing-down indicators are weak.
explosive_sync_warning slides a window across a multi-node signal array,
computes the per-node transition entropy (monitor/opt_entropy.py,
five-backend accelerated), aggregates it into a coherence-regularisation
index, and raises a fail-early alarm when the index drops a robust
(median / MAD) margin below its leading baseline. The monitor is passive:
it reads observables and emits a warning record; it never actuates.
References¶
- Scheffer et al. 2009, Nature 461, 53 — early-warning signals for critical transitions (the slowing-down framework this complements).
- Bandt & Pompe 2002, Phys. Rev. Lett. 88, 174102 — permutation entropy.
- Gómez-Gardeñes, Gómez, Arenas & Moreno 2011, Phys. Rev. Lett. 106, 128701 — explosive synchronisation as a first-order transition.
Classes¶
ExplosiveSyncWarning
dataclass
¶
ExplosiveSyncWarning(
window_starts: IntArray,
entropy_index: FloatArray,
per_node_entropy: FloatArray,
robust_z: FloatArray,
relative_drop: FloatArray,
baseline_median: float,
baseline_scale: float,
n_baseline_windows: int,
warning_triggered: bool,
warning_window: int | None,
warning_sample: int | None,
dimension: int,
delay: int,
window: int,
step: int,
z_threshold: float,
drop_threshold: float,
persistence: int,
)
Result of an explosive-synchronisation early-warning sweep.
Attributes¶
window_starts : IntArray
First sample index of each analysis window, shape (W,).
entropy_index : FloatArray
Mean transition entropy across nodes per window, shape (W,);
the headline coherence-regularisation index.
per_node_entropy : FloatArray
Per-node transition entropy, shape (W, N) — the local field.
robust_z : FloatArray
Median / MAD robust z-score of entropy_index against the
baseline, shape (W,). Strongly negative means a sharp drop.
relative_drop : FloatArray
Fractional drop of entropy_index below the baseline median,
shape (W,).
baseline_median : float
Median entropy index over the leading baseline windows.
baseline_scale : float
Robust scale (1.4826 × MAD) of the baseline windows.
n_baseline_windows : int
Number of leading windows used to fit the baseline.
warning_triggered : bool
Whether a sustained drop crossed both the z and relative-drop gates.
warning_window : int | None
Index of the first window of the triggering run, or None.
warning_sample : int | None
Sample index window_starts[warning_window], or None.
dimension, delay, window, step : int
Echoed analysis parameters.
z_threshold, drop_threshold : float
Echoed alarm gates.
persistence : int
Echoed number of consecutive breaching windows required to alarm.
Methods:¶
summary ¶
Return a flat scalar summary for logging or metric export.
Returns¶
dict[str, float | int | bool | None] Window/baseline counts, the baseline fit, the entropy-index and robust-z extremes, the maximum relative drop, and the alarm verdict.
Source code in src/scpn_phase_orchestrator/monitor/explosive_sync.py
Functions:¶
explosive_sync_warning ¶
explosive_sync_warning(
signals: FloatArray,
*,
dimension: int = DEFAULT_DIMENSION,
delay: int = DEFAULT_DELAY,
window: int = 128,
step: int = 16,
baseline_fraction: float = 0.25,
min_baseline_windows: int = 3,
z_threshold: float = 3.0,
drop_threshold: float = 0.1,
persistence: int = 2,
) -> ExplosiveSyncWarning
Sweep a multi-node signal for an explosive-synchronisation warning.
Parameters¶
signals : FloatArray
Per-node scalar observables (e.g. phase velocity), shape (N, T);
a one-dimensional array is treated as a single node.
dimension, delay : int
Ordinal-pattern embedding dimension D in [2, 7] and positive
delay τ passed to transition_entropy.
window : int
Analysis window length in samples; must admit at least two ordinal
transitions, i.e. window ≥ (D − 1)·τ + 3.
step : int
Hop between consecutive window starts in samples.
baseline_fraction : float
Leading fraction of windows used to fit the baseline, in (0, 1).
min_baseline_windows : int
Lower bound on the number of baseline windows.
z_threshold : float
Robust z-score magnitude below which a window breaches the gate.
drop_threshold : float
Minimum fractional drop below the baseline median to breach the gate.
persistence : int
Number of consecutive breaching windows required to raise the alarm.
Returns¶
ExplosiveSyncWarning The per-window entropy field, baseline fit, and the alarm decision.
Raises¶
ValueError If the inputs are malformed or the window does not fit the series.
Source code in src/scpn_phase_orchestrator/monitor/explosive_sync.py
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 | |