Skip to main content

ontologos_core/
trace.rs

1//! Engine-agnostic inference trace types for explanation generation.
2
3use serde::{Deserialize, Serialize};
4
5use crate::axiom::AxiomId;
6use crate::entity::EntityId;
7
8/// What an inference step concludes.
9#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
10#[serde(rename_all = "snake_case", tag = "kind")]
11pub enum TraceConclusion {
12    /// A new or existing ontology axiom.
13    Axiom {
14        /// Concluded axiom id.
15        id: AxiomId,
16    },
17    /// EL completion: `sub ⊑ sup`.
18    SubClassOf {
19        /// Subclass entity.
20        sub: EntityId,
21        /// Superclass entity.
22        sup: EntityId,
23    },
24    /// EL completion: `class ⊑ ∃property.filler`.
25    Existential {
26        /// Subject class.
27        class: EntityId,
28        /// Object property.
29        property: EntityId,
30        /// Filler class.
31        filler: EntityId,
32    },
33    /// EL completion: `subProperty ⊑ superProperty`.
34    SubObjectPropertyOf {
35        /// Sub property.
36        sub: EntityId,
37        /// Super property.
38        sup: EntityId,
39    },
40}
41
42/// A premise referenced by an inference step.
43#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
44#[serde(rename_all = "snake_case", tag = "kind")]
45pub enum TracePremise {
46    /// An ontology axiom used as a premise.
47    Axiom {
48        /// Premise axiom id.
49        id: AxiomId,
50    },
51    /// EL graph edge `sub ⊑ sup` used as a premise.
52    SubClassOf {
53        /// Subclass entity.
54        sub: EntityId,
55        /// Superclass entity.
56        sup: EntityId,
57    },
58    /// EL graph edge `sub ⊑ ∃property.filler` used as a premise.
59    Existential {
60        /// Subject class.
61        class: EntityId,
62        /// Object property.
63        property: EntityId,
64        /// Filler class.
65        filler: EntityId,
66    },
67    /// EL graph edge `subProperty ⊑ superProperty` used as a premise.
68    SubObjectPropertyOf {
69        /// Sub property.
70        sub: EntityId,
71        /// Super property.
72        sup: EntityId,
73    },
74}
75
76/// A single recorded inference step.
77#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
78pub struct TraceStep {
79    /// Rule name (engine-specific snake_case identifier).
80    pub rule: String,
81    /// Premises for this step.
82    pub premises: Vec<TracePremise>,
83    /// What this step concludes.
84    pub conclusion: TraceConclusion,
85}
86
87/// Ordered list of inference steps from a reasoning run.
88#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
89pub struct InferenceTrace {
90    /// Steps in derivation order.
91    pub steps: Vec<TraceStep>,
92}
93
94impl InferenceTrace {
95    /// Create an empty trace.
96    #[must_use]
97    pub fn new() -> Self {
98        Self::default()
99    }
100
101    /// Append a step.
102    pub fn push(&mut self, step: TraceStep) {
103        self.steps.push(step);
104    }
105}