pub fn upper_bound_on_overall_score(simplicity: f64, coverage: f64, density: f64) -> f64 {
return overall_score(simplicity, coverage, density, 1.0);
}
pub fn overall_score(simplicity: f64, coverage: f64, density: f64, alignment: f64) -> f64 {
return simplicity * 0.35 + coverage * 0.15 + density * 0.3 + alignment * 0.2;
}
pub fn compute_preferred_number_of_labels(available_space: u32, vertical_direction: bool) -> i32 {
let best_spacing = if vertical_direction { 5.6 } else { 15.0 };
let preferred_nr_labels = ((available_space as f32) / best_spacing) as i32;
return std::cmp::max(2, std::cmp::min(20, preferred_nr_labels));
}
pub fn compute_simplicity_score(_labels: &Vec<f64>, i: i32, j: i32, q_len: usize) -> f64 {
return 1.0 - (i as f64) / ((q_len as f64) - 1.0) - ((j as f64) - 1.0);
}
pub fn compute_coverage_score(labels: &Vec<f64>, x_min: f64, x_max: f64) -> f64 {
if labels.len() < 2 {
return 0.0;
}
let l0 = labels.first().unwrap();
let l1 = labels.last().unwrap();
return 1.0
- 5.0 * ((x_max - l1).powf(2.0) + (x_min - l0).powf(2.0)) / ((x_max - x_min).powf(2.0));
}
pub fn compute_density_score(labels: &Vec<f64>, preferred_nr: i32) -> f64 {
let n = labels.len() as f64;
let p = preferred_nr as f64;
return 2.0 - f64::max(n / p, p / n);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn preferred_label_count_smoke_tests() {
compute_preferred_number_of_labels(66, false);
compute_preferred_number_of_labels(21, true);
}
#[test]
fn simplicity_score_of_first_choice_labels_should_be_one() {
let labels = vec![1.0, 2.0, 3.0];
let score = compute_simplicity_score(&labels, 0, 1, 5);
assert!((score - 1.0).abs() < 1e-6);
}
#[test]
fn simplicity_score_of_later_choice_labels_should_be_less_than_one() {
let labels = vec![1.0, 2.0, 3.0];
let score = compute_simplicity_score(&labels, 1, 2, 5);
assert!(score < 0.9);
}
#[test]
fn coverage_score_of_full_cover_labels_should_be_one() {
let labels = vec![1.0, 2.0, 3.0];
let score = compute_coverage_score(&labels, 1.0, 3.0);
assert!((score - 1.0).abs() < 1e-6);
}
#[test]
fn coverage_score_of_partial_cover_labels_should_be_less_than_one() {
let labels = vec![1.0, 2.0, 3.0];
let score = compute_coverage_score(&labels, -1.0, 5.5);
assert!(score < 0.9);
}
#[test]
fn desity_score_of_preferred_count_should_be_one() {
let labels = vec![1.0, 2.0, 3.0];
let score = compute_density_score(&labels, 3);
assert!((score - 1.0).abs() < 1e-6);
}
#[test]
fn desity_score_of_too_few_labels_should_be_less_than_one() {
let labels = vec![1.0, 2.0, 3.0];
let score = compute_density_score(&labels, 5);
assert!(score < 0.9);
}
#[test]
fn desity_score_of_too_many_labels_should_be_less_than_one() {
let labels = vec![1.0, 2.0, 3.0];
let score = compute_density_score(&labels, 2);
assert!(score < 0.9);
}
}