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

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 00:39:52 UTC