Get "java.util.NoSuchElementException" while reasoning
Opened this issue · 4 comments
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)
....
I'm using version 2.6.4-SNAPSHOT. However, the Pellet reasoner already has this bug.
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);
}
}
Ah ok. So I guess it's a bug that can be easily fixed.
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.