1

Consider the following example: rangeB is contained in rangeA

:rangeA :lowerLimit :LeftMarginA ;
        :upperLimit :RightMarginA .

:rangeB :lowerLimit :LeftMarginB ;
        :upperLimit :RightMarginB .

:LeftMarginA :hasValue 20 ;
:RightMarginA  :hasValue 80 .

:LeftMarginB :hasValue 30 ;
:RightMarginB  :hasValue 60 .

How to get inference results using SPARQL or SWRL

 :rangeA  :Contains :rangeB 

My idea is:

if (:LeftMarginB >= :LeftMarginA) && (:RightMarginB <= :RightMarginA) then :rangeA :contains :rangeB

But how do I write this SPARQL or SWRL statement?
Thanks for help.

joylix
  • 95
  • 7
  • 1
    and what does not work with SPARQL now? I mean just translate your if statement as a SPARQL `FILTER` expression and you're done. – UninformedUser Nov 05 '21 at 15:50

3 Answers3

1

If you can write a SELECT query that selects one range that contains another, it's just one more step to convert it into a CONSTRUCT WHERE query that generates the triple that captures your inference. For instance:

Some Data

@prefix : <urn:ex:>

:x :lower 30 ; :upper 60 .
:y :lower 20 ; :upper 80 .

A query

prefix : <urn:ex:>

construct {
  ?a :contains ?b
} where {
        ?a :lower ?la ; :upper ?ua .
        ?b :lower ?lb ; :upper ?ub .

        filter ( ?lb < ?la && ?ua < ?ub )
}

The result

@prefix :      <urn:ex:> .

:x      :contains  :y .
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
0

I've tested and this does work:

   prefix :      <#> 
    CONSTRUCT { ?rangeA :contains ?rangeB . }
    WHERE {
       {
         SELECT ?rangeA ?rangeB
         WHERE {
           ?rangeA :lowerLimit ?LeftMarginA ;
                 :upperLimit ?RightMarginA .
           ?rangeB :lowerLimit ?LeftMarginB ;
            :upperLimit ?RightMarginB .
          ?LeftMarginA :hasValue ?valueLA.
          ?RightMarginA :hasValue ?valueRA.
          ?LeftMarginB :hasValue ?valueLB.
          ?RightMarginB :hasValue ?valueRB.
           Filter ((?valueLB >= ?valueLA) && (?valueRB <= ?valueRA)
           && (?rangeA !=?rangeB))    ​
          }
        }
     }

But that doesn't take into account the inclusion of the boundary. If consider boundary inclusion like :

:LeftMarginA :hasValue 20 ;
    :inclusive True.
:RightMarginA  :hasValue 80 ;
    :inclusive False.

How can SPARQL statements be modified to work properly?

joylix
  • 95
  • 7
  • just extend your filter and use `if` feature of SPARQL 1.1: `?LeftMarginA :hasValue ?valueLA ; :inclusive ?leftInclusive . ?RightMarginA :hasValue ?valueRA ; :inclusive ?rightInclusive . Filter (if(?leftInclusive, ?valueLB >= ?valueLA, ?valueLB > ?valueLA) && if(?rightInclusive, ?valueRB <= ?valueRA, ?valueRB < ?valueRA) && (?rangeA !=?rangeB))` – UninformedUser Nov 05 '21 at 19:07
  • Thanks UninformedUser. It looks pretty good that way. What about if rangeA =(20,80], rangeB=[20,60), the leftMarginB is inclusive but leftMarginA is exclusive, this should infer rangeB notIncludeIn rangeA – joylix Nov 06 '21 at 04:30
  • what is with it? the `FILTER` will evaluate to `false` which means your `CONSTRUCT` query will not return `:rangeA :contains :rangeB .` In that case the absence of the triple means obviously the opposite - why would you want this explicitly as triple as well? – UninformedUser Nov 06 '21 at 08:06
0

Thank you all, the final solution is as follows:

#-----rdf data
@prefix : <#> .
:rangeA :lowerLimit 20 ;
        :lowerLimitInclusiveA false ;
        :upperLimit 80 ;
        :upperLimitInclusiveA false .

:rangeB :lowerLimit 20.5 ;
        :lowerLimitInclusiveB false ;
        :upperLimit 60 ;
        :upperLimitInclusiveB false .

#---sparql query ========================
prefix :      <#> 
    CONSTRUCT { ?rangeA :contains ?rangeB . }
    WHERE {
       {
         SELECT ?rangeA ?rangeB
         WHERE {
           ?rangeA :lowerLimit ?LeftMarginA ;
                 :lowerLimitInclusiveA ?lowerA ;
                 :upperLimit ?RightMarginA ;
                 :upperLimitInclusiveA ?upperA .
           ?rangeB :lowerLimit ?LeftMarginB ;
                 :lowerLimitInclusiveB ?lowerB ;
                 :upperLimit ?RightMarginB ;
                 :upperLimitInclusiveB ?upperB .                          
Filter (if(?lowerA,?LeftMarginB>=?LeftMarginA, ?LeftMarginB>?LeftMarginA) 
         &&   if(?upperA, ?RightMarginB<=?RightMarginA, ?RightMarginB<?RightMarginA)
         && (?rangeA!= ?rangeB))
          }
        }
     }
joylix
  • 95
  • 7