Skip to content

Latest commit

 

History

History
1027 lines (807 loc) · 45.6 KB

monitor.md

File metadata and controls

1027 lines (807 loc) · 45.6 KB

Monitor

The monitor subsystem provides 30+ dynamical observers plus STL runtime monitoring for different aspects of oscillator network behavior. Most oscillator simulators provide only the global order parameter R. SPO's monitors report local coherence, cross-frequency coupling, causal information flow, topological invariants, and thermodynamic irreversibility — phenomena that R alone cannot capture.

Detailed module references:

Hybrid Classical-Quantum Order Parameter

compute_hybrid_entanglement_order_parameter() evaluates local quantum co-simulation evidence only. It combines Kuramoto R/Psi with bipartition Von Neumann entropy, normalised entropy, participation ratio, deterministic record hashing, and the quantum_cosimulation_monitor_not_qpu_execution claim boundary.

The monitor now accepts an explicit simulator_backend contract:

  • numpy_statevector_density_matrix: default compatibility path accepting either statevectors or density matrices.
  • numpy_statevector: requires a one-dimensional statevector payload.
  • numpy_density_matrix: requires a square Hermitian positive-semidefinite density matrix payload representing a pure state. Mixed-state reduced entropy is not promoted as entanglement evidence.

All backends are local NumPy simulators. They do not execute QPU workloads, apply controls, or promote simulator evidence to hardware evidence.

Phase and quantum arrays are validated without text, boolean, or complex-to-real coercion, and malformed array protocols fail at the monitor boundary. Published results independently replay scalar domains, bipartition coverage, entropy normalisation, participation bounds, simulator/no-QPU flags, and the canonical record hash, so direct construction cannot fabricate contradictory audit evidence.

::: scpn_phase_orchestrator.monitor.hybrid_order

Hybrid Order Scenario Fixtures

build_hybrid_order_parameter_scenarios() emits deterministic review fixtures for quantum-simulation, power-grid, and cardiac-rhythm examples. Scenario and candidate records are JSON-safe, non-actuating, execution-disabled, and carry the same no-QPU claim boundary for Studio and audit use.

Fixture entropy is computed from the declared bipartition's Schmidt spectrum, not from computational-basis probabilities. Validation replays each candidate's unit-normalised amplitudes, entropy, phase-derived order metrics, unique identity, and scenario hash; coercive phase aliases cannot enter review evidence.

::: scpn_phase_orchestrator.monitor.hybrid_order_examples

Boundary Observer

Detects when oscillator dynamics violate configured safety/performance boundaries. Fires alerts when R drops below R_good threshold or exceeds R_bad threshold. Used by the supervisor to trigger regime transitions.

::: scpn_phase_orchestrator.monitor.boundaries

Coherence Monitor

Tracks the Kuramoto order parameter R over time with configurable thresholds for phase-lock detection. Provides R_good (target coherence) and R_bad (harmful mode-locking) as dual objectives.

::: scpn_phase_orchestrator.monitor.coherence

Session Start Gate

Verifies that the oscillator network reaches a minimum coherence threshold before the main control loop engages. Prevents the supervisor from acting on transient startup dynamics.

The gate is fail-closed on malformed evidence: phase and imprint vectors must be one-dimensional real numeric arrays with finite entries and the expected oscillator count, the imprint vector must be non-negative, and every extractor record must be a PhaseState whose quality is a finite real in [0, 1] and whose amplitude is a finite, non-negative real. Amplitudes weight the per-channel quality score, so a non-finite amplitude would otherwise make the score NaN and silently drop the low-quality warning. Python and NumPy reals are accepted; booleans, complex values, text and other objects are not. A session with no extractor records fails as a signal collapse. Any violation is recorded as a report error and fails the gate; an invalid n_osc (a Python or NumPy integer, not a boolean) raises instead of reporting.

::: scpn_phase_orchestrator.monitor.session_start

Merge Window Monitor

MergeWindowMonitor is the PHA-C.4 gate for moving-frame runs where phase lock and axial position lock must both hold before a merge is accepted. It computes wrapped phase dispersion around theta_ref, axial spatial dispersion around z_ref, and a consecutive joint-lock counter. The monitor reports lock_achieved=True only after the configured number of consecutive samples passes both predicates.

See the Merge Window reference for the contract, use cases, and benchmark command.

::: scpn_phase_orchestrator.monitor.merge_window

Signal Temporal Logic Runtime Verification

STLMonitor evaluates runtime safety formulas over scalar monitor traces. It uses rtamt when available for full STL syntax and includes a builtin robustness evaluator for common safety forms:

  • always (R >= 0.3)
  • eventually (R >= 0.8)
  • always (R >= 0.85 and amplitude_spread < 0.2)
  • always[0,20] (R >= 0.3) — bounded, holds over the next 20 steps
  • eventually[0,50] (R >= 0.8) — bounded, holds within the next 50 steps

The bounded operators always[a,b] / eventually[a,b] take an integer discrete step window (0 <= a <= b) and reduce the pointwise robustness over that window at the initial time, clamped to the trace end — the value matches what rtamt reports at time zero, so the result is identical whether or not rtamt is installed. A window that starts past the trace end is a vacuous quantifier: always yields +inf and eventually yields -inf. until, nested temporal operators, and other syntax still require the optional rtamt backend and raise a clear ImportError when it is absent.

Positive robustness means the formula is satisfied; negative robustness means violated. Zero robustness does not decide a strict predicate, so the builtin backend reports satisfied from the predicates with their own operators: always (R > 0.3) over R = [0.3, 0.5] has robustness 0 and is not satisfied, while always (R >= 0.3) over the same trace is. The automaton and controller synthesis use the same reading. The rtamt backend returns robustness only, so an rtamt result is satisfied only when its robustness is strictly positive. For syntax that goes to rtamt, the reported robustness is the minimum of the robustness rtamt returns at every time step, so the formula must hold from every step, not only from time zero. evaluate_result() returns an audit-ready result with the formula, robustness, satisfaction boolean, and backend name.

Predicate thresholds may be written as integers, decimals (0.5, .5, 5.) or in exponent form (5e-1); a threshold that overflows to infinity, such as 1e999, is rejected when the monitor is built. Parse and evaluation failures inside rtamt (syntax errors, a signal missing from the trace, unknown functions) are raised as ValueError.

Trace signals are validated at the public boundary before builtin evaluation, rtamt handoff, automaton synthesis, controller synthesis, or closed-loop planning. Each signal must be a one-dimensional, finite, real-valued numeric sequence with no boolean aliases; complex/object-complex payloads and NaN/Inf samples are rejected because they do not define ordered STL predicate robustness.

from scpn_phase_orchestrator.monitor.stl import STLMonitor

monitor = STLMonitor("always (R >= 0.3)")
result = monitor.evaluate_result({"R": [0.9, 0.8, 0.6]})
assert result.satisfied

synthesise_stl_monitoring_automaton() converts supported builtin formulas into an audit-ready runtime automaton. The automaton records the state sequence, trace-indexed transitions, first violation or satisfaction index, pointwise robustness margins, and final satisfaction result.

from scpn_phase_orchestrator.monitor.stl import (
    synthesise_stl_monitoring_automaton,
)

automaton = synthesise_stl_monitoring_automaton(
    "always (R >= 0.3)",
    {"R": [0.9, 0.2, 0.6]},
)
audit_payload = automaton.to_audit_record()
assert audit_payload["states"][1]["first_hit_index"] == 1

Policy YAML integration is available through load_policy_stl_specs(), evaluate_policy_stl_specs(), and synthesise_policy_stl_automata() in scpn_phase_orchestrator.supervisor.policy_rules. This keeps STL specification loading in the policy DSL while preserving STLMonitor and the automata synthesizer as runtime evaluators.

synthesise_stl_controller_candidates() adds the first controller-synthesis linkage. It consumes a builtin STL automaton plus the same trace and emits non-actuating signal-level candidates for the weakest violated predicate. The result is an audit/review artefact only: actuating is always False, and callers must still pass any candidate through policy, projection, safety, and actuation gates.

from scpn_phase_orchestrator.monitor.stl import (
    synthesise_stl_controller_candidates,
)

synthesis = synthesise_stl_controller_candidates(
    automaton,
    {"R": [0.9, 0.2, 0.6]},
    action_map={"R": "raise_coupling"},
)
audit_payload = synthesis.to_audit_record()
assert audit_payload["actuating"] is False

project_stl_controller_candidates() then maps those candidates through explicit policy-approved projection templates and the standard ActionProjector. It still returns a review plan only: actuating remains False, unmapped candidates are rejected with reasons, and the approved entries are bounded ControlAction proposals rather than applied commands.

from scpn_phase_orchestrator.monitor.stl import (
    STLActionProjectionTemplate,
    project_stl_controller_candidates,
)

plan = project_stl_controller_candidates(
    synthesis,
    (
        STLActionProjectionTemplate(
            action="raise_coupling",
            knob="K",
            scope="global",
            base_value=0.9,
            step=10.0,
            ttl_s=0.5,
            previous_value=0.9,
            value_bounds=(0.0, 1.0),
            rate_limit=0.05,
        ),
    ),
)
assert plan.to_audit_record()["actuating"] is False

synthesise_stl_closed_loop_plan() now also records a runtime_actuation_gate audit section. The gate routes projected ControlAction proposals through ActuationMapper using the same explicit projection templates, records deterministic actuator-command evidence, and keeps non_actuating plus execution_disabled true. This is the intended use case for STL closed-loop planning: prove that a violated safety formula can be translated into bounded, mapper-valid runtime actions for operator review without enabling live actuation.

from scpn_phase_orchestrator.monitor.stl import (
    synthesise_stl_closed_loop_plan,
)

closed_loop_plan = synthesise_stl_closed_loop_plan(
    automaton,
    {"R": [0.1, 0.2, 0.75]},
    (projection_template,),
    horizon_steps=4,
    action_map={"R": "raise_coupling"},
)
gate = closed_loop_plan.to_audit_record()["runtime_actuation_gate"]
assert gate["execution_disabled"] is True

Curated phase-field specification catalogue

PHASE_FIELD_SPECIFICATIONS is a small, curated catalogue of named single-signal safety properties for Kuramoto-type phase fields — an order-parameter floor, a coupling-gain ceiling, a chimera-index ceiling, a Sakaguchi phase-lag bound, and a winding-stability bound. Each PhaseFieldSpecification renders a builtin-compatible STL formula, so it evaluates without rtamt, and carries a physical rationale plus a soft/hard severity tier. The thresholds are documented engineering defaults, not empirically fitted constants: robustness measures runtime signal margin, it is not a formal proof of correctness. Look one up by name with phase_field_specification() and enumerate the keys with phase_field_specification_names().

from scpn_phase_orchestrator.monitor.stl import phase_field_specification

spec = phase_field_specification("order_parameter_floor")
assert spec.spec == "always (R >= 0.3)"
result = spec.evaluate({"R": [0.9, 0.8, 0.6]})
assert result.satisfied and result.backend == "builtin"

::: scpn_phase_orchestrator.monitor.stl

Chimera State Detection

Phase and coupling measurements reject boolean, text, complex and temporal aliases before conversion, including object-carried temporal values. Numeric object arrays remain supported; backend local-order values obey the same source type contract.

The monitor classifies instantaneous local coherence on directed positive non-self adjacency. Edge amplitudes are unweighted; negative edges do not count. The exact magnitude factorization avoids extreme-angle subtraction overflow. Coherent means R_i > 0.7, incoherent means R_i < 0.3, and the index is the remaining boundary fraction. Those thresholds are implementation choices; a snapshot or a positive boundary fraction does not establish a persistent chimera.

from scpn_phase_orchestrator.monitor.chimera import detect_chimera

state = detect_chimera(phases, knm, backend="python")
# coherent_indices and incoherent_indices: strict threshold populations
# chimera_index: boundary_count / N (zero for an empty population)

A named missing owner raises ImportError; automatic selection uses cached availability in Rust/Mojo/Julia/Go/Python order. Numerical failures propagate. See the complete measurement, runtime and comparison contract. The JAX model uses different adjacency, index and masks.

::: scpn_phase_orchestrator.monitor.chimera

Entrainment Verification Score (EVS)

Detailed documentation: EVS (Entrainment) — detailed reference

Three-criterion battery that distinguishes genuine entrainment (phase-locking to a stimulus) from broadband artifacts. All three criteria must pass for is_entrained=True:

  1. ITPC persistence: Mean inter-trial phase coherence across time points must exceed threshold (default 0.6)
  2. Survival during pause: ITPC must remain elevated after the stimulus stops, proving the oscillator was entrained (not just responding reactively; default threshold 0.4)
  3. Frequency specificity: ITPC at the target frequency divided by ITPC at a control frequency must exceed threshold (default 1.5), proving the locking is frequency-specific

Usage:

from scpn_phase_orchestrator.monitor.evs import EVSMonitor

monitor = EVSMonitor(
    itpc_threshold=0.5,
    persistence_threshold=0.3,
    specificity_threshold=2.0,
)
result = monitor.evaluate(
    phases_trials,        # (n_trials, T) phase matrix
    pause_indices=list(range(500, 600)),
    target_freq=10.0,     # stimulus frequency in Hz
    control_freq=7.0,     # comparison frequency in Hz
)
# result.is_entrained: bool
# result.itpc_value, result.persistence_score, result.specificity_ratio

::: scpn_phase_orchestrator.monitor.evs options: members: - EVSMonitor

EVS rejects coercive phase aliases before ITPC, normalises pause indices to a unique in-range set, and verifies every native specificity score against the canonical NumPy calculation before it can affect the entrainment verdict.

Partial Information Decomposition (PID)

Decomposes the information that two oscillator groups carry about the global synchronisation state into redundancy (information both groups share) and synergy (information available only from the joint observation), with a 5-backend fallback chain (Rust → Mojo → Julia → Go → Python).

Theory: Williams & Beer 2010 (arXiv:1004.2515). Mutual information is a property of a distribution, so the input is a phase history (T, N) (T timesteps, N oscillators). Each timestep is reduced to three circular observables — the global order-parameter phase (target Y) and the two group order-parameter phases (sources A, B) — binned into n_bins phase bins (default 32). With the specific information I_spec(Y=y; S) = Σ_s p(s|y)·log[p(y|s)/p(y)]:

redundancy  I_red = Σ_y p(y)·min( I_spec(Y=y; A), I_spec(Y=y; B) )   # I_min
synergy     I_syn = MI(A,B; Y) − MI(A; Y) − MI(B; Y) + I_red

Each source's unique information is MI(S; Y) − I_red; all components are non-negative and MI(A; Y) = I_red + U_A holds by construction. A single snapshot (T = 1) carries no distributional information, so every component is 0; meaningful decomposition needs T ≥ 2. Histories, group indices, bin counts, and backend scalar outputs are validated as finite real quantities; boolean aliases, numeric-string aliases, complex dtypes, and out-of-range indices are rejected before estimation or backend acceptance.

Usage:

from scpn_phase_orchestrator.monitor.pid import redundancy, synergy

# history: (T, N) phase history; groups are oscillator index sets into N
R = redundancy(history, group_a=[0, 1, 2], group_b=[3, 4, 5])
S = synergy(history, group_a=[0, 1, 2], group_b=[3, 4, 5])

High synergy means the groups carry complementary information — neither alone predicts the target, but together they do. This detects higher-order functional relationships invisible to pairwise PLV. The polyglot parity gate benchmark_pid_polyglot_parity_gate (benchmarks/pid_benchmark.py, wired into benchmarks/reference_suite.py as pid_polyglot) verifies cross-backend parity of the redundancy/synergy estimates and the decomposition contracts (a co-varying source pair has positive synergy; a fully redundant configuration has vanishing synergy).

::: scpn_phase_orchestrator.monitor.pid

Integrated-Information Monitor

Estimates an approximate Phi-style global integration metric from phase trajectories. The monitor builds a pairwise circular mutual-information matrix, evaluates unique bipartitions, and reports the minimum cross-partition information as phi.

This is an engineering proxy for comparing regime traces and writing audit records. It is not an exact IIT quantity and is not a consciousness claim. Phase-series inputs, bin/sample counts, audit scalars, partitions, and pairwise mutual-information matrices are validated as finite real-valued contracts. Boolean aliases, complex dtypes, and object arrays carrying Python or NumPy complex scalar aliases are rejected before circular histogram estimation or audit-record acceptance; numeric text and broken array protocols also fail at the monitor boundary. A directly constructed result independently recomputes total integration, the canonical minimum bipartition, and phi from its pairwise-MI matrix before it can become audit evidence.

Usage:

from scpn_phase_orchestrator.monitor import (
    benchmark_integrated_information_approximations,
    integrated_information,
)

# phase_series: (n_oscillators, n_samples)
result = integrated_information(phase_series, n_bins=16)
record = result.to_audit_record()

benchmark = benchmark_integrated_information_approximations()
benchmark_record = benchmark.to_audit_record()

benchmark_integrated_information_approximations() runs deterministic synthetic calibration cases for independent, modular, phase-lagged chain, noisy locked, and globally locked phase regimes. It is a numerical approximation benchmark, not a hardware performance benchmark; the audit record documents ordering margins and preserves the same engineering-proxy claim boundary. Studio renders those audit records through the public scpn_phase_orchestrator.studio.build_integrated_information_panel() facade, which keeps the monitor passive, requires the explicit engineering-proxy claim boundary, and exposes Phi, normalised Phi, total-integration ranges, and minimum partitions for operator review without enabling actuation or consciousness claims.

::: scpn_phase_orchestrator.monitor.information_integration

Lyapunov Exponent

Real-time estimation of the maximal Lyapunov exponent from phase trajectories. The Lyapunov exponent characterizes the system's sensitivity to initial conditions:

  • λ > 0: chaotic (exponential divergence of nearby trajectories)
  • λ ≈ 0: edge of chaos (critical regime, maximal computational capacity)
  • λ < 0: stable attractor (perturbations decay exponentially)

The "edge of chaos" (λ ≈ 0) is where flexible, high-capacity dynamics operate (PNAS 2022) and where reservoir computing achieves optimal performance (arXiv:2407.16172).

The spectrum surface validates phase/frequency vectors, coupling/lag matrices, and optional backend spectra before float coercion. Boolean aliases, complex aliases, numeric-string aliases, non-finite values, unsorted spectra, and wrong cardinality fail closed before publication.

::: scpn_phase_orchestrator.monitor.lyapunov

Digital-Twin Confidence

Scores how well a running orchestrator tracks its physical or simulated twin from a phase-histogram Jensen–Shannon divergence and an order-parameter Wasserstein-1 distance, calibrated against a nominal baseline into a confidence in [0, 1] plus an operator status. See the dedicated Twin Confidence page for the formalism, the polyglot backend chain, and benchmarks.

The public and direct backend boundaries reject boolean aliases, complex aliases, numeric-string aliases, non-finite payloads, shape mismatches, invalid order-parameter ranges, and backend-output range violations before divergence evidence can feed the operator summary, Prometheus export, Studio panel, or conformal twin-confidence gate.

::: scpn_phase_orchestrator.monitor.twin_confidence

Conformal Twin-Confidence Gate

Wraps the twin-confidence stream in a distribution-free admission gate. From a trusted nominal calibration window it learns a threshold on the composite z-deviation such that nominal ticks stay inside the band with probability 1 − target_miscoverage, then admits a tick only when its score is inside the band. The threshold adapts online by Adaptive Conformal Inference (Gibbs & Candès, 2021) so the long-run empirical miscoverage tracks the target under non-stationarity, and it can be regime-conditioned (a separate band per detected sync / chimera / chaotic regime). The band never extends past the largest nominal calibration score: when the calibration set is too small for the requested level, or a run of misses drives the adaptive miscoverage to zero, the gate uses that score instead of an infinite band, so a tick beyond every nominal sample is always flagged and the coverage guarantee is given up rather than the gate opened. Review-only: a flagged tick signals the twin has drifted beyond its calibrated band and autonomy should narrow. In the generic simulation loop, callers can supply a calibrated gate and deployment-specific twin-confidence source; rejected conformal ticks suppress the current policy action set and are recorded in result/audit surfaces. The default CLI run has no observed-twin feed, so this admission gate is opt-in.

::: scpn_phase_orchestrator.monitor.twin_conformal_gate

Conformal Alarm Streams

Extends the same finite-sample split-conformal calibration to early-warning alarm streams. ConformalAlarmStream learns an alarm threshold from a window of trusted nominal (transition-free) detector scores so that, on exchangeable nominal operation, the probability of a false alarm is bounded by the configured target_false_alarm (the conformal alpha); the guarantee is the marginal split-conformal one and nothing more. It flags an alarm whenever a live score exceeds the threshold, reports the running empirical false-alarm rate over the ticks it is told are nominal, and can adapt the threshold online by Adaptive Conformal Inference (Gibbs & Candès, 2021) when the nominal distribution drifts — consuming only nominal ticks, because an alarm on an event tick is a detection, not a false alarm. It makes no claim about detection power. Review-only: an alarm signals the nominal false-alarm budget was exceeded at a calibrated rate.

Configuration and decision records normalise valid Python/NumPy real scalars to JSON-safe floats and reject boolean or non-finite numeric aliases. Nominal labels must be exact booleans (or None for an unlabelled tick), regime keys must be non-empty text, and direct decision records enforce unit-interval rates, non-negative tick counts, and finite scores before audit serialisation.

from scpn_phase_orchestrator.monitor.conformal_alarm import (
    ConformalAlarmConfig,
    ConformalAlarmStream,
)

stream = ConformalAlarmStream(ConformalAlarmConfig(target_false_alarm=0.1))
stream.calibrate(nominal_scores)          # trusted transition-free window
decision = stream.update(live_score, is_nominal=False)
assert isinstance(decision.alarm, bool)

::: scpn_phase_orchestrator.monitor.conformal_alarm

Entropy Production Rate

Original phase, frequency, coupling and control values must be plain real numbers; temporal, boolean, text and complex aliases are refused before conversion. Real numeric object arrays are supported. Direct Rust calls require contiguous float64 vectors with exact frequency and flattened coupling cardinality, finite controls and a nonnegative timestep. Overflowed dissipation is refused; valid empty networks and zero timesteps retain a zero result.

Measures the thermodynamic irreversibility of the phase dynamics. Higher entropy production means the system is further from equilibrium — it is actively dissipating energy to maintain its current synchronization state.

Theory: For Kuramoto dynamics, entropy production rate is proportional to the mean squared coupling torque. A system at thermal equilibrium (detailed balance) has zero entropy production; a synchronised Kuramoto network actively maintained by coupling has positive entropy production.

The public dispatcher and backend adapters reject boolean aliases, numeric-string aliases, complex/object-complex payloads, non-finite values, shape mismatches, negative timesteps, and negative backend entropy-rate outputs before publishing a dissipation value.

::: scpn_phase_orchestrator.monitor.entropy_prod

Winding Number

Topological invariant counting how many times the phase wraps around the circle [0, 2π) over a time window. The winding number is an integer-valued quantity that is robust to noise and small perturbations.

Usage:

from scpn_phase_orchestrator.monitor.winding import winding_numbers

# phases_history: (T, N) phase trajectory
w = winding_numbers(phases_history)  # (N,) integer winding numbers

Different winding numbers for different oscillators indicate frequency differences; a sudden change in winding number signals a phase slip (loss of synchronization with a specific partner).

Public and direct accelerator contracts reject boolean aliases, numeric-string aliases, complex/object-complex payloads, non-finite phase histories, malformed cardinality, non-integer winding outputs, out-of-bound winding counts, and exact-reference divergence before integer winding evidence reaches reports or benchmark gates.

::: scpn_phase_orchestrator.monitor.winding

Inter-Trial Phase Coherence (ITPC)

Standard neuroscience measure of phase consistency across repeated trials or time windows. ITPC = |mean(exp(i*theta))| computed across trials at each time point.

ITPC = 1: perfect phase alignment across trials (stimulus-locked). ITPC ≈ 0: random phase relationship (no consistent response).

Used by the EVS monitor as one of three entrainment criteria.

::: scpn_phase_orchestrator.monitor.itpc

Phase Transfer Entropy

Directed information-theoretic measure of causal influence between oscillators. Transfer entropy TE(i→j) quantifies how much the past of oscillator i reduces uncertainty about the future of oscillator j, beyond what j's own past provides.

Key property: Unlike PLV (symmetric), transfer entropy is directional — TE(i→j) ≠ TE(j→i) in general. This detects causal coupling direction, not just correlation.

Used by the te_adaptive coupling module to adapt K_ij based on measured causal information flow (Lizier 2012).

::: scpn_phase_orchestrator.monitor.transfer_entropy

Recurrence Quantification Analysis (RQA)

Extracts dynamical invariants from phase trajectories via recurrence plots. RQA is powerful because it works on short, non-stationary time series where spectral methods fail.

Eight measures:

Measure Symbol Meaning
Recurrence rate RR Density of recurrence points
Determinism DET Fraction forming diagonal lines → deterministic dynamics
Average diagonal L Mean diagonal line length → prediction horizon
Max diagonal L_max Inversely related to max Lyapunov exponent
Diagonal entropy ENTR Complexity of deterministic structure
Laminarity LAM Fraction forming vertical lines → laminar states
Trapping time TT Mean time in laminar state
Max vertical V_max Longest laminar episode

Cross-RQA extends this to detect synchronization between two oscillator groups by computing the cross-recurrence matrix.

Usage:

from scpn_phase_orchestrator.monitor.recurrence import rqa, cross_rqa

# Auto-RQA on a single trajectory
result = rqa(trajectory, epsilon=0.3, metric="angular")
print(f"DET={result.determinism:.3f}, LAM={result.laminarity:.3f}")

# Cross-RQA between two oscillator groups
cr = cross_rqa(traj_a, traj_b, epsilon=0.3)
print(f"Cross-DET={cr.determinism:.3f}")

References: Eckmann, Kamphorst & Ruelle 1987; Zbilut & Webber 1992; Marwan et al. 2007, Phys. Reports 438:237-329.

::: scpn_phase_orchestrator.monitor.recurrence

Delay Embedding (Attractor Reconstruction)

Reconstructs the full state-space attractor from a scalar observable using Takens' embedding theorem. This is the prerequisite for computing correlation dimension, Lyapunov exponents from scalar data, and recurrence analysis on scalar measurements.

Three-step procedure:

  1. Optimal delay τ via first minimum of average mutual information (Fraser & Swinney 1986)
  2. Optimal dimension m via False Nearest Neighbors (Kennel, Brown & Abarbanel 1992)
  3. Embedding constructs vectors v(t) = [x(t), x(t-τ), ..., x(t-(m-1)τ)]

Inputs and backend outputs are validated as finite real-valued arrays. Boolean, text, complex and temporal aliases are rejected before the Rust/Mojo/Julia/Go backend chain because Takens delay coordinates, Fraser-Swinney mutual information, and false-nearest-neighbour distances are defined over real scalar observations. Real numeric object samples remain supported. Delay, dimension, histogram and FNN metadata preserve their original integer/real types; the installed Rust ABI also checks finite samples and size products before allocation. The embedding source-type benchmark records actual supported backend contracts and measurement limits. The Mojo subprocess adapter also validates raw stdout cardinality for delay-coordinate rows, mutual-information scalars, and nearest-neighbour distance/index pairs before numeric parsing, so blank-line insertion or missing rows cannot be normalised into a plausible embedding payload.

Usage:

from scpn_phase_orchestrator.monitor.embedding import auto_embed

# Automatic: determines τ and m, then embeds
result = auto_embed(signal)
print(f"τ={result.delay}, m={result.dimension}")
trajectory = result.trajectory  # (T', m) array

# Manual control
from scpn_phase_orchestrator.monitor.embedding import (
    optimal_delay, optimal_dimension, delay_embed,
)
tau = optimal_delay(signal, max_lag=100)
m = optimal_dimension(signal, delay=tau, max_dim=10)
embedded = delay_embed(signal, delay=tau, dimension=m)

References: Takens 1981, Lecture Notes in Mathematics 898:366-381.

::: scpn_phase_orchestrator.monitor.embedding

Psychedelic State Metrics

The psychedelic monitor is a research diagnostic for phase-dispersion simulation inspired by entropic-brain hypotheses. Public Python calls and Go/Julia/Mojo entropy adapters reject boolean aliases, numeric-string aliases, complex phases, object arrays carrying Python or NumPy complex scalar aliases, non-finite phases, invalid bin counts, numeric-string entropy payloads, complex entropy payloads, and invalid coupling-reduction backend matrices before results are accepted. This preserves the circular Shannon entropy and Kuramoto coupling semantics over real-valued phase observations; it is not a clinical, dosage, or actuation interface.

Direct accelerator boundary contract: Go, Julia, and Mojo entropy adapters use one shared float64 validation path before loading shared-library, Julia, or subprocess runtimes. Empty phase samples return zero entropy without requiring optional runtimes, matching the public Python fallback and preserving the Shannon special case for an empty empirical distribution. Direct backend entropy outputs are also revalidated as finite real scalars in the physical interval [0, log(n_bins)] and must not arrive as numeric strings; malformed Mojo raw stdout line counts, blank-line insertion, and non-scalar tokens are rejected before the value reaches downstream monitor logic.

::: scpn_phase_orchestrator.monitor.psychedelic

Fractal Dimension

Estimates the fractal dimension of attractors from embedded trajectories. Two complementary measures:

Correlation dimension D₂ (Grassberger & Procaccia 1983): Counts the fraction of point pairs within distance ε, then extracts the power-law exponent C(ε) ~ ε^D₂. The scaling region is automatically identified as the range with most stable local slopes.

Kaplan-Yorke dimension D_KY (Kaplan & Yorke 1979): Computed from the Lyapunov spectrum as D_KY = j + (Σᵢ₌₁ʲ λᵢ)/|λⱼ₊₁| where j is the largest index with non-negative cumulative sum. The Kaplan-Yorke conjecture equates D_KY to the information dimension.

Usage:

from scpn_phase_orchestrator.monitor.dimension import (
    correlation_dimension, kaplan_yorke_dimension,
)

# From embedded trajectory
result = correlation_dimension(trajectory, n_epsilons=30)
print(f"D2={result.D2:.2f}, scaling={result.scaling_range}")

# From Lyapunov spectrum
from scpn_phase_orchestrator.monitor.lyapunov import lyapunov_spectrum
spec = lyapunov_spectrum(phases, omegas, knm, alpha)
D_KY = kaplan_yorke_dimension(spec)
print(f"D_KY={D_KY:.2f}")

References: Grassberger & Procaccia 1983, Phys. Rev. Lett. 50:346-349; Kaplan & Yorke 1979, Lecture Notes in Mathematics 730:228-237.

::: scpn_phase_orchestrator.monitor.dimension

Poincare Sections

Detects when a trajectory crosses a hyperplane, extracts the crossing points (Poincare map), and computes return time statistics. Return time regularity distinguishes periodic orbits (constant return time) from chaotic ones (fluctuating return times).

Public and direct accelerator contracts reject boolean aliases, numeric-string aliases, complex values, non-finite values, malformed cardinality, and out-of-range crossing counts before section evidence reaches reports. Mojo text output keeps an explicit crossing-count header plus exact raw-line cardinality because stdout is a text transport.

Detailed documentation: Poincare section monitor

Two interfaces:

  • poincare_section(): general hyperplane crossing for any state-space trajectory
  • phase_poincare(): specialized for phase oscillators — detects when one oscillator crosses a reference phase value

Usage:

from scpn_phase_orchestrator.monitor.poincare import (
    poincare_section, phase_poincare,
)

# General hyperplane section
result = poincare_section(trajectory, normal=[1, 0, 0])
print(f"Mean return time: {result.mean_return_time:.1f}")
print(f"Return time std: {result.std_return_time:.3f}")

# Phase-specific section
result = phase_poincare(phases, oscillator_idx=0, section_phase=0.0)

::: scpn_phase_orchestrator.monitor.poincare

Sleep Stage Classifier

AASM sleep staging mapped to the Kuramoto order parameter R. Classifies phases into Wake/N1/N2/N3/REM based on R thresholds and a functional desynchronisation flag. Includes ultradian (~90 min) cycle phase estimation. Detailed documentation: Sleep Staging — detailed reference

::: scpn_phase_orchestrator.monitor.sleep_staging

Hybrid Order Monitoring

Hybrid classical/quantum order-parameter monitors and deterministic example fixtures for review-only cosimulation evidence.

::: scpn_phase_orchestrator.monitor.hybrid_order

::: scpn_phase_orchestrator.monitor.hybrid_order_examples

Information Replay Examples

Domain-specific information replay fixtures for cyber-industrial, infrastructure, and physiology validation paths. Physiology replay records enforce non-actuating audit boundaries, integer sample/bin/oscillator counts, finite non-negative metrics, unit-interval normalised Phi, and minimum partitions free of boolean aliases and object-complex integer aliases before replay corpus relationships are accepted. The corpus is exactly four uniquely named canonical cases with consistent sample/bin geometry; each expected-relationship string is bound to its case and normalised Phi is replayed from Phi and n_bins. Infrastructure replay records apply the same engineering-proxy boundary to power-grid and traffic-corridor replay corpora: sample/bin/oscillator counts are integer-only, metrics are finite real non-negative values, normalised Phi is bounded to the unit interval, and minimum partitions reject boolean aliases plus object-complex integer aliases before the re-synchronisation/recovery ordering contracts are accepted. The corpus is exactly four uniquely named canonical cases with consistent sample/bin geometry; each expected-relationship string is bound to its case and normalised Phi is replayed from Phi and n_bins. Cyber-industrial replay records apply the same boundary to lateral-movement and manufacturing SPC corpora so containment/recovery ordering claims are accepted only after integer-only record counts, finite real metrics, bounded normalised Phi, and minimum partitions free of boolean aliases and object-complex integer aliases pass validation. The corpus is exactly four uniquely named canonical cases with consistent sample/bin geometry; each expected-relationship string is bound to its case and normalised Phi is replayed from Phi and n_bins.

::: scpn_phase_orchestrator.monitor.information_replay_cyber_industrial

::: scpn_phase_orchestrator.monitor.information_replay_infrastructure

::: scpn_phase_orchestrator.monitor.information_replay_physiology

Self-Model Reconfiguration

Self-model error records and review-only reconfiguration examples. Phase, order-signal, and channel-weight evidence must be finite, real, and non-coercive: boolean, complex, numeric-text, arbitrary conversion objects, and broken array protocols fail before discrepancy arithmetic. Channel labels and domain/scenario identifiers are canonical non-empty strings; labels are also unique. Optional order-specific RMSE and max-absolute thresholds are applied independently and retained in the audit record, falling back to the phase thresholds only when omitted.

Frozen SelfModelErrorResult construction is itself an evidence boundary. It replays channel lengths, aggregate and weighted metric equations, threshold decisions, optional order evidence, non-actuation flags, backend/claim identity, and the canonical record hash. A directly constructed contradictory result therefore cannot be serialised as monitor evidence.

Replay-backed reconfiguration proposals preserve the same custody boundary. Direct construction canonicalises phase vectors to read-only finite real arrays and rejects boolean, complex, numeric-text, arbitrary conversion, and broken array-protocol inputs before circular-error arithmetic. Domain, scenario, proposed-action, blocked-field, boolean safety-gate, positive-threshold, and lowercase SHA-256 identities fail closed. Nested proposal evidence must be strict JSON with string keys and finite values.

Replayed scenario records admit exactly the documented schema. Validation recomputes the canonical scenario hash and independently verifies the derived threshold-safety decision and phase-error summary, so an extra unsigned field or tampering with either derived record cannot survive as review evidence. The records remain operator-review-only and execution-disabled.

::: scpn_phase_orchestrator.monitor.self_model

::: scpn_phase_orchestrator.monitor.self_model_examples

Early-Warning Detector Suite

Three complementary passive detectors share one alarm contract — a robust (median / MAD) z-score against a leading baseline, a relative-change gate, and a persistence run — so they can be compared, and fused, at a matched false-alarm rate. Each reads a different moment of an approaching synchronisation transition (a seizure onset, a grid coherence collapse): critical slowing down reads the second-moment variance / autocorrelation rise, rising synchronisation reads the first-moment Kuramoto order-parameter rise, and the ordinal-transition-entropy detector reads a regularisation drop. All are passive — they read observables and emit a warning record; they never actuate. A fair head-to-head (bench/early_warning_leadtime.py) established that the detection is a commodity, so the value is the auditable, sealed early-warning evidence around the alarm, not a claim that any one detector warns earlier.

Explosive-sync signals are non-empty, finite, real, and non-coercive. Its published warning record owns read-only array copies and replays the entropy mean, baseline median/MAD, derived scores, window grid, and sustained-breach decision before summary or metric export.

The three warning detectors, observable bundle and ensemble reject temporal measurement values, including timedelta64 inside object arrays, before float conversion. Window/count controls, scalar gates, sampling rates, member baseline counts and bootstrap seeds retain their original numeric-type checks. Real numeric object samples remain supported; Boolean breach masks remain exact Boolean arrays. The source-type benchmark records real public detector and complete phase-to-ensemble runs, numeric-object parity and kernel-absent/kernel-present environment comparisons. These warning APIs have no direct native counterpart; different NumPy versions and shared host load limit timing comparisons. The underlying ordinal-entropy primitive selected Mojo in the kernel-absent environment and Rust in the kernel-present environment. The measured suite fused scores differ by at most 4.51e-10 on this fixture, while alarm verdicts agree; this is not exact cross-environment output parity.

Critical Slowing Down

Rising variance and lag-one autocorrelation of an observable ahead of a critical transition (Scheffer et al. 2009; Dakos et al. 2012) — the classical early-warning baseline, implemented as a passive windowed monitor. Either a rising variance or a lengthening autocorrelation is a valid warning; requiring both understates the classical method.

::: scpn_phase_orchestrator.monitor.critical_slowing_down

Critical-slowing-down signal ingress requires a non-empty finite real one- or two-dimensional array and rejects boolean, complex, and text-coercible aliases. Multiscale windows are a non-empty integer sequence. Surrogate RNG custody accepts only a non-negative Python/NumPy integer seed, an explicit NumPy Generator, or None; boolean seeds are rejected before bootstrap.

Rising Synchronisation

A sustained rise in the windowed Kuramoto order parameter R(t) = |⟨e^{iθ}⟩|, the first-moment coherence precursor complementary to the slowing-down and entropy indicators.

::: scpn_phase_orchestrator.monitor.synchronisation

Ensemble Fusion

Fuses the suite over one window grid: a weighted rule (weighted mean of the members' oriented z-scores against a scalar threshold, calibratable to a matched false-alarm rate) and a vote rule (at least min_votes members breach their own gate). The gain from fusion must be reported as an improvement in matched-false-alarm lead time, never as a raw detection rate — an OR of the members trivially raises the rate by spending the false-alarm budget.

::: scpn_phase_orchestrator.monitor.ensemble_warning

Each MemberEvidence record owns immutable copies of one non-empty, strictly increasing window grid and aligned finite-real/boolean vectors. Member names are unique, native direction is canonical, and oriented z-scores must equal the native score for rising alarms or its negation for dropping alarms. Weighted fusion does not apply the vote-only quorum upper bound; vote fusion still requires min_votes <= member_count.

Domain-Adaptable Suite

Runs the three members and the weighted fusion over one neutral observable bundle (SuiteObservables: per-node phases, their sin(phase) projection, and the cross-node order parameter), so a scalp-EEG seizure, a grid coherence collapse, and a cardiac arrhythmia are screened by the same suite. Each is a synchronisation transition in a population of coupled oscillators; the only per-domain work is a DomainObservableAdapter that turns that domain's raw signals into the bundle. The suite itself is domain-neutral — it never learns where the observables came from.

::: scpn_phase_orchestrator.monitor.early_warning_suite

SuiteObservables is a coherent evidence bundle, not three independent arrays: phase_field must equal sin(phases) and order_parameter must equal the cross-node Kuramoto magnitude derived from those same phases. Arrays must be finite real and non-coercive; valid numeric-object inputs normalise to contiguous float64. Suite thresholds are prevalidated as a complete mapping of non-negative finite real values before any detector executes.

Original numerical input types

See numerical source types for text, boolean and temporal refusal, numeric-object compatibility and current language measurements.