mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-11-26 14:54:27 +01:00
Simplify graph-based ranking rule impl
This commit is contained in:
parent
dd491320e5
commit
825f742000
@ -88,9 +88,8 @@ pub struct GraphBasedRankingRuleState<G: RankingRuleGraphTrait> {
|
|||||||
conditions_cache: ConditionDocIdsCache<G>,
|
conditions_cache: ConditionDocIdsCache<G>,
|
||||||
/// Cache used to optimistically discard paths that resolve to no documents.
|
/// Cache used to optimistically discard paths that resolve to no documents.
|
||||||
dead_ends_cache: DeadEndsCache<G::Condition>,
|
dead_ends_cache: DeadEndsCache<G::Condition>,
|
||||||
/// A structure giving the list of possible costs from each node to the end node,
|
/// A structure giving the list of possible costs from each node to the end node
|
||||||
/// along with a set of unavoidable edges that must be traversed to achieve that distance.
|
all_distances: MappedInterner<Vec<u16>, QueryNode>,
|
||||||
all_distances: MappedInterner<Vec<(u16, SmallBitmap<G::Condition>)>, QueryNode>,
|
|
||||||
/// An index in the first element of `all_distances`, giving the cost of the next bucket
|
/// An index in the first element of `all_distances`, giving the cost of the next bucket
|
||||||
cur_distance_idx: usize,
|
cur_distance_idx: usize,
|
||||||
}
|
}
|
||||||
@ -108,7 +107,7 @@ impl<'ctx, G: RankingRuleGraphTrait> RankingRule<'ctx, QueryGraph> for GraphBase
|
|||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let graph = RankingRuleGraph::build(ctx, query_graph.clone())?;
|
let graph = RankingRuleGraph::build(ctx, query_graph.clone())?;
|
||||||
let condition_docids_cache = ConditionDocIdsCache::default();
|
let condition_docids_cache = ConditionDocIdsCache::default();
|
||||||
let dead_end_path_cache = DeadEndsCache::new(&graph.conditions_interner);
|
let dead_ends_cache = DeadEndsCache::new(&graph.conditions_interner);
|
||||||
|
|
||||||
// Then pre-compute the cost of all paths from each node to the end node
|
// Then pre-compute the cost of all paths from each node to the end node
|
||||||
let all_distances = graph.initialize_distances_with_necessary_edges();
|
let all_distances = graph.initialize_distances_with_necessary_edges();
|
||||||
@ -116,7 +115,7 @@ impl<'ctx, G: RankingRuleGraphTrait> RankingRule<'ctx, QueryGraph> for GraphBase
|
|||||||
let state = GraphBasedRankingRuleState {
|
let state = GraphBasedRankingRuleState {
|
||||||
graph,
|
graph,
|
||||||
conditions_cache: condition_docids_cache,
|
conditions_cache: condition_docids_cache,
|
||||||
dead_ends_cache: dead_end_path_cache,
|
dead_ends_cache,
|
||||||
all_distances,
|
all_distances,
|
||||||
cur_distance_idx: 0,
|
cur_distance_idx: 0,
|
||||||
};
|
};
|
||||||
@ -149,7 +148,7 @@ impl<'ctx, G: RankingRuleGraphTrait> RankingRule<'ctx, QueryGraph> for GraphBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the cost of the paths to compute
|
// Retrieve the cost of the paths to compute
|
||||||
let (cost, _) =
|
let cost =
|
||||||
state.all_distances.get(state.graph.query_graph.root_node)[state.cur_distance_idx];
|
state.all_distances.get(state.graph.query_graph.root_node)[state.cur_distance_idx];
|
||||||
state.cur_distance_idx += 1;
|
state.cur_distance_idx += 1;
|
||||||
|
|
||||||
@ -158,7 +157,7 @@ impl<'ctx, G: RankingRuleGraphTrait> RankingRule<'ctx, QueryGraph> for GraphBase
|
|||||||
let GraphBasedRankingRuleState {
|
let GraphBasedRankingRuleState {
|
||||||
graph,
|
graph,
|
||||||
conditions_cache: condition_docids_cache,
|
conditions_cache: condition_docids_cache,
|
||||||
dead_ends_cache: dead_end_path_cache,
|
dead_ends_cache,
|
||||||
all_distances,
|
all_distances,
|
||||||
cur_distance_idx: _,
|
cur_distance_idx: _,
|
||||||
} = &mut state;
|
} = &mut state;
|
||||||
@ -174,15 +173,15 @@ impl<'ctx, G: RankingRuleGraphTrait> RankingRule<'ctx, QueryGraph> for GraphBase
|
|||||||
// For each path of the given cost, we will compute its associated
|
// For each path of the given cost, we will compute its associated
|
||||||
// document ids.
|
// document ids.
|
||||||
// In case the path does not resolve to any document id, we try to figure out why
|
// In case the path does not resolve to any document id, we try to figure out why
|
||||||
// and update the `dead_end_path_cache` accordingly.
|
// and update the `dead_ends_cache` accordingly.
|
||||||
// Updating the dead_end_path_cache helps speed up the execution of `visit_paths_of_cost` and reduces
|
// Updating the dead_ends_cache helps speed up the execution of `visit_paths_of_cost` and reduces
|
||||||
// the number of future candidate paths given by that same function.
|
// the number of future candidate paths given by that same function.
|
||||||
graph.visit_paths_of_cost(
|
graph.visit_paths_of_cost(
|
||||||
graph.query_graph.root_node,
|
graph.query_graph.root_node,
|
||||||
cost,
|
cost,
|
||||||
all_distances,
|
all_distances,
|
||||||
dead_end_path_cache,
|
dead_ends_cache,
|
||||||
|path, graph, dead_end_path_cache| {
|
|path, graph, dead_ends_cache| {
|
||||||
if universe.is_empty() {
|
if universe.is_empty() {
|
||||||
return Ok(ControlFlow::Break(()));
|
return Ok(ControlFlow::Break(()));
|
||||||
}
|
}
|
||||||
@ -211,7 +210,7 @@ impl<'ctx, G: RankingRuleGraphTrait> RankingRule<'ctx, QueryGraph> for GraphBase
|
|||||||
// and caches accordingly and skip to the next candidate path.
|
// and caches accordingly and skip to the next candidate path.
|
||||||
if condition_docids.is_empty() {
|
if condition_docids.is_empty() {
|
||||||
// 1. Store in the cache that this edge is empty for this universe
|
// 1. Store in the cache that this edge is empty for this universe
|
||||||
dead_end_path_cache.forbid_condition(latest_condition);
|
dead_ends_cache.forbid_condition(latest_condition);
|
||||||
// 2. remove all the edges with this condition from the ranking rule graph
|
// 2. remove all the edges with this condition from the ranking rule graph
|
||||||
graph.remove_edges_with_condition(latest_condition);
|
graph.remove_edges_with_condition(latest_condition);
|
||||||
// 3. Also remove the entry from the condition_docids_cache, since we don't need it anymore
|
// 3. Also remove the entry from the condition_docids_cache, since we don't need it anymore
|
||||||
@ -226,7 +225,7 @@ impl<'ctx, G: RankingRuleGraphTrait> RankingRule<'ctx, QueryGraph> for GraphBase
|
|||||||
let len_prefix = subpath_docids.len() - 1;
|
let len_prefix = subpath_docids.len() - 1;
|
||||||
// First, we know that this path is empty, and thus any path
|
// First, we know that this path is empty, and thus any path
|
||||||
// that is a superset of it will also be empty.
|
// that is a superset of it will also be empty.
|
||||||
dead_end_path_cache.forbid_condition_after_prefix(
|
dead_ends_cache.forbid_condition_after_prefix(
|
||||||
visited_conditions[..len_prefix].iter().copied(),
|
visited_conditions[..len_prefix].iter().copied(),
|
||||||
latest_condition,
|
latest_condition,
|
||||||
);
|
);
|
||||||
@ -244,7 +243,7 @@ impl<'ctx, G: RankingRuleGraphTrait> RankingRule<'ctx, QueryGraph> for GraphBase
|
|||||||
};
|
};
|
||||||
subprefix.push(*past_condition);
|
subprefix.push(*past_condition);
|
||||||
if condition_docids.is_disjoint(subpath_docids) {
|
if condition_docids.is_disjoint(subpath_docids) {
|
||||||
dead_end_path_cache.forbid_condition_after_prefix(
|
dead_ends_cache.forbid_condition_after_prefix(
|
||||||
subprefix.iter().copied(),
|
subprefix.iter().copied(),
|
||||||
latest_condition,
|
latest_condition,
|
||||||
);
|
);
|
||||||
@ -253,8 +252,8 @@ impl<'ctx, G: RankingRuleGraphTrait> RankingRule<'ctx, QueryGraph> for GraphBase
|
|||||||
|
|
||||||
// keep the same prefix and check the intersection with
|
// keep the same prefix and check the intersection with
|
||||||
// all the remaining conditions
|
// all the remaining conditions
|
||||||
let mut forbidden = dead_end_path_cache.forbidden.clone();
|
let mut forbidden = dead_ends_cache.forbidden.clone();
|
||||||
let mut cursor = dead_end_path_cache;
|
let mut cursor = dead_ends_cache;
|
||||||
for &c in visited_conditions[..len_prefix].iter() {
|
for &c in visited_conditions[..len_prefix].iter() {
|
||||||
cursor = cursor.advance(c).unwrap();
|
cursor = cursor.advance(c).unwrap();
|
||||||
forbidden.union(&cursor.forbidden);
|
forbidden.union(&cursor.forbidden);
|
||||||
@ -301,7 +300,7 @@ impl<'ctx, G: RankingRuleGraphTrait> RankingRule<'ctx, QueryGraph> for GraphBase
|
|||||||
G::log_state(
|
G::log_state(
|
||||||
&original_graph,
|
&original_graph,
|
||||||
&good_paths,
|
&good_paths,
|
||||||
dead_end_path_cache,
|
dead_ends_cache,
|
||||||
original_universe,
|
original_universe,
|
||||||
all_distances,
|
all_distances,
|
||||||
cost,
|
cost,
|
||||||
|
@ -44,17 +44,17 @@ pub enum SearchEvents {
|
|||||||
ProximityState {
|
ProximityState {
|
||||||
graph: RankingRuleGraph<ProximityGraph>,
|
graph: RankingRuleGraph<ProximityGraph>,
|
||||||
paths: Vec<Vec<Interned<ProximityCondition>>>,
|
paths: Vec<Vec<Interned<ProximityCondition>>>,
|
||||||
dead_end_path_cache: DeadEndsCache<ProximityCondition>,
|
dead_ends_cache: DeadEndsCache<ProximityCondition>,
|
||||||
universe: RoaringBitmap,
|
universe: RoaringBitmap,
|
||||||
distances: MappedInterner<Vec<(u16, SmallBitmap<ProximityCondition>)>, QueryNode>,
|
distances: MappedInterner<Vec<u16>, QueryNode>,
|
||||||
cost: u16,
|
cost: u16,
|
||||||
},
|
},
|
||||||
TypoState {
|
TypoState {
|
||||||
graph: RankingRuleGraph<TypoGraph>,
|
graph: RankingRuleGraph<TypoGraph>,
|
||||||
paths: Vec<Vec<Interned<TypoCondition>>>,
|
paths: Vec<Vec<Interned<TypoCondition>>>,
|
||||||
dead_end_path_cache: DeadEndsCache<TypoCondition>,
|
dead_ends_cache: DeadEndsCache<TypoCondition>,
|
||||||
universe: RoaringBitmap,
|
universe: RoaringBitmap,
|
||||||
distances: MappedInterner<Vec<(u16, SmallBitmap<TypoCondition>)>, QueryNode>,
|
distances: MappedInterner<Vec<u16>, QueryNode>,
|
||||||
cost: u16,
|
cost: u16,
|
||||||
},
|
},
|
||||||
RankingRuleSkipBucket {
|
RankingRuleSkipBucket {
|
||||||
@ -170,15 +170,15 @@ impl SearchLogger<QueryGraph> for DetailedSearchLogger {
|
|||||||
&mut self,
|
&mut self,
|
||||||
query_graph: &RankingRuleGraph<ProximityGraph>,
|
query_graph: &RankingRuleGraph<ProximityGraph>,
|
||||||
paths_map: &[Vec<Interned<ProximityCondition>>],
|
paths_map: &[Vec<Interned<ProximityCondition>>],
|
||||||
dead_end_path_cache: &DeadEndsCache<ProximityCondition>,
|
dead_ends_cache: &DeadEndsCache<ProximityCondition>,
|
||||||
universe: &RoaringBitmap,
|
universe: &RoaringBitmap,
|
||||||
distances: &MappedInterner<Vec<(u16, SmallBitmap<ProximityCondition>)>, QueryNode>,
|
distances: &MappedInterner<Vec<u16>, QueryNode>,
|
||||||
cost: u16,
|
cost: u16,
|
||||||
) {
|
) {
|
||||||
self.events.push(SearchEvents::ProximityState {
|
self.events.push(SearchEvents::ProximityState {
|
||||||
graph: query_graph.clone(),
|
graph: query_graph.clone(),
|
||||||
paths: paths_map.to_vec(),
|
paths: paths_map.to_vec(),
|
||||||
dead_end_path_cache: dead_end_path_cache.clone(),
|
dead_ends_cache: dead_ends_cache.clone(),
|
||||||
universe: universe.clone(),
|
universe: universe.clone(),
|
||||||
distances: distances.clone(),
|
distances: distances.clone(),
|
||||||
cost,
|
cost,
|
||||||
@ -189,15 +189,15 @@ impl SearchLogger<QueryGraph> for DetailedSearchLogger {
|
|||||||
&mut self,
|
&mut self,
|
||||||
query_graph: &RankingRuleGraph<TypoGraph>,
|
query_graph: &RankingRuleGraph<TypoGraph>,
|
||||||
paths_map: &[Vec<Interned<TypoCondition>>],
|
paths_map: &[Vec<Interned<TypoCondition>>],
|
||||||
dead_end_path_cache: &DeadEndsCache<TypoCondition>,
|
dead_ends_cache: &DeadEndsCache<TypoCondition>,
|
||||||
universe: &RoaringBitmap,
|
universe: &RoaringBitmap,
|
||||||
distances: &MappedInterner<Vec<(u16, SmallBitmap<TypoCondition>)>, QueryNode>,
|
distances: &MappedInterner<Vec<u16>, QueryNode>,
|
||||||
cost: u16,
|
cost: u16,
|
||||||
) {
|
) {
|
||||||
self.events.push(SearchEvents::TypoState {
|
self.events.push(SearchEvents::TypoState {
|
||||||
graph: query_graph.clone(),
|
graph: query_graph.clone(),
|
||||||
paths: paths_map.to_vec(),
|
paths: paths_map.to_vec(),
|
||||||
dead_end_path_cache: dead_end_path_cache.clone(),
|
dead_ends_cache: dead_ends_cache.clone(),
|
||||||
universe: universe.clone(),
|
universe: universe.clone(),
|
||||||
distances: distances.clone(),
|
distances: distances.clone(),
|
||||||
cost,
|
cost,
|
||||||
@ -357,7 +357,7 @@ results.{cur_ranking_rule}{cur_activated_id} {{
|
|||||||
SearchEvents::ProximityState {
|
SearchEvents::ProximityState {
|
||||||
graph,
|
graph,
|
||||||
paths,
|
paths,
|
||||||
dead_end_path_cache,
|
dead_ends_cache,
|
||||||
universe,
|
universe,
|
||||||
distances,
|
distances,
|
||||||
cost,
|
cost,
|
||||||
@ -373,7 +373,7 @@ results.{cur_ranking_rule}{cur_activated_id} {{
|
|||||||
ctx,
|
ctx,
|
||||||
graph,
|
graph,
|
||||||
paths,
|
paths,
|
||||||
dead_end_path_cache,
|
dead_ends_cache,
|
||||||
distances.clone(),
|
distances.clone(),
|
||||||
&mut new_file,
|
&mut new_file,
|
||||||
);
|
);
|
||||||
@ -390,7 +390,7 @@ results.{cur_ranking_rule}{cur_activated_id} {{
|
|||||||
SearchEvents::TypoState {
|
SearchEvents::TypoState {
|
||||||
graph,
|
graph,
|
||||||
paths,
|
paths,
|
||||||
dead_end_path_cache,
|
dead_ends_cache,
|
||||||
universe,
|
universe,
|
||||||
distances,
|
distances,
|
||||||
cost,
|
cost,
|
||||||
@ -406,7 +406,7 @@ results.{cur_ranking_rule}{cur_activated_id} {{
|
|||||||
ctx,
|
ctx,
|
||||||
graph,
|
graph,
|
||||||
paths,
|
paths,
|
||||||
dead_end_path_cache,
|
dead_ends_cache,
|
||||||
distances.clone(),
|
distances.clone(),
|
||||||
&mut new_file,
|
&mut new_file,
|
||||||
);
|
);
|
||||||
@ -429,7 +429,7 @@ results.{cur_ranking_rule}{cur_activated_id} {{
|
|||||||
ctx: &mut SearchContext,
|
ctx: &mut SearchContext,
|
||||||
node_idx: Interned<QueryNode>,
|
node_idx: Interned<QueryNode>,
|
||||||
node: &QueryNode,
|
node: &QueryNode,
|
||||||
distances: &[(u16, SmallBitmap<R::Condition>)],
|
distances: &[u16],
|
||||||
file: &mut File,
|
file: &mut File,
|
||||||
) {
|
) {
|
||||||
match &node.data {
|
match &node.data {
|
||||||
@ -490,9 +490,8 @@ shape: class"
|
|||||||
let p = ctx.word_interner.get(*use_prefix_db);
|
let p = ctx.word_interner.get(*use_prefix_db);
|
||||||
writeln!(file, "use prefix DB : {p}").unwrap();
|
writeln!(file, "use prefix DB : {p}").unwrap();
|
||||||
}
|
}
|
||||||
for (d, edges) in distances.iter() {
|
for d in distances.iter() {
|
||||||
writeln!(file, "\"distance {d}\" : {:?}", edges.iter().collect::<Vec<_>>())
|
writeln!(file, "\"d_{d}\" : distance").unwrap();
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln!(file, "}}").unwrap();
|
writeln!(file, "}}").unwrap();
|
||||||
@ -527,8 +526,8 @@ shape: class"
|
|||||||
ctx: &mut SearchContext,
|
ctx: &mut SearchContext,
|
||||||
graph: &RankingRuleGraph<R>,
|
graph: &RankingRuleGraph<R>,
|
||||||
paths: &[Vec<Interned<R::Condition>>],
|
paths: &[Vec<Interned<R::Condition>>],
|
||||||
dead_end_paths_cache: &DeadEndsCache<R::Condition>,
|
_dead_ends_cache: &DeadEndsCache<R::Condition>,
|
||||||
distances: MappedInterner<Vec<(u16, SmallBitmap<R::Condition>)>, QueryNode>,
|
distances: MappedInterner<Vec<u16>, QueryNode>,
|
||||||
file: &mut File,
|
file: &mut File,
|
||||||
) {
|
) {
|
||||||
writeln!(file, "direction: right").unwrap();
|
writeln!(file, "direction: right").unwrap();
|
||||||
|
@ -8,7 +8,6 @@ use super::query_graph::QueryNode;
|
|||||||
use super::ranking_rule_graph::{
|
use super::ranking_rule_graph::{
|
||||||
DeadEndsCache, ProximityCondition, ProximityGraph, RankingRuleGraph, TypoCondition, TypoGraph,
|
DeadEndsCache, ProximityCondition, ProximityGraph, RankingRuleGraph, TypoCondition, TypoGraph,
|
||||||
};
|
};
|
||||||
use super::small_bitmap::SmallBitmap;
|
|
||||||
use super::{RankingRule, RankingRuleQueryTrait};
|
use super::{RankingRule, RankingRuleQueryTrait};
|
||||||
|
|
||||||
/// Trait for structure logging the execution of a search query.
|
/// Trait for structure logging the execution of a search query.
|
||||||
@ -66,9 +65,9 @@ pub trait SearchLogger<Q: RankingRuleQueryTrait> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
query_graph: &RankingRuleGraph<ProximityGraph>,
|
query_graph: &RankingRuleGraph<ProximityGraph>,
|
||||||
paths: &[Vec<Interned<ProximityCondition>>],
|
paths: &[Vec<Interned<ProximityCondition>>],
|
||||||
dead_end_path_cache: &DeadEndsCache<ProximityCondition>,
|
dead_ends_cache: &DeadEndsCache<ProximityCondition>,
|
||||||
universe: &RoaringBitmap,
|
universe: &RoaringBitmap,
|
||||||
distances: &MappedInterner<Vec<(u16, SmallBitmap<ProximityCondition>)>, QueryNode>,
|
distances: &MappedInterner<Vec<u16>, QueryNode>,
|
||||||
cost: u16,
|
cost: u16,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -77,9 +76,9 @@ pub trait SearchLogger<Q: RankingRuleQueryTrait> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
query_graph: &RankingRuleGraph<TypoGraph>,
|
query_graph: &RankingRuleGraph<TypoGraph>,
|
||||||
paths: &[Vec<Interned<TypoCondition>>],
|
paths: &[Vec<Interned<TypoCondition>>],
|
||||||
dead_end_path_cache: &DeadEndsCache<TypoCondition>,
|
dead_ends_cache: &DeadEndsCache<TypoCondition>,
|
||||||
universe: &RoaringBitmap,
|
universe: &RoaringBitmap,
|
||||||
distances: &MappedInterner<Vec<(u16, SmallBitmap<TypoCondition>)>, QueryNode>,
|
distances: &MappedInterner<Vec<u16>, QueryNode>,
|
||||||
cost: u16,
|
cost: u16,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -137,9 +136,9 @@ impl<Q: RankingRuleQueryTrait> SearchLogger<Q> for DefaultSearchLogger {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_query_graph: &RankingRuleGraph<ProximityGraph>,
|
_query_graph: &RankingRuleGraph<ProximityGraph>,
|
||||||
_paths_map: &[Vec<Interned<ProximityCondition>>],
|
_paths_map: &[Vec<Interned<ProximityCondition>>],
|
||||||
_dead_end_path_cache: &DeadEndsCache<ProximityCondition>,
|
_dead_ends_cache: &DeadEndsCache<ProximityCondition>,
|
||||||
_universe: &RoaringBitmap,
|
_universe: &RoaringBitmap,
|
||||||
_distances: &MappedInterner<Vec<(u16, SmallBitmap<ProximityCondition>)>, QueryNode>,
|
_distances: &MappedInterner<Vec<u16>, QueryNode>,
|
||||||
_cost: u16,
|
_cost: u16,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
@ -148,9 +147,9 @@ impl<Q: RankingRuleQueryTrait> SearchLogger<Q> for DefaultSearchLogger {
|
|||||||
&mut self,
|
&mut self,
|
||||||
_query_graph: &RankingRuleGraph<TypoGraph>,
|
_query_graph: &RankingRuleGraph<TypoGraph>,
|
||||||
_paths: &[Vec<Interned<TypoCondition>>],
|
_paths: &[Vec<Interned<TypoCondition>>],
|
||||||
_dead_end_path_cache: &DeadEndsCache<TypoCondition>,
|
_dead_ends_cache: &DeadEndsCache<TypoCondition>,
|
||||||
_universe: &RoaringBitmap,
|
_universe: &RoaringBitmap,
|
||||||
_distances: &MappedInterner<Vec<(u16, SmallBitmap<TypoCondition>)>, QueryNode>,
|
_distances: &MappedInterner<Vec<u16>, QueryNode>,
|
||||||
_cost: u16,
|
_cost: u16,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#![allow(clippy::too_many_arguments)]
|
#![allow(clippy::too_many_arguments)]
|
||||||
|
|
||||||
use std::collections::btree_map::Entry;
|
use std::collections::{BTreeSet, VecDeque};
|
||||||
use std::collections::{BTreeMap, VecDeque};
|
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
|
|
||||||
use super::{DeadEndsCache, RankingRuleGraph, RankingRuleGraphTrait};
|
use super::{DeadEndsCache, RankingRuleGraph, RankingRuleGraphTrait};
|
||||||
@ -15,8 +14,8 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
from: Interned<QueryNode>,
|
from: Interned<QueryNode>,
|
||||||
cost: u16,
|
cost: u16,
|
||||||
all_distances: &MappedInterner<Vec<(u16, SmallBitmap<G::Condition>)>, QueryNode>,
|
all_distances: &MappedInterner<Vec<u16>, QueryNode>,
|
||||||
dead_end_path_cache: &mut DeadEndsCache<G::Condition>,
|
dead_ends_cache: &mut DeadEndsCache<G::Condition>,
|
||||||
mut visit: impl FnMut(
|
mut visit: impl FnMut(
|
||||||
&[Interned<G::Condition>],
|
&[Interned<G::Condition>],
|
||||||
&mut Self,
|
&mut Self,
|
||||||
@ -27,11 +26,11 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
|||||||
from,
|
from,
|
||||||
cost,
|
cost,
|
||||||
all_distances,
|
all_distances,
|
||||||
dead_end_path_cache,
|
dead_ends_cache,
|
||||||
&mut visit,
|
&mut visit,
|
||||||
&mut vec![],
|
&mut vec![],
|
||||||
&mut SmallBitmap::for_interned_values_in(&self.conditions_interner),
|
&mut SmallBitmap::for_interned_values_in(&self.conditions_interner),
|
||||||
dead_end_path_cache.forbidden.clone(),
|
dead_ends_cache.forbidden.clone(),
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -39,8 +38,8 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
from: Interned<QueryNode>,
|
from: Interned<QueryNode>,
|
||||||
cost: u16,
|
cost: u16,
|
||||||
all_distances: &MappedInterner<Vec<(u16, SmallBitmap<G::Condition>)>, QueryNode>,
|
all_distances: &MappedInterner<Vec<u16>, QueryNode>,
|
||||||
dead_end_path_cache: &mut DeadEndsCache<G::Condition>,
|
dead_ends_cache: &mut DeadEndsCache<G::Condition>,
|
||||||
visit: &mut impl FnMut(
|
visit: &mut impl FnMut(
|
||||||
&[Interned<G::Condition>],
|
&[Interned<G::Condition>],
|
||||||
&mut Self,
|
&mut Self,
|
||||||
@ -62,7 +61,7 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
|||||||
None => {
|
None => {
|
||||||
if edge.dest_node == self.query_graph.end_node {
|
if edge.dest_node == self.query_graph.end_node {
|
||||||
any_valid = true;
|
any_valid = true;
|
||||||
let control_flow = visit(prev_conditions, self, dead_end_path_cache)?;
|
let control_flow = visit(prev_conditions, self, dead_ends_cache)?;
|
||||||
match control_flow {
|
match control_flow {
|
||||||
ControlFlow::Continue(_) => {}
|
ControlFlow::Continue(_) => {}
|
||||||
ControlFlow::Break(_) => return Ok(true),
|
ControlFlow::Break(_) => return Ok(true),
|
||||||
@ -73,7 +72,7 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
|||||||
edge.dest_node,
|
edge.dest_node,
|
||||||
cost - edge.cost as u16,
|
cost - edge.cost as u16,
|
||||||
all_distances,
|
all_distances,
|
||||||
dead_end_path_cache,
|
dead_ends_cache,
|
||||||
visit,
|
visit,
|
||||||
prev_conditions,
|
prev_conditions,
|
||||||
cur_path,
|
cur_path,
|
||||||
@ -83,12 +82,10 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
|||||||
}
|
}
|
||||||
Some(condition) => {
|
Some(condition) => {
|
||||||
if forbidden_conditions.contains(condition)
|
if forbidden_conditions.contains(condition)
|
||||||
|| !all_distances.get(edge.dest_node).iter().any(
|
|| all_distances
|
||||||
|(next_cost, necessary_conditions)| {
|
.get(edge.dest_node)
|
||||||
(*next_cost == cost - edge.cost as u16)
|
.iter()
|
||||||
&& !forbidden_conditions.intersects(necessary_conditions)
|
.all(|next_cost| *next_cost != cost - edge.cost as u16)
|
||||||
},
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -96,14 +93,14 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
|||||||
prev_conditions.push(condition);
|
prev_conditions.push(condition);
|
||||||
let mut new_forbidden_conditions = forbidden_conditions.clone();
|
let mut new_forbidden_conditions = forbidden_conditions.clone();
|
||||||
if let Some(next_forbidden) =
|
if let Some(next_forbidden) =
|
||||||
dead_end_path_cache.forbidden_conditions_after_prefix(prev_conditions)
|
dead_ends_cache.forbidden_conditions_after_prefix(prev_conditions)
|
||||||
{
|
{
|
||||||
new_forbidden_conditions.union(&next_forbidden);
|
new_forbidden_conditions.union(&next_forbidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
let next_any_valid = if edge.dest_node == self.query_graph.end_node {
|
let next_any_valid = if edge.dest_node == self.query_graph.end_node {
|
||||||
any_valid = true;
|
any_valid = true;
|
||||||
let control_flow = visit(prev_conditions, self, dead_end_path_cache)?;
|
let control_flow = visit(prev_conditions, self, dead_ends_cache)?;
|
||||||
match control_flow {
|
match control_flow {
|
||||||
ControlFlow::Continue(_) => {}
|
ControlFlow::Continue(_) => {}
|
||||||
ControlFlow::Break(_) => return Ok(true),
|
ControlFlow::Break(_) => return Ok(true),
|
||||||
@ -114,7 +111,7 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
|||||||
edge.dest_node,
|
edge.dest_node,
|
||||||
cost - edge.cost as u16,
|
cost - edge.cost as u16,
|
||||||
all_distances,
|
all_distances,
|
||||||
dead_end_path_cache,
|
dead_ends_cache,
|
||||||
visit,
|
visit,
|
||||||
prev_conditions,
|
prev_conditions,
|
||||||
cur_path,
|
cur_path,
|
||||||
@ -129,8 +126,8 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
|||||||
any_valid |= next_any_valid;
|
any_valid |= next_any_valid;
|
||||||
|
|
||||||
if next_any_valid {
|
if next_any_valid {
|
||||||
forbidden_conditions = dead_end_path_cache
|
forbidden_conditions =
|
||||||
.forbidden_conditions_for_all_prefixes_up_to(prev_conditions);
|
dead_ends_cache.forbidden_conditions_for_all_prefixes_up_to(prev_conditions);
|
||||||
if cur_path.intersects(&forbidden_conditions) {
|
if cur_path.intersects(&forbidden_conditions) {
|
||||||
break 'edges_loop;
|
break 'edges_loop;
|
||||||
}
|
}
|
||||||
@ -140,16 +137,13 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
|||||||
Ok(any_valid)
|
Ok(any_valid)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize_distances_with_necessary_edges(
|
pub fn initialize_distances_with_necessary_edges(&self) -> MappedInterner<Vec<u16>, QueryNode> {
|
||||||
&self,
|
|
||||||
) -> MappedInterner<Vec<(u16, SmallBitmap<G::Condition>)>, QueryNode> {
|
|
||||||
let mut distances_to_end = self.query_graph.nodes.map(|_| vec![]);
|
let mut distances_to_end = self.query_graph.nodes.map(|_| vec![]);
|
||||||
let mut enqueued = SmallBitmap::new(self.query_graph.nodes.len());
|
let mut enqueued = SmallBitmap::new(self.query_graph.nodes.len());
|
||||||
|
|
||||||
let mut node_stack = VecDeque::new();
|
let mut node_stack = VecDeque::new();
|
||||||
|
|
||||||
*distances_to_end.get_mut(self.query_graph.end_node) =
|
*distances_to_end.get_mut(self.query_graph.end_node) = vec![0];
|
||||||
vec![(0, SmallBitmap::for_interned_values_in(&self.conditions_interner))];
|
|
||||||
|
|
||||||
for prev_node in self.query_graph.nodes.get(self.query_graph.end_node).predecessors.iter() {
|
for prev_node in self.query_graph.nodes.get(self.query_graph.end_node).predecessors.iter() {
|
||||||
node_stack.push_back(prev_node);
|
node_stack.push_back(prev_node);
|
||||||
@ -157,35 +151,20 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while let Some(cur_node) = node_stack.pop_front() {
|
while let Some(cur_node) = node_stack.pop_front() {
|
||||||
let mut self_distances = BTreeMap::<u16, SmallBitmap<G::Condition>>::new();
|
let mut self_distances = BTreeSet::<u16>::new();
|
||||||
|
|
||||||
let cur_node_edges = &self.edges_of_node.get(cur_node);
|
let cur_node_edges = &self.edges_of_node.get(cur_node);
|
||||||
for edge_idx in cur_node_edges.iter() {
|
for edge_idx in cur_node_edges.iter() {
|
||||||
let edge = self.edges_store.get(edge_idx).as_ref().unwrap();
|
let edge = self.edges_store.get(edge_idx).as_ref().unwrap();
|
||||||
let succ_node = edge.dest_node;
|
let succ_node = edge.dest_node;
|
||||||
let succ_distances = distances_to_end.get(succ_node);
|
let succ_distances = distances_to_end.get(succ_node);
|
||||||
for (succ_distance, succ_necessary_conditions) in succ_distances {
|
for succ_distance in succ_distances {
|
||||||
let mut potential_necessary_edges =
|
self_distances.insert(edge.cost as u16 + succ_distance);
|
||||||
SmallBitmap::for_interned_values_in(&self.conditions_interner);
|
|
||||||
for condition in
|
|
||||||
edge.condition.into_iter().chain(succ_necessary_conditions.iter())
|
|
||||||
{
|
|
||||||
potential_necessary_edges.insert(condition);
|
|
||||||
}
|
|
||||||
|
|
||||||
match self_distances.entry(edge.cost as u16 + succ_distance) {
|
|
||||||
Entry::Occupied(mut prev_necessary_edges) => {
|
|
||||||
prev_necessary_edges.get_mut().intersection(&potential_necessary_edges);
|
|
||||||
}
|
|
||||||
Entry::Vacant(entry) => {
|
|
||||||
entry.insert(potential_necessary_edges);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let distances_to_end_cur_node = distances_to_end.get_mut(cur_node);
|
let distances_to_end_cur_node = distances_to_end.get_mut(cur_node);
|
||||||
for (cost, necessary_edges) in self_distances.iter() {
|
for cost in self_distances.iter() {
|
||||||
distances_to_end_cur_node.push((*cost, necessary_edges.clone()));
|
distances_to_end_cur_node.push(*cost);
|
||||||
}
|
}
|
||||||
*distances_to_end.get_mut(cur_node) = self_distances.into_iter().collect();
|
*distances_to_end.get_mut(cur_node) = self_distances.into_iter().collect();
|
||||||
for prev_node in self.query_graph.nodes.get(cur_node).predecessors.iter() {
|
for prev_node in self.query_graph.nodes.get(cur_node).predecessors.iter() {
|
||||||
|
@ -112,9 +112,9 @@ pub trait RankingRuleGraphTrait: Sized {
|
|||||||
fn log_state(
|
fn log_state(
|
||||||
graph: &RankingRuleGraph<Self>,
|
graph: &RankingRuleGraph<Self>,
|
||||||
paths: &[Vec<Interned<Self::Condition>>],
|
paths: &[Vec<Interned<Self::Condition>>],
|
||||||
dead_end_path_cache: &DeadEndsCache<Self::Condition>,
|
dead_ends_cache: &DeadEndsCache<Self::Condition>,
|
||||||
universe: &RoaringBitmap,
|
universe: &RoaringBitmap,
|
||||||
distances: &MappedInterner<Vec<(u16, SmallBitmap<Self::Condition>)>, QueryNode>,
|
distances: &MappedInterner<Vec<u16>, QueryNode>,
|
||||||
cost: u16,
|
cost: u16,
|
||||||
logger: &mut dyn SearchLogger<QueryGraph>,
|
logger: &mut dyn SearchLogger<QueryGraph>,
|
||||||
);
|
);
|
||||||
|
@ -6,11 +6,10 @@ use std::iter::FromIterator;
|
|||||||
|
|
||||||
use roaring::RoaringBitmap;
|
use roaring::RoaringBitmap;
|
||||||
|
|
||||||
use super::{RankingRuleGraph, RankingRuleGraphTrait, DeadEndsCache};
|
use super::{DeadEndsCache, RankingRuleGraph, RankingRuleGraphTrait};
|
||||||
use crate::search::new::interner::{DedupInterner, Interned, MappedInterner};
|
use crate::search::new::interner::{DedupInterner, Interned, MappedInterner};
|
||||||
use crate::search::new::logger::SearchLogger;
|
use crate::search::new::logger::SearchLogger;
|
||||||
use crate::search::new::query_term::{Phrase, QueryTerm};
|
use crate::search::new::query_term::{Phrase, QueryTerm};
|
||||||
use crate::search::new::small_bitmap::SmallBitmap;
|
|
||||||
use crate::search::new::{QueryGraph, QueryNode, SearchContext};
|
use crate::search::new::{QueryGraph, QueryNode, SearchContext};
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
||||||
@ -66,13 +65,13 @@ impl RankingRuleGraphTrait for ProximityGraph {
|
|||||||
fn log_state(
|
fn log_state(
|
||||||
graph: &RankingRuleGraph<Self>,
|
graph: &RankingRuleGraph<Self>,
|
||||||
paths: &[Vec<Interned<ProximityCondition>>],
|
paths: &[Vec<Interned<ProximityCondition>>],
|
||||||
dead_end_path_cache: &DeadEndsCache<Self::Condition>,
|
dead_ends_cache: &DeadEndsCache<Self::Condition>,
|
||||||
universe: &RoaringBitmap,
|
universe: &RoaringBitmap,
|
||||||
distances: &MappedInterner<Vec<(u16, SmallBitmap<ProximityCondition>)>, QueryNode>,
|
distances: &MappedInterner<Vec<u16>, QueryNode>,
|
||||||
cost: u16,
|
cost: u16,
|
||||||
logger: &mut dyn SearchLogger<QueryGraph>,
|
logger: &mut dyn SearchLogger<QueryGraph>,
|
||||||
) {
|
) {
|
||||||
logger.log_proximity_state(graph, paths, dead_end_path_cache, universe, distances, cost);
|
logger.log_proximity_state(graph, paths, dead_ends_cache, universe, distances, cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn label_for_condition<'ctx>(
|
fn label_for_condition<'ctx>(
|
||||||
|
@ -5,7 +5,6 @@ use crate::search::new::interner::{DedupInterner, Interned, MappedInterner};
|
|||||||
use crate::search::new::logger::SearchLogger;
|
use crate::search::new::logger::SearchLogger;
|
||||||
use crate::search::new::query_graph::QueryNodeData;
|
use crate::search::new::query_graph::QueryNodeData;
|
||||||
use crate::search::new::query_term::{LocatedQueryTerm, Phrase, QueryTerm};
|
use crate::search::new::query_term::{LocatedQueryTerm, Phrase, QueryTerm};
|
||||||
use crate::search::new::small_bitmap::SmallBitmap;
|
|
||||||
use crate::search::new::{QueryGraph, QueryNode, SearchContext};
|
use crate::search::new::{QueryGraph, QueryNode, SearchContext};
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
@ -136,13 +135,13 @@ impl RankingRuleGraphTrait for TypoGraph {
|
|||||||
fn log_state(
|
fn log_state(
|
||||||
graph: &RankingRuleGraph<Self>,
|
graph: &RankingRuleGraph<Self>,
|
||||||
paths: &[Vec<Interned<TypoCondition>>],
|
paths: &[Vec<Interned<TypoCondition>>],
|
||||||
dead_end_path_cache: &DeadEndsCache<TypoCondition>,
|
dead_ends_cache: &DeadEndsCache<TypoCondition>,
|
||||||
universe: &RoaringBitmap,
|
universe: &RoaringBitmap,
|
||||||
distances: &MappedInterner<Vec<(u16, SmallBitmap<TypoCondition>)>, QueryNode>,
|
distances: &MappedInterner<Vec<u16>, QueryNode>,
|
||||||
cost: u16,
|
cost: u16,
|
||||||
logger: &mut dyn SearchLogger<QueryGraph>,
|
logger: &mut dyn SearchLogger<QueryGraph>,
|
||||||
) {
|
) {
|
||||||
logger.log_typo_state(graph, paths, dead_end_path_cache, universe, distances, cost);
|
logger.log_typo_state(graph, paths, dead_ends_cache, universe, distances, cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn label_for_condition<'ctx>(
|
fn label_for_condition<'ctx>(
|
||||||
|
Loading…
Reference in New Issue
Block a user