mirror of
https://github.com/meilisearch/meilisearch.git
synced 2024-11-27 04:25:06 +08:00
Introduce a function to ignore useless paths
This commit is contained in:
parent
d02c5cb023
commit
b9cc6c10af
@ -44,7 +44,14 @@ impl Node {
|
|||||||
// TODO we must skip the successors that have already been seen
|
// TODO we must skip the successors that have already been seen
|
||||||
// TODO we must skip the successors that doesn't return any documents
|
// TODO we must skip the successors that doesn't return any documents
|
||||||
// this way we are able to skip entire paths
|
// this way we are able to skip entire paths
|
||||||
fn successors(&self, positions: &[Vec<u32>], best_proximity: u32) -> Vec<(Node, u32)> {
|
fn successors<F>(
|
||||||
|
&self,
|
||||||
|
positions: &[Vec<u32>],
|
||||||
|
best_proximity: u32,
|
||||||
|
mut contains_documents: F,
|
||||||
|
) -> Vec<(Node, u32)>
|
||||||
|
where F: FnMut((usize, u32), (usize, u32)) -> bool,
|
||||||
|
{
|
||||||
match self {
|
match self {
|
||||||
Node::Uninit => {
|
Node::Uninit => {
|
||||||
positions[0].iter().map(|p| {
|
positions[0].iter().map(|p| {
|
||||||
@ -54,16 +61,19 @@ impl Node {
|
|||||||
// We reached the highest layer
|
// We reached the highest layer
|
||||||
n @ Node::Init { .. } if n.is_complete(positions) => vec![],
|
n @ Node::Init { .. } if n.is_complete(positions) => vec![],
|
||||||
Node::Init { layer, position, acc_proximity } => {
|
Node::Init { layer, position, acc_proximity } => {
|
||||||
let layer = layer + 1;
|
positions[layer + 1].iter().filter_map(|p| {
|
||||||
positions[layer].iter().filter_map(|p| {
|
|
||||||
let proximity = positions_proximity(*position, *p);
|
let proximity = positions_proximity(*position, *p);
|
||||||
let node = Node::Init { layer, position: *p, acc_proximity: acc_proximity + proximity };
|
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.
|
// We do not produce the nodes we have already seen in previous iterations loops.
|
||||||
if node.is_complete(positions) && acc_proximity + proximity < best_proximity {
|
if node.is_complete(positions) && acc_proximity + proximity < best_proximity {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some((node, proximity))
|
Some((node, proximity))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,18 +94,21 @@ impl Node {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BestProximity {
|
pub struct BestProximity<F> {
|
||||||
positions: Vec<Vec<u32>>,
|
positions: Vec<Vec<u32>>,
|
||||||
best_proximity: u32,
|
best_proximity: u32,
|
||||||
|
contains_documents: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BestProximity {
|
impl<F> BestProximity<F> {
|
||||||
pub fn new(positions: Vec<Vec<u32>>) -> BestProximity {
|
pub fn new(positions: Vec<Vec<u32>>, contains_documents: F) -> BestProximity<F> {
|
||||||
BestProximity { positions, best_proximity: 0 }
|
BestProximity { positions, best_proximity: 0, contains_documents }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Iterator for BestProximity {
|
impl<F> Iterator for BestProximity<F>
|
||||||
|
where F: FnMut((usize, u32), (usize, u32)) -> bool + Copy,
|
||||||
|
{
|
||||||
type Item = (u32, Vec<Vec<u32>>);
|
type Item = (u32, Vec<Vec<u32>>);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
@ -107,7 +120,7 @@ impl Iterator for BestProximity {
|
|||||||
|
|
||||||
let result = astar_bag(
|
let result = astar_bag(
|
||||||
&Node::Uninit, // start
|
&Node::Uninit, // start
|
||||||
|n| n.successors(&self.positions, self.best_proximity),
|
|n| n.successors(&self.positions, self.best_proximity, self.contains_documents),
|
||||||
|_| 0, // heuristic
|
|_| 0, // heuristic
|
||||||
|n| n.is_complete(&self.positions), // success
|
|n| n.is_complete(&self.positions), // success
|
||||||
);
|
);
|
||||||
@ -142,7 +155,7 @@ mod tests {
|
|||||||
vec![ 1, ],
|
vec![ 1, ],
|
||||||
vec![ 3, 6],
|
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((1+2, vec![vec![0, 1, 3]]))); // 3
|
||||||
assert_eq!(iter.next(), Some((2+2, vec![vec![2, 1, 3]]))); // 4
|
assert_eq!(iter.next(), Some((2+2, vec![vec![2, 1, 3]]))); // 4
|
||||||
@ -161,7 +174,7 @@ mod tests {
|
|||||||
vec![ 1, 1000, 2001 ],
|
vec![ 1, 1000, 2001 ],
|
||||||
vec![ 3, 6, 2002, 3000],
|
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+1, vec![vec![2000, 2001, 2002]]))); // 2
|
||||||
assert_eq!(iter.next(), Some((1+2, vec![vec![0, 1, 3]]))); // 3
|
assert_eq!(iter.next(), Some((1+2, vec![vec![0, 1, 3]]))); // 3
|
||||||
|
@ -119,7 +119,7 @@ impl Index {
|
|||||||
|
|
||||||
let mut documents = Vec::new();
|
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
|
// TODO we must ignore positions paths that gives nothing
|
||||||
if (proximity as usize) < words.len() - 1 {
|
if (proximity as usize) < words.len() - 1 {
|
||||||
eprintln!("Skipping too short proximities of {}.", proximity);
|
eprintln!("Skipping too short proximities of {}.", proximity);
|
||||||
|
Loading…
Reference in New Issue
Block a user