bayes-shift

    Bayesian online change point detection for streaming numeric data

    bayesian
    changepoint
    streaming
    timeseries
    Download zip
    Author
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    last month
    Downloads
    28

    No dependencies

    #BayesShift

    BayesShift 是一个 MoonBit 的在线变点检测库。它在每次收到新观测值时维护“当前段已经持续多久”的后验分布,并返回该位置开始新段的概率。适合把连续数值或事件计数流接入告警、监控、实验分析和离线评估程序。

    目前提供两套共轭观测模型:

    • 高斯未知均值模型:用于延迟、温度、传感器读数、评分等连续数值;
    • Gamma-Poisson 模型:用于请求量、错误数、事件数等非负整数计数。

    #安装与验证

    项目要求 MoonBit 0.10.14 或更高版本。

    moon fmt moon info moon check --deny-warn moon test --deny-warn moon run cmd moon run cmd/evaluate

    cmd 会运行一段均值突变的可执行示例,并打印每一步的变点概率和最大后验运行长度。 cmd/evaluate 运行固定的标注场景,输出默认、保守和敏感策略的 CSV 评估结果。 持续集成还会在 Linux 上运行 Wasm、WasmGC、JavaScript 和 Native 全目标测试。

    #性能基准

    仓库提供固定的 512 点工作负载:前半段稳定、后半段发生均值或计数率变化,运行长度上限为 64。可使用下面的命令在自己的机器上复测:

    moon bench --release --deny-warn

    基准同时运行高斯和 Gamma-Poisson 检测器。它避免把随机数据生成或输出格式化混入计时,衡量的是完整在线重放路径。CI 会执行该基准以确保性能工作负载持续可运行。

    #最小使用示例

    let model = @shift.GaussianModel::new(0.0, 1.0, 0.25).unwrap()
    let config = @shift.Config::new(0.04, 128, model).unwrap()
    let detector = @shift.Detector::new(config)

    for update in detector.replay([0.0, 0.2, -0.1, 0.0, 5.1, 4.9]).unwrap() {
    println(update.change_probability())
    }

    hazard 是每一步发生新段的先验概率。较小的值会减少告警,较大的值会提高对短段变化的灵敏度。max_run_length 给运行长度后验设上限,限制在线状态量。

    #主要接口

    模块内容
    Detector / GaussianModel连续值 BOCPD、快照恢复、批量重放
    PoissonDetector / PoissonModel计数流 BOCPD
    EventGate概率阈值、最小段长与冷却窗口组成的事件门控
    NumericSeries / TimedSeries输入验证、滚动统计、时间序列规则性检查
    threshold_points / evaluate_hazards阈值和 hazard 网格评估
    evaluate_ewma / evaluate_cusum与 EWMA、CUSUM 基线对照
    diagnose_trace / audit_series后验轨迹诊断、输入质量检查
    gaussian_segments / poisson_segments固定种子的合成实验数据

    #可复现实验

    NumericScenario::mean_shift()、two_shifts() 和 no_change() 是内置确定性场景。ExperimentPlan 固定 hazard、阈值、容忍窗口和随机种子;execute_plan 返回评分、预测边界与轨迹诊断。

    let result = @shift.execute_plan(
    @shift.default_experiment_plan(),
    @shift.NumericScenario::mean_shift(),
    @shift.GaussianModel::new(0.0, 1.0, 0.05).unwrap(),
    ).unwrap()
    println(result.summary())

    边界评分会在给定容忍窗口内一对一匹配预测和真实变点,避免同一真实变点被多个告警重复计为真阳性。

    #工程边界

    本项目关注单变量、顺序到达的变点检测与可复现实验。它不负责持久化时序数据、解析 PCAP、绘图服务或外部告警投递。应用层可以通过 Update.change_probability 和 EventGate 接入自己的存储、界面或通知系统。

    #方法与参考

    高斯和 Poisson 检测器实现 Adams 与 MacKay 在 Bayesian Online Changepoint Detection(2007)描述的运行长度递推,采用对数空间归一化以避免长序列下溢。本仓库以 MoonBit 重新实现,未复制其他项目代码。

    • Adams, R. P. and MacKay, D. J. C. (2007), Bayesian Online Changepoint Detection.
    • 许可证:Apache-2.0,详见 LICENSE。

    完整递推、观测模型、数值稳定策略、截断近似和性能测量方式见 算法说明。

    BaselineExperiment

    pub struct BaselineExperiment {
    detector : String
    scenario : String
    threshold : Double
    score : Score
    alerts : Int
    }

    Comparable result for a baseline detector on one labeled numeric trace.

    BaselineExperiment::f1

    fn BaselineExperiment::f1(self : BaselineExperiment) -> Double

    BaselineExperiment::precision

    fn BaselineExperiment::precision(self : BaselineExperiment) -> Double

    BaselineExperiment::recall

    fn BaselineExperiment::recall(self : BaselineExperiment) -> Double

    Boundary

    pub struct Boundary {
    step : Int
    }

    A labeled boundary position for deterministic detector evaluation.

    Boundary::new

    fn Boundary::new(step : Int) -> Result[Boundary, DetectError]

    BoundaryDelay

    pub struct BoundaryDelay {
    truth_step : Int
    predicted_step : Int?
    delay : Int?
    }

    ChangeEvent

    pub struct ChangeEvent {
    step : Int
    observation : Double
    probability : Double
    prior_run_length : Int
    }

    An event contains the evidence needed by a caller to make an alert decision.

    ChangeEvent::probability

    fn ChangeEvent::probability(self : ChangeEvent) -> Double

    ChangeEvent::step

    fn ChangeEvent::step(self : ChangeEvent) -> Int

    ComparisonRow

    pub struct ComparisonRow {
    detector : DetectorKind
    score : Score
    alert_count : Int
    }

    ComparisonRow::f1

    fn ComparisonRow::f1(self : ComparisonRow) -> Double

    Config

    pub struct Config {
    hazard : Double
    hazard_log : Double
    survival_log : Double
    max_run_length : Int
    model : GaussianModel
    }

    Config::new

    fn Config::new(hazard : Double, max_run_length : Int, model : GaussianModel) -> Result[Config, DetectError]

    CountExperiment

    pub struct CountExperiment {
    scenario : String
    threshold : Double
    score : Score
    maximum_probability : Double
    }

    CountScenario

    pub struct CountScenario {
    name : String
    values : Array[Int]
    boundaries : Array[Boundary]
    }

    Count stream fixture for the Poisson-Gamma model.

    CountScenario::rate_shift

    fn CountScenario::rate_shift() -> CountScenario

    CountUpdate

    pub struct CountUpdate {
    step : Int
    count : Int
    change_probability : Double
    most_likely_run_length : Int
    posterior_rate : Double
    }

    Posterior result for one count observation.

    CountUpdate::change_probability

    fn CountUpdate::change_probability(self : CountUpdate) -> Double

    CountUpdate::most_likely_run_length

    fn CountUpdate::most_likely_run_length(self : CountUpdate) -> Int

    CountUpdate::posterior_rate

    fn CountUpdate::posterior_rate(self : CountUpdate) -> Double

    CountUpdate::step

    fn CountUpdate::step(self : CountUpdate) -> Int

    CurvePoint

    pub struct CurvePoint {
    threshold : Double
    recall : Double
    precision : Double
    false_positive_rate : Double
    }

    CusumConfig

    pub struct CusumConfig {
    reference_mean : Double
    slack : Double
    threshold : Double
    }

    CUSUM is a second deterministic baseline for a known reference mean.

    CusumConfig::new

    fn CusumConfig::new(reference_mean : Double, slack : Double, threshold : Double) -> Result[CusumConfig, DetectError]

    CusumDetector

    pub struct CusumDetector {
    config : CusumConfig
    positive : Double
    negative : Double
    step : Int
    }

    CusumDetector::new

    CusumDetector::update

    fn CusumDetector::update(self : CusumDetector, value : Double) -> Result[CusumUpdate, DetectError]

    CusumUpdate

    pub struct CusumUpdate {
    step : Int
    positive : Double
    negative : Double
    drift : Bool
    }

    DetectError

    pub enum DetectError {
    InvalidHazard
    InvalidVariance
    InvalidPriorStrength
    InvalidRunLengthLimit
    NonFiniteObservation
    }

    DetectedSegment

    pub struct DetectedSegment {
    start_step : Int
    end_step : Int
    size : Int
    mean_observation : Double
    mean_change_probability : Double
    }

    Detector

    pub struct Detector {
    config : Config
    step : Int
    log_posterior : Array[Double]
    counts : Array[Int]
    sums : Array[Double]
    }

    Detector::new

    fn Detector::new(config : Config) -> Detector

    Detector::replay

    fn Detector::replay(self : Detector, observations : Array[Double]) -> Result[Array[Update], DetectError]

    Detector::restore

    fn Detector::restore(self : Detector, snapshot : Snapshot) -> Unit

    Detector::run_length_posterior

    fn Detector::run_length_posterior(self : Detector) -> Array[Double]

    Detector::snapshot

    fn Detector::snapshot(self : Detector) -> Snapshot

    Detector::steps

    fn Detector::steps(self : Detector) -> Int

    Detector::update

    fn Detector::update(self : Detector, observation : Double) -> Result[Update, DetectError]

    DetectorKind

    pub enum DetectorKind {
    Bocpd
    Ewma
    Cusum
    }

    DetectorKind::label

    fn DetectorKind::label(self : DetectorKind) -> String

    EventGate

    pub struct EventGate {
    policy : EventPolicy
    last_emitted_step : Int
    }

    Stateful debounce helper. It never mutates the detector itself.

    EventGate::new

    fn EventGate::new(policy : EventPolicy) -> EventGate

    EventGate::observe

    fn EventGate::observe(self : EventGate, update : Update) -> ChangeEvent?

    Emit at most one event per cooldown interval after a sufficiently long segment.

    EventGate::reset

    fn EventGate::reset(self : EventGate) -> Unit

    Reset only the debounce state, retaining threshold configuration.

    EventPolicy

    pub struct EventPolicy {
    probability_threshold : Double
    minimum_run_length : Int
    cooldown : Int
    }

    A threshold policy turns posterior summaries into application-level events.

    EventPolicy::new

    fn EventPolicy::new(probability_threshold : Double, minimum_run_length : Int, cooldown : Int) -> Result[EventPolicy, DetectError]

    Build a policy without embedding alert transport or side effects in the library.

    EwmaConfig

    pub struct EwmaConfig {
    alpha : Double
    z_threshold : Double
    warmup : Int
    }

    Exponentially weighted moving-average baseline for online drift comparison.

    EwmaConfig::new

    fn EwmaConfig::new(alpha : Double, z_threshold : Double, warmup : Int) -> Result[EwmaConfig, DetectError]

    EwmaDetector

    pub struct EwmaDetector {
    config : EwmaConfig
    step : Int
    mean : Double
    variance : Double
    initialized : Bool
    }

    EwmaDetector::new

    fn EwmaDetector::new(config : EwmaConfig) -> EwmaDetector

    EwmaDetector::replay

    fn EwmaDetector::replay(self : EwmaDetector, values : Array[Double]) -> Result[Array[EwmaUpdate], DetectError]

    EwmaDetector::update

    fn EwmaDetector::update(self : EwmaDetector, value : Double) -> Result[EwmaUpdate, DetectError]

    Update the EWMA mean and variance before comparing the new point to its prior state.

    EwmaUpdate

    pub struct EwmaUpdate {
    step : Int
    value : Double
    mean : Double
    variance : Double
    z : Double
    drift : Bool
    }

    ExperimentPlan

    pub struct ExperimentPlan {
    name : String
    hazard : Double
    max_run_length : Int
    threshold : Double
    tolerance : Int
    seed : Int
    }

    Immutable plan for one reproducible Gaussian BOCPD evaluation.

    ExperimentPlan::describe

    fn ExperimentPlan::describe(self : ExperimentPlan) -> String

    ExperimentPlan::new

    fn ExperimentPlan::new(name : String, hazard : Double, max_run_length : Int, threshold : Double, tolerance : Int, seed : Int) -> Result[ExperimentPlan, DetectError]

    GaussianModel

    pub struct GaussianModel {
    prior_mean : Double
    prior_strength : Double
    observation_variance : Double
    }

    GaussianModel::new

    fn GaussianModel::new(prior_mean : Double, prior_strength : Double, observation_variance : Double) -> Result[GaussianModel, DetectError]

    HazardPoint

    pub struct HazardPoint {
    hazard : Double
    best_threshold : Double
    best_score : Score
    maximum_probability : Double
    }

    HazardPoint::f1

    fn HazardPoint::f1(self : HazardPoint) -> Double

    NumericExperiment

    pub struct NumericExperiment {
    scenario : String
    hazard : Double
    threshold : Double
    score : Score
    trace : TraceSummary
    }

    A fully specified evaluation result for one detector configuration.

    NumericExperiment::f1

    fn NumericExperiment::f1(self : NumericExperiment) -> Double

    NumericExperiment::false_positives

    fn NumericExperiment::false_positives(self : NumericExperiment) -> Int

    NumericExperiment::true_positives

    fn NumericExperiment::true_positives(self : NumericExperiment) -> Int

    NumericScenario

    pub struct NumericScenario {
    name : String
    values : Array[Double]
    boundaries : Array[Boundary]
    }

    A named numeric fixture and its expected segment boundaries.

    NumericScenario::mean_shift

    fn NumericScenario::mean_shift() -> NumericScenario

    NumericScenario::no_change

    fn NumericScenario::no_change() -> NumericScenario

    NumericScenario::two_shifts

    fn NumericScenario::two_shifts() -> NumericScenario

    NumericSeries

    pub struct NumericSeries {
    values : Array[Double]
    }

    An ordered, validated numeric sequence used by offline evaluators.

    NumericSeries::at

    fn NumericSeries::at(self : NumericSeries, index : Int) -> Double?

    NumericSeries::centered

    fn NumericSeries::centered(self : NumericSeries) -> Result[Array[Double], DetectError]

    NumericSeries::cumulative_sum

    fn NumericSeries::cumulative_sum(self : NumericSeries) -> Array[Double]

    NumericSeries::difference

    fn NumericSeries::difference(self : NumericSeries) -> Array[Double]

    NumericSeries::first

    fn NumericSeries::first(self : NumericSeries) -> Double

    NumericSeries::last

    fn NumericSeries::last(self : NumericSeries) -> Double

    NumericSeries::length

    fn NumericSeries::length(self : NumericSeries) -> Int

    NumericSeries::moving_means

    fn NumericSeries::moving_means(self : NumericSeries, width : Int) -> Result[Array[Double], DetectError]

    NumericSeries::moving_ranges

    fn NumericSeries::moving_ranges(self : NumericSeries, width : Int) -> Result[Array[Double], DetectError]

    NumericSeries::new

    fn NumericSeries::new(values : Array[Double]) -> Result[NumericSeries, DetectError]

    NumericSeries::rank_indices

    fn NumericSeries::rank_indices(self : NumericSeries) -> Array[Int]

    NumericSeries::split

    fn NumericSeries::split(self : NumericSeries, width : Int) -> Result[Array[NumericSeries], DetectError]

    NumericSeries::standardized

    fn NumericSeries::standardized(self : NumericSeries) -> Result[Array[Double], DetectError]

    NumericSeries::subseries

    fn NumericSeries::subseries(self : NumericSeries, start : Int, finish : Int) -> Result[NumericSeries, DetectError]

    NumericSeries::values

    fn NumericSeries::values(self : NumericSeries) -> Array[Double]

    OnlineStats

    pub struct OnlineStats {
    count : Int
    average : Double
    sum_of_squares : Double
    minimum_value : Double?
    maximum_value : Double?
    }

    Welford running statistics for a single numeric stream.

    OnlineStats::copy

    fn OnlineStats::copy(self : OnlineStats) -> OnlineStats

    OnlineStats::count

    fn OnlineStats::count(self : OnlineStats) -> Int

    OnlineStats::maximum

    fn OnlineStats::maximum(self : OnlineStats) -> Double?

    OnlineStats::mean

    fn OnlineStats::mean(self : OnlineStats) -> Double?

    OnlineStats::merge

    fn OnlineStats::merge(self : OnlineStats, other : OnlineStats) -> OnlineStats

    OnlineStats::minimum

    fn OnlineStats::minimum(self : OnlineStats) -> Double?

    OnlineStats::new

    OnlineStats::population_variance

    fn OnlineStats::population_variance(self : OnlineStats) -> Double?

    OnlineStats::push

    fn OnlineStats::push(self : OnlineStats, value : Double) -> Result[Unit, DetectError]

    OnlineStats::push_all

    fn OnlineStats::push_all(self : OnlineStats, values : Array[Double]) -> Result[Unit, DetectError]

    OnlineStats::reset

    fn OnlineStats::reset(self : OnlineStats) -> Unit

    OnlineStats::sample_variance

    fn OnlineStats::sample_variance(self : OnlineStats) -> Double?

    OnlineStats::z_score

    fn OnlineStats::z_score(self : OnlineStats, value : Double) -> Result[Double, DetectError]

    ParkMiller

    pub struct ParkMiller {
    state : Int
    }

    A small deterministic PRNG used only for reproducible fixtures and examples.

    ParkMiller::new

    fn ParkMiller::new(seed : Int) -> Result[ParkMiller, DetectError]

    ParkMiller::next_unit

    fn ParkMiller::next_unit(self : ParkMiller) -> Double

    PlanResult

    pub struct PlanResult {
    plan : ExperimentPlan
    experiment : NumericExperiment
    diagnostics : TraceDiagnostics
    predictions : Array[Boundary]
    }

    PlanResult::summary

    fn PlanResult::summary(self : PlanResult) -> String

    PoissonConfig

    pub struct PoissonConfig {
    hazard : Double
    hazard_log : Double
    survival_log : Double
    max_run_length : Int
    model : PoissonModel
    }

    Bounded BOCPD configuration for non-negative integer observations.

    PoissonConfig::new

    fn PoissonConfig::new(hazard : Double, max_run_length : Int, model : PoissonModel) -> Result[PoissonConfig, DetectError]

    PoissonDetector

    pub struct PoissonDetector {
    config : PoissonConfig
    step : Int
    log_posterior : Array[Double]
    totals : Array[Int]
    observations : Array[Int]
    }

    Separate detector avoids making numeric and count-model callers pay for an enum dispatch.

    PoissonDetector::new

    PoissonDetector::replay

    fn PoissonDetector::replay(self : PoissonDetector, values : Array[Int]) -> Result[Array[CountUpdate], DetectError]

    PoissonDetector::run_length_posterior

    fn PoissonDetector::run_length_posterior(self : PoissonDetector) -> Array[Double]

    PoissonDetector::steps

    fn PoissonDetector::steps(self : PoissonDetector) -> Int

    PoissonDetector::update

    fn PoissonDetector::update(self : PoissonDetector, value : Int) -> Result[CountUpdate, DetectError]

    Update with a non-negative count. The change branch always predicts from the prior.

    PoissonModel

    pub struct PoissonModel {
    prior_shape : Double
    prior_rate : Double
    }

    Conjugate Gamma prior for a Poisson segment rate.

    PoissonModel::new

    fn PoissonModel::new(prior_shape : Double, prior_rate : Double) -> Result[PoissonModel, DetectError]

    ProbabilityHistogram

    pub struct ProbabilityHistogram {
    edges : Array[Double]
    counts : Array[Int]
    }

    ProbabilityHistogram::counts

    ProbabilityHistogram::edges

    fn ProbabilityHistogram::edges(self : ProbabilityHistogram) -> Array[Double]

    ProbabilityHistogram::total

    Quality

    pub struct Quality {
    values : Int
    non_finite : Int
    minimum : Double?
    maximum : Double?
    monotonic_increasing : Bool
    }

    Online quality facts for a numeric sequence.

    ReproducibilityRecord

    pub struct ReproducibilityRecord {
    project : String
    scenario : String
    observation_count : Int
    boundary_count : Int
    plan : String
    }

    ReproducibilityRecord::to_csv

    fn ReproducibilityRecord::to_csv(self : ReproducibilityRecord) -> String

    RunLengthAudit

    pub struct RunLengthAudit {
    observed_steps : Int
    retained_states : Int
    truncation_ratio : Double
    }

    RunningMoments

    pub struct RunningMoments {
    count : Int
    mean_value : Double
    m2 : Double
    m3 : Double
    m4 : Double
    }

    RunningMoments::excess_kurtosis

    fn RunningMoments::excess_kurtosis(self : RunningMoments) -> Double?

    RunningMoments::new

    RunningMoments::push

    fn RunningMoments::push(self : RunningMoments, value : Double) -> Result[Unit, DetectError]

    RunningMoments::skewness

    fn RunningMoments::skewness(self : RunningMoments) -> Double?

    Score

    pub struct Score {
    true_positives : Int
    false_positives : Int
    false_negatives : Int
    mean_delay : Double
    }

    Confusion-matrix counts for boundary matching within a tolerance window.

    Score::f1

    fn Score::f1(self : Score) -> Double

    Score::precision

    fn Score::precision(self : Score) -> Double

    Score::recall

    fn Score::recall(self : Score) -> Double

    SegmentSpec

    pub struct SegmentSpec {
    length : Int
    level : Double
    }

    Description of a constant segment for generated numeric traces.

    SegmentSpec::new

    fn SegmentSpec::new(length : Int, level : Double) -> Result[SegmentSpec, DetectError]

    SeriesAudit

    pub struct SeriesAudit {
    length : Int
    finite_values : Int
    non_finite_values : Int
    repeated_adjacent_values : Int
    increasing_steps : Int
    decreasing_steps : Int
    zero_steps : Int
    minimum : Double?
    maximum : Double?
    }

    Input audit for a numeric stream before it is handed to a detector.

    SeriesAudit::is_constant

    fn SeriesAudit::is_constant(self : SeriesAudit) -> Bool

    SeriesAudit::is_usable

    fn SeriesAudit::is_usable(self : SeriesAudit) -> Bool

    SeriesAudit::monotonic_direction

    fn SeriesAudit::monotonic_direction(self : SeriesAudit) -> String

    SeriesAudit::quality_score

    fn SeriesAudit::quality_score(self : SeriesAudit) -> Int

    SeriesAudit::range

    fn SeriesAudit::range(self : SeriesAudit) -> Double?

    SeriesAudit::recommendation

    fn SeriesAudit::recommendation(self : SeriesAudit) -> String

    SeriesAudit::summary

    fn SeriesAudit::summary(self : SeriesAudit) -> String

    Snapshot

    pub struct Snapshot {
    step : Int
    log_posterior : Array[Double]
    counts : Array[Int]
    sums : Array[Double]
    }

    ThresholdPoint

    pub struct ThresholdPoint {
    threshold : Double
    score : Score
    alerts : Int
    }

    One threshold evaluation point, suitable for CSV output or model selection.

    ThresholdPoint::f1

    fn ThresholdPoint::f1(self : ThresholdPoint) -> Double

    ThresholdPoint::false_positive_rate

    fn ThresholdPoint::false_positive_rate(self : ThresholdPoint, known_negatives : Int) -> Double

    ThresholdPoint::precision

    fn ThresholdPoint::precision(self : ThresholdPoint) -> Double

    ThresholdPoint::recall

    fn ThresholdPoint::recall(self : ThresholdPoint) -> Double

    TimedSeries

    pub struct TimedSeries {
    points : Array[TimedValue]
    }

    TimedSeries::intervals

    fn TimedSeries::intervals(self : TimedSeries) -> Array[Int]

    TimedSeries::is_regular

    fn TimedSeries::is_regular(self : TimedSeries) -> Bool

    TimedSeries::new

    fn TimedSeries::new(points : Array[TimedValue]) -> Result[TimedSeries, DetectError]

    TimedSeries::numeric

    fn TimedSeries::numeric(self : TimedSeries) -> NumericSeries

    TimedSeries::points

    fn TimedSeries::points(self : TimedSeries) -> Array[TimedValue]

    TimedSeries::values

    fn TimedSeries::values(self : TimedSeries) -> Array[Double]

    TimedValue

    pub struct TimedValue {
    time : Int
    value : Double
    }

    TimedValue::new

    fn TimedValue::new(time : Int, value : Double) -> Result[TimedValue, DetectError]

    TraceDiagnostics

    pub struct TraceDiagnostics {
    steps : Int
    mean_change_probability : Double
    maximum_change_probability : Double
    maximum_change_step : Int
    shortest_map_run_length : Int
    longest_map_run_length : Int
    mean_posterior_mean : Double
    }

    TraceDiagnostics::is_spiky

    fn TraceDiagnostics::is_spiky(self : TraceDiagnostics, threshold : Double) -> Result[Bool, DetectError]

    TraceDiagnostics::probability_ratio

    fn TraceDiagnostics::probability_ratio(self : TraceDiagnostics) -> Double

    TraceSummary

    pub struct TraceSummary {
    points : Int
    event_count : Int
    mean_change_probability : Double
    maximum_change_probability : Double
    maximum_step : Int
    final_run_length : Int
    }

    Aggregate diagnostics over a replay trace without changing detector state.

    TraceSummary::event_count

    fn TraceSummary::event_count(self : TraceSummary) -> Int

    TraceSummary::maximum_change_probability

    fn TraceSummary::maximum_change_probability(self : TraceSummary) -> Double

    TraceSummary::maximum_step

    fn TraceSummary::maximum_step(self : TraceSummary) -> Int

    TraceSummary::points

    fn TraceSummary::points(self : TraceSummary) -> Int

    Update

    pub struct Update {
    step : Int
    observation : Double
    change_probability : Double
    most_likely_run_length : Int
    posterior_mean : Double
    retained_run_lengths : Int
    }

    Update::change_probability

    fn Update::change_probability(self : Update) -> Double

    Update::most_likely_run_length

    fn Update::most_likely_run_length(self : Update) -> Int

    Update::step

    fn Update::step(self : Update) -> Int

    Window

    pub struct Window {
    capacity : Int
    storage : Array[Double]
    start : Int
    length : Int
    sum : Double
    sum_squares : Double
    }

    Fixed-capacity numeric window with O(1) mean updates and explicit quality state.

    Window::clear

    fn Window::clear(self : Window) -> Unit

    Window::is_full

    fn Window::is_full(self : Window) -> Bool

    Window::length

    fn Window::length(self : Window) -> Int

    Window::maximum

    fn Window::maximum(self : Window) -> Double?

    Window::mean

    fn Window::mean(self : Window) -> Double?

    Window::minimum

    fn Window::minimum(self : Window) -> Double?

    Window::new

    fn Window::new(capacity : Int) -> Result[Window, DetectError]

    Window::push

    fn Window::push(self : Window, value : Double) -> Result[Unit, DetectError]

    Add one finite value and evict the oldest value after reaching capacity.

    Window::values

    fn Window::values(self : Window) -> Array[Double]

    Window::variance

    fn Window::variance(self : Window) -> Double?

    Population variance; useful for short online windows where a sample correction is not wanted.

    add_normal_noise

    fn add_normal_noise(series : NumericSeries, scale : Double, seed : Int) -> Result[NumericSeries, DetectError]

    add_series

    fn add_series(left : NumericSeries, right : NumericSeries) -> Result[NumericSeries, DetectError]

    area_under_roc

    fn area_under_roc(curve : Array[CurvePoint]) -> Result[Double, DetectError]

    audit_difference

    fn audit_difference(values : Array[Double]) -> Result[SeriesAudit, DetectError]

    audit_run_length_capacity

    fn audit_run_length_capacity(updates : Array[Update], max_run_length : Int) -> Result[RunLengthAudit, DetectError]

    audit_series

    fn audit_series(values : Array[Double]) -> SeriesAudit

    baseline_experiment_csv_header

    fn baseline_experiment_csv_header() -> String

    best_f1_point

    fn best_f1_point(points : Array[ThresholdPoint]) -> Result[ThresholdPoint, DetectError]

    boundary_delays

    fn boundary_delays(truth : Array[Boundary], predicted : Array[Boundary], tolerance : Int) -> Result[Array[BoundaryDelay], DetectError]

    clip_series

    fn clip_series(series : NumericSeries, lower : Double, upper : Double) -> Result[NumericSeries, DetectError]

    compare_default_detectors

    fn compare_default_detectors(scenario : NumericScenario, model : GaussianModel, tolerance : Int) -> Result[Array[ComparisonRow], DetectError]

    concatenate_series

    fn concatenate_series(series : Array[NumericSeries]) -> Result[NumericSeries, DetectError]

    conservative_experiment_plan

    fn conservative_experiment_plan() -> ExperimentPlan

    contamination_mask

    fn contamination_mask(length : Int, probability : Double, seed : Int) -> Result[Array[Bool], DetectError]

    count_update_csv_header

    fn count_update_csv_header() -> String

    count_update_csv_row

    fn count_update_csv_row(update : CountUpdate) -> String

    cusum_boundaries

    fn cusum_boundaries(updates : Array[CusumUpdate]) -> Array[Boundary]

    default_experiment_plan

    fn default_experiment_plan() -> ExperimentPlan

    detected_segments

    fn detected_segments(updates : Array[Update], boundaries : Array[Boundary]) -> Result[Array[DetectedSegment], DetectError]

    detrend_linear

    fn detrend_linear(values : Array[Double]) -> Result[Array[Double], DetectError]

    diagnose_trace

    fn diagnose_trace(updates : Array[Update]) -> Result[TraceDiagnostics, DetectError]

    evaluate_count

    fn evaluate_count(scenario : CountScenario, model : PoissonModel, hazard : Double, max_run_length : Int, threshold : Double, tolerance : Int) -> Result[CountExperiment, DetectError]

    Evaluate a count-rate detector with the same matching rule as numeric BOCPD.

    evaluate_cusum

    fn evaluate_cusum(scenario : NumericScenario, config : CusumConfig, tolerance : Int) -> Result[BaselineExperiment, DetectError]

    evaluate_ewma

    fn evaluate_ewma(scenario : NumericScenario, config : EwmaConfig, tolerance : Int) -> Result[BaselineExperiment, DetectError]

    evaluate_hazards

    fn evaluate_hazards(scenario : NumericScenario, model : GaussianModel, hazards : Array[Double], max_run_length : Int, thresholds : Array[Double], tolerance : Int) -> Result[Array[HazardPoint], DetectError]

    evaluate_numeric

    fn evaluate_numeric(scenario : NumericScenario, model : GaussianModel, hazard : Double, max_run_length : Int, threshold : Double, tolerance : Int) -> Result[NumericExperiment, DetectError]

    Evaluate Gaussian BOCPD against a deterministic labeled scenario.

    ewma_boundaries

    fn ewma_boundaries(updates : Array[EwmaUpdate]) -> Array[Boundary]

    execute_default_plans

    fn execute_default_plans(scenario : NumericScenario, model : GaussianModel) -> Result[Array[PlanResult], DetectError]

    execute_grid

    fn execute_grid(plans : Array[ExperimentPlan], scenario : NumericScenario, model : GaussianModel) -> Result[Array[PlanResult], DetectError]

    execute_plan

    fn execute_plan(plan : ExperimentPlan, scenario : NumericScenario, model : GaussianModel) -> Result[PlanResult, DetectError]

    experiment_csv_header

    fn experiment_csv_header() -> String

    One line intended for reproducible threshold-sweep output.

    experiment_csv_row

    fn experiment_csv_row(experiment : NumericExperiment) -> String

    first_crossing

    fn first_crossing(updates : Array[Update], threshold : Double) -> Update?

    Return the first update whose probability reaches a threshold.

    format_baseline_experiment

    fn format_baseline_experiment(experiment : BaselineExperiment) -> String

    format_count_update

    fn format_count_update(update : CountUpdate) -> String

    format_diagnostics

    fn format_diagnostics(value : TraceDiagnostics) -> String

    format_plan_result

    fn format_plan_result(result : PlanResult) -> String

    format_probability_histogram

    fn format_probability_histogram(histogram : ProbabilityHistogram, width : Int) -> Result[String, DetectError]

    format_score

    fn format_score(score : Score) -> String

    format_update

    fn format_update(update : Update) -> String

    Stable text formatting for a numeric BOCPD update.

    gaussian_segments

    fn gaussian_segments(specs : Array[SegmentSpec], scale : Double, seed : Int) -> Result[NumericSeries, DetectError]

    huber_loss

    fn huber_loss(residual : Double, cutoff : Double) -> Result[Double, DetectError]

    huber_weight

    fn huber_weight(residual : Double, cutoff : Double) -> Result[Double, DetectError]

    inject_spikes

    fn inject_spikes(series : NumericSeries, positions : Array[Int], amount : Double) -> Result[NumericSeries, DetectError]

    inspect_values

    fn inspect_values(values : Array[Double]) -> Quality

    interquartile_range

    fn interquartile_range(values : Array[Double]) -> Result[Double, DetectError]

    linear_ramp

    fn linear_ramp(length : Int, start : Double, finish : Double) -> Result[NumericSeries, DetectError]

    log1mexp

    fn log1mexp(value : Double) -> Result[Double, DetectError]

    log_factorial

    fn log_factorial(value : Int) -> Result[Double, DetectError]

    log_gamma

    fn log_gamma(value : Double) -> Result[Double, DetectError]

    Lanczos approximation for log Gamma on positive arguments.

    log_sum_exp

    fn log_sum_exp(values : Array[Double]) -> Result[Double, DetectError]

    Numerically stable scalar utilities shared by alternative observation models.

    mean

    fn mean(values : Array[Double]) -> Result[Double, DetectError]

    mean_absolute_delay

    fn mean_absolute_delay(delays : Array[BoundaryDelay]) -> Int?

    mean_change_probability

    fn mean_change_probability(updates : Array[Update]) -> Result[Double, DetectError]

    median

    fn median(values : Array[Double]) -> Result[Double, DetectError]

    median_absolute_deviation

    fn median_absolute_deviation(values : Array[Double]) -> Result[Double, DetectError]

    normal_noise

    fn normal_noise(length : Int, center : Double, scale : Double, seed : Int) -> Result[Array[Double], DetectError]

    Box-Muller normal samples, deterministic for a fixed seed.

    piecewise_constant

    fn piecewise_constant(lengths : Array[Int], means : Array[Double], half_width : Double, seed : Int) -> Result[Array[Double], DetectError]

    Generate a piecewise-constant series with deterministic uniform jitter.

    plan_grid

    fn plan_grid(hazards : Array[Double], run_lengths : Array[Int], thresholds : Array[Double], tolerance : Int, seed : Int) -> Result[Array[ExperimentPlan], DetectError]

    plan_result_csv_header

    fn plan_result_csv_header() -> String

    point_at_precision

    fn point_at_precision(points : Array[ThresholdPoint], minimum_precision : Double) -> Result[ThresholdPoint, DetectError]

    poisson_sample

    fn poisson_sample(rate : Double, rng : ParkMiller) -> Result[Int, DetectError]

    poisson_segments

    fn poisson_segments(lengths : Array[Int], rates : Array[Double], seed : Int) -> Result[Array[Int], DetectError]

    posterior_chart

    fn posterior_chart(probabilities : Array[Double], width : Int) -> Result[String, DetectError]

    Render a small posterior chart in run-length order for debugging and demos.

    posterior_entropy

    fn posterior_entropy(probabilities : Array[Double]) -> Result[Double, DetectError]

    Average run-length posterior entropy in bits for a trace of posterior rows.

    posterior_quantile

    fn posterior_quantile(probabilities : Array[Double], quantile : Double) -> Result[Int, DetectError]

    precision_recall_curve

    fn precision_recall_curve(points : Array[ThresholdPoint]) -> Array[CurvePoint]

    predicted_boundaries

    fn predicted_boundaries(updates : Array[Update], threshold : Double) -> Result[Array[Boundary], DetectError]

    Extract candidate boundary positions from a posterior trace.

    probability_bar

    fn probability_bar(probability : Double, width : Int) -> Result[String, DetectError]

    Bounded ASCII bar for console output; NaN is not rendered silently.

    probability_histogram

    fn probability_histogram(updates : Array[Update], bins : Int) -> Result[ProbabilityHistogram, DetectError]

    quantile

    fn quantile(values : Array[Double], probability : Double) -> Result[Double, DetectError]

    rank_comparisons

    fn rank_comparisons(rows : Array[ComparisonRow]) -> Array[ComparisonRow]

    reproducibility_csv_header

    fn reproducibility_csv_header() -> String

    reproducibility_record

    fn reproducibility_record(scenario : NumericScenario, plan : ExperimentPlan) -> ReproducibilityRecord

    robust_scale

    fn robust_scale(values : Array[Double]) -> Result[Double, DetectError]

    robust_z_scores

    fn robust_z_scores(values : Array[Double]) -> Result[Array[Double], DetectError]

    roc_curve

    fn roc_curve(points : Array[ThresholdPoint], negatives : Int) -> Result[Array[CurvePoint], DetectError]

    rolling_median

    fn rolling_median(values : Array[Double], width : Int) -> Result[Array[Double], DetectError]

    sample_variance

    fn sample_variance(values : Array[Double]) -> Result[Double, DetectError]

    score_boundaries

    fn score_boundaries(truth : Array[Boundary], predicted : Array[Boundary], tolerance : Int) -> Result[Score, DetectError]

    Match each truth boundary to at most one closest predicted boundary.

    segment_boundaries

    fn segment_boundaries(specs : Array[SegmentSpec]) -> Array[Boundary]

    segment_boundaries_from_updates

    fn segment_boundaries_from_updates(updates : Array[Update], threshold : Double, cooldown : Int) -> Result[Array[Boundary], DetectError]

    sensitive_experiment_plan

    fn sensitive_experiment_plan() -> ExperimentPlan

    sinusoid

    fn sinusoid(length : Int, center : Double, amplitude : Double, period : Double) -> Result[NumericSeries, DetectError]

    sorted_values

    fn sorted_values(values : Array[Double]) -> Result[Array[Double], DetectError]

    Copy values into ascending order after validating all observations.

    stats_of

    fn stats_of(values : Array[Double]) -> Result[OnlineStats, DetectError]

    summarize

    fn summarize(updates : Array[Update], threshold : Double) -> Result[TraceSummary, DetectError]

    Summarize a trace under a caller-supplied probability threshold.

    sweep_cusum

    fn sweep_cusum(scenario : NumericScenario, reference_mean : Double, slacks : Array[Double], thresholds : Array[Double], tolerance : Int) -> Result[Array[BaselineExperiment], DetectError]

    sweep_ewma

    fn sweep_ewma(scenario : NumericScenario, alphas : Array[Double], z_thresholds : Array[Double], warmup : Int, tolerance : Int) -> Result[Array[BaselineExperiment], DetectError]

    sweep_thresholds

    fn sweep_thresholds(scenario : NumericScenario, model : GaussianModel, hazard : Double, max_run_length : Int, thresholds : Array[Double], tolerance : Int) -> Result[Array[NumericExperiment], DetectError]

    Pick the best threshold by F1; ties prefer the lower threshold.

    theil_sen_slope

    fn theil_sen_slope(values : Array[Double]) -> Result[Double, DetectError]

    threshold_grid

    fn threshold_grid(start : Double, finish : Double, count : Int) -> Result[Array[Double], DetectError]

    threshold_points

    fn threshold_points(updates : Array[Update], truth : Array[Boundary], thresholds : Array[Double], tolerance : Int) -> Result[Array[ThresholdPoint], DetectError]

    trapezoid_area

    fn trapezoid_area(horizontal : Array[Double], vertical : Array[Double]) -> Result[Double, DetectError]

    trimmed_mean

    fn trimmed_mean(values : Array[Double], trim_fraction : Double) -> Result[Double, DetectError]

    uniform_noise

    fn uniform_noise(length : Int, lower : Double, upper : Double, seed : Int) -> Result[Array[Double], DetectError]

    update_csv_header

    fn update_csv_header() -> String

    Stable CSV header for numeric update rows.

    update_csv_row

    fn update_csv_row(update : Update) -> String

    validate_audit

    fn validate_audit(audit : SeriesAudit) -> Result[Unit, DetectError]

    validate_scenario

    fn validate_scenario(scenario : NumericScenario) -> Result[Unit, DetectError]

    winsorize

    fn winsorize(values : Array[Double], lower_probability : Double, upper_probability : Double) -> Result[Array[Double], DetectError]

    z_score

    fn z_score(value : Double, center : Double, variance : Double) -> Result[Double, DetectError]