ontologos-rdfs 0.9.0

RDFS materialization facade over reasonable for OntoLogos
Documentation
use std::collections::BTreeMap;

use ontologos_core::{AxiomId, InferenceTrace};
use serde::Serialize;

/// RDFS TBox rule that produced an inference.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum RdfsRule {
    /// Transitive `rdfs:subClassOf`.
    ScTrans,
    /// Transitive `rdfs:subPropertyOf`.
    SpTrans,
    /// Domain inheritance along the property hierarchy (RDFS 6).
    DomInherit,
    /// Range inheritance along the property hierarchy (RDFS 8).
    RngInherit,
}

impl RdfsRule {
    #[must_use]
    pub fn as_str(self) -> &'static str {
        match self {
            Self::ScTrans => "sc_trans",
            Self::SpTrans => "sp_trans",
            Self::DomInherit => "dom_inherit",
            Self::RngInherit => "rng_inherit",
        }
    }
}

/// A single recorded inference (legacy alias; prefer [`TraceStep`]).
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct InferenceRecord {
    pub rule: RdfsRule,
    pub premises: Vec<AxiomId>,
    pub conclusion: AxiomId,
}

/// Summary of RDFS materialization over an ontology.
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct MaterializationReport {
    pub initial_axiom_count: usize,
    pub final_axiom_count: usize,
    pub inferred_by_rule: BTreeMap<RdfsRule, usize>,
    #[serde(skip_serializing_if = "trace_is_empty")]
    pub trace: InferenceTrace,
    #[serde(skip_serializing_if = "Vec::is_empty")]
    pub clashes: Vec<String>,
}

fn trace_is_empty(trace: &InferenceTrace) -> bool {
    trace.steps.is_empty()
}

impl MaterializationReport {
    #[must_use]
    pub fn inferred_total(&self) -> usize {
        self.final_axiom_count
            .saturating_sub(self.initial_axiom_count)
    }
}