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 |
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) |
in fact I edited my onto.ttl and renamed
:containsas :mcontainsand everything is working, I suspect ":contains" to be in conflict with a another concept |
Administrator
|
Yes, it conflicts with swrlb:contains (from XQuery fn:contains, see http://www.daml.org/swrl/proposal/builtins.html ).
Jiba |
Thanks
but is there a namespace problem ? In ontologies it's common to name ":" the base prefix |
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 |
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 |
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() |
Free forum by Nabble | Edit this page |