use rand::Rng;
use robust_binary_search::*;
use std::cmp;
use std::env;
use std::error::Error;
use std::fs::File;
use std::io::Write;
use std::process;
fn steps_required<R: Rng>(rng: &mut R, flakiness: f64, stiffness: f64) -> f64 {
let size = 1 << 20;
let mut max = 0;
let count = 100;
for _ in 0..count {
let mut searcher = Searcher::new(size);
let mut i = 0;
let index = (rng.gen::<f64>() * size as f64) as usize;
let max_steps = 1000;
max = cmp::max(
max,
loop {
i += 1;
let test_index = searcher.next_index();
if test_index == index || i == max_steps {
break i;
}
let heads = if rng.gen::<f64>() < flakiness {
rng.gen::<f32>() < 0.5
} else {
test_index >= index
};
searcher.report_with_stiffness(test_index, heads, stiffness);
},
);
}
max as f64
}
fn log_interpolate(index: usize, buckets: usize, min: f64, max: f64) -> f64 {
(min.ln() + index as f64 / buckets as f64 * (max / min).ln()).exp()
}
fn main() -> Result<(), Box<dyn Error>> {
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
println!("Usage: main <output_file>");
process::exit(1);
}
let mut f = File::create(&args[1])?;
let min_flakiness = 0.001;
let max_flakiness = 1.0;
let flakiness_buckets = 50;
let stiffness_buckets = 1000;
let min_stiffness = 0.1;
let max_stiffness = 128.0;
for flakiness_index in 0..flakiness_buckets {
let flakiness = log_interpolate(
flakiness_index,
flakiness_buckets,
min_flakiness,
max_flakiness,
);
let mut rng = rand::thread_rng();
let mut searcher = Searcher::new(stiffness_buckets);
let to_stiffness = |i| log_interpolate(i, stiffness_buckets, min_stiffness, max_stiffness);
let window = 1.5;
for i in 0..1000 {
let test_index = searcher.next_index();
let steps1 = steps_required(&mut rng, flakiness, to_stiffness(test_index) / window);
let steps2 = steps_required(&mut rng, flakiness, to_stiffness(test_index) * window);
let heads = if steps1 < steps2 {
true
} else {
if steps1 > steps2 {
false
} else {
rng.gen::<f32>() < 0.5
}
};
searcher.report(test_index, heads, 0.5);
let lower_bound = searcher.confidence_percentile_ceil(0.1);
let upper_bound = searcher.confidence_percentile_ceil(0.9);
println!(
"{} {} {} {} {} {}",
flakiness,
i,
to_stiffness(test_index),
to_stiffness(lower_bound),
to_stiffness(upper_bound),
searcher.likelihood(searcher.best_index())
);
if lower_bound == upper_bound {
break;
}
}
writeln!(f, "{} {}", flakiness, to_stiffness(searcher.best_index()))?;
f.sync_data()?;
}
Ok(())
}