如何使用 OWLAPI 有效地计算不相交性?

How to efficiently compute disjointness with OWLAPI?

我正在分析基于 OWLAPI 的应用程序,我发现的唯一瓶颈是计算 不相交性。 我必须检查每个 class 是否与其他 classes 不相交,如果这是 assertedinferred

计算起来似乎很繁重,因为与基于 Node 数据结构的等价性(并且检索数据效率很高)不同,不相交性是基于在 NodeSet 上,我被迫以这种方式执行更多循环。 这是我使用的程序:

private void computeDisjointness(OWLClass clazz) {

    NodeSet<OWLClass> disjointSetsFromCls = reasoner.getDisjointClasses(clazz);
    for (Node<OWLClass> singleDisjoinSet : disjointSetsFromCls) {
        for (OWLClass item : singleDisjoinSet) {
             for (OWLDisjointClassesAxiom disjAxiom : ontology.getAxioms(AxiomType.DISJOINT_CLASSES)) {
                 if(disjAxiom.containsEntityInSignature(item))
                  {
                   //asserted
                  }
                  else
                  {
                  //derived
                  }
        }
    }
}

如您所见,瓶颈是由 3 个降低应用程序速度的 for 循环造成的;此外,程序 computeDisjointness 为 ontology 的每个 class 执行。

是否有更有效的方法来获取不相交性并检查公理是否被断言或导出?

一个简单的优化是将ontology.getAxioms(AxiomType.DISJOINT_CLASSES)移动到调用方法,然后将其作为参数传入。此方法 return 在每次调用时都是一个新集,每次都具有相同的内容,因为您没有修改 ontology。因此,如果你有 N class 个,你将创建 至少 N 个相同的集合;如果许多 classes 实际上是不相交的。

优化二:检查不相交节点集的大小。大小 1 表示没有不相交,因此您可以跳过该方法的其余部分。

优化 3:跟踪您已经访问过的 classes。例如,如果您有

A disjointWith B

您的代码将在 A 上调用并循环 AB,然后在 B 上调用并重复计算。 保留一组已访问的 classes,您可以将不相交节点集中的所有元素添加到其中,当轮到 B 时,您也可以跳过 reasoner 调用。说到这里,我假设 reasoner 调用实际上是此方法中最昂贵的调用。您是否有其他情况的分析数据?

优化 4:我不相信这段代码能可靠地告诉您哪些不相交的公理被推断出来,哪些不相交公理被断言。你可以:

A disjointWith B
B disjointWith C

推理者会 return {A, B, C} 来响应 A 的不相交请求。您会在不相交公理的签名中找到所有三个元素,并发现推理者没有进行任何推理。但是输入中的公理与输出中的公理不同(许多推理者实际上 运行 吸收输入公理并将它们转换为内部表示,即具有三个操作数的公理)。 因此,我对推断和断言的定义是推理器 return 的节点集与一个不相交公理的操作数集相同。为了验证这个条件,我会采用所有不相交的公理,提取操作数集并将这些集合保存在一组集合中。然后,

  • 对于每个 class(并保持优化以仅访问每个 class 一次),
    • 获取一组不相交的节点(此处优化为不打扰如果集合中只有一个class),
    • 将其转换为一组实体,
    • 并检查之前创建的集合集合是否包含这个新集合。 如果是,这是一个断言的公理;如果不是,则推断。