adding a swrl rule through owlready2

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

adding a swrl rule through owlready2

d.onto
Hi all

These days I read the complete owlready2 documentation
My goal was to add a swrl rule to an existing ontology.

First, I created an ontology in ttl, added the rule through protégé, save it as rdfxml, then run the owlready2 reasonner and it worked correctly

Here's the ontology, it's about machines that have packages that may have CVE (vulnerabilities)
I want the reasonner to infer that if a machine has a package that has a CVE then the machine contains the CVE
(I know that we can do it without reasonning with owl:propertyChainAxiom, but it's a simple example for my first swrl rule.)
@prefix : <http://maccve/onto#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .

:Machine a owl:Class .
:CVE a owl:Class .
:Package a owl:Class .

# Machine contains Package
:contains a owl:ObjectProperty ;
         rdfs:domain :Machine ;
         rdfs:range :Package .

# Package has_CVE CVE
:has_CVE a owl:ObjectProperty ;
         rdfs:domain :Package ;
         rdfs:range :CVE .

# Cette property est determinée par swrl
:contains_CVE a owl:ObjectProperty ;
         rdfs:domain :Machine ;
         rdfs:range :CVE .


:www1 a owl:NamedIndividual, :Machine .
:www2 a owl:NamedIndividual, :Machine .

:apache12 a owl:NamedIndividual, :Package .
:apache22 a owl:NamedIndividual, :Package .

:CVE1212 a owl:NamedIndividual, :CVE .

:www1 :contains :apache12 .
:www2 :contains :apache22 .
:apache22 :has_CVE :CVE1212 .

When the reasonner is doing its job, it must answer that machine
:www2 :contains_CVE :CVE1212

Then I wanted to do the same in python, just adding the rule to a existing file
I fully understood that owlready2 is reading rdfxml, so i convert my ttl before using it

I wrote this python (addrule.py) example : open, add, save
import argparse
import pprint
import sys

import owlready2 as owl
from rdflib import Graph


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--ontology", help="ontology file", required=True)
    parser.add_argument( "--destination", help="destination ontology file", required=True)

    args = parser.parse_args()

    input_file = args.ontology
    output_file = args.destination

    onto = owl.get_ontology(input_file).load()

    with onto:
        print("\n\n")
        print(list(onto.classes()))

        onto.set_base_iri("http://maccve/onto#")

        print("\n\n")
        print(list(onto.classes()))

        print("\n\n")
        print(list(onto.individuals()))
        print("\n\n")

        class Machine(owl.Thing):
            pass
        class Package(owl.Thing):
            pass
        class CVE(owl.Thing):
            pass

        class contains(owl.ObjectProperty):
            domain = [Machine]
            range = [Package]

        class has_CVE(owl.ObjectProperty):
            domain = [Package]
            range = [CVE]

        class contains_CVE(owl.ObjectProperty):
            domain = [Machine]
            range = [CVE]

        print(Machine.iri)

        swrl_rule = """ Machine(?m) ^ Package(?p) ^ CVE(?c) ^ contains(?m, ?p) ^ has_CVE(?p, ?c) -> contains_CVE(?m, ?c) """

        rule = owl.Imp()
        rule.set_as_rule(swrl_rule)


        onto.save(file = output_file, format = "rdfxml")

if __name__ == "__main__":
    main()


But when running the reasonner on the output file, the inference is not done.
I compared onto-x1.xml (protégé generated) and onto-y1.xml (addrule.py generated) and seems very similar but onto-y1.xml is not working.

If someone could explain what I'm doing wrong I would be pleased
Thanks in advance
Reply | Threaded
Open this post in threaded view
|

Re: adding a swrl rule through owlready2

d.onto
I oppened onto-y1.xml with Protégé and the rule has been translated to :
onto:Machine(?m) ^ onto:Package(?p) ^ onto:CVE(?c) ^ swrlb:contains(?m, ?p) ^ onto:has_CVE(?p, ?c) -> onto:contains_CVE(?m, ?c)
So my problem is a namespace problem I suspect

I would also like to get rid of the
        class Machine(owl.Thing):
            pass
        class Package(owl.Thing):
            pass
        class CVE(owl.Thing):
            pass
...
part in the python

(I would like the reader to read the classes and be able to set the rule without redefining them. I did it juste because otherwise the rule.set_as_rule doesn't want to set my rule)
Reply | Threaded
Open this post in threaded view
|

Re: adding a swrl rule through owlready2

d.onto
in fact I edited my onto.ttl and renamed
:contains
as
:mcontains
and everything is working, I suspect ":contains" to be in conflict with a another concept
Reply | Threaded
Open this post in threaded view
|

Re: adding a swrl rule through owlready2

Jiba
Administrator
Yes, it conflicts with swrlb:contains (from XQuery fn:contains, see http://www.daml.org/swrl/proposal/builtins.html ).

Jiba
Reply | Threaded
Open this post in threaded view
|

Re: adding a swrl rule through owlready2

d.onto
Thanks

but is there a namespace problem ?
In ontologies it's common to name ":" the base prefix


Reply | Threaded
Open this post in threaded view
|

Re: adding a swrl rule through owlready2

Jiba
Administrator
The problem is in the SWRL rule, in this part : "contains(?m, ?p)". "contains" is ambiguous as it can refer to "http://maccve/onto#contains" or "swrlb:contains" -- Owlready chooses the latter arbitrarily.

Jiba
Reply | Threaded
Open this post in threaded view
|

Re: adding a swrl rule through owlready2

d.onto
Ok I understand, thx.

What I do not understand is how to pass the namespace "http://maccve/onto#" in the example python file in order to avoid the ambiguity.

The python class name cannot be "http://maccve/onto#contains" ...


In fact I would like to get rid of the python classes, my goal is just to add a SWRL rule to an existing ontology and then run the reasonner.

Thx in advance
Reply | Threaded
Open this post in threaded view
|

Re: adding a swrl rule through owlready2

d.onto
I finally added the namespaces in the rule and everything is working accordingly :
def main():
    """add a swrl rule."""
    parser = argparse.ArgumentParser()
    parser.add_argument("--ontology", help="ontology file", required=True)
    parser.add_argument(
        "--destination", help="destination ontology file", required=True
    )

    args = parser.parse_args()

    input_file = args.ontology
    output_file = args.destination

    onto = owl.get_ontology(input_file).load()

    with onto:
        swrl_rule = """ http://maccve/onto#Machine(?m) ^ http://maccve/onto#Package(?p) ^ http://maccve/onto#CVE(?c) ^ http://maccve/onto#mcontains(?m, ?p) ^ http://maccve/onto#has_CVE(?p, ?c) -> http://maccve/onto#contains_CVE(?m, ?c) """

        rule = owl.Imp()
        rule.set_as_rule(swrl_rule)
        onto.save(file=output_file, format="rdfxml")

if __name__ == "__main__":
    main()