我使用 OWLAPI 来区分简单断言的子类和推断的子类。 我的代码运行良好,但速度非常慢:
for(OWLClass clazz : ontology.getClassesInSignature())
{
for(OWLClass child: ontology.getClassesInSignature())
{
if(reasoner.isSatisfiable(child) )
{
NodeSet<OWLClass> subClasses = reasoner.getSubClasses(clazz, true);
OWLSubClassOfAxiom subAxiomTest = myModel.factory.getOWLSubClassOfAxiom(child, clazz);
if(!ontology.containsAxiom(subAxiomTest) && subClasses.containsEntity(child) && !clazz.isTopEntity())
{
//do something
}
}
}
}
正如您所看到的,代码很慢,因为我在每次迭代中都将每个类与所有其他类进行比较。
我找不到简单的方法
NodeSet<OWLClass> subClasses = reasoner.getSubClasses(clazz, true);
仅获取推断的结果。
有没有更有效的方法来做到这一点?
编辑:
这是我的解决方案,它极大地提高了性能。如果有人遇到同样的问题,可以尝试以下方法:
NodeSet<OWLClass> subClassesDerived = reasoner.getSubClasses(clazz, true);
for (OWLClass child : subClassesDerived.getFlattened()) {
if(reasoner.isSatisfiable(child) )
{
//Test axiom
OWLAxiom subAxiomTest = myModel.factory.getOWLSubClassOfAxiom(child, clazz);
if(!ontology.containsAxiom(subAxiomTest) && subClassesDerived.containsEntity(child) && !clazz.isTopEntity())
{
//subclass derived found - DO SOMETHING
}
}
}
最佳答案
您可以尝试几种方法。 一种方法是使用推断公理生成器并将其设置为仅生成子类公理。与推理机和本体论一起使用,它将获得所有可推断的子类公理。然后您可以检查哪些出现在原始本体中,哪些没有出现。
需要注意的一件事:在执行此操作之前以及使用较新的方法之前删除注释 - 带注释的公理相当于未带注释的公理,但不相等。保留注释会导致一些误报。
您还可以改进您的算法,尽管主要成本仍然是推理:
检查并跳过父子属于同一类的情况
获取与 owl:Nothing from the Reasoner 等效的类 - 这些都是不可满足的。在循环中跳过它们
猫头鹰:东西也一样
不是获取单个级别的子类(您传入的真实值就是这样做的),而是一次获取类的所有子类并缓存这些节点。许多 child 会在那里被发现,而无需推理。 (原因缓存了类层次结构,因此这个可能没有多大值(value))
您的循环将比较 a 和 b,然后比较 b 和 a。如果发现 a 是 b 的父类(super class),则不要检查 b 是否是 a 的父类(super class)。
在创建公理和调用推理器之前,请使用 OWLOntology 方法检查您的类是否被断言为彼此的子类或等效类。这些都是快速操作,依赖于 HashMap 索引。
编辑:在您的第二个版本之后,我将尝试以下调整:
Node<OWLClass> unsatisfiableClasses = reasoner.getUnsatisfiableClasses();
Set<OWLClass> visitedClasses = new HashSet<>();
ontology.classesInSignature().filter(clazz -> !clazz.isBuiltIn())
.filter(visitedClasses::add).filter(clazz -> !unsatisfiableClasses.contains(clazz))
.forEach(clazz -> {
NodeSet<OWLClass> subClassesDerived = reasoner.getSubClasses(clazz, true);
// for all classes equivalent to clazz, the reasoner will return the same set of
// results
Node<OWLClass> equivalentClasses = reasoner.getEquivalentClasses(clazz);
equivalentClasses.entities().forEach(c -> {
visitedClasses.add(c);
Set<OWLClassExpression> assertedChildren =
ontology.subClassAxiomsForSuperClass(c).map(OWLSubClassOfAxiom::getSubClass)
.filter(OWLClassExpression::isNamed).collect(Collectors.toSet());
subClassesDerived.entities()
.filter(child -> !unsatisfiableClasses.contains(child))
.filter(child -> !assertedChildren.contains(child)).forEach(child -> {
// subclass derived found - DO SOMETHING
// c is the superclass, child is the subclass
});
});
});
关于owl - 如何在OWL中高效地获取推断子类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60322425/