如何在 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
                    });
            });
        });