def CreateHybridPredicateRule(hybridPred, program, nsMap=None): hPred = URIRef(hybridPred + u'_derived') literals = set( reduce(lambda l, r: l + r, [ list(iterCondition(clause.formula.body)) + list(iterCondition(clause.formula.head)) for clause in program ])) for literal in literals: if GetOp(literal) == hybridPred: noArgs = len(GetArgs(literal)) if noArgs == 1: # p_derived(X) :- p(X) body = BuildUnitermFromTuple( (Variable('X'), RDF.type, hybridPred), newNss=nsMap) head = BuildUnitermFromTuple((Variable('X'), RDF.type, hPred), newNss=nsMap) vars = [Variable('X')] else: # p_derived(X,Y) :- p(X,Y) body = BuildUnitermFromTuple( (Variable('X'), hybridPred, Variable('Y')), newNss=nsMap) head = BuildUnitermFromTuple( (Variable('X'), hPred, Variable('Y')), newNss=nsMap) vars = [Variable('Y'), Variable('X')] return Rule(Clause(And([body]), head), nsMapping=nsMap, declare=vars)
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 extractImp(self, impl): body, bodyType, head, headType = self.implications[impl] head = first(self.extractPredication(head, headType)) if bodyType == RIF_NS.And: raise else: body = self.extractPredication(body, bodyType) body = And([first(body)]) if len(body) == 1 else And(body) return Rule(Clause(body, head), declare=[])
def testSerializingEvalPred(self): nsBindings = {u'bfp': BFP_NS, u'rule': BFP_RULE} evaluateTerm = Uniterm(BFP_NS.evaluate, [BFP_RULE[str(1)], Literal(1)], newNss=nsBindings) self.failUnless(repr(evaluateTerm), "bfp:evaluate(rule:1 1)") xVar = Variable('X') yVar = Variable('Y') bodyTerm = Uniterm(RDF.rest, [xVar, yVar], newNss=nsBindings) rule = Rule(Clause(bodyTerm, evaluateTerm), declare=[xVar, yVar]) self.assertEqual( repr(rule), "Forall ?X ?Y ( bfp:evaluate(rule:1 1) :- rdf:rest(?X ?Y) )")
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 = [first(self.extractPredication( i, first(self.graph.objects(i, RDF.type))) ) for i in Collection(self.graph, first(self.graph.objects(body, RIF_NS.formulas)))] else: body = self.extractPredication(body, bodyType) body = And([first(body)]) if len(body) == 1 else And(body) return Rule( Clause(body, head), declare=allVars, nsMapping=dict(self.graph.namespaces()) )
def AdornRule(derivedPreds, clause, newHead, ignoreUnboundDPreds=False, hybridPreds2Replace=None): """ Adorns a horn clause using the given new head and list of derived predicates """ assert len(list(iterCondition(clause.head))) == 1 hybridPreds2Replace = hybridPreds2Replace or [] adornedHead = AdornedUniTerm(clause.head, newHead.adornment) sip = BuildNaturalSIP(clause, derivedPreds, adornedHead, hybridPreds2Replace=hybridPreds2Replace, ignoreUnboundDPreds=ignoreUnboundDPreds) bodyPredReplace = {} def adornment(arg, headArc, x): if headArc: #Sip arc from head #don't mark bound if query has no bound/distinguished terms return (arg in x and arg in adornedHead.getDistinguishedVariables(True)) \ and 'b' or 'f' else: return arg in x and 'b' or 'f' for literal in iterCondition(sip.sipOrder): op = GetOp(literal) args = GetArgs(literal) if op in derivedPreds or (op in hybridPreds2Replace if hybridPreds2Replace else False): for N, x in IncomingSIPArcs(sip, getOccurrenceId(literal)): headArc = len(N) == 1 and N[0] == GetOp(newHead) if not set(x).difference(args): # A binding # for q is useful, however, only if it is a binding for an argument of q. bodyPredReplace[literal] = AdornedUniTerm( NormalizeUniterm(literal), [adornment(arg, headArc, x) for arg in args], literal.naf) # For a predicate occurrence with no incoming # arc, the adornment contains only f. For our purposes here, # we do not distinguish between a predicate with such an # adornment and an unadorned predicate (we do in order to support open queries) if literal not in bodyPredReplace and ignoreUnboundDPreds: bodyPredReplace[literal] = AdornedUniTerm( NormalizeUniterm(literal), ['f' for arg in GetArgs(literal)], literal.naf) if hybridPreds2Replace: atomPred = GetOp(adornedHead) if atomPred in hybridPreds2Replace: adornedHead.setOperator(URIRef(atomPred + u'_derived')) for bodAtom in [ bodyPredReplace.get(p, p) for p in iterCondition(sip.sipOrder) ]: bodyPred = GetOp(bodAtom) if bodyPred in hybridPreds2Replace: bodAtom.setOperator(URIRef(bodyPred + u'_derived')) rule = AdornedRule( Clause( And([ bodyPredReplace.get(p, p) for p in iterCondition(sip.sipOrder) ]), adornedHead)) rule.sip = sip return rule
def MagicSetTransformation(factGraph, rules, GOALS, derivedPreds=None, strictCheck=DDL_STRICTNESS_FALLBACK_DERIVED, noMagic=None, defaultPredicates=None): """ Takes a goal and a ruleset and returns an iterator over the rulest that corresponds to the magic set transformation: """ noMagic = noMagic and noMagic or [] magicPredicates = set() replacement = {} adornedProgram = SetupDDLAndAdornProgram( factGraph, rules, GOALS, derivedPreds=derivedPreds, strictCheck=strictCheck, defaultPredicates=defaultPredicates) newRules = [] for rule in adornedProgram: if rule.isSecondOrder(): import warnings warnings.warn("Second order rule no supported by GMS: %s" % rule, RuntimeWarning) magicPositions = {} #Generate magic rules for idx, pred in enumerate(iterCondition(rule.formula.body)): magicBody = [] if isinstance(pred, AdornedUniTerm): # and pred not in magicPredicates: # For each rule r in Pad, and for each occurrence of an adorned # predicate p a in its body, we generate a magic rule defining magic_p a prevPreds = [ item for _idx, item in enumerate(rule.formula.body) if _idx < idx ] if 'b' not in pred.adornment: import warnings warnings.warn( "adorned predicate w/out any bound arguments(%s in %s) !" % (pred, rule.formula), RuntimeWarning) if GetOp(pred) not in noMagic: magicPred = pred.makeMagicPred() magicPositions[idx] = (magicPred, pred) inArcs = [(N, x) for ( N, x) in IncomingSIPArcs(rule.sip, getOccurrenceId(pred)) if not set(x).difference(GetArgs(pred))] if len(inArcs) > 1: # If there are several arcs entering qi, we define the magic rule defining magic_qi # in two steps. First, for each arc Nj --> qi with label cj , we define a rule with head label_qi_j(cj ). The body # of the rule is the same as the body of the magic rule in the case where there is a single arc # entering qi (described above). Then the magic rule is defined as follows. The head is # magic_q(0). The body contains label_qi_j(cj) for all j (that is, for all arcs entering qi ). #We combine all incoming arcs into a single list of (body) conditions for the magic set PrettyPrintRule(rule) SIPRepresentation(rule.sip) print pred, magicPred _body = [] additionalRules = [] for idxSip, (N, x) in enumerate(inArcs): newPred = pred.clone() SetOp(newPred, URIRef('%s_label_%s' % (newPred.op, idxSip))) ruleBody = And( buildMagicBody(N, prevPreds, rule.formula.head, derivedPreds)) additionalRules.append( Rule(Clause(ruleBody, newPred))) _body.extend(newPred) # _body.extend(ruleBody) additionalRules.append( Rule(Clause(And(_body), magicPred))) newRules.extend(additionalRules) for i in additionalRules: print i raise NotImplementedError() else: for idxSip, (N, x) in enumerate(inArcs): ruleBody = And( buildMagicBody(N, prevPreds, rule.formula.head, derivedPreds, noMagic)) newRule = Rule(Clause(ruleBody, magicPred)) newRules.append(newRule) magicPredicates.add(magicPred) #Modify rules #we modify the original rule by inserting #occurrences of the magic predicates corresponding #to the derived predicates of the body and to the head #If there are no bound arguments in the head, we don't modify the rule idxIncrement = 0 newRule = copy.deepcopy(rule) for idx, (magicPred, origPred) in magicPositions.items(): newRule.formula.body.formulae.insert(idx + idxIncrement, magicPred) idxIncrement += 1 if 'b' in rule.formula.head.adornment and GetOp( rule.formula.head) not in noMagic: headMagicPred = rule.formula.head.makeMagicPred() if isinstance(newRule.formula.body, Uniterm): newRule.formula.body = And( [headMagicPred, newRule.formula.body]) else: newRule.formula.body.formulae.insert(0, headMagicPred) newRules.append(newRule) if not newRules: newRules.extend(AdditionalRules(factGraph)) for rule in newRules: if rule.formula.body: yield rule
def SetupDDLAndAdornProgram(factGraph, rules, GOALS, derivedPreds=None, strictCheck=DDL_STRICTNESS_FALLBACK_DERIVED, defaultPredicates=None, ignoreUnboundDPreds=False, hybridPreds2Replace=None): if not defaultPredicates: defaultPredicates = [], [] # _dPredsProvided = bool(derivedPreds) if not derivedPreds: _derivedPreds = DerivedPredicateIterator( factGraph, rules, strict=strictCheck, defaultPredicates=defaultPredicates) if not isinstance(derivedPreds, (set, list)): derivedPreds = list(_derivedPreds) else: derivedPreds.extend(_derivedPreds) hybridPreds2Replace = hybridPreds2Replace or [] adornedProgram = AdornProgram(factGraph, rules, GOALS, derivedPreds, ignoreUnboundDPreds, hybridPreds2Replace=hybridPreds2Replace) if adornedProgram != set([]): rt = reduce(lambda l, r: l + r, [ list(iterCondition(clause.formula.body)) for clause in adornedProgram ]) else: rt = set() for hybridPred, adornment in [ (t, a) for t, a in set([(URIRef(GetOp(term).split('_derived')[0] ) if GetOp(term).find('_derived') + 1 else GetOp(term), ''.join(term.adornment)) for term in rt if isinstance(term, AdornedUniTerm)]) if t in hybridPreds2Replace ]: #If there are hybrid predicates, add rules that derived their IDB counterpart #using information from the adorned queries to determine appropriate arity #and adornment hybridPred = URIRef(hybridPred) hPred = URIRef(hybridPred + u'_derived') if len(adornment) == 1: # p_derived^{a}(X) :- p(X) body = BuildUnitermFromTuple((Variable('X'), RDF.type, hybridPred)) head = BuildUnitermFromTuple((Variable('X'), RDF.type, hPred)) else: # p_derived^{a}(X, Y) :- p(X, Y) body = BuildUnitermFromTuple( (Variable('X'), hybridPred, Variable('Y'))) head = BuildUnitermFromTuple((Variable('X'), hPred, Variable('Y'))) _head = AdornedUniTerm(head, list(adornment)) rule = AdornedRule(Clause(And([body]), _head.clone())) rule.sip = Graph() adornedProgram.add(rule) if factGraph is not None: factGraph.adornedProgram = adornedProgram return adornedProgram