Skip to main content

Crate snomed_classify

Crate snomed_classify 

Source
Expand description

EL-profile subsumption classifier for SNOMED CT OWL axioms, per spec/13-classification.md.

SNOMED CT’s logic profile is OWL 2 EL, chosen specifically because EL subsumption is decidable in polynomial time via a completion (saturation) algorithm — the same family of algorithm real SNOMED CT reasoners (ELK, CEL) implement. This crate implements that algorithm (Baader/Brandt/Lutz, “Pushing the EL Envelope”, IJCAI 2005, plus the EL+ role-hierarchy/composition extension for property chains and transitive attributes SNOMED CT actually uses) from scratch, in terms of snomed_owl::Axiomsnomed-owl parses syntax, this crate reasons over the result.

classify answers subsumption (“is A a subtype of B, according to these axioms”). necessary_normal_form builds on it to answer the downstream question: what minimal set of RF2 Relationship rows would a release actually ship for a classified concept (spec/14) — proximal parents and redundancy-reduced, role-grouped attributes.

use snomed_core::sctid::SctId;
use snomed_owl::{parse, Axiom};
use snomed_classify::classify;

let axioms: Vec<Axiom> = [
    "SubClassOf(:64572001 :404684003)", // |Disease| ⊑ |Clinical finding|
    "SubClassOf(:22298006 :64572001)",  // |Myocardial infarction| ⊑ |Disease|
]
.iter()
.map(|s| parse(s).unwrap())
.collect();

let report = classify(&axioms);
let mi = SctId::parse("22298006").unwrap();
let finding = SctId::parse("404684003").unwrap();
assert!(report.classification.is_subsumed_by(mi, finding)); // transitively entailed
assert!(report.skipped.is_empty());

Structs§

Attribute
One necessary-normal-form relationship: group is 0 for ungrouped (spec/07’s relationshipGroup convention), otherwise a group number assigned 1..N in a stable (sorted) order — this crate generates from a single axiom set with no prior release to number against, so there’s no attempt to preserve any particular numbering scheme beyond that.
Classification
The result of classify: every named concept’s entailed named superclasses (transitively closed).
ClassificationReport
classify’s result: the classification, plus every input construct it recognized but couldn’t model (spec/13’s “Scope” section) — reported, never silently dropped without a trace.
NecessaryNormalForm
A concept’s necessary normal form: its proximal (most specific entailed, non-redundant) parents, and its redundancy-reduced attributes.
NecessaryNormalFormReport
necessary_normal_form’s result: one NecessaryNormalForm per named concept the input axioms said anything about, plus every construct recognized but not modeled (spec/14’s scope), reported never silently dropped.

Enums§

SkippedConstruct
#[non_exhaustive] per spec/rust-api-stability.md: this enum grows every time a construct is recognized but not modeled, and a consumer only ever reports what it holds.

Functions§

classify
Computes the full entailed subsumption hierarchy over axioms, via the EL completion algorithm (spec/13-classification.md).
necessary_normal_form
Computes the necessary normal form of every concept axioms mention, via classification (spec/13) plus stated-profile redundancy elimination (spec/14). axioms is read multiple times (classification, stated-profile extraction, role hierarchy) — a slice, not a single-pass iterator, unlike classify.