在我的应用程序中,我需要将命名个体添加到本体。稍后我需要能够检索这些命名的个体并确定它们的推断类型,但由于某种原因,我无法检索它们的类型。根据我使用的OWL推理器,我得到异常或空集。
以下是一个说明问题的自包含示例:
package owl.api.test.StandaloneOWLNamedIndividualRetrievalv5;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Set;
import java.util.stream.Collectors;
import org.semanticweb.HermiT.ReasonerFactory;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.model.OWLOntologyStorageException;
import org.semanticweb.owlapi.model.PrefixManager;
import org.semanticweb.owlapi.model.parameters.ChangeApplied;
import org.semanticweb.owlapi.reasoner.NodeSet;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.semanticweb.owlapi.reasoner.OWLReasonerFactory;
import org.semanticweb.owlapi.search.EntitySearcher;
import org.semanticweb.owlapi.util.DefaultPrefixManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
import openllet.owlapi.OpenlletReasonerFactory;
import uk.ac.manchester.cs.jfact.JFactFactory;
public class App {
private static Logger logger = LoggerFactory
.getLogger(owl.api.test.StandaloneOWLNamedIndividualRetrievalv5.App.class);
// Why This Failure marker
private static final Marker WTF_MARKER = MarkerFactory.getMarker("WTF");
public static void main(String[] args) {
try {
// Setup physical IRI for storing ontology
Path path = Paths.get(".").toAbsolutePath().normalize();
IRI loadDocumentIRI = IRI.create("file:" + path.toFile().getAbsolutePath() + "/SimpleOntology.owl");
logger.trace("documentIRI=" + loadDocumentIRI);
IRI saveDocumentIRI = IRI.create("file:" + path.toFile().getAbsolutePath() + "/SimpleOntologyUpdated.owl");
logger.trace("documentIRI=" + saveDocumentIRI);
// Initialize
OWLOntologyManager manager = OWLManager.createOWLOntologyManager();
OWLDataFactory dataFactory = manager.getOWLDataFactory();
OWLOntology ontology = manager.loadOntologyFromOntologyDocument(loadDocumentIRI);
// OWLReasonerFactory reasonerFactory = new JFactFactory();
OWLReasonerFactory reasonerFactory = new ReasonerFactory();
// OWLReasonerFactory reasonerFactory = OpenlletReasonerFactory.getInstance();
OWLReasoner reasoner = reasonerFactory.createReasoner(ontology);
PrefixManager pm = new DefaultPrefixManager(ontology.getOntologyID().getOntologyIRI().get().getIRIString());
// Get references to a new named individual and an existing class
OWLIndividual individual = dataFactory.getOWLNamedIndividual("#ind1", pm);
OWLClass owlClass = dataFactory.getOWLClass("#ClassB", pm);
// Create class assertion axiom
OWLClassAssertionAxiom classAssertionAxiom = dataFactory.getOWLClassAssertionAxiom(owlClass, individual);
// Add class assertion axiom to ontology
ChangeApplied changeApplied = manager.addAxiom(ontology, classAssertionAxiom);
logger.trace("ChangeApplied = " + changeApplied);
if (changeApplied.equals(ChangeApplied.SUCCESSFULLY)) {
try {
manager.saveOntology(ontology, saveDocumentIRI);
} catch (OWLOntologyStorageException e) {
logger.error(e.getMessage());
}
}
// Now try to retrieve the individual
logger.trace(
"Trying to retrieve individual = " + classAssertionAxiom.getIndividual().asOWLNamedIndividual());
Set<Object> classExpressionTypes = EntitySearcher.getTypes(classAssertionAxiom.getIndividual(), ontology)
.collect(Collectors.toSet());
logger.trace("Individual = " + classAssertionAxiom.getIndividual() + " has types based on EntitySearcher "
+ classExpressionTypes);
NodeSet<OWLClass> types = reasoner.getTypes(classAssertionAxiom.getIndividual().asOWLNamedIndividual(),
false);
logger.trace("Individual = " + classAssertionAxiom.getIndividual()
+ " has types based on reasoner.getTypes " + types);
} catch (Throwable t) {
logger.error(WTF_MARKER, t.getMessage(), t);
}
}
}
这是我用来测试的简单本体:
<?xml version="1.0"?>
<rdf:RDF xmlns="http://www.semanticweb.org/2017/simple#"
xml:base="http://www.semanticweb.org/2017/simple"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:xml="http://www.w3.org/XML/1998/namespace"
xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<owl:Ontology rdf:about="http://www.semanticweb.org/2017/simple"/>
<owl:Class rdf:about="http://www.semanticweb.org/2017/simple#ClassA"/>
<owl:Class rdf:about="http://www.semanticweb.org/2017/simple#ClassB">
<rdfs:subClassOf rdf:resource="http://www.semanticweb.org/2017/simple#ClassA"/>
</owl:Class>
</rdf:RDF>
运行此代码后,我希望它会确定单个ind1
的类型为Thing
,ClassA
和ClassB
。
认为此问题可能与特定的OWL推理器有关,我尝试使用JFact
,HermiT
和Openllet
。 JFact
引发NullPointerException
,HermiT
仅返回owl:Thing
和Openllet
。但是,当我将对本体的更改保存到文件并重新加载时,我可以找到使用任何这些reasoners添加的个体的推断类型。
我已经使用OWL API的5.1.2和4.5.0版进行了测试。我也试过调用reasoner.precomputeInferences()
,即使文档声明这不是必要的,但它没有任何区别。
答案 0 :(得分:2)
reasonerFactory.createReasoner(ontology)
创建一个缓冲推理器,即在更改本体后必须手动同步。
来自Javadoc的更多细节:
本体变更管理(缓冲和非缓冲模式)
在创建时,
OWLReasoner
将在根中加载公理 本体进口关闭。它将自己作为一个倾听者 管理根本体的OWLOntologyManager
。推理者会 听取任何OWLOntologyChanges
并对他们做出适当的回应 在回答任何疑问之前。如果是推理者的BufferingMode
(getBufferingMode()
的答案是BufferingMode.NON_BUFFERING
) 本体更改由推理器立即处理,以便任何 在对更改进行回答后询问 改变了本体论。如果推理器的BufferingMode是BufferingMode.BUFFERING
然后将本体更改存储在缓冲区中 并且仅在使用冲洗缓冲区时将其考虑在内flush()
方法。在推理时,根本体中的公理 进口封闭,减去由此返回的公理getPendingAxiomAdditions()
方法,加上由公式返回的公理getPendingAxiomRemovals()
被考虑在内。注意 无法保证推理器的实施会响应 以增量(和有效方式)方式改变。
两个选项:
reasoner.flush()
。reasonerFactory.createNonBufferingReasoner(ontology)
答案 1 :(得分:0)
问题在于推理者确实使用了本体论是在创建推理器的时候。我现在不使用Protege(桌面),它使用底层的OWL API。我这样做并且在Protege中使用推理器你应该注意到在更改本体之后你必须刷新推理器。在Protege中,这也在窗口底部的状态行中指示。
每次更改本体时都必须重新创建推理器。解决您的示例中的问题在检索个体的块之前添加以下行:
reasoner = reasonerFactory.createReasoner(ontology);
祝你好运
延