use std::fmt;
pub const DEFAULT_DO_NO_HARM_DELTA: f64 = 1.0e-3;
const EM_DASH: &str = "\u{2014}";
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum CertVerdict {
Fail,
Refine,
Pass,
}
impl CertVerdict {
pub fn tag(self) -> &'static str {
match self {
CertVerdict::Pass => "PASS",
CertVerdict::Refine => "REFINE",
CertVerdict::Fail => "FAIL",
}
}
pub fn is_pass(self) -> bool {
matches!(self, CertVerdict::Pass)
}
}
impl fmt::Display for CertVerdict {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.tag())
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct CertResult {
pub verdict: CertVerdict,
pub value: f64,
pub threshold: f64,
pub margin: f64,
}
impl CertResult {
fn smaller_is_better(value: f64, threshold: f64, slack: f64) -> CertResult {
let margin = threshold - value;
let verdict = if !value.is_finite() || !threshold.is_finite() {
CertVerdict::Fail
} else if value <= threshold * (1.0 - slack) {
CertVerdict::Pass
} else if value <= threshold {
CertVerdict::Refine
} else {
CertVerdict::Fail
};
CertResult { verdict, value, threshold, margin }
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct FrameBounds {
pub a_bound: f64,
pub b_bound: f64,
}
impl FrameBounds {
pub fn new(a_bound: f64, b_bound: f64) -> FrameBounds {
FrameBounds { a_bound, b_bound }
}
pub fn from_ratio(ratio: f64) -> FrameBounds {
FrameBounds { a_bound: 1.0, b_bound: ratio }
}
pub fn ratio(&self) -> f64 {
if self.a_bound > 0.0 {
self.b_bound / self.a_bound
} else {
f64::INFINITY
}
}
}
pub fn frame_ratio_cert(bounds: FrameBounds, tol: f64) -> CertResult {
let excess = (bounds.ratio() - 1.0).abs();
CertResult::smaller_is_better(excess, tol, 0.5)
}
pub fn truncation_bound(rho: f64) -> f64 {
(-0.5 * rho * rho).exp()
}
pub fn truncation_cert(rho: f64, tol: f64) -> CertResult {
let bound = truncation_bound(rho);
CertResult::smaller_is_better(bound, tol, 0.5)
}
pub fn refine_delta(energy_l: f64, energy_l_plus_1: f64) -> f64 {
let gap = (energy_l_plus_1 - energy_l).abs();
let base = energy_l.abs();
if base > 0.0 {
gap / base
} else if gap == 0.0 {
0.0
} else {
f64::INFINITY
}
}
pub fn refine_cert(energy_l: f64, energy_l_plus_1: f64, tol: f64) -> CertResult {
let delta = refine_delta(energy_l, energy_l_plus_1);
CertResult::smaller_is_better(delta, tol, 0.5)
}
pub fn do_no_harm_budget(delta: f64, min_se: f64) -> f64 {
if delta.is_finite() && min_se.is_finite() && delta > 0.0 && min_se > 0.0 {
delta * min_se
} else {
0.0
}
}
pub fn do_no_harm_cert(max_tol: f64, delta: f64, min_se: f64) -> CertResult {
let budget = do_no_harm_budget(delta, min_se);
let margin = budget - max_tol;
let verdict = if !max_tol.is_finite() || budget <= 0.0 {
CertVerdict::Fail
} else if max_tol <= budget {
CertVerdict::Pass
} else {
CertVerdict::Fail
};
CertResult { verdict, value: max_tol, threshold: budget, margin }
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct MeasureJetCertInputs {
pub frame: FrameBounds,
pub truncation_rho: f64,
pub energy_l: f64,
pub energy_l_plus_1: f64,
pub delta: f64,
pub min_se: f64,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct MeasureJetCertBattery {
pub frame: CertResult,
pub truncation: CertResult,
pub refine: CertResult,
pub do_no_harm: CertResult,
pub budget: f64,
}
impl MeasureJetCertBattery {
pub fn assemble(inputs: MeasureJetCertInputs) -> MeasureJetCertBattery {
let budget = do_no_harm_budget(inputs.delta, inputs.min_se);
let frame = frame_ratio_cert(inputs.frame, budget);
let truncation = truncation_cert(inputs.truncation_rho, budget);
let refine = refine_cert(inputs.energy_l, inputs.energy_l_plus_1, budget);
let max_tol = frame
.value
.max(truncation.value)
.max(refine.value);
let do_no_harm = do_no_harm_cert(max_tol, inputs.delta, inputs.min_se);
MeasureJetCertBattery { frame, truncation, refine, do_no_harm, budget }
}
pub fn verdict(&self) -> CertVerdict {
self.frame
.verdict
.min(self.truncation.verdict)
.min(self.refine.verdict)
.min(self.do_no_harm.verdict)
}
pub fn all_pass(&self) -> bool {
self.verdict().is_pass()
}
pub fn report_lines(&self) -> Vec<String> {
let row = |label: &str, r: &CertResult| -> String {
format!(
" {label:<22} value={} threshold={} margin={} [{}]",
fmt_sci(r.value),
fmt_sci(r.threshold),
fmt_sci(r.margin),
r.verdict.tag(),
)
};
vec![
"measure-jet certificate battery (V∞ §7)".to_string(),
format!(" do-no-harm budget δ·min se = {}", fmt_sci(self.budget)),
row("frame ratio B/A", &self.frame),
row("far-field truncation", &self.truncation),
row("refine-one-level", &self.refine),
row("do-no-harm", &self.do_no_harm),
format!(" overall: [{}]", self.verdict().tag()),
]
}
}
impl fmt::Display for MeasureJetCertBattery {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for line in self.report_lines() {
writeln!(f, "{line}")?;
}
Ok(())
}
}
fn fmt_sci(x: f64) -> String {
if x.is_finite() {
format!("{x:.6e}")
} else {
EM_DASH.to_string()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn truncation_bound_matches_closed_form() {
for &rho in &[0.0_f64, 0.5, 1.0, 2.0, 3.0, 4.5] {
let expected = (-0.5 * rho * rho).exp();
let got = truncation_bound(rho);
assert_eq!(got, expected, "rho={rho}");
}
assert_eq!(truncation_bound(0.0), 1.0);
}
#[test]
fn do_no_harm_boundary() {
let delta = 1.0e-3;
let min_se = 2.0;
let budget = do_no_harm_budget(delta, min_se);
assert_eq!(budget, 2.0e-3);
let inside = do_no_harm_cert(budget * 0.5, delta, min_se);
assert_eq!(inside.verdict, CertVerdict::Pass);
assert!(inside.margin > 0.0);
let at = do_no_harm_cert(budget, delta, min_se);
assert_eq!(at.verdict, CertVerdict::Pass);
assert_eq!(at.margin, 0.0);
let over = do_no_harm_cert(budget * (1.0 + 1.0e-9), delta, min_se);
assert_eq!(over.verdict, CertVerdict::Fail);
assert!(over.margin < 0.0);
}
#[test]
fn do_no_harm_degenerate_se_fails() {
let d = DEFAULT_DO_NO_HARM_DELTA;
assert_eq!(do_no_harm_budget(d, 0.0), 0.0);
assert_eq!(do_no_harm_budget(d, -1.0), 0.0);
assert_eq!(do_no_harm_budget(d, f64::NAN), 0.0);
let r = do_no_harm_cert(1.0e-30, d, 0.0);
assert_eq!(r.verdict, CertVerdict::Fail);
}
#[test]
fn refine_delta_monotone_in_gap() {
let base = 4.0_f64;
let gaps = [0.0_f64, 0.1, 0.5, 1.0, 2.0, 10.0];
let mut prev = f64::NEG_INFINITY;
for &g in &gaps {
let d = refine_delta(base, base + g);
assert!(d >= prev, "non-monotone at gap={g}: {d} < {prev}");
prev = d;
}
assert_eq!(refine_delta(4.0, 5.0), 0.25);
assert_eq!(refine_delta(4.0, 3.0), refine_delta(4.0, 5.0));
}
#[test]
fn refine_delta_zero_base() {
assert_eq!(refine_delta(0.0, 0.0), 0.0);
assert_eq!(refine_delta(0.0, 1.0), f64::INFINITY);
}
#[test]
fn frame_ratio_tight_is_zero_excess() {
let tight = FrameBounds::new(1.0, 1.0);
assert_eq!(tight.ratio(), 1.0);
let cert = frame_ratio_cert(tight, 1.0e-3);
assert_eq!(cert.value, 0.0);
assert_eq!(cert.verdict, CertVerdict::Pass);
assert_eq!(FrameBounds::from_ratio(3.0).ratio(), 3.0);
assert!(FrameBounds::new(0.0, 1.0).ratio().is_infinite());
}
#[test]
fn verdict_ordering() {
assert!(CertVerdict::Fail < CertVerdict::Refine);
assert!(CertVerdict::Refine < CertVerdict::Pass);
assert_eq!(
CertVerdict::Pass.min(CertVerdict::Fail),
CertVerdict::Fail
);
}
#[test]
fn battery_all_pass_and_renders() {
let inputs = MeasureJetCertInputs {
frame: FrameBounds::new(1.0, 1.0), truncation_rho: 6.0, energy_l: 1.0,
energy_l_plus_1: 1.0, delta: 1.0, min_se: 1.0e-3, };
let battery = MeasureJetCertBattery::assemble(inputs);
assert!(battery.all_pass(), "battery: {battery}");
assert_eq!(battery.verdict(), CertVerdict::Pass);
let lines = battery.report_lines();
assert!(lines[0].contains("V∞ §7"));
assert!(lines.iter().any(|l| l.contains("frame ratio B/A")));
assert!(lines.iter().any(|l| l.contains("PASS")));
let shown = format!("{battery}");
assert!(shown.contains("do-no-harm"));
}
#[test]
fn battery_fails_on_over_budget_truncation() {
let inputs = MeasureJetCertInputs {
frame: FrameBounds::new(1.0, 1.0),
truncation_rho: 0.5, energy_l: 1.0,
energy_l_plus_1: 1.0,
delta: 1.0e-3,
min_se: 1.0e-3, };
let battery = MeasureJetCertBattery::assemble(inputs);
assert!(!battery.all_pass());
assert_eq!(battery.verdict(), CertVerdict::Fail);
assert_eq!(battery.truncation.verdict, CertVerdict::Fail);
}
}