如何在 OWL 中有效地获取推断的子类?
How to efficiently get inferred subclasses in OWL?
我正在使用 OWLAPI 来区分简单 断言 的子 class 和 推断 [=30] 的子class =].
我的代码工作正常,但它真的很慢:
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
}
}
}
}
如您所见,代码很慢,因为我在每次迭代中将每个 class 与所有其他的进行比较。
我找不到简单的方法,因为
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
}
}
}
您可以尝试几种方法。
一种方法是使用推断公理生成器并将其设置为仅生成 subclass 公理。与 reasoner 和 ontology 一起使用,它将为您提供所有可推断的 subclass 公理。然后您可以检查哪些出现在原始 ontology 中,哪些没有。
需要注意的一件事:在执行此操作之前以及在使用较新的方法之前删除注释 - 带注释的公理等同于未带注释的公理但不相等。留下注释会导致一些误报。
你也可以改进你的算法,虽然主要成本仍然是推理:
检查并跳过 parent 和 child 相同的情况 class
从推理机中得到等同于owl:Nothing的classes——这些都是不可满足的。在循环中跳过它们
owl:Thing
也一样
不是获取单个级别的子classes(你传递的真实值就是这样做的)获取[=48=的所有子classes =] 并缓存这些节点。在没有推理调用的情况下,将在那里找到许多 children。 (Reasoners 缓存 class 层次结构,所以这个可能不值多少钱)
您的循环将比较 a 和 b,然后是 b 和 a。如果发现 a 是 b 的超class,请不要检查 b 是否是 a 的超class。
在创建公理和调用推理器之前,请使用 OWLOntology 方法检查您的 classes 是否被断言为彼此的子class 或等价物。这些是快速操作,依赖于 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
});
});
});
我正在使用 OWLAPI 来区分简单 断言 的子 class 和 推断 [=30] 的子class =]. 我的代码工作正常,但它真的很慢:
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
}
}
}
}
如您所见,代码很慢,因为我在每次迭代中将每个 class 与所有其他的进行比较。
我找不到简单的方法,因为
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
}
}
}
您可以尝试几种方法。 一种方法是使用推断公理生成器并将其设置为仅生成 subclass 公理。与 reasoner 和 ontology 一起使用,它将为您提供所有可推断的 subclass 公理。然后您可以检查哪些出现在原始 ontology 中,哪些没有。
需要注意的一件事:在执行此操作之前以及在使用较新的方法之前删除注释 - 带注释的公理等同于未带注释的公理但不相等。留下注释会导致一些误报。
你也可以改进你的算法,虽然主要成本仍然是推理:
检查并跳过 parent 和 child 相同的情况 class
从推理机中得到等同于owl:Nothing的classes——这些都是不可满足的。在循环中跳过它们
owl:Thing
也一样
不是获取单个级别的子classes(你传递的真实值就是这样做的)获取[=48=的所有子classes =] 并缓存这些节点。在没有推理调用的情况下,将在那里找到许多 children。 (Reasoners 缓存 class 层次结构,所以这个可能不值多少钱)
您的循环将比较 a 和 b,然后是 b 和 a。如果发现 a 是 b 的超class,请不要检查 b 是否是 a 的超class。
在创建公理和调用推理器之前,请使用 OWLOntology 方法检查您的 classes 是否被断言为彼此的子class 或等价物。这些是快速操作,依赖于 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
});
});
});