[
https://issues.apache.org/jira/browse/JENA-2355?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17772468#comment-17772468
]
Jan Martin Keil commented on JENA-2355:
---------------------------------------
Ok. Reading the documentation again, I learned that the inverse direction is
needed for backward execution / function used as test in the rule head. That
way, the other functions should ideally also get this feature.
Further, I had a look into Util.java and found that [Util#compare(Number ,
Number)|https://github.com/apache/jena/blob/ac5c1e6188aa586ad106f8c83af18eee1b19b52d/jena-core/src/main/java/org/apache/jena/reasoner/rulesys/Util.java#L95]
does not properly apply the XQuery/XPath rules too. It promotes to xsd:decimal
instead of xsd:float or xsd:double in case of different numeric types. That is
more precise from the mathematical point of view, but not consistent with the
specified behavior in SPARQL. Should this be changed too?
> Rule Math Builtins do not support xsd:decimal
> ---------------------------------------------
>
> Key: JENA-2355
> URL: https://issues.apache.org/jira/browse/JENA-2355
> Project: Apache Jena
> Issue Type: Bug
> Components: Reasoners
> Affects Versions: Jena 4.9.0
> Reporter: Jan Martin Keil
> Priority: Major
>
> The [builtin|https://jena.apache.org/documentation/inference/#RULEbuiltins]
> math functions of the rule reasoners do not properly support xsd:decimal. For
> example, sum(1.1, 1.1) = 2.0 (returned as integer) and quotient(0.1, 0.1)
> throws "ArithmeticException: / by zero". Here some detailed tests:
> {code:java}
> import org.apache.jena.rdf.model.*;
> import org.apache.jena.reasoner.rulesys.GenericRuleReasoner;
> import org.apache.jena.reasoner.rulesys.Rule;
> import org.apache.jena.riot.Lang;
> import org.apache.jena.riot.RDFParser;
> import org.junit.jupiter.api.Assertions;
> import org.junit.jupiter.api.Test;
> public class ApacheJenaRuleDecimalTest {
> Property a = ResourceFactory.createProperty("http://example/a");
> Property b = ResourceFactory.createProperty("http://example/b");
> Property sum = ResourceFactory.createProperty("http://example/sum");
> Property difference =
> ResourceFactory.createProperty("http://example/difference");
> Property product =
> ResourceFactory.createProperty("http://example/product");
> Property quotient =
> ResourceFactory.createProperty("http://example/quotient");
> String rules =
> "(?r <http://example/a> ?a) (?r <http://example/b> ?b) sum(?a,
> ?b, ?c) -> (?r <http://example/sum> ?c) ." +
> "(?r <http://example/a> ?a) (?r <http://example/b> ?b)
> difference(?a, ?b, ?c) -> (?r <http://example/difference> ?c) ." +
> "(?r <http://example/a> ?a) (?r <http://example/b> ?b)
> product(?a, ?b, ?c) -> (?r <http://example/product> ?c) ." +
> "(?r <http://example/a> ?a) (?r <http://example/b> ?b)
> quotient(?a, ?b, ?c) -> (?r <http://example/quotient> ?c) .";
> GenericRuleReasoner reasoner = new
> GenericRuleReasoner(Rule.parseRules(rules));
> @Test
> public void test1k0() {
> Model model = ModelFactory.createDefaultModel();
> RDFParser.fromString(
> "<http://example/decimal-decimal> <http://example/a>
> 1.0 ; <http://example/b> 1.0 ." +
> "<http://example/double-decimal>
> <http://example/a> 1.0e0 ; <http://example/b> 1.0 ." +
> "<http://example/decimal-double>
> <http://example/a> 1.0 ; <http://example/b> 1.0e0 ." +
> "<http://example/double-double>
> <http://example/a> 1.0e0 ; <http://example/b> 1.0e0 .")
> .lang(Lang.TTL).parse(model);
> System.out.println("Original Statement:");
> model.listStatements().forEach(s -> System.out.println(s));
> System.out.println("Deducted Statement:");
> InfModel infModel = ModelFactory.createInfModel(reasoner, model);
> infModel.getDeductionsModel().listStatements().forEach(s ->
> System.out.println(s));
> infModel.getDeductionsModel().listStatements(null, sum, (RDFNode)
> null)
> .forEach(s -> Assertions.assertEquals(s.getDouble(), 2.0,
> s.getSubject().getLocalName()));
> infModel.getDeductionsModel().listStatements(null, difference,
> (RDFNode) null)
> .forEach(s -> Assertions.assertEquals(s.getDouble(), 0.0,
> s.getSubject().getLocalName()));
> infModel.getDeductionsModel().listStatements(null, product, (RDFNode)
> null)
> .forEach(s -> Assertions.assertEquals(s.getDouble(), 1.0,
> s.getSubject().getLocalName()));
> infModel.getDeductionsModel().listStatements(null, quotient,
> (RDFNode) null)
> .forEach(s -> Assertions.assertEquals(s.getDouble(), 1.0,
> s.getSubject().getLocalName()));
> }
> @Test
> public void test1k1() {
> Model model = ModelFactory.createDefaultModel();
> RDFParser.fromString(
> "<http://example/decimal-decimal> <http://example/a>
> 1.1 ; <http://example/b> 1.1 ." +
> "<http://example/double-decimal>
> <http://example/a> 1.1e0 ; <http://example/b> 1.1 ." +
> "<http://example/decimal-double>
> <http://example/a> 1.1 ; <http://example/b> 1.1e0 ." +
> "<http://example/double-double>
> <http://example/a> 1.1e0 ; <http://example/b> 1.1e0 .")
> .lang(Lang.TTL).parse(model);
> System.out.println("Original Statement:");
> model.listStatements().forEach(s -> System.out.println(s));
> System.out.println("Deducted Statement:");
> InfModel infModel = ModelFactory.createInfModel(reasoner, model);
> infModel.getDeductionsModel().listStatements().forEach(s ->
> System.out.println(s));
> infModel.getDeductionsModel().listStatements(null, sum, (RDFNode)
> null)
> .forEach(s -> Assertions.assertEquals(s.getDouble(), 2.2,
> s.getSubject().getLocalName()));
> infModel.getDeductionsModel().listStatements(null, difference,
> (RDFNode) null)
> .forEach(s -> Assertions.assertEquals(s.getDouble(), 0.0,
> s.getSubject().getLocalName()));
> infModel.getDeductionsModel().listStatements(null, product, (RDFNode)
> null)
> .forEach(s -> Assertions.assertEquals(s.getDouble(), 1.21,
> s.getSubject().getLocalName()));
> infModel.getDeductionsModel().listStatements(null, quotient,
> (RDFNode) null)
> .forEach(s -> Assertions.assertEquals(s.getDouble(), 1.0,
> s.getSubject().getLocalName()));
> }
> @Test
> public void test0k1() {
> Model model = ModelFactory.createDefaultModel();
> RDFParser.fromString(
> "<http://example/decimal-decimal> <http://example/a>
> 0.1 ; <http://example/b> 0.1 ." +
> "<http://example/double-decimal>
> <http://example/a> 0.1e0 ; <http://example/b> 0.1 ." +
> "<http://example/decimal-double>
> <http://example/a> 0.1 ; <http://example/b> 0.1e0 ." +
> "<http://example/double-double>
> <http://example/a> 0.1e0 ; <http://example/b> 0.1e0 .")
> .lang(Lang.TTL).parse(model);
> System.out.println("Original Statement:");
> model.listStatements().forEach(s -> System.out.println(s));
> System.out.println("Deducted Statement:");
> InfModel infModel = ModelFactory.createInfModel(reasoner, model);
> infModel.getDeductionsModel().listStatements().forEach(s ->
> System.out.println(s));
> infModel.getDeductionsModel().listStatements(null, sum, (RDFNode)
> null)
> .forEach(s -> Assertions.assertEquals(s.getDouble(), 0.2,
> s.getSubject().getLocalName()));
> infModel.getDeductionsModel().listStatements(null, difference,
> (RDFNode) null)
> .forEach(s -> Assertions.assertEquals(s.getDouble(), 0.0,
> s.getSubject().getLocalName()));
> infModel.getDeductionsModel().listStatements(null, product, (RDFNode)
> null)
> .forEach(s -> Assertions.assertEquals(s.getDouble(), 0.01,
> s.getSubject().getLocalName()));
> infModel.getDeductionsModel().listStatements(null, quotient,
> (RDFNode) null)
> .forEach(s -> Assertions.assertEquals(s.getDouble(), 1.0,
> s.getSubject().getLocalName()));
> }
> }
> {code}
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]