RDFS Materialization¶
RDFS TBox materialization via ontologos-rdfs: transitive subClassOf / subPropertyOf closure and object-property domain/range inheritance.
Prerequisites¶
- Rust 1.88+
- An OWL/RDF file (
.owl,.rdf,.ttl,.ofn) or a repository clone for benchmark examples
Run the CLI¶
Build from a clone (CLI is not on crates.io):
Prefer materialize over classify — both run the same RDFS engine in v0.4, but classify is named like OWL taxonomy classification tools (ELK/HermiT) and is easy to misread.
Expected text output (Family corpus, abbreviated):
status: materialized
initial_axiom_count: 57
final_axiom_count: 62
inferred_axioms: 5
inferred_by_rule:
rng_inherit: 5
JSON output: ./target/release/ontologos --format json materialize path/to/ontology.owl
Library (crates.io)¶
Add dependencies:
Load and materialize:
use ontologos_parser::load_ontology;
use ontologos_rdfs::RdfsEngine;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let path = std::path::Path::new("ontology.owl");
let mut ontology = load_ontology(path)?;
let initial = ontology.axiom_count();
let report = RdfsEngine::new().materialize(&mut ontology)?;
println!("initial axioms: {initial}");
println!("final axioms: {}", report.final_axiom_count);
println!("inferred: {}", report.inferred_total());
for (rule, count) in &report.inferred_by_rule {
println!(" {}: {count}", rule.as_str());
}
Ok(())
}
Do not call Reasoner::classify() on core for RDFS — it returns a delegate hint. Use RdfsEngine::materialize or ontologos_rdfs::classify_reasoner.
Via the reasoner facade¶
use ontologos_core::{Profile, Reasoner};
use ontologos_parser::load_ontology;
use ontologos_rdfs::classify_reasoner;
let ontology = load_ontology(path)?;
let mut reasoner = Reasoner::builder()
.profile(Profile::Rdfs)
.build(ontology)?;
classify_reasoner(&mut reasoner)?;
println!("axioms: {}", reasoner.ontology().axiom_count());
Reading the report¶
| Field | Meaning |
|---|---|
initial_axiom_count |
Axioms before materialization |
final_axiom_count |
Axioms after RDFS closure |
inferred_by_rule |
Per-rule counts (subclass_trans, subprop_trans, dom_inherit, rng_inherit) |
traces |
Per-inference records when tracing is enabled |
inferred_total() equals final_axiom_count - initial_axiom_count.
What RDFS materializes (v0.4)¶
| Input in core | Materialized |
|---|---|
SubClassOf |
Transitive closure |
SubObjectPropertyOf |
Transitive closure |
ObjectPropertyDomain / ObjectPropertyRange |
Inherited along subPropertyOf |
EquivalentClasses |
Stored only — mutual subsumption via OWL RL saturation |
| ABox assertions | Not propagated — use RL saturation |
Python¶
from ontologos import Reasoner
reasoner = Reasoner("ontology.owl", profile="rdfs")
reasoner.classify()
print(reasoner.parse_meta["mapped_axiom_count"])
See Python guide for limitations.
Next steps¶
- OWL RL saturation — adds equivalence, ABox propagation, and more
- Choosing an API — RDFS vs RL vs future EL
- Profile detection
- Troubleshooting