我正在使用OWLAPI来区分简单的asserted子类和inferred的子类。我的代码工作正常,但速度确实很慢:
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:的类,推理者什么都没用-这些都不满足。跳过循环
与猫头鹰相同:事物
而不是获取单个级别的子类(您传递的真实值会这样做)立即获取一个类的所有子类并缓存这些节点。在没有推理呼叫的情况下,将发现许多儿童。 (原因是缓存类的层次结构,所以这一类可能不值多少)
您的循环将比较a和b,然后比较b和a。如果您发现a是b的超类,请不要检查b是否是a的超类。
在创建公理并调用推理器之前,请使用OWLOntology方法检查您的类是否被声明为彼此的子类或等效类。这些是快速的操作,依赖于哈希图索引。