use super::{EntailmentEngine, EntailmentError, Triple, TripleStore};
use crate::entailment::rdf_entailment::{rdfs_iri, rdf_iri};
#[derive(Debug, Default, Clone)]
pub struct RdfsEntailmentEngine;
impl RdfsEntailmentEngine {
pub fn new() -> Self {
Self
}
fn maybe_add(store: &TripleStore, result: &mut Vec<Triple>, t: Triple) {
if !store.contains(&t.subject, &t.predicate, &t.object)
&& !result.iter().any(|r| r == &t)
{
result.push(t);
}
}
fn rule_rdfs2(store: &TripleStore, result: &mut Vec<Triple>) {
let domain_pred = rdfs_iri("domain");
let rdf_type = rdf_iri("type");
let domain_pairs: Vec<(String, String)> = store
.get_all_p(&domain_pred)
.into_iter()
.map(|t| (t.subject.clone(), t.object.clone()))
.collect();
for (prop, class) in &domain_pairs {
for triple in store.iter() {
if &triple.predicate == prop {
let inferred = Triple::new(&triple.subject, &rdf_type, class);
Self::maybe_add(store, result, inferred);
}
}
}
}
fn rule_rdfs3(store: &TripleStore, result: &mut Vec<Triple>) {
let range_pred = rdfs_iri("range");
let rdf_type = rdf_iri("type");
let range_pairs: Vec<(String, String)> = store
.get_all_p(&range_pred)
.into_iter()
.map(|t| (t.subject.clone(), t.object.clone()))
.collect();
for (prop, class) in &range_pairs {
for triple in store.iter() {
if &triple.predicate == prop {
let inferred = Triple::new(&triple.object, &rdf_type, class);
Self::maybe_add(store, result, inferred);
}
}
}
}
fn rule_rdfs5(store: &TripleStore, result: &mut Vec<Triple>) {
let sub_prop = rdfs_iri("subPropertyOf");
let pairs: Vec<(String, String)> = store
.get_all_p(&sub_prop)
.into_iter()
.map(|t| (t.subject.clone(), t.object.clone()))
.collect();
for (p, q) in &pairs {
for (q2, r) in &pairs {
if q == q2 && p != r {
let inferred = Triple::new(p, &sub_prop, r);
Self::maybe_add(store, result, inferred);
}
}
}
}
fn rule_rdfs6(store: &TripleStore, result: &mut Vec<Triple>) {
let rdf_type = rdf_iri("type");
let rdf_property = rdf_iri("Property");
let sub_prop = rdfs_iri("subPropertyOf");
for triple in store.get_all_p(&rdf_type) {
if triple.object == rdf_property {
let u = &triple.subject;
let inferred = Triple::new(u, &sub_prop, u);
Self::maybe_add(store, result, inferred);
}
}
}
fn rule_rdfs7(store: &TripleStore, result: &mut Vec<Triple>) {
let sub_prop = rdfs_iri("subPropertyOf");
let pairs: Vec<(String, String)> = store
.get_all_p(&sub_prop)
.into_iter()
.map(|t| (t.subject.clone(), t.object.clone()))
.collect();
for (p, q) in &pairs {
if p == q {
continue; }
for triple in store.iter() {
if &triple.predicate == p {
let inferred = Triple::new(&triple.subject, q, &triple.object);
Self::maybe_add(store, result, inferred);
}
}
}
}
fn rule_rdfs8(store: &TripleStore, result: &mut Vec<Triple>) {
let rdf_type = rdf_iri("type");
let rdfs_class = rdfs_iri("Class");
let rdfs_resource = rdfs_iri("Resource");
let sub_class = rdfs_iri("subClassOf");
for triple in store.get_all_p(&rdf_type) {
if triple.object == rdfs_class {
let u = &triple.subject;
let inferred = Triple::new(u, &sub_class, &rdfs_resource);
Self::maybe_add(store, result, inferred);
}
}
}
fn rule_rdfs9(store: &TripleStore, result: &mut Vec<Triple>) {
let rdf_type = rdf_iri("type");
let sub_class = rdfs_iri("subClassOf");
let class_pairs: Vec<(String, String)> = store
.get_all_p(&sub_class)
.into_iter()
.map(|t| (t.subject.clone(), t.object.clone()))
.collect();
for (c, d) in &class_pairs {
if c == d {
continue; }
for triple in store.get_all_p(&rdf_type) {
if &triple.object == c {
let inferred = Triple::new(&triple.subject, &rdf_type, d);
Self::maybe_add(store, result, inferred);
}
}
}
}
fn rule_rdfs10(store: &TripleStore, result: &mut Vec<Triple>) {
let rdf_type = rdf_iri("type");
let rdfs_class = rdfs_iri("Class");
let sub_class = rdfs_iri("subClassOf");
for triple in store.get_all_p(&rdf_type) {
if triple.object == rdfs_class {
let u = &triple.subject;
let inferred = Triple::new(u, &sub_class, u);
Self::maybe_add(store, result, inferred);
}
}
}
fn rule_rdfs11(store: &TripleStore, result: &mut Vec<Triple>) {
let sub_class = rdfs_iri("subClassOf");
let pairs: Vec<(String, String)> = store
.get_all_p(&sub_class)
.into_iter()
.map(|t| (t.subject.clone(), t.object.clone()))
.collect();
for (c, d) in &pairs {
for (d2, e) in &pairs {
if d == d2 && c != e {
let inferred = Triple::new(c, &sub_class, e);
Self::maybe_add(store, result, inferred);
}
}
}
}
fn rule_rdfs12(store: &TripleStore, result: &mut Vec<Triple>) {
let rdf_type = rdf_iri("type");
let rdfs_cmp = rdfs_iri("ContainerMembershipProperty");
let rdfs_member = rdfs_iri("member");
let sub_prop = rdfs_iri("subPropertyOf");
for triple in store.get_all_p(&rdf_type) {
if triple.object == rdfs_cmp {
let u = &triple.subject;
let inferred = Triple::new(u, &sub_prop, &rdfs_member);
Self::maybe_add(store, result, inferred);
}
}
}
}
impl EntailmentEngine for RdfsEntailmentEngine {
fn entail(&self, store: &TripleStore) -> Result<Vec<Triple>, EntailmentError> {
let mut result: Vec<Triple> = Vec::new();
Self::rule_rdfs2(store, &mut result);
Self::rule_rdfs3(store, &mut result);
Self::rule_rdfs5(store, &mut result);
Self::rule_rdfs6(store, &mut result);
Self::rule_rdfs7(store, &mut result);
Self::rule_rdfs8(store, &mut result);
Self::rule_rdfs9(store, &mut result);
Self::rule_rdfs10(store, &mut result);
Self::rule_rdfs11(store, &mut result);
Self::rule_rdfs12(store, &mut result);
Ok(result)
}
}