owl - 如何在OWL中高效地获取推断子类?

标签 owl owl-api

我使用 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/

相关文章:

rdf - 猫头鹰有芝麻之类的东西吗

java - 按顺序获取同等类(class)

java - 将字符串转换为复杂的 OWL 公理

Sparql 1.1 获取特定类的所有实例,但不包括子类的任何实例

java - 将 OWL 公理转换为曼彻斯特语法

logic - OWL 2 中两个域表达式之间的等价

OWL通用量化

java - 获取类 OwlApi 的子类

java - 处理dl查询中的数据值限制

jena - OWL API、Jena API、Protege API,用哪一个