def transform(self, graph): """ Flattens conjunctions ( A1 and ( B1 and B2 ) and A2 ) = ( A1 and B1 and B2 and A2 ) """ Individual.factoryGraph = graph for conjunctId in graph.subjects(predicate=OWL_NS.intersectionOf): conjunct = BooleanClass(conjunctId) nestedConjuncts = [ BooleanClass(i) for i in conjunct if (i, OWL_NS.intersectionOf, None) in graph] if nestedConjuncts: def collapseConjunctTerms(left, right): list(left) + list(right) if len(nestedConjuncts) == 1: newTopLevelItems = list(nestedConjuncts[0]) else: newTopLevelItems = reduce( collapseConjunctTerms, nestedConjuncts) for nc in nestedConjuncts: nc.clear() del conjunct[conjunct.index(nc.identifier)] nc.delete() for newItem in newTopLevelItems: conjunct.append(newItem)
def transform(self, graph): """ Transforms a universal restriction on a 'pure' nominal range into a conjunction of value restriction (using set theory and demorgan's laws) """ Individual.factoryGraph = graph for restriction, intermediateCl, \ nominal, prop, partition in graph.query( self.NOMINAL_QUERY, initNs={'owl': OWL_NS, 'rdfs': RDFS}): exceptions = EnumeratedClass() partition = Collection(graph, partition) nominalCollection = Collection(graph, nominal) for i in partition: if i not in nominalCollection: exceptions._rdfList.append(i) # exceptions += i exists = Class(complementOf=(Property(prop) | some | exceptions)) for s, p, o in graph.triples((None, None, restriction)): graph.add((s, p, exists.identifier)) Individual(restriction).delete() #purge nominalization placeholder iClass = BooleanClass(intermediateCl) iClass.clear() iClass.delete()
def setUp(self): self.tBoxGraph = Graph() self.tBoxGraph.namespace_manager.bind('ex', EX) self.tBoxGraph.namespace_manager.bind('owl', OWL_NS) Individual.factoryGraph = self.tBoxGraph self.classB = Class(EX.b) self.classE = Class(EX.e) self.classF = Class(EX.f) self.classA = BooleanClass(EX.a, operator=OWL_NS.unionOf, members=[self.classE, self.classF]) self.classC = BooleanClass(EX.c, operator=OWL_NS.unionOf, members=[self.classA, self.classB]) self.ruleStore, self.ruleGraph = SetupRuleStore()
def Th(owlGraph, _class, variable=Variable('X'), position=LHS): """ DLP head (antecedent) knowledge assertional forms (ABox assertions, conjunction of ABox assertions, and universal role restriction assertions) """ props = list(set(owlGraph.predicates(subject=_class))) if OWL_NS.allValuesFrom in props: #http://www.w3.org/TR/owl-semantics/#owl_allValuesFrom for s, p, o in owlGraph.triples((_class, OWL_NS.allValuesFrom, None)): prop = list(owlGraph.objects(subject=_class, predicate=OWL_NS.onProperty))[0] newVar = Variable(BNode()) body = Uniterm(prop, [variable, newVar], newNss=owlGraph.namespaces()) for head in Th(owlGraph, o, variable=newVar): yield Clause(body, head) elif OWL_NS.hasValue in props: prop = list(owlGraph.objects(subject=_class, predicate=OWL_NS.onProperty))[0] o = first(owlGraph.objects(subject=_class, predicate=OWL_NS.hasValue)) yield Uniterm(prop, [variable, o], newNss=owlGraph.namespaces()) elif OWL_NS.someValuesFrom in props: #http://www.w3.org/TR/owl-semantics/#someValuesFrom for s, p, o in owlGraph.triples((_class, OWL_NS.someValuesFrom, None)): prop = list(owlGraph.objects(subject=_class, predicate=OWL_NS.onProperty))[0] newVar = BNode() yield And([Uniterm(prop, [variable, newVar], newNss=owlGraph.namespaces()), generatorFlattener(Th(owlGraph, o, variable=newVar))]) elif OWL_NS.intersectionOf in props: from FuXi.Syntax.InfixOWL import BooleanClass yield And([first(Th(owlGraph, h, variable)) for h in BooleanClass(_class)]) else: #Simple class yield Uniterm(RDF.type, [variable, isinstance(_class, BNode) and SkolemizeExistentialClasses(_class) or _class], newNss=owlGraph.namespaces())
def transform(self, graph): """ Transforms a 'pure' nominal range into a disjunction of value restrictions """ Individual.factoryGraph = graph for restriction, intermediateCl, nominal, prop in graph.query( self.NOMINAL_QUERY, initNs={'owl': OWL_NS}): nominalCollection = Collection(graph, nominal) # purge restriction restr = Class(restriction) parentSets = [i for i in restr.subClassOf] restr.clearOutDegree() newConjunct = BooleanClass(restriction, OWL_NS.unionOf, [Property(prop) | value | val for val in nominalCollection], graph) newConjunct.subClassOf = parentSets # purge nominalization placeholder iClass = BooleanClass(intermediateCl) iClass.clear() iClass.delete()
def transform(self, graph): """ Transforms a universal restriction on a 'pure' nominal range into a conjunction of value restriction (using set theory and demorgan's laws) """ Individual.factoryGraph = graph for restriction, intermediateCl, nominal, prop, partition in graph.query( self.NOMINAL_QUERY, initNs={ u'owl': OWL_NS, u'rdfs': str(RDFS) }): exceptions = EnumeratedClass() partition = Collection(graph, partition) nominalCollection = Collection(graph, nominal) for i in partition: if i not in nominalCollection: exceptions._rdfList.append(i) #exceptions+=i exists = Class(complementOf=(Property(prop) | some | exceptions)) for s, p, o in graph.triples((None, None, restriction)): graph.add((s, p, exists.identifier)) Individual(restriction).delete() #purge nominalization placeholder iClass = BooleanClass(intermediateCl) iClass.clear() iClass.delete()
def transform(self, graph): """ Flattens conjunctions ( A1 and ( B1 and B2 ) and A2 ) = ( A1 and B1 and B2 and A2 ) """ Individual.factoryGraph = graph for conjunctId in graph.subjects(predicate=OWL_NS.intersectionOf): conjunct = BooleanClass(conjunctId) nestedConjuncts = [ BooleanClass(i) for i in conjunct if (i, OWL_NS.intersectionOf, None) in graph ] if nestedConjuncts: def collapseConjunctTerms(left, right): list(left) + list(right) if len(nestedConjuncts) == 1: newTopLevelItems = list(nestedConjuncts[0]) else: newTopLevelItems = reduce(collapseConjunctTerms, nestedConjuncts) for nc in nestedConjuncts: nc.clear() del conjunct[conjunct.index(nc.identifier)] nc.delete() for newItem in newTopLevelItems: conjunct.append(newItem)
def transform(self, graph): """ Transforms a 'pure' nominal range into a disjunction of value restrictions """ Individual.factoryGraph = graph for restriction, intermediateCl, nominal, prop in graph.query( self.NOMINAL_QUERY, initNs={u'owl': OWL_NS}): nominalCollection = Collection(graph, nominal) #purge restriction restr = Class(restriction) parentSets = [i for i in restr.subClassOf] restr.clearOutDegree() newConjunct = BooleanClass( restriction, OWL_NS.unionOf, [Property(prop) | value | val for val in nominalCollection], graph) newConjunct.subClassOf = parentSets #purge nominalization placeholder iClass = BooleanClass(intermediateCl) iClass.clear() iClass.delete()
def transform(self, graph): """ Uses DeMorgan's laws to reduce negated disjunctions to a conjunction of negated formulae """ Individual.factoryGraph = graph for disjunctId in graph.subjects(predicate=OWL_NS.unionOf): if (None, OWL_NS.complementOf, disjunctId) in graph and \ isinstance(disjunctId, BNode): # not ( A1 or A2 or .. or An ) # = # ( not A1 and not A2 and .. and not An ) disjunct = BooleanClass(disjunctId, operator=OWL_NS.unionOf) items = list(disjunct) newConjunct = BooleanClass( members=[~Class(item) for item in items]) for negation in graph.subjects(predicate=OWL_NS.complementOf, object=disjunctId): Class(negation).replace(newConjunct) if not isinstance(negation, BNode): newConjunct.identifier = negation disjunct.clear() disjunct.delete() elif ((disjunctId, OWL_NS.unionOf, None) in graph) and not \ [item for item in BooleanClass(disjunctId, operator=OWL_NS.unionOf) if not Class(item).complementOf]: #( not A1 or not A2 or .. or not An ) # = #not ( A1 and A2 and .. and An ) disjunct = BooleanClass(disjunctId, operator=OWL_NS.unionOf) items = [Class(item).complementOf for item in disjunct] for negation in disjunct: Class(negation).delete() negatedConjunct = ~ BooleanClass(members=items) disjunct.clear() disjunct.replace(negatedConjunct)
def ProcessConcept(klass, owlGraph, FreshConcept, newOwlGraph): """ This method implements the pre-processing portion of the completion-based procedure and recursively transforms the input ontology one concept at a time """ iD = klass.identifier # maps the identifier to skolem:bnodeLabel if # the identifier is a BNode or to skolem:newBNodeLabel # if its a URI FreshConcept[iD] = SkolemizeExistentialClasses( BNode() if isinstance(iD, URIRef) else iD ) # A fresh atomic concept (A_c) newCls = Class(FreshConcept[iD], graph=newOwlGraph) cls = CastClass(klass, owlGraph) # determine if the concept is the left, right (or both) # operand of a subsumption axiom in the ontology location = WhichSubsumptionOperand(iD, owlGraph) # log.debug(repr(cls)) if isinstance(iD, URIRef): # An atomic concept? if location in [LEFT_SUBSUMPTION_OPERAND, BOTH_SUBSUMPTION_OPERAND]: log.debug( "Original (atomic) concept appears in the left HS of a subsumption axiom") # If class is left operand of subsumption operator, # assert (in new OWL graph) that A_c subsumes the concept _cls = Class(cls.identifier, graph=newOwlGraph) newCls += _cls log.debug("%s subsumes %s" % (newCls, _cls)) if location in [RIGHT_SUBSUMPTION_OPERAND, BOTH_SUBSUMPTION_OPERAND]: log.debug( "Original (atomic) concept appears in the right HS of a subsumption axiom") # If class is right operand of subsumption operator, # assert that it subsumes A_c _cls = Class(cls.identifier, graph=newOwlGraph) _cls += newCls log.debug("%s subsumes %s" % (_cls, newCls)) elif isinstance(cls, Restriction): if location != NEITHER_SUBSUMPTION_OPERAND: # appears in at least one subsumption operator # An existential role restriction log.debug( "Original (role restriction) appears in a subsumption axiom") role = Property(cls.onProperty, graph=newOwlGraph) fillerCls = ProcessConcept( Class(cls.restrictionRange), owlGraph, FreshConcept, newOwlGraph) # leftCls is (role SOME fillerCls) leftCls = role | some | fillerCls log.debug("let leftCls be %s" % leftCls) if location in [LEFT_SUBSUMPTION_OPERAND, BOTH_SUBSUMPTION_OPERAND]: # if appears as the left operand, we say A_c subsumes # leftCls newCls += leftCls log.debug("%s subsumes leftCls" % newCls) if location in [RIGHT_SUBSUMPTION_OPERAND, BOTH_SUBSUMPTION_OPERAND]: # if appears as right operand, we say left Cls subsumes A_c leftCls += newCls log.debug("leftCls subsumes %s" % newCls) else: assert isinstance(cls, BooleanClass), "Not ELH ontology: %r" % cls assert cls._operator == OWL_NS.intersectionOf, "Not ELH ontology" log.debug( "Original conjunction (or boolean operator wlog ) appears in a subsumption axiom") # A boolean conjunction if location != NEITHER_SUBSUMPTION_OPERAND: members = [ProcessConcept(Class(c), owlGraph, FreshConcept, newOwlGraph) for c in cls] newBoolean = BooleanClass( BNode(), members=members, graph=newOwlGraph) # create a boolean conjunction of the fresh concepts corresponding # to processing each member of the existing conjunction if location in [LEFT_SUBSUMPTION_OPERAND, BOTH_SUBSUMPTION_OPERAND]: # if appears as the left operand, we say the new conjunction # is subsumed by A_c newCls += newBoolean log.debug("%s subsumes %s" % (newCls, newBoolean)) if location in [RIGHT_SUBSUMPTION_OPERAND, BOTH_SUBSUMPTION_OPERAND]: # if appears as the right operand, we say A_c is subsumed by # the new conjunction newBoolean += newCls log.debug("%s subsumes %s" % (newBoolean, newCls)) return newCls
def transform(self, graph): """ Uses demorgan's laws to reduce negated disjunctions to a conjunction of negated formulae """ Individual.factoryGraph = graph for disjunctId in graph.subjects(predicate=OWL_NS.unionOf): if (None, OWL_NS.complementOf, disjunctId) in graph and \ isinstance(disjunctId, BNode): #not ( A1 or A2 or .. or An ) # = # ( not A1 and not A2 and .. and not An ) disjunct = BooleanClass(disjunctId, operator=OWL_NS.unionOf) items = list(disjunct) newConjunct = BooleanClass( members=[~Class(item) for item in items]) for negation in graph.subjects(predicate=OWL_NS.complementOf, object=disjunctId): Class(negation).replace(newConjunct) if not isinstance(negation, BNode): newConjunct.identifier = negation disjunct.clear() disjunct.delete() elif ((disjunctId, OWL_NS.unionOf, None) in graph) and not \ [item for item in BooleanClass(disjunctId, operator=OWL_NS.unionOf) if not Class(item).complementOf]: #( not A1 or not A2 or .. or not An ) # = #not ( A1 and A2 and .. and An ) disjunct = BooleanClass(disjunctId, operator=OWL_NS.unionOf) items = [Class(item).complementOf for item in disjunct] for negation in disjunct: Class(negation).delete() negatedConjunct = ~BooleanClass(members=items) disjunct.clear() disjunct.replace(negatedConjunct)