def extractRule(self,rule): vars,impl = self.rules[rule] body,bodyType,head,headType = self.implications[impl] allVars = map(self.extractTerm,Collection(self.graph,vars)) head = first(self.extractPredication(head,headType)) if bodyType == RIF_NS.And: body = map( lambda i: first(self.extractPredication( i, first(self.graph.objects(i,RDF.type))) ), Collection(self.graph,first(self.graph.objects(body,RIF_NS.formulas))) ) else: body = self.extractPredication(body,bodyType) if isinstance(body,list): body = And([first(body)]) if len(body) == 1 else And(body) nsMapping = {} nsMapping.update(self.nsBindings) return Rule( Clause(body,head), declare=allVars, nsMapping=nsMapping )
def IncomingSIPArcs(sip, predOcc): """docstring for IncomingSIPArcs""" for s, p, o in sip.triples((None, None, predOcc)): if (p, RDF.type, MAGIC.SipArc) in sip: if (s, RDF.type, MAGIC.BoundHeadPredicate) in sip: yield [s], Collection(sip, first(sip.objects(p, MAGIC.bindings))) else: yield Collection(sip, s), Collection( sip, first(sip.objects(p, MAGIC.bindings)))
def RenderSIPCollection(sipGraph, dot=None): try: from pydot import Node, Edge, Dot except: import warnings warnings.warn("Missing pydot library", ImportWarning) if not dot: dot = Dot(graph_type='digraph') dot.leftNodesLookup = {} nodes = {} for N, prop, q in sipGraph.query( 'SELECT ?N ?prop ?q { ?prop a magic:SipArc . ?N ?prop ?q . }', initNs={u'magic': MAGIC}): if MAGIC.BoundHeadPredicate in sipGraph.objects(subject=N, predicate=RDF.type): NCol = [N] else: NCol = Collection(sipGraph, N) if q not in nodes: newNode = Node(makeMD5Digest(q), label=normalizeTerm(q, sipGraph), shape='plaintext') nodes[q] = newNode dot.add_node(newNode) bNode = BNode() nodeLabel = ', '.join([normalizeTerm(term, sipGraph) for term in NCol]) edgeLabel = ', '.join([ var.n3() for var in Collection( sipGraph, first(sipGraph.objects(prop, MAGIC.bindings))) ]) markedEdgeLabel = '' if nodeLabel in dot.leftNodesLookup: bNode, leftNode, markedEdgeLabel = dot.leftNodesLookup[nodeLabel] # print "\t",nodeLabel,edgeLabel, markedEdgeLabel,not edgeLabel == markedEdgeLabel else: leftNode = Node(makeMD5Digest(bNode), label=nodeLabel, shape='plaintext') dot.leftNodesLookup[nodeLabel] = (bNode, leftNode, edgeLabel) nodes[bNode] = leftNode dot.add_node(leftNode) if not edgeLabel == markedEdgeLabel: edge = Edge(leftNode, nodes[q], label=edgeLabel) dot.add_edge(edge) return dot
def getRuleset(self): """ >>> parser = RIFCoreParser('http://www.w3.org/2005/rules/test/repository/tc/Frames/Frames-premise.rif') >>> for rule in parser.getRuleset(): print rule Forall ?Customer ( ns1:discount(?Customer 10) :- ns1:status(?Customer "gold"^^<http://www.w3.org/2001/XMLSchema#string>) ) Forall ?Customer ( ns1:discount(?Customer 5) :- ns1:status(?Customer "silver"^^<http://www.w3.org/2001/XMLSchema#string>) ) >>> parser = RIFCoreParser('http://www.w3.org/2005/rules/test/repository/tc/Guards_and_subtypes/Guards_and_subtypes-premise.rif') >>> for rule in parser.getRuleset(): print rule """ self.members = dict((_member,(_cls,_inst)) for _member,_cls,_inst in self.graph.query(MEMBER_PARTS,initNs=rif_namespaces) ) self.exists = dict((exists,(formula, formulaType, vars)) for exists, formula, formulaType, vars in self.graph.query(EXISTS_PARTS,initNs=rif_namespaces) ) self.implications = dict([(impl,(body,bodyType,head,headType)) for impl,body,bodyType,head,headType in self.graph.query(IMPLIES_PARTS,initNs=rif_namespaces)]) self.rules = dict([ (rule,(vars,impl)) for rule,vars,impl in self.graph.query(RULE_PARTS, initNs=rif_namespaces)]) self.frames = dict([ (frame,(obj,slots)) for frame,obj,slots in self.graph.query(FRAME_PARTS, initNs=rif_namespaces)]) self.atoms = dict([ (atom,(args,op)) for atom, args, op in self.graph.query( ATOM_PARTS, initNs=rif_namespaces) ]) self.externals = dict([(external,(args,op)) for external,args,op in self.graph.query( EXTERNAL_PARTS, initNs=rif_namespaces) ]) rt = set() groundFacts = set() for sentenceCollection in self.graph.objects(predicate=RIF_NS.sentences): col = Collection(self.graph,sentenceCollection) for sentence in col: if RIF_NS.Implies in self.graph.objects(sentence,RDF.type): rt.add(self.extractImp(sentence)) elif RIF_NS.Forall in self.graph.objects(sentence,RDF.type): rt.add(self.extractRule(sentence)) elif RIF_NS.Frame in self.graph.objects(sentence,RDF.type): frames = self.extractFrame(sentence) for term in frames: if term.isGround(): triple = term.toRDFTuple() if triple not in groundFacts: groundFacts.add(triple) additionalFacts,additionalRules=self.handleImport() if additionalRules: rt.update(additionalRules) if additionalFacts: groundFacts.update(additionalFacts) return list(rt),list(groundFacts)
def extractExists(self,exists_resource): formula, formulaType, vars = self.exists[exists_resource] allVars = map(self.extractTerm,Collection(self.graph,vars)) if formulaType == RIF_NS.And: formula = And(map( lambda i: first(self.extractPredication( i, first(self.graph.objects(i,RDF.type))) ), Collection(self.graph,first(self.graph.objects(formula,RIF_NS.formulas))) )) else: formula = self.extractPredication(formula,formulaType) return Exists(formula,allVars)
def handleConjunct(conjunction, owlGraph, o, conjunctVar=Variable('X')): for bodyTerm in Collection(owlGraph, o): negatedFormula = False addToConjunct = None for negatedFormula in owlGraph.objects(subject=bodyTerm, predicate=OWL_NS.complementOf): addToConjunct = Tc(owlGraph, negatedFormula) if negatedFormula: #addToConjunct will be the term we need to add to the conjunct conjunction.append(addToConjunct) else: normalizedBodyTerm = NormalizeBooleanClassOperand( bodyTerm, owlGraph) bodyUniTerm = Uniterm(RDF.type, [conjunctVar, normalizedBodyTerm], newNss=owlGraph.namespaces()) processedBodyTerm = Tb(owlGraph, bodyTerm, conjunctVar) classifyingClause = NormalizeClause( Clause(processedBodyTerm, bodyUniTerm)) redundantClassifierClause = processedBodyTerm == bodyUniTerm if isinstance(normalizedBodyTerm, URIRef) and normalizedBodyTerm.find( SKOLEMIZED_CLASS_NS) == -1: conjunction.append(bodyUniTerm) elif (bodyTerm,OWL_NS.someValuesFrom,None) in owlGraph or\ (bodyTerm,OWL_NS.hasValue,None) in owlGraph: conjunction.extend(classifyingClause.body) elif (bodyTerm, OWL_NS.allValuesFrom, None) in owlGraph: raise MalformedDLPFormulaError( "Universal restrictions can only be used as the second argument to rdfs:subClassOf (GCIs)" ) elif (bodyTerm, OWL_NS.unionOf, None) in owlGraph: conjunction.append(classifyingClause.body) elif (bodyTerm, OWL_NS.intersectionOf, None) in owlGraph: conjunction.append(bodyUniTerm)
def SIPRepresentation(sipGraph): rt = [] for N, prop, q in sipGraph.query( 'SELECT ?N ?prop ?q { ?prop a magic:SipArc . ?N ?prop ?q . }', initNs={u'magic': MAGIC}): if MAGIC.BoundHeadPredicate in sipGraph.objects(subject=N, predicate=RDF.type): NCol = [N] else: NCol = Collection(sipGraph, N) rt.append("{ %s } -> %s %s" % (', '.join( [normalizeTerm(term, sipGraph) for term in NCol]), ', '.join([ var.n3() for var in Collection( sipGraph, first(sipGraph.objects(prop, MAGIC.bindings))) ]), normalizeTerm(q, sipGraph))) return rt
def collectSip(left, right): if isinstance(left, list): vars = CollectSIPArcVars(left, right, phBoundVars) if not vars and ignoreUnboundDPreds: raise InvalidSIPException("No bound variables for %s" % right) leftList = Collection(sipGraph, None) left = list(set(left)) [leftList.append(i) for i in [GetOp(ii) for ii in left]] left.append(right) arc = SIPGraphArc(leftList.uri, getOccurrenceId(right, occurLookup), vars, sipGraph) return left else: left.isHead = True vars = CollectSIPArcVars(left, right, phBoundVars) if not vars and ignoreUnboundDPreds: raise InvalidSIPException("No bound variables for %s" % right) ph = GetOp(left) q = getOccurrenceId(right, occurLookup) if boundHead: arc = SIPGraphArc(ph, q, vars, sipGraph, headPassing=boundHead) sipGraph.add((ph, RDF.type, MAGIC.BoundHeadPredicate)) rt = [left, right] else: rt = [right] return rt
def extractAtom(self,atom): args,op = self.atoms[atom] op = self.extractTerm(op) args = map(self.extractTerm,Collection(self.graph,args)) if len(args) > 2: raise NotImplementedError( "FuXi RIF Core parsing only supports subset involving binary/unary Atoms" ) return Uniterm(op,args,newNss=self.nsBindings)
def extractFrame(self,frame): obj,slots = self.frames[frame] rt=[] for slot in Collection(self.graph,slots): k = self.extractTerm(first(self.graph.objects(slot,RIF_NS.slotkey))) v = self.extractTerm(first(self.graph.objects(slot,RIF_NS.slotvalue))) rt.append( Uniterm(k,[self.extractTerm(obj),v],newNss=self.nsBindings) ) return rt
def Tb(owlGraph, _class, variable=Variable('X')): """ DLP body (consequent knowledge assertional forms (ABox assertions, conjunction / disjunction of ABox assertions, and exisential role restriction assertions) These are all common EL++ templates for KR """ props = list(set(owlGraph.predicates(subject=_class))) if OWL_NS.intersectionOf in props and not isinstance(_class, URIRef): for s, p, o in owlGraph.triples((_class, OWL_NS.intersectionOf, None)): conj = [] handleConjunct(conj, owlGraph, o, variable) return And(conj) elif OWL_NS.unionOf in props and not isinstance(_class, URIRef): #http://www.w3.org/TR/owl-semantics/#owl_unionOf for s, p, o in owlGraph.triples((_class, OWL_NS.unionOf, None)): return Or([Tb(owlGraph,c,variable=variable) \ for c in Collection(owlGraph,o)]) elif OWL_NS.someValuesFrom in props: #http://www.w3.org/TR/owl-semantics/#owl_someValuesFrom prop = list( owlGraph.objects(subject=_class, predicate=OWL_NS.onProperty))[0] o = list( owlGraph.objects(subject=_class, predicate=OWL_NS.someValuesFrom))[0] newVar = Variable(BNode()) body = Uniterm(prop, [variable, newVar], newNss=owlGraph.namespaces()) head = Th(owlGraph, o, variable=newVar) return And([ Uniterm(prop, [variable, newVar], newNss=owlGraph.namespaces()), Tb(owlGraph, o, variable=newVar) ]) elif OWL_NS.hasValue in props: #http://www.w3.org/TR/owl-semantics/#owl_hasValue #Domain-specific rules for hasValue #Can be achieved via pD semantics prop = list( owlGraph.objects(subject=_class, predicate=OWL_NS.onProperty))[0] o = first(owlGraph.objects(subject=_class, predicate=OWL_NS.hasValue)) return Uniterm(prop, [variable, o], newNss=owlGraph.namespaces()) elif OWL_NS.complementOf in props: return Tc(owlGraph, first(owlGraph.objects(_class, OWL_NS.complementOf))) else: #simple class #"Named" Uniterm _classTerm = SkolemizeExistentialClasses(_class) return Uniterm(RDF.type, [variable, _classTerm], newNss=owlGraph.namespaces())
def __init__(self, left, right, variables, graph=None, headPassing=False): self.variables = variables self.left = left self.right = right self.graph = graph is None and Graph() or graph self.arc = SKOLEMIZED_CLASS_NS[BNode()] self.graph.add((self.arc, RDF.type, MAGIC.SipArc)) varsCol = Collection(self.graph, BNode()) [varsCol.append(i) for i in self.variables] self.graph.add((self.arc, MAGIC.bindings, varsCol.uri)) if headPassing: self.boundHeadPredicate = True self.graph.add((self.left, self.arc, self.right)) else: self.boundHeadPredicate = False self.graph.add((self.left, self.arc, self.right))
def predicate(self, predicate, object, depth=1): writer = self.writer store = self.store writer.push(predicate) if isinstance(object, Literal): attributes = "" if object.language: writer.attribute(XMLLANG, object.language) if object.datatype: writer.attribute(RDF.datatype, object.datatype) writer.text(object) elif object in self.__serialized or not (object, None, None) in store: if isinstance(object, BNode): if more_than(store.triples((None, None, object)), 0): writer.attribute(RDF.nodeID, fix(object)) else: writer.attribute(RDF.resource, self.relativize(object)) else: items = [] for item in store.items(object): # add a strict option to items? if isinstance(item, Literal): items = None # can not serialize list with literal values in them with rdf/xml else: items.append(item) if first(store.objects(object, RDF.first)): # may not have type RDF.List collection = object self.__serialized[object] = 1 # TODO: warn that any assertions on object other than # RDF.first and RDF.rest are ignored... including RDF.List writer.attribute(RDF.parseType, "Collection") col = Collection(store, object) for item in col: self.forceRDFAbout.add(item) self.subject(item) self.__serialized[item] = 1 else: if depth <= self.max_depth: self.subject(object, depth + 1) elif isinstance(object, BNode): writer.attribute(RDF.nodeID, fix(object)) else: writer.attribute(RDF.resource, self.relativize(object)) writer.pop(predicate)
def GetTests(): manifestGraph = Graph().parse(open('SPARQL/W3C/entailment/manifest.ttl'), format='n3') rt = manifestGraph.query(MANIFEST_QUERY, initNs=nsMap, DEBUG=False) for test, name, queryFile, rdfDoc, regime, result in rt: if isinstance(regime, BNode): regime = list(Collection(manifestGraph, regime)) else: regime = [regime] named_graph_query = MANIFEST_NAMED_GRAPHS_QUERY % (test.n3()) named_graphs = list( manifestGraph.query(named_graph_query, initNs=nsMap)) yield test.split(TEST)[-1], \ name, \ queryFile, \ rdfDoc, \ regime, \ result,\ named_graphs
def extractPredication(self,predication,predType): if predType == RIF_NS.Frame: return self.extractFrame(predication) elif predType == RIF_NS.Atom: return [self.extractAtom(predication)] elif predType == RIF_NS.Exists: return [self.extractExists(predication)] elif predType == RIF_NS.Member: _cls,_inst = self.members[predication] return [Uniterm( RDF.type, [self.extractTerm(_inst), self.extractTerm(_cls)], newNss=self.nsBindings)] elif predType == RIF_NS.External: # N3Builtin(self,uri,func,argument,result) args,op = self.externals[predication] args = map(self.extractTerm,Collection(self.graph,args)) op = self.extractTerm(op) return [ExternalFunction(Uniterm(op,args))] else: raise SyntaxError("Unsupported RIF in RDF type: %s"%predType.n3())
def IdentifyDerivedPredicates(ddlMetaGraph, tBox, ruleset=None): """ See: http://code.google.com/p/fuxi/wiki/DataDescriptionLanguage# """ dPreds = set() basePreds = set() DDL = Namespace( 'http://code.google.com/p/fuxi/wiki/DataDescriptionLanguage#') if ruleset: for rule in ruleset: dPreds.add(GetOp(rule.formula.head)) for derivedClassList in ddlMetaGraph.subjects(predicate=RDF.type, object=DDL.DerivedClassList): dPreds.update(Collection(ddlMetaGraph, derivedClassList)) for derivedClassList in ddlMetaGraph.subjects( predicate=RDF.type, object=DDL.DerivedPropertyList): dPreds.update(Collection(ddlMetaGraph, derivedClassList)) derivedPropPrefixes = [] basePropPrefixes = [] for derivedPropPrefixList in ddlMetaGraph.subjects( predicate=RDF.type, object=DDL.DerivedPropertyPrefix): derivedPropPrefixes.extend( Collection(ddlMetaGraph, derivedPropPrefixList)) for basePropPrefixList in ddlMetaGraph.subjects( predicate=RDF.type, object=DDL.BasePropertyPrefix): basePropPrefixes.extend(Collection(ddlMetaGraph, basePropPrefixList)) for prop in tBox.query(OWL_PROPERTIES_QUERY): if first(itertools.ifilter(lambda prefix:prop.startswith(prefix), derivedPropPrefixes)) and \ (prop,RDF.type,OWL_NS.AnnotationProperty) not in tBox: dPreds.add(prop) if first(itertools.ifilter(lambda prefix:prop.startswith(prefix), basePropPrefixes)) and \ (prop,RDF.type,OWL_NS.AnnotationProperty) not in tBox and \ prop not in dPreds: basePreds.add(prop) derivedClassPrefixes = [] for derivedClsPrefixList in ddlMetaGraph.subjects( predicate=RDF.type, object=DDL.DerivedClassPrefix): derivedClassPrefixes.extend( Collection(ddlMetaGraph, derivedClsPrefixList)) baseClassPrefixes = [] for baseClsPrefixList in ddlMetaGraph.subjects(predicate=RDF.type, object=DDL.BaseClassPrefix): baseClassPrefixes.extend(Collection(ddlMetaGraph, baseClsPrefixList)) for cls in tBox.subjects(predicate=RDF.type, object=OWL_NS.Class): if first( itertools.ifilter(lambda prefix: cls.startswith(prefix), baseClassPrefixes)): if cls not in dPreds: basePreds.add(cls) if first( itertools.ifilter(lambda prefix: cls.startswith(prefix), derivedClassPrefixes)): if cls not in basePreds: dPreds.add(cls) nsBindings = dict([(prefix, nsUri) for prefix, nsUri in itertools.chain( tBox.namespaces(), ddlMetaGraph.namespaces()) if prefix]) for queryNode in ddlMetaGraph.subjects(predicate=RDF.type, object=DDL.DerivedClassQuery): query = first(ddlMetaGraph.objects(queryNode, RDF.value)) for cls in tBox.query(query, initNs=nsBindings): dPreds.add(cls) for baseClsList in ddlMetaGraph.subjects(predicate=RDF.type, object=DDL.BaseClassList): basePreds.update(Collection(ddlMetaGraph, baseClsList)) dPreds.difference_update(basePreds) return dPreds
def BuildNaturalSIP(clause, derivedPreds, adornedHead, hybridPreds2Replace=None, ignoreUnboundDPreds=False): """ Natural SIP: Informally, for a rule of a program, a sip represents a decision about the order in which the predicates of the rule will be evaluated, and how values for variables are passed from predicates to other predicates during evaluation >>> ruleStore,ruleGraph=SetupRuleStore(StringIO(PROGRAM2)) >>> ruleStore._finalize() >>> fg=Graph().parse(StringIO(PROGRAM2),format='n3') >>> rs=Ruleset(n3Rules=ruleGraph.store.rules,nsMapping=ruleGraph.store.nsMgr) >>> for rule in rs: print rule Forall ?Y ?X ( ex:sg(?X ?Y) :- ex:flat(?X ?Y) ) Forall ?Y ?Z4 ?X ?Z1 ?Z2 ?Z3 ( ex:sg(?X ?Y) :- And( ex:up(?X ?Z1) ex:sg(?Z1 ?Z2) ex:flat(?Z2 ?Z3) ex:sg(?Z3 ?Z4) ex:down(?Z4 ?Y) ) ) >>> sip=BuildNaturalSIP(list(rs)[-1]) >>> for N,x in IncomingSIPArcs(sip,MAGIC.sg): print N.n3(),x.n3() ( <http://doi.acm.org/10.1145/28659.28689#up> <http://doi.acm.org/10.1145/28659.28689#sg> <http://doi.acm.org/10.1145/28659.28689#flat> ) ( ?Z3 ) ( <http://doi.acm.org/10.1145/28659.28689#up> <http://doi.acm.org/10.1145/28659.28689#sg> ) ( ?Z1 ) >>> sip=BuildNaturalSIP(list(rs)[-1],[MAGIC.sg]) >>> list(sip.query('SELECT ?q { ?prop a magic:SipArc . [] ?prop ?q . }',initNs={u'magic':MAGIC})) [rdflib.URIRef('http://doi.acm.org/10.1145/28659.28689#sg'), rdflib.URIRef('http://doi.acm.org/10.1145/28659.28689#sg')] """ from FuXi.Rete.Magic import AdornedUniTerm occurLookup = {} boundHead = isinstance(adornedHead, AdornedUniTerm) and 'b' in adornedHead.adornment phBoundVars = list(adornedHead.getDistinguishedVariables(varsOnly=True)) # assert isinstance(clause.head,Uniterm),"Only one literal in the head!" def collectSip(left, right): if isinstance(left, list): vars = CollectSIPArcVars(left, right, phBoundVars) if not vars and ignoreUnboundDPreds: raise InvalidSIPException("No bound variables for %s" % right) leftList = Collection(sipGraph, None) left = list(set(left)) [leftList.append(i) for i in [GetOp(ii) for ii in left]] left.append(right) arc = SIPGraphArc(leftList.uri, getOccurrenceId(right, occurLookup), vars, sipGraph) return left else: left.isHead = True vars = CollectSIPArcVars(left, right, phBoundVars) if not vars and ignoreUnboundDPreds: raise InvalidSIPException("No bound variables for %s" % right) ph = GetOp(left) q = getOccurrenceId(right, occurLookup) if boundHead: arc = SIPGraphArc(ph, q, vars, sipGraph, headPassing=boundHead) sipGraph.add((ph, RDF.type, MAGIC.BoundHeadPredicate)) rt = [left, right] else: rt = [right] return rt sipGraph = Graph() if isinstance(clause.body, And): if ignoreUnboundDPreds: foundSip = False sips = findFullSip(([clause.head], None), clause.body) while not foundSip: try: sip = sips.next() except StopIteration: #Throw SIP exception if sip isn't found (probably means #query + rules combination is 'malformed') raise InvalidSIPException( "Unable to find a sip for %s (%s)" % (clause, adornedHead)) try: reduce(collectSip, iterCondition(And(sip))) foundSip = True bodyOrder = sip except InvalidSIPException: foundSip = False else: if first( itertools.ifilter( lambda i: isinstance(i, Uniterm) and i.naf or False, clause.body)): #There are negative literals in body, ensure #the given sip order puts negated literals at the end bodyOrder = first( itertools.ifilter( ProperSipOrderWithNegation, findFullSip(([clause.head], None), clause.body))) else: bodyOrder = first( findFullSip(([clause.head], None), clause.body)) assert bodyOrder, "Couldn't find a valid SIP for %s" % clause reduce(collectSip, iterCondition(And(bodyOrder))) sipGraph.sipOrder = And(bodyOrder[1:]) #assert validSip(sipGraph),sipGraph.serialize(format='n3') else: if boundHead: reduce( collectSip, itertools.chain(iterCondition(clause.head), iterCondition(clause.body))) sipGraph.sipOrder = clause.body if derivedPreds: # We therefore generalize our notation to allow # more succint representation of sips, in which only arcs entering # derived predicates are represented. arcsToRemove = [] collectionsToClear = [] for N, prop, q in sipGraph.query( 'SELECT ?N ?prop ?q { ?prop a magic:SipArc . ?N ?prop ?q . }', initNs={u'magic': MAGIC}): if occurLookup[q] not in derivedPreds and ( occurLookup[q] not in hybridPreds2Replace if hybridPreds2Replace else False): arcsToRemove.extend([(N, prop, q), (prop, None, None)]) collectionsToClear.append(Collection(sipGraph, N)) #clear bindings collection as well bindingsColBNode = first(sipGraph.objects( prop, MAGIC.bindings)) collectionsToClear.append( Collection(sipGraph, bindingsColBNode)) for removeSts in arcsToRemove: sipGraph.remove(removeSts) for col in collectionsToClear: col.clear() return sipGraph
def T(owlGraph, complementExpansions=[], derivedPreds=[]): """ #Subsumption (purely for TBOX classification) {?C rdfs:subClassOf ?SC. ?A rdfs:subClassOf ?C} => {?A rdfs:subClassOf ?SC}. {?C owl:equivalentClass ?A} => {?C rdfs:subClassOf ?A. ?A rdfs:subClassOf ?C}. {?C rdfs:subClassOf ?SC. ?SC rdfs:subClassOf ?C} => {?C owl:equivalentClass ?SC}. T(rdfs:subClassOf(C,D)) -> Th(D(y)) :- Tb(C(y)) T(owl:equivalentClass(C,D)) -> { T(rdfs:subClassOf(C,D) T(rdfs:subClassOf(D,C) } A generator over the Logic Programming rules which correspond to the DL ( unary predicate logic ) subsumption axiom described via rdfs:subClassOf """ for s, p, o in owlGraph.triples((None, OWL_NS.complementOf, None)): if isinstance(o, URIRef) and isinstance(s, URIRef): headLiteral = Uniterm( RDF.type, [Variable("X"), SkolemizeExistentialClasses(s)], newNss=owlGraph.namespaces()) yield NormalizeClause(Clause(Tc(owlGraph, o), headLiteral)) for c, p, d in owlGraph.triples((None, RDFS.subClassOf, None)): try: yield NormalizeClause(Clause(Tb(owlGraph, c), Th(owlGraph, d))) except UnsupportedNegation: import warnings warnings.warn( "Unable to handle negation in DL axiom (%s), skipping" % c, #e.msg, SyntaxWarning, 3) #assert isinstance(c,URIRef),"%s is a kind of %s"%(c,d) for c, p, d in owlGraph.triples((None, OWL_NS.equivalentClass, None)): if c not in derivedPreds: yield NormalizeClause(Clause(Tb(owlGraph, c), Th(owlGraph, d))) yield NormalizeClause(Clause(Tb(owlGraph, d), Th(owlGraph, c))) for s, p, o in owlGraph.triples((None, OWL_NS.intersectionOf, None)): try: if s not in complementExpansions: if s in derivedPreds: import warnings warnings.warn( "Derived predicate (%s) is defined via a conjunction (consider using a complex GCI) " % owlGraph.qname(s), SyntaxWarning, 3) elif isinstance( s, BNode): # and (None,None,s) not in owlGraph:# and \ #(s,RDFS.subClassOf,None) in owlGraph: #complex GCI, pass over (handled) by Tb continue conjunction = [] handleConjunct(conjunction, owlGraph, o) body = And(conjunction) head = Uniterm(RDF.type, [Variable("X"), SkolemizeExistentialClasses(s)], newNss=owlGraph.namespaces()) # O1 ^ O2 ^ ... ^ On => S(?X) yield Clause(body, head) if isinstance(s, URIRef): # S(?X) => O1 ^ O2 ^ ... ^ On # special case, owl:intersectionOf is a neccessary and sufficient # criteria and should thus work in *both* directions # This rule is not added for anonymous classes or derived predicates if s not in derivedPreds: yield Clause(head, body) except UnsupportedNegation: import warnings warnings.warn( "Unable to handle negation in DL axiom (%s), skipping" % s, #e.msg, SyntaxWarning, 3) for s, p, o in owlGraph.triples((None, OWL_NS.unionOf, None)): if isinstance(s, URIRef): #special case, owl:unionOf is a neccessary and sufficient #criteria and should thus work in *both* directions body = Or([Uniterm(RDF.type,[Variable("X"), NormalizeBooleanClassOperand(i,owlGraph)], newNss=owlGraph.namespaces()) \ for i in Collection(owlGraph,o)]) head = Uniterm(RDF.type, [Variable("X"), s], newNss=owlGraph.namespaces()) yield Clause(body, head) for s, p, o in owlGraph.triples((None, OWL_NS.inverseOf, None)): # T(owl:inverseOf(P,Q)) -> { Q(x,y) :- P(y,x) # P(y,x) :- Q(x,y) } newVar = Variable(BNode()) s = SkolemizeExistentialClasses(s) if isinstance(s, BNode) else s o = SkolemizeExistentialClasses(o) if isinstance(o, BNode) else o body1 = Uniterm(s, [newVar, Variable("X")], newNss=owlGraph.namespaces()) head1 = Uniterm(o, [Variable("X"), newVar], newNss=owlGraph.namespaces()) yield Clause(body1, head1) newVar = Variable(BNode()) body2 = Uniterm(o, [Variable("X"), newVar], newNss=owlGraph.namespaces()) head2 = Uniterm(s, [newVar, Variable("X")], newNss=owlGraph.namespaces()) yield Clause(body2, head2) for s, p, o in owlGraph.triples( (None, RDF.type, OWL_NS.TransitiveProperty)): #T(owl:TransitiveProperty(P)) -> P(x,z) :- P(x,y) ^ P(y,z) y = Variable(BNode()) z = Variable(BNode()) x = Variable("X") s = SkolemizeExistentialClasses(s) if isinstance(s, BNode) else s body = And([Uniterm(s,[x,y],newNss=owlGraph.namespaces()),\ Uniterm(s,[y,z],newNss=owlGraph.namespaces())]) head = Uniterm(s, [x, z], newNss=owlGraph.namespaces()) yield Clause(body, head) for s, p, o in owlGraph.triples((None, RDFS.subPropertyOf, None)): # T(rdfs:subPropertyOf(P,Q)) -> Q(x,y) :- P(x,y) x = Variable("X") y = Variable("Y") s = SkolemizeExistentialClasses(s) if isinstance(s, BNode) else s o = SkolemizeExistentialClasses(o) if isinstance(o, BNode) else o body = Uniterm(s, [x, y], newNss=owlGraph.namespaces()) head = Uniterm(o, [x, y], newNss=owlGraph.namespaces()) yield Clause(body, head) for s, p, o in owlGraph.triples((None, OWL_NS.equivalentProperty, None)): # T(owl:equivalentProperty(P,Q)) -> { Q(x,y) :- P(x,y) # P(x,y) :- Q(x,y) } x = Variable("X") y = Variable("Y") s = SkolemizeExistentialClasses(s) if isinstance(s, BNode) else s o = SkolemizeExistentialClasses(o) if isinstance(o, BNode) else o body = Uniterm(s, [x, y], newNss=owlGraph.namespaces()) head = Uniterm(o, [x, y], newNss=owlGraph.namespaces()) yield Clause(body, head) yield Clause(head, body) #Contribution (Symmetric DL roles) for s, p, o in owlGraph.triples( (None, RDF.type, OWL_NS.SymmetricProperty)): #T(owl:SymmetricProperty(P)) -> P(y,x) :- P(x,y) y = Variable("Y") x = Variable("X") s = SkolemizeExistentialClasses(s) if isinstance(s, BNode) else s body = Uniterm(s, [x, y], newNss=owlGraph.namespaces()) head = Uniterm(s, [y, x], newNss=owlGraph.namespaces()) yield Clause(body, head) for s, p, o in owlGraph.triples_choices((None, [RDFS.range, RDFS.domain], None)): s = SkolemizeExistentialClasses(s) if isinstance(s, BNode) else s if p == RDFS.range: #T(rdfs:range(P,D)) -> D(y) := P(x,y) x = Variable("X") y = Variable(BNode()) body = Uniterm(s, [x, y], newNss=owlGraph.namespaces()) head = Uniterm(RDF.type, [y, o], newNss=owlGraph.namespaces()) yield Clause(body, head) else: #T(rdfs:domain(P,D)) -> D(x) := P(x,y) x = Variable("X") y = Variable(BNode()) body = Uniterm(s, [x, y], newNss=owlGraph.namespaces()) head = Uniterm(RDF.type, [x, o], newNss=owlGraph.namespaces()) yield Clause(body, head)