如何在OWLAPI中区分断言公理与推理公理?
用OWLAPI区分断言公理与推理公理
要搞定捕获本体中已存在的断言公理和推理机推导的推理公理这件事,核心思路就是分别拿到这两类公理的集合,再通过集合操作把它们区分开。下面一步步来拆解:
1. 获取本体里的断言公理
本体中直接声明的所有公理,都能通过OWLOntology对象直接获取,这些就是实打实的断言公理:
// 假设你已经成功加载了本体ontology Set<OWLAxiom> assertedAxioms = ontology.getAxioms(); // 也可以按类型过滤,比如只获取类断言公理 Set<OWLClassAssertionAxiom> assertedClassAxioms = ontology.getAxioms(AxiomType.CLASS_ASSERTION);
2. 通过推理机获取推理公理
先初始化一个推理机(比如常用的HermiT),预计算所有推理结果后,就能拿到所有推导出来的公理:
// 初始化HermiT推理机 OWLReasonerFactory reasonerFactory = new Reasoner.ReasonerFactory(); OWLReasoner reasoner = reasonerFactory.createReasoner(ontology); reasoner.precomputeInferences(); // 预计算所有推理内容,提升后续查询效率 // 获取所有类型的推理公理 Set<OWLAxiom> inferredAxioms = reasoner.getInferredAxioms(AxiomType.values()); // 按需过滤,比如只获取子类关系的推理公理 Set<OWLSubClassOfAxiom> inferredSubClassAxioms = reasoner.getInferredAxioms(AxiomType.SUBCLASS_OF);
3. 区分两类公理:求差集
把推理公理集合里的断言公理去掉,剩下的就是本体里没有、纯靠推理机推导出来的公理:
// 新建推理公理的副本,避免修改原集合 Set<OWLAxiom> purelyInferredAxioms = new HashSet<>(inferredAxioms); // 移除所有断言公理,留下的就是纯推导结果 purelyInferredAxioms.removeAll(assertedAxioms);
结合你的层级打印代码优化
你给出的printHierarchy方法可以扩展一下,打印类层级时直接标记出哪些子类关系是断言的,哪些是推理出来的:
public void printHierarchy(OWLReasoner reasoner, OWLClass clazz, int level, Set<OWLClass> visited, OWLOntology ontology, OWLDataFactory factory) throws OWLException { // 跳过已访问的类和不可满足的Nothing类 if (!visited.contains(clazz) && reasoner.isSatisfiable(clazz)) { visited.add(clazz); // 打印带缩进的类名 System.out.printf("%s%s%n", "-".repeat(level), clazz.getIRI().getFragment()); // 获取当前类的所有直接子类(包括断言和推理的) NodeSet<OWLClass> subClasses = reasoner.getSubClasses(clazz, true); for (OWLClass subClass : subClasses.getFlattened()) { // 判断当前子类关系是否是本体中已声明的断言公理 boolean isAsserted = ontology.containsAxiom( factory.getOWLSubClassOfAxiom(subClass, clazz) ); // 打印时标记类型 System.out.printf("%s%s (%s)%n", "-".repeat(level+1), subClass.getIRI().getFragment(), isAsserted ? "断言关系" : "推理关系"); // 递归打印子类的层级 printHierarchy(reasoner, subClass, level+2, visited, ontology, factory); } } }
这里要注意两个点:
- 推理机的
getSubClasses()第二个参数direct设为true时,只返回直接子类;设为false会返回所有层级的子类。 - 用
ontology.containsAxiom()可以快速判断某个公理是否是本体里预先声明的。
内容的提问来源于stack exchange,提问作者Wall
相关产品推荐
相关产品推荐

