diff --git a/src/best_proximity.rs b/src/best_proximity.rs index bb611044e..192c387f1 100644 --- a/src/best_proximity.rs +++ b/src/best_proximity.rs @@ -44,7 +44,14 @@ impl Node { // TODO we must skip the successors that have already been seen // TODO we must skip the successors that doesn't return any documents // this way we are able to skip entire paths - fn successors(&self, positions: &[Vec], best_proximity: u32) -> Vec<(Node, u32)> { + fn successors( + &self, + positions: &[Vec], + best_proximity: u32, + mut contains_documents: F, + ) -> Vec<(Node, u32)> + where F: FnMut((usize, u32), (usize, u32)) -> bool, + { match self { Node::Uninit => { positions[0].iter().map(|p| { @@ -54,15 +61,18 @@ impl Node { // We reached the highest layer n @ Node::Init { .. } if n.is_complete(positions) => vec![], Node::Init { layer, position, acc_proximity } => { - let layer = layer + 1; - positions[layer].iter().filter_map(|p| { + positions[layer + 1].iter().filter_map(|p| { let proximity = positions_proximity(*position, *p); - let node = Node::Init { layer, position: *p, acc_proximity: acc_proximity + proximity }; - // We do not produce the nodes we have already seen in previous iterations loops. - if node.is_complete(positions) && acc_proximity + proximity < best_proximity { - None + let node = Node::Init { layer: layer + 1, position: *p, acc_proximity: acc_proximity + proximity }; + if (contains_documents)((*layer, *position), (layer + 1, *p)) { + // We do not produce the nodes we have already seen in previous iterations loops. + if node.is_complete(positions) && acc_proximity + proximity < best_proximity { + None + } else { + Some((node, proximity)) + } } else { - Some((node, proximity)) + None } }).collect() } @@ -84,18 +94,21 @@ impl Node { } } -pub struct BestProximity { +pub struct BestProximity { positions: Vec>, best_proximity: u32, + contains_documents: F, } -impl BestProximity { - pub fn new(positions: Vec>) -> BestProximity { - BestProximity { positions, best_proximity: 0 } +impl BestProximity { + pub fn new(positions: Vec>, contains_documents: F) -> BestProximity { + BestProximity { positions, best_proximity: 0, contains_documents } } } -impl Iterator for BestProximity { +impl Iterator for BestProximity +where F: FnMut((usize, u32), (usize, u32)) -> bool + Copy, +{ type Item = (u32, Vec>); fn next(&mut self) -> Option { @@ -107,7 +120,7 @@ impl Iterator for BestProximity { let result = astar_bag( &Node::Uninit, // start - |n| n.successors(&self.positions, self.best_proximity), + |n| n.successors(&self.positions, self.best_proximity, self.contains_documents), |_| 0, // heuristic |n| n.is_complete(&self.positions), // success ); @@ -142,7 +155,7 @@ mod tests { vec![ 1, ], vec![ 3, 6], ]; - let mut iter = BestProximity::new(positions); + let mut iter = BestProximity::new(positions, |_, _| true); assert_eq!(iter.next(), Some((1+2, vec![vec![0, 1, 3]]))); // 3 assert_eq!(iter.next(), Some((2+2, vec![vec![2, 1, 3]]))); // 4 @@ -161,7 +174,7 @@ mod tests { vec![ 1, 1000, 2001 ], vec![ 3, 6, 2002, 3000], ]; - let mut iter = BestProximity::new(positions); + let mut iter = BestProximity::new(positions, |_, _| true); assert_eq!(iter.next(), Some((1+1, vec![vec![2000, 2001, 2002]]))); // 2 assert_eq!(iter.next(), Some((1+2, vec![vec![0, 1, 3]]))); // 3 diff --git a/src/lib.rs b/src/lib.rs index 5e2c6192a..6918eccda 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -119,7 +119,7 @@ impl Index { let mut documents = Vec::new(); - for (proximity, mut positions) in BestProximity::new(positions) { + for (proximity, mut positions) in BestProximity::new(positions, |_, _| true) { // TODO we must ignore positions paths that gives nothing if (proximity as usize) < words.len() - 1 { eprintln!("Skipping too short proximities of {}.", proximity);