Re:Re: How to store rule-related data in RDF and query with Sparql?

Hi, Aidan,  The first Sparql statement about integer types works perfectly!  It's amazing.
The operation on the decimal query appears to have failed:
          ---------------------------------------------------
@base <http://example.org/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix : <http://example.org/#> .
:range1 a :range;
          :grade "A";
          :minInclusive 90.0;
          :maxInclusive 100.0 .
:range2 a :range;
          :grade "B";
          :minInclusive 75.0;
          :maxExclusive 90.0 .
:range3 a :range;
          :grade "C";
          :minInclusive 60.0;
          :maxExclusive 75.0 .


:range4 a :range;
          :grade "D";
          :minInclusive 0;
          :maxExclusive 60.0 .
:Bob a :Student;
     :tookTest :Test0,:Test1,:Test2, :Test3 .


:Test0 :score 91.2 .
:Test1 :score 75.5 .
:Test2 :score 73.2 .
:Test3 :score 59.5 .
---------------------------------------------------


But it gave me a clear direction and a great idea.  
I'm also trying to do this with shACL, which might be simpler.  But I'm not familiar with SH :rule yet, I don't know if that's possible£º
      https://w3c.github.io/shacl/shacl-af/#rules 
Another approach I think might be useful:
https://henrietteharmse.com/category/inferencing/ 


Thank you for your prompt reply and kind help.


Kind regards,
Joylix





















At 2021-08-09 08:39:38, "Aidan Hogan" <aidhog@gmail.com> wrote:
>Hi Joylix,
>
>I think that the solution gets a bit more difficult, but if you are 
>working with integers, you could try to query the values like this:
>
>PREFIX : <http://example.org/#>
>SELECT ?student ?test ?grade
>WHERE {
>   ?student :tookTest ?test .
>   ?test :score ?score .
>   ?range a :range .
>   ?range :grade ?grade .
>   { ?range :maxInclusive ?max }
>   UNION
>   { ?range :maxExclusive ?maxExc . BIND(?maxExc - 1 AS ?max) }
>   { ?range :minInclusive ?min }
>   UNION
>   { ?range :minExclusive ?minExc . BIND(?minExc + 1 AS ?min) }
>   FILTER(?score >= ?min && ?score <= ?max)
>}
>
>Another option (that would work also for non-integer values) would be to 
>expand the FILTER.
>
>PREFIX : <http://example.org/#>
>SELECT ?student ?test ?grade
>WHERE {
>   ?student :tookTest ?test .
>   ?test :score ?score .
>   ?range a :range .
>   ?range :grade ?grade .
>   { ?range :maxInclusive ?maxInc }
>   UNION
>   { ?range :maxExclusive ?maxExc }
>   { ?range :minInclusive ?minInc }
>   UNION
>   { ?range :minExclusive ?minExc }
>   FILTER(
>    (!isBound(?minInc) || (?score >= ?minInc)) &&
>    (!isBound(?minExc) || (?score > ?minExc)) &&
>    (!isBound(?maxInc) || (?score <= ?maxInc)) &&
>    (!isBound(?maxExc) || (?score < ?maxExc))
>   )
>}
>
>Best,
>Aidan
>
>On 2021-08-08 11:42, joylix wrote:
>> Dear Aidan, Thank you very much for the solution.
>> Also, in this case, I still don't know how to deal with the limit of 
>> boundary.
>> If I need to consider the inclusive and exclusive values of limit as:
>> :range1 a :range £»
>>           :grade "A" ;
>>           :minInclusive 90 ;
>>           :maxInclusive 100.
>> :range2 a :range £»
>>           :grade "B" ;
>>           :minInclusive 75 ;
>>           :maxExclusive 90 .
>> :range3 a :range £»
>>           :grade "C" ;
>>           :minInclusive 60 ;
>>           :maxExclusive 75 .
>> :range4 a :range £»
>>           :grade "D" ;
>>           :minInclusive 0 ;
>>           :maxExclusive 60 .
>> How can I write logical operators in A SPARQL statement based on 
>> different predicates (inclusive or exclusive)?
>> FILTER(?score >= ?lower && ?score <= ?upper)
>> So this part of the SPARQ statement ">=" is sometimes ">",  "<="  can 
>> also be  "<". Is there an easy way to deal with this situation?
>> I thought it might be easy to implement this example with shacl, but I 
>> didn't know how.
>> Thanks again for your reply and help.
>> 
>> Kind regards,
>> Joylix
>> 
>> 
>> 
>> 
>> 
>> At 2021-08-07 06:11:22, "Aidan Hogan" <aidhog@gmail.com> wrote:
>>>Hi Joylix,
>>>
>>>You could try something like:
>>>
>>>PREFIX : <http://example.org/#>
>>>SELECT ?student ?test ?grade
>>>WHERE {
>>>   ?student :tookTest ?test .
>>>   ?test :score ?score .
>>>   ?range a :range .
>>>   ?range :grade ?grade .
>>>   ?range :lowerLimit ?lower .
>>>   ?range :upperLimit ?upper .
>>>   FILTER(?score >= ?lower && ?score <= ?upper)
>>>}
>>>
>>>Not tested, but I think this should work.
>>>
>>>Best,
>>>Aidan
>>>
>>>P.S., if you want to express rules over RDF (in RDF) and like to use 
>>>SPARQL for that, you might be interested in SPIN:
>>>
>>>https://www.w3.org/Submission/spin-sparql/
>>>
>>>
>>>On 2021-08-06 4:23, joylix wrote:
>>>> Dear all, I have some data on students' test scores as follows:
>>>> 
>>>> 
>>>>     /@prefix : <http://example.org/#> ./
>>>> 
>>>>     /:Bob a :Student;/
>>>> 
>>>>     /     :tookTest :Test0,:Test1,:Test2 ,:Test3 ./
>>>> 
>>>>     /:Test0 :score 90 ./
>>>> 
>>>>     /:Test1 :score 81 ./
>>>> 
>>>>     /:Test2 :score 62 ./
>>>> 
>>>>     /:Test3 :score 32 ./
>>>> 
>>>> The rules for grading based on scores are as follows:
>>>> 
>>>>      [90-100]  --> A
>>>> 
>>>>      [75-90)   --> B
>>>> 
>>>>      [60-75)   --> C
>>>> 
>>>>      [0-60)    --> D
>>>> 
>>>> So I used the following SPARQL query to get the grade of the student's Test:
>>>> 
>>>> 
>>>>     /prefix : <http://example.org/#>/
>>>> 
>>>>     /select ?student ?test ?grade/
>>>> 
>>>>     /    WHERE { /
>>>> 
>>>>     /      ?student :tookTest ?test ./
>>>> 
>>>>     /      ?test :score ?score ./
>>>> 
>>>>     /      BIND ( IF ( ?score >= 90 , "A", IF ( ?score>=75, "B", IF (
>>>>     ?score>=60, "C", "D" ) ) ) AS ?grade )/
>>>> 
>>>>     /      }/
>>>> 
>>>> And I got the right result as such:
>>>> 
>>>> 
>>>>     student,                  test,                       grade
>>>> 
>>>>     http://example.org/#Bob,  http://example.org/#Test3,  D
>>>> 
>>>>     http://example.org/#Bob,  http://example.org/#Test2,  C
>>>> 
>>>>     http://example.org/#Bob,  http://example.org/#Test1,  B
>>>> 
>>>>     http://example.org/#Bob,  http://example.org/#Test0,  A
>>>> 
>>>>      Now my question is how to store this rule data in RDF (along with 
>>>> the score) rather than in SPARQL, so that the rule data can be defined 
>>>> and modified by the user, The server side reads the rule data to 
>>>> generate the appropriate SPARQL query.
>>>> 
>>>> My initial thoughts are as follows:
>>>> 
>>>> 
>>>>     / :range1 a :range £»/
>>>> 
>>>>     /         :grade "A" ;/
>>>> 
>>>>     /         :lowerLimit 90 ;/
>>>> 
>>>>     /         :upperLimit 100./
>>>> 
>>>>     /:range2 a :range £»/
>>>> 
>>>>     /         :grade "B" ;/
>>>> 
>>>>     /         :lowerLimit 75 ;/
>>>> 
>>>>     /         :upperLimit 89 ./
>>>> 
>>>>     /:range3 a :range £»/
>>>> 
>>>>     /         :grade "C" ;/
>>>> 
>>>>     /         :lowerLimit 60 ;/
>>>> 
>>>>     /         :upperLimit 74 ./
>>>> 
>>>>     /:range4 a :range £»/
>>>> 
>>>>     /         :grade "D" ;/
>>>> 
>>>>     /         :lowerLimit 0 ;/
>>>> 
>>>>     /         :upperLimit 59 ./
>>>> 
>>>>     /:rule1 :hasRange :range1,:range2, :range3, :range4 ./
>>>> 
>>>> 
>>>> But how do I now write the right SPARQL to read the rule and complete 
>>>> the grade transformation?
>>>> 
>>>> And how to handle with inclusive and exclusive of the boundary of limit?
>>>> Thank you for any suggestion.
>>>> 
>>>> Kind regards,
>>>> Joylix
>>>> 
>>>> 
>>>> 
>>>> 
>> 
>> 
>> 

Received on Monday, 9 August 2021 01:14:41 UTC