Apache Jena无法基于数据属性推理个体类型问题
OWL本体类型推理失败问题排查与解决
问题背景
我用Protégé创建了一个简单OWL本体,内容如下:
- 类
Person - 类
Adult:子类于Person与限制条件age exactly 1 xsd:integer[> 17]的交集 - 类
Minor:子类于Person与限制条件age exactly 1 xsd:integer[< 18]的交集 - 数据属性
age:定义域为Adult和Minor的并集,值域为xsd:integer - 个体
Child(age=12)、Grandfather(age=70)
目标是通过Jena推理,根据age值推断个体类型(如Child属于Minor),编写的代码如下:
OntModel model = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM_RULE_INF); FileManager fileManager = FileManager.getInternal(); model.read(fileManager.open(Objects.requireNonNull(getClass().getResource("/persone.owl")).toString()), null); Reasoner reasoner = ReasonerRegistry.getOWLReasoner().bindSchema(model); InfModel infModel = ModelFactory.createInfModel(reasoner, model); Resource minor = infModel.getResource("http://www.semanticweb.org/lorenzo/ontologies/2023/5/Persone#Minor"); Resource child = infModel.getResource("http://www.semanticweb.org/lorenzo/ontologies/2023/5/Persone#Child"); printStatements(infModel, child, null, null); if (infModel.contains(child, RDF.type, minor)) { System.out.println("Child is type Minor -> Inferenced correctly"); } else { System.out.println("Failed to inference Child's type correctly"); }
但推理失败,输出结果:
- (<http://www.semanticweb.org/lorenzo/ontologies/2023/5/Persone#Child> <http://www.semanticweb.org/lorenzo/ontologies/2023/5/Persone#age> '12'^^http://www.w3.org/2001/XMLSchema#integer) - (<http://www.semanticweb.org/lorenzo/ontologies/2023/5/Persone#Child> rdf:type owl:NamedIndividual) - (<http://www.semanticweb.org/lorenzo/ontologies/2023/5/Persone#Child> rdf:type owl:Thing) - (<http://www.semanticweb.org/lorenzo/ontologies/2023/5/Persone#Child> owl:sameAs <http://www.semanticweb.org/lorenzo/ontologies/2023/5/Persone#Child>) - (<http://www.semanticweb.org/lorenzo/ontologies/2023/5/Persone#Child> rdf:type rdfs:Resource) - (<http://www.semanticweb.org/lorenzo/ontologies/2023/5/Persone#Child> rdf:type 2449192a-2fc0-426e-a3ab-f9ef16f56342) Failed to inference Child's type correctly
问题原因
- 推理器能力不足:Jena自带的
OWL_DL_MEM_RULE_INF规则推理器对OWL 2的数值限制推理支持有限,无法处理基于数据属性数值比较的类成员推断。 - 本体类定义不严谨:将
Adult和Minor定义为交集的子类,而非等价类。推理器需要明确的等价类定义,才能反向推断个体所属类。
解决方案
1. 修正本体类定义
在Protégé中,将Adult和Minor的定义从SubClass Of改为Equivalent To:
Adult等价于:Person and (age exactly 1 xsd:integer[> 17])Minor等价于:Person and (age exactly 1 xsd:integer[< 18])
2. 更换支持OWL 2的推理器
使用HermiT或Pellet这类完整的OWL 2推理器,替代Jena自带的规则推理器。以下是使用HermiT的代码示例:
import org.semanticweb.HermiT.ReasonerFactory; import org.apache.jena.ontology.OntModel; import org.apache.jena.ontology.OntModelSpec; import org.apache.jena.rdf.model.InfModel; import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.rdf.model.Resource; import org.apache.jena.util.FileManager; import org.apache.jena.reasoner.Reasoner; import java.util.Objects; public class OntologyInference { public static void main(String[] args) { // 创建基础本体模型 OntModel model = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM); FileManager fileManager = FileManager.getInternal(); model.read(fileManager.open(Objects.requireNonNull(OntologyInference.class.getResource("/persone.owl")).toString()), null); // 初始化HermiT推理器 ReasonerFactory reasonerFactory = new ReasonerFactory(); Reasoner reasoner = reasonerFactory.createReasoner(model.getOntModelSpec().getProfile()); InfModel infModel = ModelFactory.createInfModel(reasoner, model); // 获取资源引用 Resource minor = infModel.getResource("http://www.semanticweb.org/lorenzo/ontologies/2023/5/Persone#Minor"); Resource child = infModel.getResource("http://www.semanticweb.org/lorenzo/ontologies/2023/5/Persone#Child"); // 输出所有相关语句 printStatements(infModel, child, null, null); // 验证推理结果 if (infModel.contains(child, org.apache.jena.vocabulary.RDF.type, minor)) { System.out.println("Child is type Minor -> Inferenced correctly"); } else { System.out.println("Failed to inference Child's type correctly"); } } private static void printStatements(InfModel model, Resource subject, org.apache.jena.rdf.model.Property predicate, org.apache.jena.rdf.model.RDFNode object) { model.listStatements(subject, predicate, object).forEachRemaining(stmt -> { System.out.println(" - (" + stmt.getSubject() + " " + stmt.getPredicate() + " " + stmt.getObject() + ")"); }); } }
3. 添加依赖(Maven)
在pom.xml中添加HermiT和Jena的依赖:
<dependencies> <!-- Jena本体API --> <dependency> <groupId>org.apache.jena</groupId> <artifactId>jena-ontology</artifactId> <version>4.9.0</version> </dependency> <!-- HermiT推理器 --> <dependency> <groupId>net.sourceforge.owlapi</groupId> <artifactId>org.semanticweb.hermit</artifactId> <version>1.4.3.517</version> </dependency> </dependencies>
验证效果
修改后运行代码,推理器会正确推断出Child rdf:type Minor,输出中会包含该语句,并打印Child is type Minor -> Inferenced correctly。
内容的提问来源于stack exchange,提问作者Alessio Rubicini
相关产品推荐
相关产品推荐

