How to determine if one range contains another?

Viewed 57

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.

3 Answers

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 .

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?

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))
          }
        }
     }
Related