Galigator / openllet

Openllet is an OWL 2 reasoner in Java, build on top of Pellet.
https://www.w3.org/TR/owl2-primer/
Other
99 stars 26 forks source link

Get "java.util.NoSuchElementException" while reasoning #35

Open greeny277 opened 6 years ago

greeny277 commented 6 years ago

Hey.

I get a NoSuchElementException while reasoning. It appeared after I changed the datatype of a property from xsd:decimal to xsd:float. It could be, that I made something wrong. Either way, I don't think that the reasoner should throw this exception and at least use a try{...}catch(Exception e){...} construct.

Best regards,

Christian

Classifying:  20% complete in 00:01Exception in thread "main" java.util.NoSuchElementException
        at openllet.core.datatypes.EmptyIterator.next(EmptyIterator.java:35)
        at openllet.core.boxes.abox.Literal.checkClash(Literal.java:403)
        at openllet.core.boxes.abox.Literal.addType(Literal.java:284)
        at openllet.core.tableau.completion.CompletionStrategy.addType(CompletionStrategy.java:420)
        at openllet.core.rules.ContinuousRulesStrategy.addType(ContinuousRulesStrategy.java:96)
        at openllet.core.tableau.completion.rule.AllValuesRule.applyAllValues(AllValuesRule.java:181)
        at openllet.core.tableau.completion.rule.AllValuesRule.applyAllValues(AllValuesRule.java:118)
        at openllet.core.tableau.completion.CompletionStrategy.addType(CompletionStrategy.java:452)
        at openllet.core.rules.ContinuousRulesStrategy.addType(ContinuousRulesStrategy.java:96)
        at openllet.core.tableau.branch.DisjunctionBranch.tryBranch(DisjunctionBranch.java:215)
        at openllet.core.tableau.branch.Branch.tryNext(Branch.java:130)
        at openllet.core.tableau.completion.rule.DisjunctionRule.applyDisjunctionRule(DisjunctionRule.java:101)
        at openllet.core.tableau.completion.rule.DisjunctionRule.apply(DisjunctionRule.java:58)
        at openllet.core.tableau.completion.rule.AbstractTableauRule.apply(AbstractTableauRule.java:106)
        at openllet.core.rules.ContinuousRulesStrategy.complete(ContinuousRulesStrategy.java:251)
        at openllet.core.boxes.abox.ABoxImpl.lambda$isConsistent$12(ABoxImpl.java:1417)
        at openllet.core.utils.Timers.execute(Timers.java:118)
        at openllet.core.boxes.abox.ABoxImpl.isConsistent(ABoxImpl.java:1417)
        at openllet.core.boxes.abox.ABoxImpl.isSatisfiable(ABoxImpl.java:621)
        at openllet.core.boxes.abox.ABoxImpl.isSubClassOf(ABoxImpl.java:566)
        at openllet.core.taxonomy.CDOptimizedTaxonomyBuilder.subsumes(CDOptimizedTaxonomyBuilder.java:1163)
        at openllet.core.taxonomy.CDOptimizedTaxonomyBuilder.subCheckWithCache(CDOptimizedTaxonomyBuilder.java:1121)
        at openllet.core.taxonomy.CDOptimizedTaxonomyBuilder.nodeSubsumes(CDOptimizedTaxonomyBuilder.java:1130)
        at openllet.core.taxonomy.CDOptimizedTaxonomyBuilder.search(CDOptimizedTaxonomyBuilder.java:1045)
        at openllet.core.taxonomy.CDOptimizedTaxonomyBuilder.doTopSearch(CDOptimizedTaxonomyBuilder.java:964)
        at openllet.core.taxonomy.CDOptimizedTaxonomyBuilder.classify(CDOptimizedTaxonomyBuilder.java:830)
        at openllet.core.taxonomy.CDOptimizedTaxonomyBuilder.classify(CDOptimizedTaxonomyBuilder.java:266)
        at openllet.core.taxonomy.CDOptimizedTaxonomyBuilder.classify(CDOptimizedTaxonomyBuilder.java:212)
        at openllet.core.KnowledgeBaseImpl.classify(KnowledgeBaseImpl.java:1919)
        at openllet.core.KnowledgeBaseImpl.realize(KnowledgeBaseImpl.java:1938)
        at openllet.core.knowledge.InstancesBase.getTypes(InstancesBase.java:366)
        at openllet.query.sparqldl.engine.CombinedQueryEngine.exec(CombinedQueryEngine.java:356)
        at openllet.query.sparqldl.engine.CombinedQueryEngine.exec(CombinedQueryEngine.java:304)
        at openllet.query.sparqldl.engine.CombinedQueryEngine.exec(CombinedQueryEngine.java:249)
        at openllet.query.sparqldl.engine.QueryEngine.execSingleQuery(QueryEngine.java:313)
        at openllet.query.sparqldl.engine.QueryEngine.exec(QueryEngine.java:124)
        at openllet.query.sparqldl.jena.SparqlDLExecution.exec(SparqlDLExecution.java:240)
        at openllet.query.sparqldl.jena.SparqlDLExecution.execSelect(SparqlDLExecution.java:203)
....
greeny277 commented 6 years ago

I'm using version 2.6.4-SNAPSHOT. However, the Pellet reasoner already has this bug.

ignazio1977 commented 6 years ago

at least use a try{...}catch(Exception e){...} construct

That's a reasonable expectation but the issue here is more subtle.

There is a .next() on an empty iterator, and from the code I suspect there is an incorrect condition being checked:

                 if (dtReasoner.isSatisfiable(types))
            {
                if (!dtReasoner.containsAtLeast(2, types))

                                   ^^^^^^^^^^^^^^^ This is strange. 

I think the ! is misplaced - it's trying to merge nodes when there are not at least two nodes, i.e., when there is one node or no nodes, like in this case. I suspect the intention was to only merge nodes when there are two or more nodes (and where the .next() operation would have been safe)

                {
                    /*
                     * This literal is a variable, but given _current ranges can only
                     * take on a single _value.  Merge with that _value.
                     */
                    final Object value = dtReasoner.valueIterator(types).next();
                    final ATermAppl valueTerm = dtReasoner.getLiteral(value);
                    Literal valueLiteral = _abox.getLiteral(valueTerm);
                    if (valueLiteral == null)
                        /*
                         * No dependency set is used here because omitting it prevents the
                         * constant literal from being removed during backtrack
                         */
                        valueLiteral = _abox.addLiteral(valueTerm);
                    DependencySet mergeDs = DependencySet.INDEPENDENT;
                    for (final DependencySet ds : _depends.values())
                        mergeDs = mergeDs.union(ds, _abox.doExplanation());
                    _merge = new NodeMerge(this, valueLiteral, mergeDs);
                }
            }
greeny277 commented 6 years ago

Ah ok. So I guess it's a bug that can be easily fixed.

Galigator commented 5 years ago

In fact I spend some weekends on it. It is harder to fix because simple change around this create problems elsewhere. It may need a modern rewrite with less mutable structures.