Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SWRL rules in OWL 2

I'm currently discovering all the possibilities of the Owlready library. Right now I'm trying to process some SWRL rules and so far it's been going very good, but I'm stuck at one point.

I've defined some rules in my ontology and now I want to see all the results (so, everything inferred from a rule).

For example, if I had a rule

has_brother(David, ?b) ^ has_child(?b, ?s) -> has_uncle(?s, David)

and David has two brothers, John and Pete, and John's kid is Anna, Pete's kid is Simon, I would like too see something like:

has_brother(David, John) ^ has_child(John, Anna) -> has_uncle(Anna, David)

has_brother(David, Pete) ^ has_child(Pete, Simon) -> has_uncle(Simon, David)

Is this possible in any way? I thought that maybe if I run the reasoner, I could see it in its output, but I can't find this anywhere.

I appreciate any help possible!

like image 386
mathbbandstuff Avatar asked Nov 01 '25 09:11

mathbbandstuff


1 Answers

This is my solution:



import owlready2 as owl

onto = owl.get_ontology("http://test.org/onto.owl")

with onto:
    class Person(owl.Thing):
        pass

    class has_brother(owl.ObjectProperty, owl.SymmetricProperty, owl.IrreflexiveProperty):
        domain = [Person]
        range = [Person]
    
    class has_child(Person >> Person):
        pass
    
    class has_uncle(Person >> Person):
        pass

    rule1 = owl.Imp()
    rule1.set_as_rule(
        "has_brother(?p, ?b), has_child(?p, ?c) -> has_uncle(?c, ?b)"
    )

    # This rule gives "irreflexive transitivity",
    # i.e. transitivity, as long it does not lead to has_brother(?a, ?a)"
    rule2 = owl.Imp()
    rule2.set_as_rule(
        "has_brother(?a, ?b), has_brother(?b, ?c), differentFrom(?a, ?c) -> has_brother(?a, ?c)"
    )
    
david = Person("David")
john = Person("John")
pete = Person("Pete")
anna = Person("Anna")
simon = Person("Simon")

owl.AllDifferent([david, john, pete, anna, simon])

david.has_brother.extend([john, pete])

john.has_child.append(anna)
pete.has_child.append(simon)

print("Uncles of Anna:", anna.has_uncle) # -> []
print("Uncles of Simon:", simon.has_uncle) # -> []
owl.sync_reasoner(infer_property_values=True)
print("Uncles of Anna:", anna.has_uncle) # -> [onto.Pete, onto.David]
print("Uncles of Simon:", simon.has_uncle) # -> [onto.John, onto.David]

Notes:

One might think has_brother is

  • symmetric, i.e. has_brother(A, B)has_brother(B, A)
  • transitive, i.e. has_brother(A, B) + has_brother(B, C) ⇒ has_brother(A, C)
  • irreflexive, i.e. no one is his own brother.

However, transitivity only holds if the unique name assumption holds. Otherwise A could be the same individual as C and this conflicts irreflexivity. Thus I used a rule for this kind of "weak transitivity".

Once, has_brother works as expected the uncle rule also does. Of course, the reasoner must run before.

Update: I published the solution in this Jupyter notebook (which also contains the output of the execution).

like image 158
cknoll Avatar answered Nov 02 '25 22:11

cknoll



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!