在不重新加载 ontology 的情况下,无法检索通过 OWL API 添加的命名个人的推论
Cannot retrieve inferences for named individual added via OWL API without reloading ontology
在我的应用程序中,我需要将指定的个人添加到 ontology。稍后我需要能够检索这些命名的个体并确定它们的推断类型,但由于某种原因我无法检索它们的类型。根据我使用的 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);
}
}
}
这是我用来测试的简单 ontology:
<?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
仅 returns owl:Thing
而 Openllet
什么也没有。但是,当我将对 ontology 的更改保存到文件并重新加载它时,我可以找到我使用这些推理器中的任何一个添加的个人的推断类型。
我已经用 OWL API 的 5.1.2 和 4.5.0 版本对此进行了测试。我也尝试过调用 reasoner.precomputeInferences()
,尽管文档说明这不是必需的,但没有任何区别。
问题是推理器确实在创建推理器时使用了 ontology。如果您使用 Protege(桌面),我现在不知道,它在后台使用 OWL API。我这样做并且还在 Protege 中使用了推理器,您应该注意到在对 ontology 进行更改后必须刷新推理器。在 Protege 中,这也显示在 window.
底部的状态行中
每次更改 ontology 时都必须重新创建推理器。解决示例中的问题在检索个人的块之前添加以下行:
reasoner = reasonerFactory.createReasoner(ontology);
此致
延斯
reasonerFactory.createReasoner(ontology)
创建一个缓冲推理器,即它必须在您更改 ontology.
后手动同步
来自 Javadoc 的更多详细信息:
Ontology Change Management (Buffering and Non-Buffering Modes)
At creation time, an OWLReasoner
will load the axioms in the root
ontology imports closure. It will attach itself as a listener to the
OWLOntologyManager
that manages the root ontology. The reasoner will
listen to any OWLOntologyChanges
and respond appropriately to them
before answering any queries. If the BufferingMode
of the reasoner
(the answer to getBufferingMode()
is BufferingMode.NON_BUFFERING
) the
ontology changes are processed by the reasoner immediately so that any
queries asked after the changes are answered with respect to the
changed ontologies. If the BufferingMode of the reasoner is
BufferingMode.BUFFERING
then ontology changes are stored in a buffer
and are only taken into consideration when the buffer is flushed with
the flush()
method. When reasoning, axioms in the root ontology
imports closure, minus the axioms returned by the
getPendingAxiomAdditions()
method, plus the axioms returned by the
getPendingAxiomRemovals()
are taken into consideration. Note that
there is no guarantee that the reasoner implementation will respond to
changes in an incremental (and efficient manner) manner.
两个选项:
- 在向推理者询问推论之前请致电
reasoner.flush()
。
- 创建一个非缓冲推理器,即使用
reasonerFactory.createNonBufferingReasoner(ontology)
在我的应用程序中,我需要将指定的个人添加到 ontology。稍后我需要能够检索这些命名的个体并确定它们的推断类型,但由于某种原因我无法检索它们的类型。根据我使用的 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);
}
}
}
这是我用来测试的简单 ontology:
<?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
仅 returns owl:Thing
而 Openllet
什么也没有。但是,当我将对 ontology 的更改保存到文件并重新加载它时,我可以找到我使用这些推理器中的任何一个添加的个人的推断类型。
我已经用 OWL API 的 5.1.2 和 4.5.0 版本对此进行了测试。我也尝试过调用 reasoner.precomputeInferences()
,尽管文档说明这不是必需的,但没有任何区别。
问题是推理器确实在创建推理器时使用了 ontology。如果您使用 Protege(桌面),我现在不知道,它在后台使用 OWL API。我这样做并且还在 Protege 中使用了推理器,您应该注意到在对 ontology 进行更改后必须刷新推理器。在 Protege 中,这也显示在 window.
底部的状态行中每次更改 ontology 时都必须重新创建推理器。解决示例中的问题在检索个人的块之前添加以下行:
reasoner = reasonerFactory.createReasoner(ontology);
此致
延斯
reasonerFactory.createReasoner(ontology)
创建一个缓冲推理器,即它必须在您更改 ontology.
来自 Javadoc 的更多详细信息:
Ontology Change Management (Buffering and Non-Buffering Modes)
At creation time, an
OWLReasoner
will load the axioms in the root ontology imports closure. It will attach itself as a listener to theOWLOntologyManager
that manages the root ontology. The reasoner will listen to anyOWLOntologyChanges
and respond appropriately to them before answering any queries. If theBufferingMode
of the reasoner (the answer togetBufferingMode()
isBufferingMode.NON_BUFFERING
) the ontology changes are processed by the reasoner immediately so that any queries asked after the changes are answered with respect to the changed ontologies. If the BufferingMode of the reasoner isBufferingMode.BUFFERING
then ontology changes are stored in a buffer and are only taken into consideration when the buffer is flushed with theflush()
method. When reasoning, axioms in the root ontology imports closure, minus the axioms returned by thegetPendingAxiomAdditions()
method, plus the axioms returned by thegetPendingAxiomRemovals()
are taken into consideration. Note that there is no guarantee that the reasoner implementation will respond to changes in an incremental (and efficient manner) manner.
两个选项:
- 在向推理者询问推论之前请致电
reasoner.flush()
。 - 创建一个非缓冲推理器,即使用
reasonerFactory.createNonBufferingReasoner(ontology)