Make PathSet strongly typed

This commit is contained in:
Loïc Lecrenier
2023-03-16 09:58:59 +01:00
parent a49ddec9df
commit 7b1d8f4c6d
12 changed files with 102 additions and 87 deletions

View File

@ -24,7 +24,11 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
cost: u16,
all_distances: &MappedInterner<Vec<(u16, SmallBitmap<G::EdgeCondition>)>, QueryNode>,
empty_paths_cache: &mut DeadEndPathCache<G>,
mut visit: impl FnMut(&[u16], &mut Self, &mut DeadEndPathCache<G>) -> Result<ControlFlow<()>>,
mut visit: impl FnMut(
&[Interned<G::EdgeCondition>],
&mut Self,
&mut DeadEndPathCache<G>,
) -> Result<ControlFlow<()>>,
) -> Result<()> {
let _ = self.visit_paths_of_cost_rec(
from,
@ -44,8 +48,12 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
cost: u16,
all_distances: &MappedInterner<Vec<(u16, SmallBitmap<G::EdgeCondition>)>, QueryNode>,
empty_paths_cache: &mut DeadEndPathCache<G>,
visit: &mut impl FnMut(&[u16], &mut Self, &mut DeadEndPathCache<G>) -> Result<ControlFlow<()>>,
prev_conditions: &mut Vec<u16>,
visit: &mut impl FnMut(
&[Interned<G::EdgeCondition>],
&mut Self,
&mut DeadEndPathCache<G>,
) -> Result<ControlFlow<()>>,
prev_conditions: &mut Vec<Interned<G::EdgeCondition>>,
cur_path: &mut SmallBitmap<G::EdgeCondition>,
forbidden_conditions: &mut SmallBitmap<G::EdgeCondition>,
) -> Result<bool> {
@ -92,8 +100,7 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
continue;
}
cur_path.insert(condition);
// TODO: typed path set
prev_conditions.push(condition.into_inner());
prev_conditions.push(condition);
let mut new_forbidden_conditions = forbidden_conditions.clone();
new_forbidden_conditions
@ -101,7 +108,7 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
empty_paths_cache.prefixes.final_edges_after_prefix(
prev_conditions,
&mut |x| {
new_forbidden_conditions.insert(Interned::new(x));
new_forbidden_conditions.insert(x);
},
);
let next_any_valid = if edge.dest_node == self.query_graph.end_node {
@ -137,12 +144,11 @@ impl<G: RankingRuleGraphTrait> RankingRuleGraph<G> {
}
forbidden_conditions.union(&empty_paths_cache.conditions);
for prev_condition in prev_conditions.iter() {
forbidden_conditions.union(
empty_paths_cache.condition_couples.get(Interned::new(*prev_condition)),
);
forbidden_conditions
.union(empty_paths_cache.condition_couples.get(*prev_condition));
}
empty_paths_cache.prefixes.final_edges_after_prefix(prev_conditions, &mut |x| {
forbidden_conditions.insert(Interned::new(x));
forbidden_conditions.insert(x);
});
}
}

View File

@ -11,7 +11,7 @@ pub struct DeadEndPathCache<G: RankingRuleGraphTrait> {
/// The set of edge conditions that resolve to no documents.
pub conditions: SmallBitmap<G::EdgeCondition>,
/// A set of path prefixes that resolve to no documents.
pub prefixes: PathSet,
pub prefixes: PathSet<G::EdgeCondition>,
/// A set of empty couples of edge conditions that resolve to no documents.
pub condition_couples: MappedInterner<SmallBitmap<G::EdgeCondition>, G::EdgeCondition>,
}
@ -40,13 +40,13 @@ impl<G: RankingRuleGraphTrait> DeadEndPathCache<G> {
pub fn add_condition(&mut self, condition: Interned<G::EdgeCondition>) {
self.conditions.insert(condition);
self.condition_couples.get_mut(condition).clear();
self.prefixes.remove_edge(condition.into_inner()); // TODO: typed PathSet
self.prefixes.remove_edge(condition);
for (_, edges2) in self.condition_couples.iter_mut() {
edges2.remove(condition);
}
}
/// Store in the cache that every path containing the given prefix resolves to no documents.
pub fn add_prefix(&mut self, prefix: &[u16]) {
pub fn add_prefix(&mut self, prefix: &[Interned<G::EdgeCondition>]) {
// TODO: typed PathSet
self.prefixes.insert(prefix.iter().copied());
}
@ -63,15 +63,15 @@ impl<G: RankingRuleGraphTrait> DeadEndPathCache<G> {
/// Returns true if the cache can determine that the given path resolves to no documents.
pub fn path_is_dead_end(
&self,
path: &[u16],
path: &[Interned<G::EdgeCondition>],
path_bitmap: &SmallBitmap<G::EdgeCondition>,
) -> bool {
if path_bitmap.intersects(&self.conditions) {
return true;
}
for edge in path.iter() {
for condition in path.iter() {
// TODO: typed path
let forbidden_other_edges = self.condition_couples.get(Interned::new(*edge));
let forbidden_other_edges = self.condition_couples.get(*condition);
if path_bitmap.intersects(forbidden_other_edges) {
return true;
}

View File

@ -117,7 +117,7 @@ pub trait RankingRuleGraphTrait: Sized {
fn log_state(
graph: &RankingRuleGraph<Self>,
paths: &[Vec<u16>],
paths: &[Vec<Interned<Self::EdgeCondition>>],
empty_paths_cache: &DeadEndPathCache<Self>,
universe: &RoaringBitmap,
distances: &MappedInterner<Vec<(u16, SmallBitmap<Self::EdgeCondition>)>, QueryNode>,

View File

@ -2,14 +2,34 @@
// For the empty_prefixes field in the EmptyPathsCache only :/
// but it could be used for more, like efficient computing of a set of paths
use crate::search::new::interner::Interned;
/// A set of [`Path`]
#[derive(Default, Debug, Clone)]
pub struct PathSet {
nodes: Vec<(u16, PathSet)>,
pub struct PathSet<T> {
nodes: Vec<(Interned<T>, Self)>,
is_end: bool,
}
impl PathSet {
pub fn insert(&mut self, mut edges: impl Iterator<Item = u16>) {
impl<T> Clone for PathSet<T> {
fn clone(&self) -> Self {
Self { nodes: self.nodes.clone(), is_end: self.is_end }
}
}
impl<T> std::fmt::Debug for PathSet<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PathSet").field("nodes", &self.nodes).field("is_end", &self.is_end).finish()
}
}
impl<T> Default for PathSet<T> {
fn default() -> Self {
Self { nodes: Default::default(), is_end: Default::default() }
}
}
impl<T> PathSet<T> {
pub fn insert(&mut self, mut edges: impl Iterator<Item = Interned<T>>) {
match edges.next() {
None => {
self.is_end = true;
@ -27,7 +47,7 @@ impl PathSet {
}
}
pub fn remove_edge(&mut self, forbidden_edge: u16) {
pub fn remove_edge(&mut self, forbidden_edge: Interned<T>) {
let mut i = 0;
while i < self.nodes.len() {
let should_remove = if self.nodes[i].0 == forbidden_edge {
@ -46,7 +66,11 @@ impl PathSet {
}
}
pub fn final_edges_after_prefix(&self, prefix: &[u16], visit: &mut impl FnMut(u16)) {
pub fn final_edges_after_prefix(
&self,
prefix: &[Interned<T>],
visit: &mut impl FnMut(Interned<T>),
) {
let [first_edge, remaining_prefix @ ..] = prefix else {
for node in self.nodes.iter() {
if node.1.is_end {
@ -62,7 +86,7 @@ impl PathSet {
}
}
pub fn contains_prefix_of_path(&self, path: &[u16]) -> bool {
pub fn contains_prefix_of_path(&self, path: &[Interned<T>]) -> bool {
if self.is_end {
return true;
}

View File

@ -66,7 +66,7 @@ impl RankingRuleGraphTrait for ProximityGraph {
fn log_state(
graph: &RankingRuleGraph<Self>,
paths: &[Vec<u16>],
paths: &[Vec<Interned<ProximityCondition>>],
empty_paths_cache: &DeadEndPathCache<Self>,
universe: &RoaringBitmap,
distances: &MappedInterner<Vec<(u16, SmallBitmap<ProximityCondition>)>, QueryNode>,

View File

@ -137,7 +137,7 @@ impl RankingRuleGraphTrait for TypoGraph {
fn log_state(
graph: &RankingRuleGraph<Self>,
paths: &[Vec<u16>],
paths: &[Vec<Interned<TypoEdge>>],
empty_paths_cache: &DeadEndPathCache<Self>,
universe: &RoaringBitmap,
distances: &MappedInterner<Vec<(u16, SmallBitmap<TypoEdge>)>, QueryNode>,