Skip to main content

fukurow_dl/
model.rs

1//! OWL DL データモデル
2
3use fukurow_lite::model::{Class as OwlLiteClass, Property as OwlLiteProperty, Individual, OwlIri};
4use serde::{Deserialize, Serialize};
5use std::collections::HashSet;
6
7/// OWL DL Class Expression (extends OWL Lite)
8#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
9pub enum ClassExpression {
10    /// Named class (from OWL Lite)
11    Named(OwlIri),
12
13    /// owl:Thing (⊤)
14    Thing,
15
16    /// owl:Nothing (⊥)
17    Nothing,
18
19    /// Intersection of classes: C1 ⊓ C2 ⊓ ... ⊓ Cn
20    IntersectionOf(Vec<ClassExpression>),
21
22    /// Union of classes: C1 ⊔ C2 ⊔ ... ⊔ Cn
23    UnionOf(Vec<ClassExpression>),
24
25    /// Complement of class: ¬C
26    ComplementOf(Box<ClassExpression>),
27
28    /// Enumeration of individuals: {i1, i2, ..., in}
29    OneOf(Vec<Individual>),
30
31    /// Existential restriction: ∃R.C
32    SomeValuesFrom {
33        property: PropertyExpression,
34        class: Box<ClassExpression>,
35    },
36
37    /// Universal restriction: ∀R.C
38    AllValuesFrom {
39        property: PropertyExpression,
40        class: Box<ClassExpression>,
41    },
42
43    /// Has value: ∃R.{i}
44    HasValue {
45        property: PropertyExpression,
46        individual: Individual,
47    },
48
49    /// Minimum cardinality: ≥n R.C
50    MinCardinality {
51        cardinality: u32,
52        property: PropertyExpression,
53        class: Option<Box<ClassExpression>>, // None means owl:Thing
54    },
55
56    /// Maximum cardinality: ≤n R.C
57    MaxCardinality {
58        cardinality: u32,
59        property: PropertyExpression,
60        class: Option<Box<ClassExpression>>, // None means owl:Thing
61    },
62
63    /// Exact cardinality: =n R.C
64    ExactCardinality {
65        cardinality: u32,
66        property: PropertyExpression,
67        class: Option<Box<ClassExpression>>, // None means owl:Thing
68    },
69}
70
71/// OWL DL Property Expression
72#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
73pub enum PropertyExpression {
74    /// Object property
75    ObjectProperty(OwlIri),
76
77    /// Data property
78    DataProperty(OwlIri),
79
80    /// Inverse property: R⁻
81    InverseOf(Box<PropertyExpression>),
82}
83
84/// OWL DL Axiom (extends OWL Lite)
85#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
86pub enum Axiom {
87    /// OWL Lite axioms (re-exported)
88    OwlLite(fukurow_lite::Axiom),
89
90    /// SubClassOf with complex class expressions
91    SubClassOf(ClassExpression, ClassExpression),
92
93    /// EquivalentClasses with complex expressions
94    EquivalentClasses(Vec<ClassExpression>),
95
96    /// DisjointClasses with complex expressions
97    DisjointClasses(Vec<ClassExpression>),
98
99    /// SubPropertyOf with property expressions
100    SubPropertyOf(PropertyExpression, PropertyExpression),
101
102    /// EquivalentProperties
103    EquivalentProperties(Vec<PropertyExpression>),
104
105    /// ObjectPropertyDomain with complex class
106    ObjectPropertyDomain(PropertyExpression, ClassExpression),
107
108    /// ObjectPropertyRange with complex class
109    ObjectPropertyRange(PropertyExpression, ClassExpression),
110
111    /// Functional property
112    FunctionalProperty(PropertyExpression),
113
114    /// Inverse functional property
115    InverseFunctionalProperty(PropertyExpression),
116
117    /// Transitive property
118    TransitiveProperty(PropertyExpression),
119
120    /// Symmetric property
121    SymmetricProperty(PropertyExpression),
122
123    /// Asymmetric property
124    AsymmetricProperty(PropertyExpression),
125
126    /// Reflexive property
127    ReflexiveProperty(PropertyExpression),
128
129    /// Irreflexive property
130    IrreflexiveProperty(PropertyExpression),
131
132    /// Property disjointness
133    DisjointProperties(Vec<PropertyExpression>),
134
135    /// Same individual
136    SameIndividual(Vec<Individual>),
137
138    /// Different individuals
139    DifferentIndividuals(Vec<Individual>),
140
141    /// Class assertion with complex class
142    ClassAssertion(ClassExpression, Individual),
143
144    /// Object property assertion
145    ObjectPropertyAssertion(PropertyExpression, Individual, Individual),
146
147    /// Negative object property assertion
148    NegativeObjectPropertyAssertion(PropertyExpression, Individual, Individual),
149
150    /// Data property assertion (for completeness)
151    DataPropertyAssertion(OwlIri, Individual, String), // Simplified: IRI, Individual, Value
152
153    /// Negative data property assertion
154    NegativeDataPropertyAssertion(OwlIri, Individual, String),
155}
156
157/// OWL DL Ontology (extends OWL Lite)
158#[derive(Debug, Clone, Serialize, Deserialize)]
159pub struct OwlDlOntology {
160    /// Ontology IRI
161    pub iri: Option<OwlIri>,
162
163    /// All axioms in the ontology
164    pub axioms: Vec<Axiom>,
165
166    /// All classes mentioned (for compatibility)
167    pub classes: HashSet<OwlLiteClass>,
168
169    /// All properties mentioned (for compatibility)
170    pub properties: HashSet<OwlLiteProperty>,
171
172    /// All individuals mentioned
173    pub individuals: HashSet<Individual>,
174
175    /// Class expressions (for OWL DL specific constructs)
176    pub class_expressions: HashSet<ClassExpression>,
177
178    /// Property expressions (for OWL DL specific constructs)
179    pub property_expressions: HashSet<PropertyExpression>,
180}
181
182impl OwlDlOntology {
183    pub fn new() -> Self {
184        Self {
185            iri: None,
186            axioms: Vec::new(),
187            classes: HashSet::new(),
188            properties: HashSet::new(),
189            individuals: HashSet::new(),
190            class_expressions: HashSet::new(),
191            property_expressions: HashSet::new(),
192        }
193    }
194
195    pub fn with_iri(iri: OwlIri) -> Self {
196        Self {
197            iri: Some(iri),
198            axioms: Vec::new(),
199            classes: HashSet::new(),
200            properties: HashSet::new(),
201            individuals: HashSet::new(),
202            class_expressions: HashSet::new(),
203            property_expressions: HashSet::new(),
204        }
205    }
206
207    pub fn add_axiom(&mut self, axiom: Axiom) {
208        // Extract entities from axioms
209        match &axiom {
210            Axiom::OwlLite(lite_axiom) => {
211                // Handle OWL Lite axioms by converting to DL format
212                match lite_axiom {
213                    fukurow_lite::Axiom::SubClassOf(c1, c2) => {
214                        let ce1 = Self::owl_lite_class_to_expression(c1.clone());
215                        let ce2 = Self::owl_lite_class_to_expression(c2.clone());
216                        self.add_class_expression(&ce1);
217                        self.add_class_expression(&ce2);
218                    }
219                    fukurow_lite::Axiom::EquivalentClasses(classes) => {
220                        for class in classes {
221                            let expr = Self::owl_lite_class_to_expression(class.clone());
222                            self.add_class_expression(&expr);
223                        }
224                    }
225                    fukurow_lite::Axiom::DisjointClasses(classes) => {
226                        for class in classes {
227                            let expr = Self::owl_lite_class_to_expression(class.clone());
228                            self.add_class_expression(&expr);
229                        }
230                    }
231                    fukurow_lite::Axiom::SubPropertyOf(p1, p2) => {
232                        let pe1 = Self::owl_lite_property_to_expression(p1.clone());
233                        let pe2 = Self::owl_lite_property_to_expression(p2.clone());
234                        self.add_property_expression(&pe1);
235                        self.add_property_expression(&pe2);
236                    }
237                    fukurow_lite::Axiom::EquivalentProperties(properties) => {
238                        for prop in properties {
239                            let expr = Self::owl_lite_property_to_expression(prop.clone());
240                            self.add_property_expression(&expr);
241                        }
242                    }
243                    fukurow_lite::Axiom::ObjectPropertyDomain(p, c) => {
244                        let pe = Self::owl_lite_property_to_expression(p.clone());
245                        let ce = Self::owl_lite_class_to_expression(c.clone());
246                        self.add_property_expression(&pe);
247                        self.add_class_expression(&ce);
248                    }
249                    fukurow_lite::Axiom::ObjectPropertyRange(p, c) => {
250                        let pe = Self::owl_lite_property_to_expression(p.clone());
251                        let ce = Self::owl_lite_class_to_expression(c.clone());
252                        self.add_property_expression(&pe);
253                        self.add_class_expression(&ce);
254                    }
255                    fukurow_lite::Axiom::FunctionalProperty(p) |
256                    fukurow_lite::Axiom::InverseFunctionalProperty(p) |
257                    fukurow_lite::Axiom::TransitiveProperty(p) |
258                    fukurow_lite::Axiom::SymmetricProperty(p) => {
259                        let pe = Self::owl_lite_property_to_expression(p.clone());
260                        self.add_property_expression(&pe);
261                    }
262                    fukurow_lite::Axiom::SameIndividual(individuals) => {
263                        self.individuals.extend(individuals.iter().cloned());
264                    }
265                    fukurow_lite::Axiom::DifferentIndividuals(individuals) => {
266                        self.individuals.extend(individuals.iter().cloned());
267                    }
268                    fukurow_lite::Axiom::ClassAssertion(c, i) => {
269                        let ce = Self::owl_lite_class_to_expression(c.clone());
270                        self.add_class_expression(&ce);
271                        self.individuals.insert(i.clone());
272                    }
273                    fukurow_lite::Axiom::ObjectPropertyAssertion(p, i1, i2) => {
274                        let pe = Self::owl_lite_property_to_expression(p.clone());
275                        self.add_property_expression(&pe);
276                        self.individuals.insert(i1.clone());
277                        self.individuals.insert(i2.clone());
278                    }
279                    fukurow_lite::Axiom::NegativeObjectPropertyAssertion(p, i1, i2) => {
280                        let pe = Self::owl_lite_property_to_expression(p.clone());
281                        self.add_property_expression(&pe);
282                        self.individuals.insert(i1.clone());
283                        self.individuals.insert(i2.clone());
284                    }
285                }
286            }
287            Axiom::SubClassOf(ce1, ce2) => {
288                self.add_class_expression(ce1);
289                self.add_class_expression(ce2);
290            }
291            Axiom::EquivalentClasses(expressions) => {
292                for expr in expressions {
293                    self.add_class_expression(expr);
294                }
295            }
296            Axiom::DisjointClasses(expressions) => {
297                for expr in expressions {
298                    self.add_class_expression(expr);
299                }
300            }
301            Axiom::SubPropertyOf(pe1, pe2) => {
302                self.add_property_expression(pe1);
303                self.add_property_expression(pe2);
304            }
305            Axiom::EquivalentProperties(expressions) => {
306                for expr in expressions {
307                    self.add_property_expression(expr);
308                }
309            }
310            Axiom::ObjectPropertyDomain(pe, ce) => {
311                self.add_property_expression(pe);
312                self.add_class_expression(ce);
313            }
314            Axiom::ObjectPropertyRange(pe, ce) => {
315                self.add_property_expression(pe);
316                self.add_class_expression(ce);
317            }
318            Axiom::FunctionalProperty(pe) |
319            Axiom::InverseFunctionalProperty(pe) |
320            Axiom::TransitiveProperty(pe) |
321            Axiom::SymmetricProperty(pe) |
322            Axiom::AsymmetricProperty(pe) |
323            Axiom::ReflexiveProperty(pe) |
324            Axiom::IrreflexiveProperty(pe) => {
325                self.add_property_expression(pe);
326            }
327            Axiom::DisjointProperties(expressions) => {
328                for expr in expressions {
329                    self.add_property_expression(expr);
330                }
331            }
332            Axiom::SameIndividual(individuals) => {
333                self.individuals.extend(individuals.iter().cloned());
334            }
335            Axiom::DifferentIndividuals(individuals) => {
336                self.individuals.extend(individuals.iter().cloned());
337            }
338            Axiom::ClassAssertion(ce, i) => {
339                self.add_class_expression(ce);
340                self.individuals.insert(i.clone());
341            }
342            Axiom::ObjectPropertyAssertion(pe, i1, i2) |
343            Axiom::NegativeObjectPropertyAssertion(pe, i1, i2) => {
344                self.add_property_expression(pe);
345                self.individuals.insert(i1.clone());
346                self.individuals.insert(i2.clone());
347            }
348            Axiom::DataPropertyAssertion(_, i, _) |
349            Axiom::NegativeDataPropertyAssertion(_, i, _) => {
350                self.individuals.insert(i.clone());
351            }
352        }
353
354        self.axioms.push(axiom);
355    }
356
357    fn owl_lite_class_to_expression(class: OwlLiteClass) -> ClassExpression {
358        match class {
359            OwlLiteClass::Named(iri) => ClassExpression::Named(iri),
360            OwlLiteClass::Thing => ClassExpression::Thing,
361            OwlLiteClass::Nothing => ClassExpression::Nothing,
362        }
363    }
364
365    fn owl_lite_property_to_expression(property: OwlLiteProperty) -> PropertyExpression {
366        match property {
367            OwlLiteProperty::Object(iri) => PropertyExpression::ObjectProperty(iri),
368            OwlLiteProperty::Data(iri) => PropertyExpression::DataProperty(iri),
369        }
370    }
371
372    pub fn add_class_expression(&mut self, expr: &ClassExpression) {
373        // Recursively collect all class expressions
374        self.collect_class_expressions(expr);
375    }
376
377    pub fn add_property_expression(&mut self, expr: &PropertyExpression) {
378        // Recursively collect all property expressions
379        self.collect_property_expressions(expr);
380    }
381
382    fn collect_class_expressions(&mut self, expr: &ClassExpression) {
383        match expr {
384            ClassExpression::Named(iri) => {
385                self.classes.insert(OwlLiteClass::Named(iri.clone()));
386            }
387            ClassExpression::Thing => {
388                self.classes.insert(OwlLiteClass::Thing);
389            }
390            ClassExpression::Nothing => {
391                self.classes.insert(OwlLiteClass::Nothing);
392            }
393            ClassExpression::IntersectionOf(expressions) |
394            ClassExpression::UnionOf(expressions) => {
395                for expr in expressions {
396                    self.collect_class_expressions(expr);
397                }
398            }
399            ClassExpression::ComplementOf(expr) => {
400                self.collect_class_expressions(expr);
401            }
402            ClassExpression::OneOf(individuals) => {
403                self.individuals.extend(individuals.iter().cloned());
404            }
405            ClassExpression::SomeValuesFrom { class, .. } |
406            ClassExpression::AllValuesFrom { class, .. } => {
407                self.collect_class_expressions(class);
408            }
409            ClassExpression::HasValue { individual, .. } => {
410                self.individuals.insert(individual.clone());
411            }
412            ClassExpression::MinCardinality { class, .. } |
413            ClassExpression::MaxCardinality { class, .. } |
414            ClassExpression::ExactCardinality { class, .. } => {
415                if let Some(class) = class {
416                    self.collect_class_expressions(class);
417                }
418            }
419        }
420        self.class_expressions.insert(expr.clone());
421    }
422
423    fn collect_property_expressions(&mut self, expr: &PropertyExpression) {
424        match expr {
425            PropertyExpression::ObjectProperty(iri) => {
426                self.properties.insert(OwlLiteProperty::Object(iri.clone()));
427            }
428            PropertyExpression::DataProperty(iri) => {
429                self.properties.insert(OwlLiteProperty::Data(iri.clone()));
430            }
431            PropertyExpression::InverseOf(expr) => {
432                self.collect_property_expressions(expr);
433            }
434        }
435        self.property_expressions.insert(expr.clone());
436    }
437}