Как эффективно получить предполагаемые подклассы в OWL? - PullRequest
2 голосов
/ 20 февраля 2020

Я использую OWLAPI для различения guish между подклассами, которые просто заявлены , и теми, которые выведены . Мой код работает нормально, но он действительно медленный:

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
                }
            }
        }

1 Ответ

3 голосов
/ 21 февраля 2020

Есть несколько подходов, которые вы можете попробовать. Одним из способов является использование предполагаемого генератора аксиом и настройка его генерации только аксиом подкласса. Используемый с аргументами и онтологией, он получит все аксиомы подкласса. Затем вы можете проверить, какие из них присутствуют в исходной онтологии, а какие нет.

Одна вещь, на которую следует обратить внимание: удалите аннотации, прежде чем делать это, и перед использованием более молодого подхода - аннотированные аксиомы эквивалентны неаннотированным аксиомам, но не равны. Оставив аннотации в, вы получите несколько ложных срабатываний.

Вы также можете улучшить свой алгоритм, хотя основными затратами по-прежнему будут рассуждения:

  • Проверьте и пропустите случаи, когда родительский и child - это один и тот же класс

  • Получить классы, эквивалентные сове: Ничего от рассудителя - все это неудовлетворительно. Пропустите их в циклах

  • То же самое для совы: Thing

  • Вместо получения подклассов для одного уровня (истинное значение, которое вы передаете делает это) получает все подклассы класса одновременно и кэширует эти узлы. Там будет много детей без звонков. (Разумники кэшируют иерархию классов, так что эта может не стоить много)

  • Ваши циклы будут сравнивать a и b, затем b и a. Если вы обнаружите, что a является суперклассом класса b, не проверяйте, является ли b суперклассом класса a.

  • Перед созданием аксиом и вызовом аргумента, проверьте с помощью методов 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
                    });
            });
        });
...