///|
/// A deterministic benchmark case for regression testing and demonstrations.
pub(all) struct BenchmarkCase {
name : String
scenario : RewardScenario
expected_min_total : Double
expected_max_total : Double
} derive(Debug)
///|
pub fn make_benchmark_case(
name : String,
steps : Array[RewardStep],
expected_min_total : Double,
expected_max_total : Double,
) -> BenchmarkCase {
if steps.length() == 0 || expected_min_total > expected_max_total {
panic()
}
BenchmarkCase::{
name,
scenario: RewardScenario::{ name, steps },
expected_min_total,
expected_max_total,
}
}
///|
pub fn benchmark_cases() -> Array[BenchmarkCase] {
let cases = Array::new()
cases.push(
make_benchmark_case("baseline", sample_scenarios()[0].steps, -10.0, 10.0),
)
cases.push(
make_benchmark_case("sparse-goal", sample_scenarios()[1].steps, -10.0, 10.0),
)
cases.push(
make_benchmark_case(
"control-loop",
sample_scenarios()[2].steps,
-10.0,
10.0,
),
)
let dense = [
RewardStep::{ index: 0, terms: sample_terms(), terminal: false },
RewardStep::{ index: 1, terms: oscillating_terms(), terminal: false },
RewardStep::{ index: 2, terms: sample_terms(), terminal: true },
]
cases.push(make_benchmark_case("dense-progress", dense, -10.0, 10.0))
let failure = [
RewardStep::{ index: 0, terms: sparse_terms(), terminal: false },
RewardStep::{ index: 1, terms: sparse_terms(), terminal: true },
]
cases.push(make_benchmark_case("collision-recovery", failure, -10.0, 10.0))
cases
}
///|
pub fn run_benchmarks(config : RewardConfig) -> Array[TraceSummary] {
let cases = benchmark_cases()
let results = Array::new(capacity=cases.length())
for case in cases {
let (_, summary) = evaluate_trace(case.scenario.steps, config)
if summary.total_clipped < case.expected_min_total ||
summary.total_clipped > case.expected_max_total {
panic()
}
results.push(summary)
}
results
}
///|
pub fn benchmark_report(config : RewardConfig) -> String {
let cases = benchmark_cases()
let summaries = run_benchmarks(config)
let mut text = "Benchmark report (\{config.mode.label()})\n"
for i, case in cases {
let summary = summaries[i]
text = text +
"- \{case.name}: total=\{summary.total_clipped}, span=\{summary.reward_span}, sparse=\{summary.sparse_steps}\n"
}
text
}