use crate::{Uncertain, UncertainError};
pub fn evaluate_hypothesis(
uncertain_bool: &Uncertain<bool>,
threshold: f64,
confidence: f64,
epsilon: f64,
max_samples: usize,
initial_sample_index: u64,
) -> Result<bool, UncertainError> {
let alpha_error = 1.0 - confidence; let beta_error = alpha_error;
let a_boundary = (beta_error / (1.0 - alpha_error)).ln();
let b_boundary = ((1.0 - beta_error) / alpha_error).ln();
let p0 = (threshold - epsilon).clamp(0.0, 1.0 - f64::EPSILON); let p1 = (threshold + epsilon).clamp(f64::EPSILON, 1.0);
let mut successes = 0;
let mut samples_drawn = 0;
let batch_size = 10;
while samples_drawn < max_samples {
let current_batch_size = (batch_size).min(max_samples - samples_drawn);
if current_batch_size == 0 {
break;
}
for _ in 0..current_batch_size {
let sample_result =
uncertain_bool.sample_with_index(initial_sample_index + samples_drawn as u64)?; if sample_result {
successes += 1;
}
samples_drawn += 1;
}
let n = samples_drawn as f64;
let x = successes as f64;
let term1 = if p1 > f64::EPSILON && p0 > f64::EPSILON {
(p1 / p0).ln()
} else {
0.0
};
let term2 = if (1.0 - p1) > f64::EPSILON && (1.0 - p0) > f64::EPSILON {
((1.0 - p1) / (1.0 - p0)).ln()
} else {
0.0
};
let llr = x * term1 + (n - x) * term2;
if llr <= a_boundary {
return Ok(false);
} else if llr >= b_boundary {
return Ok(true);
}
}
let final_p = successes as f64 / samples_drawn as f64;
Ok(final_p > threshold)
}