Skip to content

Commit

Permalink
Update ComponentMappedIndex to use HashSet
Browse files Browse the repository at this point in the history
This trades performance for stable iteration order
  • Loading branch information
phillord committed Jun 28, 2024
1 parent 18aa36c commit e3f929d
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 16 deletions.
5 changes: 4 additions & 1 deletion src/io/owx/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1436,7 +1436,10 @@ pub mod test {

assert_eq!(ont.i().annotation_assertion().count(), 2);

let aa = ont.i().annotation_assertion().next().unwrap();
let mut v: Vec<_> = ont.i().annotation_assertion().collect();
v.sort();
let aa = v[0];

assert_eq!(*(aa.subject), *"http://www.example.com/iri#C");

assert_eq!(
Expand Down
36 changes: 21 additions & 15 deletions src/ontology/component_mapped.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use super::set::SetOntology;
use crate::model::*;
use std::{
cell::RefCell,
collections::{BTreeMap, BTreeSet, VecDeque},
collections::{HashMap, HashSet, VecDeque},
iter::FromIterator,
ops::Deref,
rc::Rc,
Expand Down Expand Up @@ -57,16 +57,15 @@ macro_rules! onimpl {
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ComponentMappedIndex<A, AA> {
component: RefCell<BTreeMap<ComponentKind, BTreeSet<AA>>>,
pub struct ComponentMappedIndex<A: ForIRI, AA: ForIndex<A>> {
component: RefCell<HashMap<ComponentKind, HashSet<AA>>>,
pd: PhantomData<A>,
}

impl<A: ForIRI, AA: ForIndex<A>> ComponentMappedIndex<A, AA> {
pub fn new() -> ComponentMappedIndex<A, AA> {
ComponentMappedIndex {
component: RefCell::new(BTreeMap::new()),
pd: Default::default(),
..Default::default()
}
}

Expand All @@ -76,18 +75,18 @@ impl<A: ForIRI, AA: ForIndex<A>> ComponentMappedIndex<A, AA> {
/// instantiated, which means that it effects equality of the
/// ontology. It should only be used where the intention is to
/// update the ontology.
fn component_as_ptr(&self, cmk: ComponentKind) -> *mut BTreeMap<ComponentKind, BTreeSet<AA>> {
fn component_as_ptr(&self, cmk: ComponentKind) -> *mut HashMap<ComponentKind, HashSet<AA>> {
self.component.borrow_mut().entry(cmk).or_default();
self.component.as_ptr()
}

/// Fetch the components for the given kind.
fn set_for_kind(&self, cmk: ComponentKind) -> Option<&BTreeSet<AA>> {
fn set_for_kind(&self, cmk: ComponentKind) -> Option<&HashSet<AA>> {
unsafe { (*self.component.as_ptr()).get(&cmk) }
}

/// Fetch the components for given kind as a mutable ref.
fn mut_set_for_kind(&mut self, cmk: ComponentKind) -> &mut BTreeSet<AA> {
fn mut_set_for_kind(&mut self, cmk: ComponentKind) -> &mut HashSet<AA> {
unsafe { (*self.component_as_ptr(cmk)).get_mut(&cmk).unwrap() }
}

Expand Down Expand Up @@ -203,7 +202,7 @@ onimpl! {AnnotationPropertyDomain, annotation_property_domain}
onimpl! {AnnotationPropertyRange, annotation_property_range}
onimpl! {Rule, rule}

impl<A, AA> Default for ComponentMappedIndex<A, AA> {
impl<A: ForIRI, AA: ForIndex<A>> Default for ComponentMappedIndex<A, AA> {
fn default() -> Self {
Self {
component: Default::default(),
Expand All @@ -222,7 +221,7 @@ impl<A: ForIRI, AA: ForIndex<A>> IntoIterator for ComponentMappedIndex<A, AA> {
// The collect switches the type which shows up in the API. Blegh.
let v: Vec<AnnotatedComponent<A>> = btreemap
.into_values()
.flat_map(BTreeSet::into_iter)
.flat_map(HashSet::into_iter)
.map(|fi| fi.unwrap())
.collect();

Expand All @@ -234,7 +233,7 @@ impl<A: ForIRI, AA: ForIndex<A>> IntoIterator for ComponentMappedIndex<A, AA> {
pub struct ComponentMappedIter<'a, A: ForIRI, AA: ForIndex<A>> {
ont: &'a ComponentMappedIndex<A, AA>,
kinds: VecDeque<&'a ComponentKind>,
inner: Option<<&'a BTreeSet<AA> as IntoIterator>::IntoIter>,
inner: Option<<&'a HashSet<AA> as IntoIterator>::IntoIter>,
}

impl<'a, A: ForIRI, AA: ForIndex<A>> Iterator for ComponentMappedIter<'a, A, AA> {
Expand All @@ -249,7 +248,7 @@ impl<'a, A: ForIRI, AA: ForIndex<A>> Iterator for ComponentMappedIter<'a, A, AA>
// Attempt to consume the iterator for the next component kind
if !self.kinds.is_empty() {
let kind = self.kinds.pop_front().unwrap();
self.inner = self.ont.set_for_kind(*kind).map(BTreeSet::iter);
self.inner = self.ont.set_for_kind(*kind).map(HashSet::iter);
self.next()
} else {
None
Expand Down Expand Up @@ -280,7 +279,9 @@ impl<A: ForIRI, AA: ForIndex<A>> OntologyIndex<A, AA> for ComponentMappedIndex<A
}

#[derive(Debug, Eq, PartialEq)]
pub struct ComponentMappedOntology<A, AA>(OneIndexedOntology<A, AA, ComponentMappedIndex<A, AA>>);
pub struct ComponentMappedOntology<A: ForIRI, AA: ForIndex<A>>(
OneIndexedOntology<A, AA, ComponentMappedIndex<A, AA>>,
);

pub type RcComponentMappedOntology = ComponentMappedOntology<RcStr, Rc<AnnotatedComponent<RcStr>>>;
pub type ArcComponentMappedOntology =
Expand Down Expand Up @@ -481,7 +482,10 @@ mod test {
o.insert(decl3.clone());

// Iteration is based on ascending order of axiom kinds.
let mut it = o.into_iter();
// Iteration is set based so undefined in order. So, sort first.
let mut v: Vec<_> = o.into_iter().collect();
v.sort();
let mut it = v.into_iter();
assert_eq!(
it.next(),
Some(AnnotatedComponent::from(Component::DeclareClass(decl1)))
Expand Down Expand Up @@ -538,7 +542,9 @@ mod test {
o.insert(decl3.clone());

// Iteration is based on ascending order of axiom kinds.
let mut it = (&o).i().iter();
let mut v: Vec<_> = (&o).i().iter().collect();
v.sort();
let mut it = v.into_iter();
assert_eq!(
it.next(),
Some(&AnnotatedComponent::from(Component::DeclareClass(decl1)))
Expand Down
1 change: 1 addition & 0 deletions src/visitor/mutable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,7 @@ mod test {
let mut walk = super::WalkMut::new(LabeltoFred);
let mut vec = ont.into_iter().collect();
walk.ontology_vec(&mut vec);
vec.sort();

match &vec[2] {
AnnotatedComponent {
Expand Down

0 comments on commit e3f929d

Please sign in to comment.