如何使用 OWLAPI 有效地计算不相交性?
How to efficiently compute disjointness with OWLAPI?
我正在分析基于 OWLAPI 的应用程序,我发现的唯一瓶颈是计算 不相交性。
我必须检查每个 class 是否与其他 classes 不相交,如果这是 asserted 或 inferred。
计算起来似乎很繁重,因为与基于 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
上调用并循环 A
和 B
,然后在 B
上调用并重复计算。
保留一组已访问的 classes,您可以将不相交节点集中的所有元素添加到其中,当轮到 B
时,您也可以跳过 reasoner 调用。说到这里,我假设 reasoner 调用实际上是此方法中最昂贵的调用。您是否有其他情况的分析数据?
优化 4:我不相信这段代码能可靠地告诉您哪些不相交的公理被推断出来,哪些不相交公理被断言。你可以:
A disjointWith B
B disjointWith C
推理者会 return {A, B, C}
来响应 A
的不相交请求。您会在不相交公理的签名中找到所有三个元素,并发现推理者没有进行任何推理。但是输入中的公理与输出中的公理不同(许多推理者实际上 运行 吸收输入公理并将它们转换为内部表示,即具有三个操作数的公理)。
因此,我对推断和断言的定义是推理器 return 的节点集与一个不相交公理的操作数集相同。为了验证这个条件,我会采用所有不相交的公理,提取操作数集并将这些集合保存在一组集合中。然后,
- 对于每个 class(并保持优化以仅访问每个 class 一次),
- 获取一组不相交的节点(此处优化为不打扰如果集合中只有一个class),
- 将其转换为一组实体,
- 并检查之前创建的集合集合是否包含这个新集合。
如果是,这是一个断言的公理;如果不是,则推断。
我正在分析基于 OWLAPI 的应用程序,我发现的唯一瓶颈是计算 不相交性。 我必须检查每个 class 是否与其他 classes 不相交,如果这是 asserted 或 inferred。
计算起来似乎很繁重,因为与基于 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
上调用并循环 A
和 B
,然后在 B
上调用并重复计算。
保留一组已访问的 classes,您可以将不相交节点集中的所有元素添加到其中,当轮到 B
时,您也可以跳过 reasoner 调用。说到这里,我假设 reasoner 调用实际上是此方法中最昂贵的调用。您是否有其他情况的分析数据?
优化 4:我不相信这段代码能可靠地告诉您哪些不相交的公理被推断出来,哪些不相交公理被断言。你可以:
A disjointWith B
B disjointWith C
推理者会 return {A, B, C}
来响应 A
的不相交请求。您会在不相交公理的签名中找到所有三个元素,并发现推理者没有进行任何推理。但是输入中的公理与输出中的公理不同(许多推理者实际上 运行 吸收输入公理并将它们转换为内部表示,即具有三个操作数的公理)。
因此,我对推断和断言的定义是推理器 return 的节点集与一个不相交公理的操作数集相同。为了验证这个条件,我会采用所有不相交的公理,提取操作数集并将这些集合保存在一组集合中。然后,
- 对于每个 class(并保持优化以仅访问每个 class 一次),
- 获取一组不相交的节点(此处优化为不打扰如果集合中只有一个class),
- 将其转换为一组实体,
- 并检查之前创建的集合集合是否包含这个新集合。 如果是,这是一个断言的公理;如果不是,则推断。