1313__copyright__ = "Copyright (c) 2026 PySATL project"
1414__license__ = "SPDX-License-Identifier: MIT"
1515
16+ import dataclasses
1617from collections .abc import Sequence
1718from pathlib import Path
1819from typing import Any
2324from pysatl_cpd .benchmark .noreset .noreset_detection_trace import NoResetDetectionTrace
2425from pysatl_cpd .benchmark .noreset .threshold_policy import ThresholdPolicy
2526from pysatl_cpd .benchmark .online_benchmark_runner import OnlineBenchmarkRunner
26- from pysatl_cpd .core .online . ionline_algorithm import OnlineAlgorithm
27+ from pysatl_cpd .core .algorithm_entry import AlgorithmEntry
2728from pysatl_cpd .core .online .online_cpd_solver import OnlineCpdSolver
2829from pysatl_cpd .core .online .online_detection_trace import OnlineDetectionTrace
2930
@@ -32,16 +33,17 @@ class NoResetBenchmarkRunner[ProviderT: LabeledData[Any]](OnlineBenchmarkRunner[
3233 """
3334 Optimised benchmark runner for series with a single change point.
3435
35- For each (algorithm, provider) pair the solver is executed exactly
36+ For each (algorithm entry , provider) pair the solver is executed exactly
3637 once with threshold=inf, producing a full detection function trace.
3738 All threshold evaluations are then simulated by applying a
3839 ThresholdPolicy to that cached trace, avoiding redundant solver runs.
3940 Caching is handled entirely by BenchmarkExecutor.
4041
4142 Parameters
4243 ----------
43- algorithms : Sequence[tuple[OnlineAlgorithm[Any, Any, Any], Sequence[float]]]
44- Sequence of (algorithm, thresholds) pairs to evaluate.
44+ entries : Sequence[AlgorithmEntry]
45+ Sequence of AlgorithmEntry objects containing algorithm, thresholds,
46+ and an optional data transformer.
4547 providers : Sequence[ProviderT]
4648 Labeled data providers to run against.
4749 metrics : dict[str, MultipleRunMetric[NoResetDetectionTrace[Any], ProviderT, Any]]
@@ -54,11 +56,13 @@ class NoResetBenchmarkRunner[ProviderT: LabeledData[Any]](OnlineBenchmarkRunner[
5456 dump_dir : Path | str | None, optional
5557 Directory for caching inf traces via BenchmarkExecutor.
5658 If None, caching is disabled. Default is None.
59+ verbose : bool, default=False
60+ If True, displays progress bars during execution.
5761 """
5862
5963 def __init__ (
6064 self ,
61- algorithms : Sequence [tuple [ OnlineAlgorithm [ Any , Any , Any ], Sequence [ float ] ]],
65+ entries : Sequence [AlgorithmEntry [ Any , Any , Any ]],
6266 providers : Sequence [ProviderT ],
6367 metrics : dict [str , MultipleRunMetric [NoResetDetectionTrace [Any ], ProviderT , Any ]],
6468 solver : OnlineCpdSolver ,
@@ -67,7 +71,7 @@ def __init__(
6771 verbose : bool = False ,
6872 ) -> None :
6973 super ().__init__ (
70- algorithms = algorithms ,
74+ entries = entries ,
7175 providers = providers ,
7276 metrics = metrics ,
7377 solver = solver ,
@@ -76,8 +80,11 @@ def __init__(
7680 )
7781 self ._policy = policy
7882
83+ # Replace all thresholds with inf for initial pre-caching run
84+ inf_entries = [dataclasses .replace (entry , thresholds = [float ("inf" )]) for entry in entries ]
85+
7986 executor : BenchmarkExecutor [Any ] = BenchmarkExecutor (
80- algorithms = [( algorithm , [ float ( "inf" )]) for algorithm , _ in algorithms ] ,
87+ entries = inf_entries ,
8188 providers = list (providers ),
8289 solver = self ._solver ,
8390 dump_dir = self ._dump_dir ,
@@ -86,26 +93,27 @@ def __init__(
8693 self ._inf_trace_cache : dict [tuple [str , int , str ], OnlineDetectionTrace [Any ]] = {}
8794
8895 for record , trace in executor .execute ():
96+ # record.algorithm maps to entry.full_name, hash maps to entry.full_hash
8997 key = (record .algorithm , record .configuration_hash , record .data )
9098 self ._inf_trace_cache [key ] = trace
9199
92100 def _collect_runs (
93101 self ,
94- algorithm : OnlineAlgorithm [Any , Any , Any ],
102+ entry : AlgorithmEntry [Any , Any , Any ],
95103 threshold : float ,
96104 providers : Sequence [ProviderT ],
97105 ) -> list [tuple [NoResetDetectionTrace [Any ], ProviderT ]]:
98106 """
99- Collect NoReset runs for a given algorithm and threshold.
107+ Collect NoReset runs for a given algorithm entry and threshold.
100108
101109 For each provider, retrieves the inf trace via BenchmarkExecutor
102110 and applies the ThresholdPolicy to produce a lightweight
103111 NoResetDetectionTrace.
104112
105113 Parameters
106114 ----------
107- algorithm : OnlineAlgorithm[Any, Any, Any]
108- The algorithm to evaluate.
115+ entry : AlgorithmEntry
116+ The algorithm configuration entry to evaluate.
109117 threshold : float
110118 The detection threshold to simulate.
111119 providers : Sequence[ProviderT]
@@ -119,8 +127,8 @@ def _collect_runs(
119127 if not providers :
120128 return []
121129
122- algo_name = str ( algorithm )
123- config_hash = hash ( algorithm . configuration )
130+ algo_name = entry . full_name
131+ config_hash = entry . full_hash
124132 runs : list [tuple [NoResetDetectionTrace [Any ], ProviderT ]] = []
125133
126134 for provider in providers :
0 commit comments