use crate::collections::RankedFeatureList;
use crate::dto::{process_threshold_pairs, OptimizationResult};
pub fn optimize(
ranked_feature_list1: &RankedFeatureList,
ranked_feature_list2: &RankedFeatureList,
permute: bool,
population_size: usize,
debug: bool,
) -> OptimizationResult {
let results = process_threshold_pairs(
ranked_feature_list1,
ranked_feature_list2,
permute,
population_size,
debug,
);
if debug {
OptimizationResult::Debug(results)
} else {
let min_pvalue = results
.iter()
.map(|r| r.pvalue)
.fold(f64::INFINITY, f64::min);
let mut best_results: Vec<_> = results
.into_iter()
.filter(|res| res.pvalue == min_pvalue)
.collect();
if best_results.len() > 1 {
eprintln!(
"Multiple results with the same minimum p-value ({:.15}). \
Choosing the result with the largest intersection size.",
min_pvalue
);
let max_intersect = best_results
.iter()
.map(|res| res.intersection_size)
.max()
.unwrap();
best_results.retain(|res| res.intersection_size == max_intersect);
if best_results.len() > 1 {
eprintln!(
"Multiple results with the same maximum intersection size ({}). \
Choosing an arbitrary result based on the order of thresholds.",
max_intersect
);
}
best_results.sort_by_key(|res| (res.rank1, res.rank2));
}
OptimizationResult::Best(best_results.into_iter().next().unwrap())
}
}
#[cfg(test)]
mod tests {
use crate::collections::{Feature, FeatureList, RankedFeatureList};
use crate::dto::{optimize, OptimizationResult};
#[test]
fn test_full_optimization_with_permutation() {
let genes1 = FeatureList::from(vec![
Feature::from("gene1"),
Feature::from("gene2"),
Feature::from("gene3"),
Feature::from("gene4"),
Feature::from("gene5"),
Feature::from("gene6"),
Feature::from("gene7"),
Feature::from("gene8"),
Feature::from("gene9"),
Feature::from("gene10"),
]);
let ranks1 = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let ranked1 = RankedFeatureList::from(genes1, ranks1).unwrap();
let genes2 = FeatureList::from(vec![
Feature::from("gene7"),
Feature::from("gene3"),
Feature::from("gene9"),
Feature::from("gene1"),
Feature::from("gene5"),
Feature::from("gene10"),
Feature::from("gene4"),
Feature::from("gene8"),
Feature::from("gene6"),
Feature::from("gene2"),
]);
let ranks2 = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let ranked2 = RankedFeatureList::from(genes2, ranks2).unwrap();
let population_size: usize = 10;
let result = optimize(&ranked1, &ranked2, false, population_size, false);
assert!(matches!(result, OptimizationResult::Best(_)));
if let OptimizationResult::Best(best) = result {
assert_eq!(best.rank1, 3);
assert_eq!(best.rank2, 4);
assert_eq!(best.pvalue, 0.33333333333333337);
println!(
"Best result: Rank1 {}, Rank2 {}, P-value {}",
best.rank1, best.rank2, best.pvalue
);
}
let result_permuted = optimize(&ranked1, &ranked2, true, population_size, false);
assert!(matches!(result_permuted, OptimizationResult::Best(_)));
if let OptimizationResult::Best(best) = result_permuted {
println!(
"Best result: Rank1 {}, Rank2 {}, P-value {}",
best.rank1, best.rank2, best.pvalue
);
}
}
}