我目前正在将 OWLAPI 与 HermiT Reasoner 结合使用,并且遇到了在我看来是一个错误的问题。 我定义了几种更新本体的方法,在单元测试期间我得到了几个相互矛盾的结果。
我的方法可以添加、删除和测试个体的存在,让它属于某个特定的类或让它属于
owl:Thing
。
这是一个矛盾的例子:被移除的个体仍然作为
owl:Thing
的实例存在。
boolean added = ontology.addIndividualToClass("Person", login);
Assert.isTrue(added, "The individual must be present.");
ontology.think();
boolean exists = ontology.doesIndividualBelongToClass("Person", login);
Assert.isTrue(exists, "The individual must be found.");
boolean removed = ontology.removeIndividualFromClass("Person", login);
Assert.isTrue(removed, "The individual must be removed.");
ontology.think();
// The next assertions is satisfied.
exists = ontology.doesIndividualBelongToClass("Person", login);
Assert.isTrue(!exists, "The individual must not be found.");
// The next assertions will fire, interrupting the test.
exists = ontology.doesIndividualExist(login);
Assert.isTrue(!exists, "The individual must not be present.");
我的方法是这样运作的:
所有方法似乎都能正确运行,但当删除现有个体时,它仍然显示为推断的。方法
think()
基本上是 flush()
的包装,并强制本体应用所有未决的更改。我在缓冲模式下使用 HermiT,我注意到切换到非缓冲并不能解决问题。
public boolean addIndividualToClass(String className, String login) {
[...] // Checks on parameters.
OWLNamedIndividual individual = dataFactory.getOWLNamedIndividual(individualName, prefixManager);
if (individual == null) throw new IllegalArgumentException("Could not get named individual.");
OWLClassAssertionAxiom classAssertion = dataFactory.getOWLClassAssertionAxiom(clazz, individual);
ChangeApplied changed = ontology.add(classAssertion);
return changed.equals(ChangeApplied.SUCCESSFULLY) || changed.equals(ChangeApplied.NO_OPERATION);
}
public boolean removeIndividualFromClass(String clazz, String individualName) {
[...] // Checks on parameters.
Optional<OWLClassAssertionAxiom> individualAssertionOpt =
ontology
.getClassAssertionAxioms(clazz)
.stream()
.filter(
i -> i.getIndividual().asOWLNamedIndividual().getIRI().getRemainder().orElse("").matches(individualName)
)
.findFirst();
if (!individualAssertionOpt.isPresent())
return false;
else {
ChangeApplied changed = ontology.remove(individualAssertionOpt.get());
return changed.equals(ChangeApplied.SUCCESSFULLY) || changed.equals(ChangeApplied.NO_OPERATION);
}
}
我在使用以下两种方法时遇到问题:
public boolean doesIndividualBelongToClass(String className, String name) {
[...] // Parameters tests and retrieval of 'clazz'.
Set<OWLNamedIndividual> inferredIndividuals =
reasoner
.getInstances(clazz, false)
.getFlattened()
.stream()
.filter(i -> i.getIRI().getRemainder().orElse("").equals(name))
.collect(Collectors.toSet());
Set<OWLNamedIndividual> assertedIndividuals = ontology
.individualsInSignature()
.filter(i -> i.getIRI().getRemainder().orElse("").equals(name))
.filter(
i -> reasoner
.getTypes(i)
.entities()
.filter(t -> t.getIRI().getRemainder().orElse("").equals(className))
.findFirst()
.isPresent()
).collect(Collectors.toSet());
inferredIndividuals.addAll(assertedIndividuals);
return inferredIndividuals
.stream()
.findFirst()
.isPresent();
}
public boolean doesIndividualExist(String login) {
return doesIndividualBelongToClass("owl:Thing", login);
}
一旦删除某个人,
doesIndividualExist()
返回 true,其中 doesIndividualBelongToClass()
返回 false。在调试过程中,我注意到被删除的个体仍然作为 owl:Thing
类的实例存在。
我仔细检查并开始通过方法询问DL查询
resoner.isSatisfiable()
:
DL 查询 {X}
,其中 X
是已删除的个人名称,结果是可以满足的。
我又做了一个测试:我保存了本体,用Protege浏览它,发现删除了不存在的个体,都没有推断出。
有人知道解决方法或实际的解决方案吗? 我是不是错过了什么?
OWLRasoner 实例可以是缓冲的或非缓冲的 - HermiT 推理机可以使用任一设置创建。 缓冲推理机将看到您对本体所做的更改,但不会将这些更改应用于其内部模型,直到您对其调用flush()方法。非缓冲推理机将立即对其内部模型应用更改。
要确认这是否是您问题背后的原因,请说明您如何创建 OWLRasoner 实例。 OWLReasonerFactory 具有创建缓冲和非缓冲推理器的方法。