use crate::eval::Evaluator;
use crate::ranklist::RankList;
#[derive(Debug, Clone)]
pub struct MAP;
impl Evaluator for MAP {
fn evaluate_ranklist(&self, ranklist: &RankList) -> f32 {
let mut average_precision = 0.0f32;
let mut num_relevant_docs = 0;
for i in 0..ranklist.len() {
match ranklist.get(i) {
Ok(dp) => {
if dp.get_label() > 0 {
num_relevant_docs += 1;
average_precision += num_relevant_docs as f32 / (i as f32 + 1.0);
}
}
Err(_) => {
break;
}
}
}
match num_relevant_docs {
0 => 0.0,
_ => average_precision / num_relevant_docs as f32,
}
}
}
impl ToString for MAP {
fn to_string(&self) -> String {
"MAP".to_string()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::datapoint::DataPoint;
use crate::ranklist::RankList;
use crate::rl;
use crate::utils::random;
use approx::relative_eq;
#[test]
fn test_map() {
let ranklist = rl!(
(0, 9, random::randomize_uniform(0f32, 100f32, 20), "doc1"),
(1, 9, random::randomize_uniform(0f32, 100f32, 20), "doc2"),
(1, 9, random::randomize_uniform(0f32, 100f32, 20), "doc3"),
(0, 9, random::randomize_uniform(0f32, 100f32, 20), "doc4"),
(1, 9, random::randomize_uniform(0f32, 100f32, 20), "doc5"),
(0, 9, random::randomize_uniform(0f32, 100f32, 20), "doc6")
);
let map = MAP;
let map_score = map.evaluate_ranklist(&ranklist);
assert!(relative_eq!(map_score, 0.588, max_relative = 0.01f32));
}
}