Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StackOverflowError with SWRL reasoning in openllet #24

Open
JackJackie opened this issue Oct 3, 2017 · 10 comments
Open

StackOverflowError with SWRL reasoning in openllet #24

JackJackie opened this issue Oct 3, 2017 · 10 comments
Labels
bug Developper confirm there is a bug in the product. can't reproduce Developper can't reproduce the issue, more information may be need

Comments

@JackJackie
Copy link

Hi all,

I'm raising a new issue around a StackOverflowError of openllet. I'm using the same set-up of Apache Jena Fuseki and the openllet reasoner as @barrynl describes in #21.

I've build a small ontology with Protege and defined a SWRL rule on top of it. This rule also uses SWRL Build-In functions to subtract and compare values. The SWRL rule used is:

wapa:ActualStock(?s1) ^ wapa:hasQuantityValue(?s1, ?q1) ^ wapa:hasStockYearMonth(?s1, ?date1) ^ swrlb:date(?date1, ?y, ?m1, ?d1, ?t1) ^ wapa:isStockOf(?s1, ?v) ^ wapa:isInStockAt(?s1, ?co) ^

wapa:ActualStock(?s2) ^ wapa:hasQuantityValue(?s2, ?q2) ^ wapa:hasStockYearMonth(?s2, ?date2) ^ swrlb:date(?date2, ?y, ?m2, ?d2, ?t2) ^ wapa:isStockOf(?s2, ?v) ^ wapa:isInStockAt(?s2, ?co) ^

swrlb:subtract(1, ?m1, ?m2) ^ swrlb:subtract(?moved, ?q2, ?q1) ^

wapa:MovedStock(?c) ^ wapa:isStockOf(?c, ?v) ^ wapa:isInStockAt(?c, ?co)

->

wapa:hasQuantityValue(?c, ?moved)

Please find below also the first part of the error message. As you can see there is a loop in the message that continues until the stack is full. I cannot retrieve where the reasoner gets stuck into a loop and how the SWRL rule is causing this.

Hopefully someone can help?

Thanks in advance, Jack

 java.lang.StackOverflowError
 	at openllet.core.datatypes.types.floating.FloatingPointInterval.valid(FloatingPointInterval.java:166)
 	at openllet.core.datatypes.DiscreteInterval.contains(DiscreteInterval.java:171)
 	at openllet.core.datatypes.types.floating.FloatingPointInterval.contains(FloatingPointInterval.java:94)
 	at openllet.core.datatypes.types.floating.RestrictedFloatingPointDatatype.contains(RestrictedFloatingPointDatatype.java:195)
 	at openllet.core.datatypes.DatatypeReasonerImpl.containedIn(DatatypeReasonerImpl.java:307)
 	at openllet.core.datatypes.DatatypeReasonerImpl.isSatisfiable(DatatypeReasonerImpl.java:717)
 	at openllet.core.datatypes.DatatypeReasonerImpl.isSatisfiable(DatatypeReasonerImpl.java:679)
 	at openllet.core.boxes.abox.Literal.checkClash(Literal.java:369)
 	at openllet.core.boxes.abox.Literal.addType(Literal.java:286)
 	at openllet.core.tableau.completion.CompletionStrategy.addType(CompletionStrategy.java:419)
 	at openllet.core.rules.ContinuousRulesStrategy.addType(ContinuousRulesStrategy.java:93)
 	at openllet.core.tableau.completion.CompletionStrategy.applyDomainRange(CompletionStrategy.java:616)
 	at openllet.core.tableau.completion.CompletionStrategy.applyPropertyRestrictions(CompletionStrategy.java:579)
 	at openllet.core.tableau.completion.CompletionStrategy.addEdge(CompletionStrategy.java:566)
 	at openllet.core.rules.ContinuousRulesStrategy.addEdge(ContinuousRulesStrategy.java:81)
 	at openllet.core.rules.rete.ProductionNode$Edge.activate(ProductionNode.java:159)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaMemoryNode.activate(BetaMemoryNode.java:74)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaMemoryNode.activate(BetaMemoryNode.java:74)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaMemoryNode.activate(BetaMemoryNode.java:74)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaMemoryNode.activate(BetaMemoryNode.java:74)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaBuiltinNode.activate(BetaBuiltinNode.java:46)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaBuiltinNode.activate(BetaBuiltinNode.java:46)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaMemoryNode.activate(BetaMemoryNode.java:74)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaBuiltinNode.activate(BetaBuiltinNode.java:46)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaMemoryNode.activate(BetaMemoryNode.java:58)
 	at openllet.core.rules.rete.AlphaNode.lambda$activate$1(AlphaNode.java:52)
 	at java.util.Vector.forEach(Vector.java:1249)
 	at openllet.core.rules.rete.AlphaNode.activate(AlphaNode.java:52)
 	at openllet.core.rules.rete.AlphaEdgeNode.activate(AlphaEdgeNode.java:76)
 	at openllet.core.rules.rete.AlphaNetwork.activateEdge(AlphaNetwork.java:169)
 	at openllet.core.rules.ContinuousRulesStrategy.addEdge(ContinuousRulesStrategy.java:85)
 	at openllet.core.rules.rete.ProductionNode$Edge.activate(ProductionNode.java:159)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaMemoryNode.activate(BetaMemoryNode.java:74)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaMemoryNode.activate(BetaMemoryNode.java:74)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaMemoryNode.activate(BetaMemoryNode.java:74)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaMemoryNode.activate(BetaMemoryNode.java:74)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaBuiltinNode.activate(BetaBuiltinNode.java:46)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaBuiltinNode.activate(BetaBuiltinNode.java:46)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaMemoryNode.activate(BetaMemoryNode.java:74)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaBuiltinNode.activate(BetaBuiltinNode.java:46)
 	at openllet.core.rules.rete.BetaNode.activateChildren(BetaNode.java:27)
 	at openllet.core.rules.rete.BetaMemoryNode.activate(BetaMemoryNode.java:58)
 	at openllet.core.rules.rete.AlphaNode.lambda$activate$1(AlphaNode.java:52)
 	at java.util.Vector.forEach(Vector.java:1249)
@Galigator Galigator added the bug Developper confirm there is a bug in the product. label Oct 3, 2017
@Galigator
Copy link
Owner

Version 2.6.1 ? Do you have a small ontology that produce the error ? something I could try.

@Galigator
Copy link
Owner

Galigator commented Oct 3, 2017

It is possible that the problem came from the rule itself. Sometime the production of a predicat (wapa:hasQuantityValue(?c, ?moved)) can lead to application of the rule one more time. Then the new predicat lead to application one more time etc... The endless loop is logical not in the reasonner.

That why I absolutely need the ontology to understand what is the problem.

@JackJackie
Copy link
Author

Hi @Galigator, the version we use is 2.6.0. Well, the rule does work with the Pellet reasoner in Protege, so, I assume that the rule itself is correct. I'll attach the turtle-file as .txt.
bigtu-wapa-model+instances.txt

Hopefully, you can use it to find out what the problem is.

Thanks again, Jack

@Galigator
Copy link
Owner

Thx for the ontology.
I have made some trys with the OwlApi(like Protege) and it looks okay.

Also when using jena with Openllet 2.6.2, there is no java.lang.StackOverflowError .
But results aren't correct because in openllet-jena some builtin are missing. "date", "substract" are not set.

@Galigator
Copy link
Owner

By playing around with your ontology.
I manage to create an infinite loop.
It look like ordering on some iterator is important to create the bug.
But most of ordering depend on hashcodes that rely on natives.

By the way, there is no support for swrlb-builtins in the openllet-jena module; maybe I could try to add it.

@JackJackie
Copy link
Author

Hi, thanks for all your efforts!

Good to know that the rule itself is correct. Sorry to hear that the reasoning depends on the order of some iterator. Of course, you are free to add functionality to the openllet-jena module :-). I also look into alternatives to see what kind of SWRL support they provide.

Best, Jack

@Galigator
Copy link
Owner

Galigator commented Oct 4, 2017

I am a stupid hedgehog.

Jena does support the builtins you are using; the builtin that aren't support are only the following ones :
addYearMonthDurations; subtractYearMonthDurations; multiplyYearMonthDuration; divideYearMonthDuration; addDayTimeDurations; subtractDayTimeDurations; multiplyDayTimeDuration; divideDayTimeDuration; subtractDates; subtractTimes; dYearMonthDurationToDateTime; addDayTimeDurationToDateTime;subtractYearMonthDurationFromDateTime; subtractDayTimeDurationFromDateTime; addYearMonthDurationToDate; addDayTimeDurationToDate; subtractYearMonthDurationFromDate; subtractDayTimeDurationFromDate; addDayTimeDurationToTime; subtractDayTimeDurationFromTime: subtractDateTimesYieldingYearMonthDuration; subtractDateTimesYieldingDayTimeDuration;

Then by adding, the namespace that are missing in your file :

@prefix swrl: <http://www.w3.org/2003/11/swrl#> .
@prefix swrlb: <http://www.w3.org/2003/11/swrlb#> .

results are goods with the 2.6.2 :

		@Test
	public void testSWRLConsistencyWithBuiltIn()
	{
		final InputStream stream = AddDelTripleInferenceTest.class.getResourceAsStream("/bigtu-wapa-model.instances.ttl");
		final OntModel ontoModelInferred = ModelFactory.createOntologyModel(PelletReasonerFactory.THE_SPEC);
		ontoModelInferred.read(stream, null, "TURTLE");
		ontoModelInferred.prepare();

		final Resource s = ontoModelInferred.createResource("http://wapa#Moved-Jun-17-1");
		final Property p = ontoModelInferred.createProperty("http://bwapa#hasQuantityValue");
		{

			final Literal o = ontoModelInferred.createTypedLiteral(40.0);
			final Statement stmt = ResourceFactory.createStatement(s, p, o);
			assertTrue(ontoModelInferred.contains(stmt));
		}

		{
			final Literal o = ontoModelInferred.createTypedLiteral(41.0);
			final Statement stmt = ResourceFactory.createStatement(s, p, o);
			assertFalse(ontoModelInferred.contains(stmt));
		}

		ontoModelInferred.listObjectsOfProperty(s, p).forEachRemaining(System.out::println);

	}
``` (I shorten the wapas namespaces to read them faster).

@JackJackie
Copy link
Author

Thx for all the work! Good to know...I'll try to make it work in our Jena Fuseki server!

Best, Jack.

@Galigator
Copy link
Owner

Did you make it work with success ?

@JackJackie
Copy link
Author

Hi, to be honest...unfortunately not!
We downloaded your 2.6.3 version of openllet, build the .jar files and incorporated them into our Apache Jena Fuseki config file to call the reasoner via the "openllet.jena.PelletReasonerFactory" class as shown below.

So, the facts are that the ontology and reasoning works with Protege, with your implementation but not in Jena Fuseki. And thus the problem will somewhere in there, meaning that Jena Fuseki uses your openllet implementation differently.

Next step would be to dive into the Jena Fuseki source code to find out how the openllet reasoner is being used. However, we are reluctant to do that as it takes a lot of time. So, a good example of how others are using the combination of Jena Fuseki and openllet would be welcome.

# Licensed under the terms of http://www.apache.org/licenses/LICENSE-2.0

@prefix : <#> .
@prefix fuseki: <http://jena.apache.org/fuseki#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix tdb: <http://jena.hpl.hp.com/2008/tdb#> .
@prefix ja: <http://jena.hpl.hp.com/2005/11/Assembler#> .

[] rdf:type fuseki:Server ;
	fuseki:services (
	<#service1>
	) .

# Custom code.
[] ja:loadClass "com.hp.hpl.jena.tdb.TDB" .

# TDB
tdb:DatasetTDB rdfs:subClassOf ja:RDFDataset .
tdb:GraphTDB rdfs:subClassOf ja:Model .

## ---------------------------------------------------------------
## Service with only SPARQL query on an inference model.
## Inference model bbase data in TDB.

<#service1> rdf:type fuseki:Service ;
	fuseki:name "pizza" ; # http://host/pizza
	fuseki:serviceQuery "query" ; # SPARQL query service
	fuseki:serviceUpdate "update" ;
	fuseki:serviceUpload "upload" ; # Non-SPARQL upload service
	fuseki:serviceReadWriteGraphStore "data" ; # SPARQL Graph store protocol (read and write)
	# A separate read-only graph store endpoint:
	fuseki:serviceReadGraphStore "get" ; # SPARQL Graph store protocol (read only)
	fuseki:dataset <#dataset> .

<#dataset> rdf:type ja:RDFDataset ;
	ja:defaultGraph <#model_inf> .

<#model_inf> a ja:InfModel ;
	ja:baseModel <#tdbGraph> ;
	ja:content <#test-inf> ;
	ja:reasoner [
#		ja:reasonerURL <http://jena.hpl.hp.com/2003/RDFSExptRuleReasoner>
		ja:reasonerClass "openllet.jena.PelletReasonerFactory"
	] .

<#tdbGraph> rdf:type tdb:GraphTDB ;
	tdb:dataset <#tdbDataset> .

<#tdbDataset> rdf:type tdb:DatasetTDB ;
	tdb:location "DB" ;
	#set the timeout for a SPARQL query in milliseconds. 0 means no timeout and the query never times out.
	ja:context [ ja:cxtName "arq:queryTimeout" ;  ja:cxtValue "0" ] .

<#test-inf> ja:externalContent <file:///opt/ontology-plus-data.ttl> .

@Galigator Galigator added the can't reproduce Developper can't reproduce the issue, more information may be need label Nov 2, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Developper confirm there is a bug in the product. can't reproduce Developper can't reproduce the issue, more information may be need
Projects
None yet
Development

No branches or pull requests

2 participants