def _run_pre_inference(self, target_graph, inference_option): try: if inference_option == 'rdfs': inferencer = owlrl.DeductiveClosure(CustomRDFSSemantics) elif inference_option == 'owlrl': inferencer = owlrl.DeductiveClosure(owlrl.OWLRL_Semantics) elif inference_option == 'both' or inference_option == 'all'\ or inference_option == 'rdfsowlrl': inferencer = owlrl.DeductiveClosure(CustomRDFSOWLRLSemantics) else: raise ReportableRuntimeError( "Don't know how to do '{}' type inferencing." .format(inference_option)) except Exception as e: # pragma: no cover self.logger.error("Error during creation of OWL-RL Deductive Closure") if isinstance(e, ReportableRuntimeError): raise e raise ReportableRuntimeError("Error during creation of OWL-RL Deductive Closure\n" "{}".format(str(e.args[0]))) try: inferencer.expand(target_graph) except Exception as e: # pragma: no cover self.logger.error("Error while running OWL-RL Deductive Closure") raise ReportableRuntimeError("Error while running OWL-RL Deductive Closure\n" "{}".format(str(e.args[0])))
def _run_pre_inference(cls, target_graph: GraphLike, inference_option: str, logger: Optional[logging.Logger] = None): """ Note, this is the OWL/RDFS pre-inference, it is not the Advanced Spec SHACL-Rule inferencing step. :param target_graph: :type target_graph: rdflib.Graph|rdflib.ConjunctiveGraph|rdflib.Dataset :param inference_option: :type inference_option: str :return: :rtype: NoneType """ # Lazy import owlrl import owlrl from .inference import CustomRDFSOWLRLSemantics, CustomRDFSSemantics if logger is None: logger = logging.getLogger(__name__) try: if inference_option == 'rdfs': inferencer = owlrl.DeductiveClosure(CustomRDFSSemantics) elif inference_option == 'owlrl': inferencer = owlrl.DeductiveClosure(owlrl.OWLRL_Semantics) elif inference_option == 'both' or inference_option == 'all' or inference_option == 'rdfsowlrl': inferencer = owlrl.DeductiveClosure(CustomRDFSOWLRLSemantics) else: raise ReportableRuntimeError( "Don't know how to do '{}' type inferencing.".format( inference_option)) except Exception as e: # pragma: no cover logger.error("Error during creation of OWL-RL Deductive Closure") if isinstance(e, ReportableRuntimeError): raise e raise ReportableRuntimeError( "Error during creation of OWL-RL Deductive Closure\n{}".format( str(e.args[0]))) if isinstance(target_graph, (rdflib.Dataset, rdflib.ConjunctiveGraph)): named_graphs = [ rdflib.Graph(target_graph.store, i, namespace_manager=target_graph.namespace_manager) if not isinstance(i, rdflib.Graph) else i for i in target_graph.store.contexts(None) ] else: named_graphs = [target_graph] try: for g in named_graphs: inferencer.expand(g) except Exception as e: # pragma: no cover logger.error("Error while running OWL-RL Deductive Closure") raise ReportableRuntimeError( "Error while running OWL-RL Deductive Closure\n{}".format( str(e.args[0])))
def test_cax_dw(): """ Test cax-dw rule for OWL 2 RL. If:: T(?c1, owl:disjointWith, ?c2) T(?x, rdf:type, ?c1) T(?x, rdf:type, ?c2) then:: false """ g = Graph() x = T.x c1 = T.c1 c2 = T.c2 g.add((c1, OWL.disjointWith, c2)) g.add((x, RDF.type, c1)) g.add((x, RDF.type, c2)) owlrl.DeductiveClosure(owlrl.OWLRL_Semantics).expand(g) result = next(g.objects(predicate=DAML.error)) expected = Literal( 'Disjoint classes http://test.org/c1 and http://test.org/c2' ' have a common individual http://test.org/x') assert expected == result
def test_cls_maxc2(): """ Test cls-maxc2 rule for OWL 2 RL. If:: T(?x, owl:maxCardinality, "1"^^xsd:nonNegativeInteger) T(?x, owl:onProperty, ?p) T(?u, rdf:type, ?x) T(?u, ?p, ?y1) T(?u, ?p, ?y2) then:: T(?y1, owl:sameAs, ?y2) """ g = Graph() x = T.x p = T.p u = T.u y1 = T.y1 y2 = T.y2 g.add((x, OWL.maxCardinality, Literal(1))) g.add((x, OWL.onProperty, p)) g.add((u, RDF.type, x)) g.add((u, p, y1)) g.add((u, p, y2)) owlrl.DeductiveClosure(owlrl.OWLRL_Semantics).expand(g) assert (y1, OWL.sameAs, y2) in g
def test_one_time_rules(): """ Test OWL 2 RL extras closure one time rules. """ data = """ @prefix : <http://test.org/> . @prefix owl: <http://www.w3.org/2002/07/owl#> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . :t a rdfs:Datatype ; owl:onDatatype xsd:integer; owl:withRestrictions ( [xsd:minInclusive "1"^^xsd:integer] [xsd:maxInclusive "6"^^xsd:integer] ). """ g = Graph() g.parse(io.StringIO(data), format='n3') lt = Literal(2, datatype=XSD.integer) g.add((lt, RDF.type, XSD.integer)) g.add((T.a, T.p, lt)) owlrl.DeductiveClosure(owlrl.OWLRL_Extension).expand(g) assert (lt, RDF.type, T.t) in g
def test_cls_avf(): """ Test for cls-avf rule for OWL 2 RL. If:: T(?x, owl:allValuesFrom, ?y) T(?x, owl:onProperty, ?p) T(?u, rdf:type, ?x) T(?u, ?p, ?v) and type restriction *valid*, then:: T(?v, rdf:type, ?y) """ g = Graph() x = T.x p = T.p u = T.u y = T.y v = T.v g.add((x, OWL.allValuesFrom, y)) g.add((x, OWL.onProperty, p)) g.add((u, RDF.type, x)) g.add((u, p, v)) owlrl.DeductiveClosure(owlrl.OWLRL_Semantics).expand(g) assert (v, RDF.type, y) in g
def test_cls_maxc1(): """ Test cls-maxc1 rule for OWL 2 RL. If:: T(?x, owl:maxCardinality, "0"^^xsd:nonNegativeInteger) T(?x, owl:onProperty, ?p) T(?u, rdf:type, ?x) T(?u, ?p, ?y) then:: false """ g = Graph() x = T.x p = T.p c = T.C u = T.u y = T.y g.add((x, OWL.maxCardinality, Literal(0))) g.add((x, OWL.onProperty, p)) g.add((x, OWL.onClass, c)) g.add((u, RDF.type, x)) g.add((u, p, y)) owlrl.DeductiveClosure(owlrl.OWLRL_Semantics).expand(g) result = next(g.objects(predicate=DAML.error)) expected = Literal('Erroneous usage of maximum cardinality with' ' http://test.org/x and http://test.org/y') assert expected == result
def expand(self, graph): """ Applies OWLRL reasoning from the Python owlrl library to the graph Args: graph (brickschema.graph.Graph): a Graph object containing triples """ owlrl.DeductiveClosure(owlrl.OWLRL_Semantics).expand(graph)
def rdfs_infer(self): owlrl.RDFSClosure.RDFS_Semantics(self.g, True, True, True) closure_class = owlrl.return_closure_class(owl_closure=True, rdfs_closure=True, owl_extras=True, trimming=True) owlrl.DeductiveClosure(closure_class, improved_datatypes=False, rdfs_closure=True, axiomatic_triples=False, datatype_axioms=False).expand(self.g)
def test_dt_type2(): """ Test dt-type2 rule for OWL 2 RL. """ p_one = Literal(1, datatype=XSD.positiveInteger) g = Graph() g.add((T.A, T.prop, p_one)) owlrl.DeductiveClosure(owlrl.OWLRL_Semantics).expand(g) assert (T.A, T.prop, p_one) in g assert (p_one, RDF.type, XSD.positiveInteger) in g
def reason_rdfs(g): """ Applies RDFS reasoning. Takes a few seconds. Lets us use: - class hierarchy (rdf:type, not rdf:type/rdfs:subClassOf*) """ start_time = time.time() owlrl.DeductiveClosure(owlrl.RDFS_Semantics).expand(g) end_time = time.time() print('owlrl reasoning took {0} seconds.'.format(int(end_time - start_time)))
def performReasoning(self, ontology_file): print("Triples including ontology: '" + str(len(self.g)) + "'.") #We should load the ontology first self.g.load(ontology_file, format='ttl') #e.g., format=ttl #We apply reasoning and expand the graph with new triples owlrl.DeductiveClosure(owlrl.OWLRL_Semantics, axiomatic_triples=False, datatype_axioms=False).expand(sellf.g) print("Triples after OWL 2 RL reasoning: '" + str(len(self.g)) + "'.")
def test_profile_owlrl(): print(f'Python: {sys.version}') print(f'RDFLib: {rdflib.__version__}') print(f'OWL RL: {owlrl.__version__}') graph = rdflib.Graph().parse( 'https://schema.org/version/latest/schemaorg-current-https.jsonld', format='json-ld', ) with cProfile.Profile() as profiler: owlrl.DeductiveClosure(OWLRL_Extension).expand(graph) Stats(profiler).strip_dirs().sort_stats(SortKey.TIME).print_stats(10)
def test_one_time_rules(): """ Test RDFS closure one time rules. """ g = Graph() lt1 = Literal(10, datatype=XSD.integer) lt2 = Literal(10, datatype=XSD.nonNegativeInteger) g.add((T.a1, T.p, lt1)) g.add((T.a2, T.p, lt2)) owlrl.DeductiveClosure(owlrl.RDFS_Semantics).expand(g) assert (T.a1, T.p, lt2) in g assert (T.a2, T.p, lt1) in g
def test_d_axioms(): """ Test adding datatype axioms for RDFS closure. """ g = Graph() g.add((T.a1, T.p, Literal(10, datatype=XSD.integer))) g.add((T.a2, T.p, Literal('11', datatype=XSD.string))) g.add((T.a3, T.p, Literal('t'))) # no datatype owlrl.DeductiveClosure(owlrl.RDFS_Semantics, datatype_axioms=True).expand(g) assert (Literal(10, datatype=XSD.integer), RDF.type, XSD.integer) in g assert (Literal('11', datatype=XSD.string), RDF.type, XSD.string) in g assert next(g.subjects(Literal('t'), RDF.type), None) is None
def reason_owlrl(g): """ Applies full OWL RL Reasoning. WARNING: takes a few hours. Lets us use: - tags <--> classes - measures properties - transitive properties - inverse properties - class hierarchy (rdf:type, not rdf:type/rdfs:subClassOf*) """ start_time = time.time() owlrl.DeductiveClosure(owlrl.OWLRL_Semantics).expand(g) end_time = time.time() print('owlrl reasoning took {0} seconds.'.format(int(end_time - start_time)))
def expand(self, graph): """ Applies RDFS reasoning from the Python owlrl library to the graph Args: graph (brickschema.graph.Graph): a Graph object containing triples Returns: graph (brickschema.graph.Graph): a Graph object containing the inferred triples in addition to the regular graph """ _inherit_bindings(graph, self.g) for triple in graph: self.g.add(triple) owlrl.DeductiveClosure(owlrl.RDFS_Semantics).expand(self.g.g) return _return_correct_type(graph, self.g)
def test_basic(): # create an RDF graph, load a simple OWL ontology and data g = rdflib.Graph() try: g.parse('relatives.ttl', format='turtle') except FileNotFoundError: # This test might be run from the parent directory root g.parse('test/relatives.ttl', format='turtle') # run a simple SPARQL query against it, no inferencing, should find 15 results q = ''' PREFIX : <http://example.org/relatives#> SELECT (COUNT(?s) AS ?cnt) WHERE { ?s a :Person . } ''' for r in g.query(q): cnt = int(r[0]) assert cnt == 15 # run a SELECT query for grandParents, no inferencing, should find 0 results q = ''' PREFIX : <http://example.org/relatives#> SELECT (COUNT(?gc) AS ?cnt) WHERE { ?gc :hasGrandparent ?gp . } ''' for r in g.query(q): cnt = int(r[0]) assert cnt == 0 # expand the graph with OWL-RL semantics owlrl.DeductiveClosure(owlrl.OWLRL_Semantics).expand(g) # run a SELECT query for grandParents, should find 7 results q = ''' PREFIX : <http://example.org/relatives#> SELECT (COUNT(?gc) AS ?cnt) WHERE { ?gc :hasGrandparent ?gp . } ''' for r in g.query(q): cnt = int(r[0]) assert cnt == 7
def main(): try: import owlrl except ImportError: logging.warn("owlrl library not available, skipping") return args = ExtensionArgumentParser().parse_args() client = args.client assertions_graph = client.get_assertions() logging.info("owlrl_reasoner: {} assertions at start", len(assertions_graph)) expanded_assertions_graph = rdflib.Graph() for assertion in assertions_graph: expanded_assertions_graph.add(assertion) reasoner = owlrl.DeductiveClosure(owlrl.OWLRL_Extension, rdfs_closure=False, axiomatic_triples=False, datatype_axioms=False) reasoner.expand(expanded_assertions_graph) logging.info("owlrl_reasoner: {} assertions in expanded graph", len(expanded_assertions_graph)) new_assertions = expanded_assertions_graph - assertions_graph logging.info("owlrl_reasoner: {} new assertions in expanded graph", len(new_assertions)) if not new_assertions: return bnode_assertions_count = 0 for s, p, o in new_assertions: if isinstance(s, rdflib.BNode) and isinstance( o, rdflib.BNode) and p == rdflib.OWL["sameAs"]: bnode_assertions_count += 1 if bnode_assertions_count == len(new_assertions): logging.info( "owlrl_reasoner: only produced bnode owl:sameAs otherBnode assertions, ignoring" ) return new_nanopublication = Nanopublication.from_assertions(new_assertions) logging.info("owlrl_reasoner: new nanopublication: {}", new_nanopublication) client.put_nanopublication(new_nanopublication)
def test_owlrl_literal_subject(): logger.info(sys.version) logger.info('rdflib=={}'.format(rdflib.__version__, )) logger.info('owlrl=={}'.format(owlrl.__version__, )) graph = Graph() graph.parse('http://www.w3.org/ns/prov#') assert not find_literal_subject_triples(graph), ( 'Import of PROV-O ontology creates triples where Literal is a subject.' ) owlrl.DeductiveClosure(OWLRL_Extension).expand(graph) literal_triples = find_literal_subject_triples(graph) assert not literal_triples, ( 'OWL RL creates triples with literal as subject. Example: {t}'.format( t=literal_triples[0], ))
def perform_reasoning(self, ontology_file: str) -> None: """ Expand the graph with the inferred triples. """ # print(guess_format(ontology_file)) self.graph.load(ontology_file, format=guess_format(ontology_file)) print(f"Triples including ontology: {len(self.graph)}.") # We apply reasoning and expand the graph with new triples owlrl.DeductiveClosure( owlrl.CombinedClosure.RDFS_OWLRL_Semantics, axiomatic_triples=False, datatype_axioms=False, ).expand(self.graph) print(f"Triples after OWL 2 RL reasoning: {len(self.graph)}.")
def test_dt_not_type(): """ Test dt-not-type rule for OWL 2 RL. """ m_one = Literal(-1, datatype=XSD.nonNegativeInteger) g = Graph() g.add((T.A, T.prop, m_one)) owlrl.DeductiveClosure(owlrl.OWLRL_Semantics).expand(g) # TODO, we know this one fails. It is not supposed to. #assert (m_one, RDF.type, XSD.nonNegativeInteger) not in g assert True result = next(g.objects(predicate=DAML.error)) expected = Literal( 'Lexical value of the literal \'-1\' does not match its datatype' ' (http://www.w3.org/2001/XMLSchema#nonNegativeInteger)') assert expected == result
def _perform_reasoning(graph: rdflib.Graph) -> None: """ Subtask OA.2 Expand the graph with the inferred triples, using reasoning. """ tic = time.perf_counter() print(f"Triples including ontology: {len(graph)}.") # Happy with this reasoner owlrl.DeductiveClosure( owlrl.OWLRL.OWLRL_Semantics, axiomatic_triples=False, datatype_axioms=False, ).expand(graph) toc = time.perf_counter() print(f"Finished reasoning on graph in {toc - tic} seconds.") print(f"Triples after OWL 2 RL reasoning: {len(graph)}.")
def performReasoning(self, ontology_file): """ A function used to expand a knowledge grpah with inferences using an ontology ... Attributes ---------- ontology_file : string the name of the turtle file that has the reference ontology (extension included) """ #We should load the ontology first self.loadGraph(ontology_file) # self.g.load(ontology_file, format='ttl') #e.g., format=ttl print(f"Triples including ontology: {str(len(self.g))}.") #We apply reasoning and expand the graph with new triples owlrl.DeductiveClosure(owlrl.OWLRL_Semantics, axiomatic_triples=False, datatype_axioms=False).expand(self.g) print(f"Triples after OWL 2 RL reasoning: {str(len(self.g))}.")
def perform_reasoning(self, ontology_file: str) -> None: """ Subtask SPARQL.1 Expand the graph with the inferred triples, using reasoning. """ tic = time.perf_counter() # print(guess_format(ontology_file)) self.graph.load(ontology_file, format=guess_format(ontology_file)) print(f"Triples including ontology: {len(self.graph)}.") # Happy with this reasoner owlrl.DeductiveClosure( owlrl.OWLRL.OWLRL_Semantics, axiomatic_triples=False, datatype_axioms=False, ).expand(self.graph) toc = time.perf_counter() print(f"Finished reasoning on graph in {toc - tic} seconds.") print(f"Triples after OWL 2 RL reasoning: {len(self.graph)}.")
def test_dt_type1(): """ Test dt-type1 rule for OWL 2 RL. """ g = Graph() owlrl.DeductiveClosure(owlrl.OWLRL_Semantics).expand(g) assert (RDF.PlainLiteral, RDF.type, RDFS.Datatype) in g assert (RDF.XMLLiteral, RDF.type, RDFS.Datatype) in g assert (RDFS.Literal, RDF.type, RDFS.Datatype) in g assert (XSD.decimal, RDF.type, RDFS.Datatype) in g assert (XSD.integer, RDF.type, RDFS.Datatype) in g assert (XSD.nonNegativeInteger, RDF.type, RDFS.Datatype) in g assert (XSD.nonPositiveInteger, RDF.type, RDFS.Datatype) in g assert (XSD.positiveInteger, RDF.type, RDFS.Datatype) in g assert (XSD.negativeInteger, RDF.type, RDFS.Datatype) in g assert (XSD.long, RDF.type, RDFS.Datatype) in g assert (XSD.int, RDF.type, RDFS.Datatype) in g assert (XSD.short, RDF.type, RDFS.Datatype) in g assert (XSD.byte, RDF.type, RDFS.Datatype) in g assert (XSD.unsignedLong, RDF.type, RDFS.Datatype) in g assert (XSD.unsignedInt, RDF.type, RDFS.Datatype) in g assert (XSD.unsignedShort, RDF.type, RDFS.Datatype) in g assert (XSD.unsignedByte, RDF.type, RDFS.Datatype) in g assert (XSD.float, RDF.type, RDFS.Datatype) in g assert (XSD.double, RDF.type, RDFS.Datatype) in g assert (XSD.string, RDF.type, RDFS.Datatype) in g assert (XSD.normalizedString, RDF.type, RDFS.Datatype) in g assert (XSD.token, RDF.type, RDFS.Datatype) in g assert (XSD.language, RDF.type, RDFS.Datatype) in g assert (XSD.Name, RDF.type, RDFS.Datatype) in g assert (XSD.NCName, RDF.type, RDFS.Datatype) in g assert (XSD.NMTOKEN, RDF.type, RDFS.Datatype) in g assert (XSD.boolean, RDF.type, RDFS.Datatype) in g assert (XSD.hexBinary, RDF.type, RDFS.Datatype) in g assert (XSD.base64Binary, RDF.type, RDFS.Datatype) in g assert (XSD.anyURI, RDF.type, RDFS.Datatype) in g assert (XSD.dateTime, RDF.type, RDFS.Datatype) in g assert (XSD.dateTimeStamp, RDF.type, RDFS.Datatype) in g
def test_cls_avf_error(mock_rtc): """ Test restriction type check for cls-avf rule for OWL 2 RL. If:: T(?x, owl:allValuesFrom, ?y) T(?x, owl:onProperty, ?p) T(?u, rdf:type, ?x) T(?u, ?p, ?v) and type restriction *invalid*, then:: false """ g = Graph() x = T.x p = T.p u = T.u y = T.y v = T.v g.add((x, OWL.allValuesFrom, y)) g.add((x, OWL.onProperty, p)) g.add((u, RDF.type, x)) g.add((u, p, v)) # trigger invalid restriction type mock_rtc.return_value = False owlrl.DeductiveClosure(owlrl.OWLRL_Semantics).expand(g) result = next(g.objects(predicate=DAML.error)) expected = Literal( 'Violation of type restriction for allValuesFrom in http://test.org/p' ' for datatype http://test.org/y on value http://test.org/v') assert expected == result
def performReasoning(graph, ontology_file): """ A function used to expand a knowledge grpah with inferences using an ontology ... Attributes ---------- graph : Graph the KG to be expanded file_output : string the name of the turtle file that has the reference ontology (extension included) """ print("Triples including ontology: '" + str(len(graph)) + "'.") #We should load the ontology first graph.load(ontology_file, format='ttl') #e.g., format=ttl #We apply reasoning and expand the graph with new triples owlrl.DeductiveClosure(owlrl.OWLRL_Semantics, axiomatic_triples=False, datatype_axioms=False).expand(graph) print("Triples after OWL 2 RL reasoning: '" + str(len(graph)) + "'.")
def expand(self) -> None: """ Expand deductive closure under RDFS semantics. """ owlrl.DeductiveClosure(owlrl.RDFS_Semantics).expand(self)
query = """ SELECT ?pizzaName ?pizzaDescription WHERE{ ?pizza a pizza:MeatyPizza; zdetor:name ?pizzaName; zdetor:description ?pizzaDescription . } """ ## print("Performing the reasoning") start = time.time() #perform the reasoning with the created ontology and save to a new KG in ttl format owlrl.DeductiveClosure(owlrl.OWLRL_Semantics, axiomatic_triples=False, datatype_axioms=False).expand(solution.g) print(f"Triples after OWL 2 RL reasoning: {len(solution.g)}.") end = time.time() print(f"Processing time {round((end-start)/60,2)} min") filename = 'output_files/zdetor_pizza_alignment_data_reasoned.ttl' solution.saveGraph(filename) # check for meaty pizzas if load_kg_with_data: query = """ SELECT ?pizzaName ?pizzaDescription WHERE{ ?pizza a pizza:MeatyPizza;