def __call__(self, tNode, inferredTriple, token, binding, debug=False): """ Called when a (EDB) query literal is triggered with given bindings. """ assert len(tNode.consequent) == 1 key = (self.queryLiteral, tNode, token) if key not in self.bfp.firedEDBQueries: self.bfp.firedEDBQueries.add(key) for binding in token.bindings: _bindings = dict([(k, v) for k, v in list(binding.items()) if v != None]) closure = ReadOnlyGraphAggregate([self.factGraph, self.bfp.metaInterpNetwork.inferredFacts]) closure.templateMap = self.factGraph.templateMap # For each mapping that unifies with theory if self.edbConj: _vars = set() for lit in self.edbConj: _vars.update(list(GetVariables(lit, secondOrder=True))) _qLit = EDBQuery( [copy.deepcopy(lit) for lit in self.edbConj], self.factGraph, # closure, _vars, specialBNodeHandling=self.bfp.specialBNodeHandling, ) else: _qLit = copy.deepcopy(self.queryLiteral) _qLit = EDBQuery( [_qLit], self.factGraph, # closure, list(GetVariables(_qLit, secondOrder=True)), specialBNodeHandling=self.bfp.specialBNodeHandling, ) origQuery = _qLit.copy() _qLit.ground(_bindings) if self.bfp.debug: print( "%sQuery triggered for " % (" maximal db conjunction " if self.edbConj else ""), tNode.clauseRepresentation(), ) self.bfp.edbQueries.add(_qLit) # queryVars = origQuery.getOpenVars() # tokens2Propagate=[ # t for t in token.tokens # if [ # v for v in t.getVarBindings() # if v not in queryVars # ] # ] isGround = not _qLit.returnVars rt = self.tabledQuery(_qLit) if isGround: if first(rt): self.handleQueryAnswer(origQuery, token, self.bfp.debug, ({}, binding)) else: for ans in rt: if self.bfp.debug: pprint(ans) self.handleQueryAnswer(origQuery, token, self.bfp.debug, (ans, binding))
def testQueryMemoization(self): raise SkipTest( "SKIPFAIL testQueryMemoization, see test/testBFPQueryMemoization.py") topDownStore = TopDownSPARQLEntailingStore( self.owlGraph.store, self.owlGraph, idb=self.program, DEBUG=False, nsBindings=nsMap, decisionProcedure=BFP_METHOD, identifyHybridPredicates=True) targetGraph = Graph(topDownStore) for pref, nsUri in nsMap.items(): targetGraph.bind(pref, nsUri) goal = (Variable('SUBJECT'), RDF.type, EX.C) queryLiteral = EDBQuery([BuildUnitermFromTuple(goal)], self.owlGraph, [Variable('SUBJECT')]) query = queryLiteral.asSPARQL() # rt=targetGraph.query(query,initNs=nsMap) # if len(topDownStore.edbQueries) == len(set(topDownStore.edbQueries)): # pprint(topDownStore.edbQueries) print("Queries dispatched against EDB") for query in self.owlGraph.queriesDispatched: print(query) self.failUnlessEqual( len(self.owlGraph.queriesDispatched), 4, "Duplicate query")
def testQueryMemoization(self): raise SkipTest( "SKIPFAIL testQueryMemoization, see test/testBFPQueryMemoization.py" ) topDownStore = TopDownSPARQLEntailingStore( self.owlGraph.store, self.owlGraph, idb=self.program, DEBUG=False, nsBindings=nsMap, decisionProcedure=BFP_METHOD, identifyHybridPredicates=True) targetGraph = Graph(topDownStore) for pref, nsUri in nsMap.items(): targetGraph.bind(pref, nsUri) goal = (Variable('SUBJECT'), RDF.type, EX.C) queryLiteral = EDBQuery([BuildUnitermFromTuple(goal)], self.owlGraph, [Variable('SUBJECT')]) query = queryLiteral.asSPARQL() # rt=targetGraph.query(query,initNs=nsMap) # if len(topDownStore.edbQueries) == len(set(topDownStore.edbQueries)): # pprint(topDownStore.edbQueries) print("Queries dispatched against EDB") for query in self.owlGraph.queriesDispatched: print(query) self.failUnlessEqual(len(self.owlGraph.queriesDispatched), 4, "Duplicate query")
def MagicOWLProof(self,goals,rules,factGraph,conclusionFile): progLen = len(rules) magicRuleNo = 0 dPreds = [] for rule in AdditionalRules(factGraph): rules.append(rule) if not GROUND_QUERY: goalDict = dict([((Variable('SUBJECT'),goalP,goalO),goalS) for goalS,goalP,goalO in goals]) goals = goalDict.keys() assert goals topDownStore=TopDownSPARQLEntailingStore( factGraph.store, factGraph, idb=rules, DEBUG=DEBUG, identifyHybridPredicates=True, nsBindings=nsMap) targetGraph = Graph(topDownStore) for pref,nsUri in nsMap.items(): targetGraph.bind(pref,nsUri) start = time.time() for goal in goals: queryLiteral = EDBQuery([BuildUnitermFromTuple(goal)], factGraph, None if GROUND_QUERY else [goal[0]]) query = queryLiteral.asSPARQL() print "Goal to solve ", query rt=targetGraph.query(query,initNs=nsMap) if GROUND_QUERY: self.failUnless(rt.askAnswer[0],"Failed top-down problem") else: if (goalDict[goal]) not in rt or DEBUG: for network,_goal in topDownStore.queryNetworks: print network,_goal network.reportConflictSet(True) for query in topDownStore.edbQueries: print query.asSPARQL() print "Missing", goalDict[goal] self.failUnless((goalDict[goal]) in rt, "Failed top-down problem") sTime = time.time() - start if sTime > 1: sTimeStr = "%s seconds"%sTime else: sTime = sTime * 1000 sTimeStr = "%s milli seconds"%sTime return sTimeStr
def MagicOWLProof(self, goals, rules, factGraph, conclusionFile): progLen = len(rules) magicRuleNo = 0 dPreds = [] for rule in AdditionalRules(factGraph): rules.append(rule) if not GROUND_QUERY: goalDict = dict([((Variable('SUBJECT'), goalP, goalO), goalS) for goalS, goalP, goalO in goals]) goals = goalDict.keys() assert goals topDownStore = TopDownSPARQLEntailingStore( factGraph.store, factGraph, idb=rules, DEBUG=DEBUG, identifyHybridPredicates=True, nsBindings=nsMap) targetGraph = Graph(topDownStore) for pref, nsUri in nsMap.items(): targetGraph.bind(pref, nsUri) start = time.time() for goal in goals: queryLiteral = EDBQuery([BuildUnitermFromTuple(goal)], factGraph, None if GROUND_QUERY else [goal[0]]) query = queryLiteral.asSPARQL() print "Goal to solve ", query rt = targetGraph.query(query, initNs=nsMap) if GROUND_QUERY: self.failUnless(rt.askAnswer[0], "Failed top-down problem") else: if (goalDict[goal]) not in rt or DEBUG: for network, _goal in topDownStore.queryNetworks: print network, _goal network.reportConflictSet(True) for query in topDownStore.edbQueries: print query.asSPARQL() print "Missing", goalDict[goal] self.failUnless((goalDict[goal]) in rt, "Failed top-down problem") sTime = time.time() - start if sTime > 1: sTimeStr = "%s seconds" % sTime else: sTime = sTime * 1000 sTimeStr = "%s milli seconds" % sTime return sTimeStr
def sparql_query(self, queryString, queryObj, graph, dataSetBase, extensionFunctions, initBindings={}, initNs={}, DEBUG=False): """ The default 'native' SPARQL implementation is based on sparql-p's expansion trees layered on top of the read-only RDF APIs of the underlying store """ from rdflib.sparql.Algebra import TopEvaluate from rdflib.QueryResult import QueryResult from rdflib import plugin from rdflib.sparql.bison.Query import AskQuery _expr = self.isaBaseQuery(None, queryObj) if isinstance(queryObj.query,AskQuery) and \ isinstance(_expr,BasicGraphPattern): #This is a ground, BGP, involving IDB and can be solved directly #using top-down decision procedure #First separate out conjunct into EDB and IDB predicates #(solving the former first) from FuXi.SPARQL import EDBQuery groundConjunct = [] derivedConjunct = [] for s, p, o, func in _expr.patterns: if self.derivedPredicateFromTriple((s, p, o)) is None: groundConjunct.append(BuildUnitermFromTuple((s, p, o))) else: derivedConjunct.append(BuildUnitermFromTuple((s, p, o))) if groundConjunct: baseEDBQuery = EDBQuery(groundConjunct, self.edb) subQuery, ans = baseEDBQuery.evaluate(DEBUG) assert isinstance(ans, bool), ans if groundConjunct and not ans: askResult = False else: askResult = True for derivedLiteral in derivedConjunct: goal = derivedLiteral.toRDFTuple() #Solve ground, derived goal directly goal = self.hybridPredQueryPreparation(goal) SetupDDLAndAdornProgram( self.edb, self.idb, [goal], derivedPreds=self.derivedPredicates, ignoreUnboundDPreds=True) sipCollection = PrepareSipCollection( self.edb.adornedProgram) if self.DEBUG and sipCollection: for sip in SIPRepresentation(sipCollection): print >> sys.stderr, sip pprint(list(self.edb.adornedProgram), sys.stderr) elif self.DEBUG: print >> sys.stderr, "No SIP graph!" rt, node = first( self.invokeDecisionProcedure(goal, self.edb, {}, self.DEBUG, sipCollection)) if not rt: askResult = False break return plugin.get('SPARQLQueryResult', QueryResult)(askResult) else: rt = TopEvaluate(queryObj, graph, initBindings, DEBUG=self.DEBUG, dataSetBase=dataSetBase, extensionFunctions=extensionFunctions) return plugin.get('SPARQLQueryResult', QueryResult)(rt)
def conjunctiveSipStrategy(self, goalsRemaining, factGraph, bindings=None): """ Given a conjunctive set of triples, invoke sip-strategy passing on intermediate solutions to facilitate 'join' behavior """ bindings = bindings if bindings else {} try: tp = goalsRemaining.next() assert isinstance(bindings, dict) dPred = self.derivedPredicateFromTriple(tp) if dPred is None: baseEDBQuery = EDBQuery([BuildUnitermFromTuple(tp)], self.edb, bindings=bindings) if self.DEBUG: print >>sys.stderr,"Evaluating TP against EDB: ",\ baseEDBQuery.asSPARQL() query, rt = baseEDBQuery.evaluate() if isinstance(rt, bool) and rt: yield bindings elif not isinstance(rt, bool): rt = list(rt) remaining_goals = itertools.tee(goalsRemaining, len(rt)) for idx in range(len(rt)): item = {} item.update(rt[idx]) item.update(bindings) if self.DEBUG: print >> sys.stderr, "Solution from EDB query: ", item for ansDict in self.conjunctiveSipStrategy( remaining_goals[idx], factGraph, item): yield ansDict else: queryLit = BuildUnitermFromTuple(tp) currentOp = GetOp(queryLit) queryLit.setOperator(currentOp) query = EDBQuery([queryLit], self.edb, bindings=bindings) if bindings: tp = first(query.formulae).toRDFTuple() if self.DEBUG: print >> sys.stderr, "Goal/Query: ", query.asSPARQL() tp = self.hybridPredQueryPreparation(tp) SetupDDLAndAdornProgram(self.edb, self.idb, [tp], derivedPreds=self.derivedPredicates, ignoreUnboundDPreds=True, nsBindings=self.nsBindings) sipCollection = PrepareSipCollection(self.edb.adornedProgram) if self.DEBUG and sipCollection: for sip in SIPRepresentation(sipCollection): print >> sys.stderr, sip pprint(list(self.edb.adornedProgram), sys.stderr) elif self.DEBUG: print >> sys.stderr, "No SIP graph!" for nextAnswer, ns in self.invokeDecisionProcedure( tp, factGraph, bindings, self.DEBUG, sipCollection): if isinstance(nextAnswer, dict): #Recieved solutions to 'open' query, merge with given bindings #and continue for ansDict in self.conjunctiveSipStrategy( goalsRemaining, factGraph, mergeMappings1To2(bindings, nextAnswer)): yield ansDict elif nextAnswer: #we (successfully) proved a ground query, pass on bindings assert isinstance(nextAnswer, bool) for ansDict in self.conjunctiveSipStrategy( goalsRemaining, factGraph, bindings): yield ansDict except StopIteration: yield bindings
def invokeRule(priorAnswers, bodyLiteralIterator, sip, otherargs, priorBooleanGoalSuccess=False, step=None, debug=False, buildProof=False): """ Continue invokation of rule using (given) prior answers and list of remaining body literals (& rule sip). If prior answers is a list, computation is split disjunctively [..] By combining the answers to all these subqueries, we generate answers for the original query involving the rule head Can also takes a PML step and updates it as it navigates the top-down proof tree (passing it on and updating it where necessary) """ assert not buildProof or step is not None proofLevel, memoizeMemory, sipCollection, \ factGraph, derivedPreds, processedRules = otherargs remainingBodyList = [i for i in bodyLiteralIterator] lazyGenerator = lazyGeneratorPeek(priorAnswers, 2) if lazyGenerator.successful: # There are multiple answers in this step, we need to call invokeRule # recursively for each answer, returning the first positive attempt success = False rt = None _step = None ansNo = 0 for priorAns in lazyGenerator: ansNo += 1 try: if buildProof: newStep = InferenceStep(step.parent, step.rule, source=step.source) newStep.antecedents = [ant for ant in step.antecedents] else: newStep = None for rt, _step in\ invokeRule([priorAns], iter([i for i in remainingBodyList]), sip, otherargs, priorBooleanGoalSuccess, newStep, debug=debug, buildProof=buildProof): if rt: yield rt, _step except RuleFailure: pass if not success: # None of prior answers were successful # indicate termination of rule processing raise RuleFailure( "Unable to solve either of %s against remainder of rule: %s" % ( ansNo, remainingBodyList)) # yield False, _InferenceStep(step.parent, step.rule, # source=step.source) else: lazyGenerator = lazyGeneratorPeek(lazyGenerator) projectedBindings = lazyGenerator.successful and first( lazyGenerator) or {} # First we check if we can combine a large group of subsequent body literals # into a single query # if we have a template map then we use it to further # distinguish which builtins can be solved via # cumulative SPARQl query - else we solve # builtins one at a time def sparqlResolvable(literal): if isinstance(literal, Uniterm): return not literal.naf and GetOp(literal) not in derivedPreds else: return isinstance(literal, N3Builtin) and \ literal.uri in factGraph.templateMap def sparqlResolvableNoTemplates(literal): if isinstance(literal, Uniterm): return not literal.naf and GetOp(literal) not in derivedPreds else: return False conjGroundLiterals = list( itertools.takewhile( hasattr(factGraph, 'templateMap') and sparqlResolvable or sparqlResolvableNoTemplates, remainingBodyList)) bodyLiteralIterator = iter(remainingBodyList) if len(conjGroundLiterals) > 1: # If there are literals to combine *and* a mapping from rule # builtins to SPARQL FILTER templates .. basePredicateVars = set( reduce(lambda x, y: x + y, [list(GetVariables(arg, secondOrder=True)) for arg in conjGroundLiterals])) if projectedBindings: openVars = basePredicateVars.intersection(projectedBindings) else: # We don't have any given bindings, so we need to treat # the body as an open query openVars = basePredicateVars queryConj = EDBQuery([copy.deepcopy(lit) for lit in conjGroundLiterals], factGraph, openVars, projectedBindings) query, answers = queryConj.evaluate(debug) if isinstance(answers, bool): combinedAnswers = {} rtCheck = answers else: if projectedBindings: combinedAnswers = (mergeMappings1To2(ans, projectedBindings, makeImmutable=True) for ans in answers) else: combinedAnswers = (MakeImmutableDict(ans) for ans in answers) combinedAnsLazyGenerator = lazyGeneratorPeek(combinedAnswers) rtCheck = combinedAnsLazyGenerator.successful if not rtCheck: raise RuleFailure( "No answers for combined SPARQL query: %s" % query) else: # We have solved the previous N body literals with a single # conjunctive query, now we need to make each of the literals # an antecedent to a 'query' step. if buildProof: queryStep = InferenceStep(None, source='some RDF graph') # FIXME: subquery undefined queryStep.groundQuery = subquery queryStep.bindings = {} # combinedAnswers[-1] # FIXME: subquery undefined queryHash = URIRef( "tag:[email protected]:Queries#" + makeMD5Digest(subquery)) queryStep.identifier = queryHash for subGoal in conjGroundLiterals: subNs = NodeSet(subGoal.toRDFTuple(), identifier=BNode()) subNs.steps.append(queryStep) step.antecedents.append(subNs) queryStep.parent = subNs for rt, _step in invokeRule( isinstance(answers, bool) and [ projectedBindings] or combinedAnsLazyGenerator, iter(remainingBodyList[len(conjGroundLiterals):]), sip, otherargs, isinstance(answers, bool), step, debug=debug, buildProof=buildProof): yield rt, _step else: # Continue processing rule body condition # one literal at a time try: bodyLiteral = next( bodyLiteralIterator) if py3compat.PY3 else bodyLiteralIterator.next() # if a N3 builtin, execute it using given bindings for boolean answer # builtins are moved to end of rule when evaluating rules via # sip if isinstance(bodyLiteral, N3Builtin): lhs = bodyLiteral.argument rhs = bodyLiteral.result lhs = isinstance( lhs, Variable) and projectedBindings[lhs] or lhs rhs = isinstance( rhs, Variable) and projectedBindings[rhs] or rhs assert lhs is not None and rhs is not None if bodyLiteral.func(lhs, rhs): if debug: print("Invoked %s(%s, %s) -> True" % ( bodyLiteral.uri, lhs, rhs)) # positive answer means we can continue processing the # rule body if buildProof: ns = NodeSet(bodyLiteral.toRDFTuple(), identifier=BNode()) step.antecedents.append(ns) for rt, _step in invokeRule( [projectedBindings], bodyLiteralIterator, sip, otherargs, step, priorBooleanGoalSuccess, debug=debug, buildProof=buildProof): yield rt, _step else: if debug: print("Successfully invoked %s(%s, %s) -> False" % ( bodyLiteral.uri, lhs, rhs)) raise RuleFailure("Failed builtin invokation %s(%s, %s)" % (bodyLiteral.uri, lhs, rhs)) else: # For every body literal, subqueries are generated according # to the sip sipArcPred = URIRef(GetOp(bodyLiteral) + '_' + '_'.join(GetArgs(bodyLiteral))) assert len(list(IncomingSIPArcs(sip, sipArcPred))) < 2 subquery = copy.deepcopy(bodyLiteral) subquery.ground(projectedBindings) for N, x in IncomingSIPArcs(sip, sipArcPred): # That is, each subquery contains values for the bound arguments # that are passed through the sip arcs entering the node # corresponding to that literal # Create query out of body literal and apply # sip-provided bindings subquery = copy.deepcopy(bodyLiteral) subquery.ground(projectedBindings) if literalIsGround(subquery): # subquery is ground, so there will only be boolean answers # we return the conjunction of the answers for the current # subquery answer = False ns = None answers = first( itertools.dropwhile( lambda item: not item[0], SipStrategy( subquery.toRDFTuple(), sipCollection, factGraph, derivedPreds, MakeImmutableDict(projectedBindings), processedRules, network=step is not None and step.parent.network or None, debug=debug, buildProof=buildProof, memoizeMemory=memoizeMemory, proofLevel=proofLevel))) if answers: answer, ns = answers if not answer and not bodyLiteral.naf or \ (answer and bodyLiteral.naf): # negative answer means the invokation of the rule fails # either because we have a positive literal and there # is no answer for the subgoal or the literal is # negative and there is an answer for the subgoal raise RuleFailure( "No solutions solving ground query %s" % subquery) else: if buildProof: if not answer and bodyLiteral.naf: ns.naf = True step.antecedents.append(ns) # positive answer means we can continue processing the rule body # either because we have a positive literal and answers # for subgoal or a negative literal and no answers for the # the goal for rt, _step in invokeRule( [projectedBindings], bodyLiteralIterator, sip, otherargs, True, step, debug=debug): yield rt, _step else: _answers = \ SipStrategy( subquery.toRDFTuple(), sipCollection, factGraph, derivedPreds, MakeImmutableDict( projectedBindings), processedRules, network=step is not None and step.parent.network or None, debug=debug, buildProof=buildProof, memoizeMemory=memoizeMemory, proofLevel=proofLevel) # solve (non-ground) subgoal def collectAnswers(_ans): for ans, ns in _ans: if isinstance(ans, dict): try: map = mergeMappings1To2( ans, projectedBindings, makeImmutable=True) yield map except: pass combinedAnswers = collectAnswers(_answers) answers = lazyGeneratorPeek(combinedAnswers) if not answers.successful \ and not bodyLiteral.naf \ or (bodyLiteral.naf and answers.successful): raise RuleFailure( "No solutions solving ground query %s" % subquery) else: # Either we have a positive subgoal and answers # or a negative subgoal and no answers if buildProof: if answers.successful: goals = set([g for a, g in answers]) assert len(goals) == 1 step.antecedents.append(goals.pop()) else: newNs = NodeSet( bodyLiteral.toRDFTuple(), network=step.parent.network, identifier=BNode(), naf=True) step.antecedents.append(newNs) for rt, _step in invokeRule( answers, bodyLiteralIterator, sip, otherargs, priorBooleanGoalSuccess, step, debug=debug, buildProof=buildProof): yield rt, _step except StopIteration: # Finished processing rule if priorBooleanGoalSuccess: yield projectedBindings and projectedBindings or True, step elif projectedBindings: # Return the most recent (cumulative) answers and the given # step yield projectedBindings, step else: raise RuleFailure( "Finished processing rule unsuccessfully")
def MagicOWLProof(self, goals, rules, factGraph, conclusionFile): progLen = len(rules) magicRuleNo = 0 dPreds = [] for rule in AdditionalRules(factGraph): rules.append(rule) if not GROUND_QUERY and REASONING_STRATEGY != 'gms': goalDict = dict([((Variable('SUBJECT'), goalP, goalO), goalS) for goalS, goalP, goalO in goals]) goals = goalDict.keys() assert goals if REASONING_STRATEGY == 'gms': for rule in MagicSetTransformation(factGraph, rules, goals, dPreds): magicRuleNo += 1 self.network.buildNetworkFromClause(rule) self.network.rules.add(rule) if DEBUG: log.debug("\t", rule) log.debug("rate of reduction in the size of the program: ", (100 - (float(magicRuleNo) / float(progLen)) * 100)) if REASONING_STRATEGY in ['bfp', 'sld']: # and not GROUND_QUERY: reasoningAlg = TOP_DOWN_METHOD if REASONING_STRATEGY == 'sld' \ else BFP_METHOD topDownStore = TopDownSPARQLEntailingStore( factGraph.store, factGraph, idb=rules, DEBUG=DEBUG, nsBindings=nsMap, decisionProcedure=reasoningAlg, identifyHybridPredicates=REASONING_STRATEGY == 'bfp') targetGraph = Graph(topDownStore) for pref, nsUri in nsMap.items(): targetGraph.bind(pref, nsUri) start = time.time() for goal in goals: queryLiteral = EDBQuery([BuildUnitermFromTuple(goal)], factGraph, None if GROUND_QUERY else [goal[0]]) query = queryLiteral.asSPARQL() log.debug("Goal to solve ", query) rt = targetGraph.query(query, initNs=nsMap) if GROUND_QUERY: self.failUnless(rt.askAnswer[0], "Failed top-down problem") else: if (goalDict[goal]) not in rt or DEBUG: for network, _goal in topDownStore.queryNetworks: log.debug(network, _goal) network.reportConflictSet(True) for query in topDownStore.edbQueries: log.debug(query.asSPARQL()) self.failUnless((goalDict[goal]) in rt, "Failed top-down problem") sTime = time.time() - start if sTime > 1: sTimeStr = "%s seconds" % sTime else: sTime = sTime * 1000 sTimeStr = "%s ms" % sTime return sTimeStr elif REASONING_STRATEGY == 'gms': for goal in goals: adornedGoalSeed = AdornLiteral(goal).makeMagicPred() goal = adornedGoalSeed.toRDFTuple() if DEBUG: log.debug("Magic seed fact ", adornedGoalSeed) factGraph.add(goal) timing = self.calculateEntailments(factGraph) for goal in goals: # self.failUnless(goal in self.network.inferredFacts or goal in factGraph, # "Failed GMS query") if goal not in self.network.inferredFacts and goal not in factGraph: log.debug("missing triple %s" % (pformat(goal))) # print(list(factGraph.adornedProgram)) # from FuXi.Rete.Util import renderNetwork # dot = renderNetwork( # self.network,self.network.nsMap).write_jpeg('test-fail.jpeg') self.network.reportConflictSet(True) log.debug("=== Failed: %s ====" % pformat(goal)) else: log.debug("=== Passed! ===") return timing
def sparql_query(self, queryString, queryObj, graph, dataSetBase, extensionFunctions, initBindings={}, initNs={}, DEBUG=False): """ The default 'native' SPARQL implementation is based on sparql-p's expansion trees layered on top of the read-only RDF APIs of the underlying store """ from rdflib.sparql.Algebra import TopEvaluate from rdflib.QueryResult import QueryResult from rdflib import plugin from rdflib.sparql.bison.Query import AskQuery _expr = self.isaBaseQuery(None,queryObj) if isinstance(queryObj.query,AskQuery) and \ isinstance(_expr,BasicGraphPattern): #This is a ground, BGP, involving IDB and can be solved directly #using top-down decision procedure #First separate out conjunct into EDB and IDB predicates #(solving the former first) from FuXi.SPARQL import EDBQuery groundConjunct = [] derivedConjunct = [] for s,p,o,func in _expr.patterns: if self.derivedPredicateFromTriple((s,p,o)) is None: groundConjunct.append(BuildUnitermFromTuple((s,p,o))) else: derivedConjunct.append(BuildUnitermFromTuple((s,p,o))) if groundConjunct: baseEDBQuery = EDBQuery(groundConjunct,self.edb) subQuery,ans = baseEDBQuery.evaluate(DEBUG) assert isinstance(ans,bool),ans if groundConjunct and not ans: askResult = False else: askResult = True for derivedLiteral in derivedConjunct: goal = derivedLiteral.toRDFTuple() #Solve ground, derived goal directly SetupDDLAndAdornProgram( self.edb, self.idb, [goal], derivedPreds=self.derivedPredicates, ignoreUnboundDPreds = True, hybridPreds2Replace=self.hybridPredicates) if self.hybridPredicates: lit = BuildUnitermFromTuple(goal) op = GetOp(lit) if op in self.hybridPredicates: lit.setOperator(URIRef(op+u'_derived')) goal = lit.toRDFTuple() sipCollection=PrepareSipCollection(self.edb.adornedProgram) if self.DEBUG and sipCollection: for sip in SIPRepresentation(sipCollection): print >>sys.stderr,sip pprint(list(self.edb.adornedProgram),sys.stderr) elif self.DEBUG: print >> sys.stderr, "No SIP graph!" rt,node = first(self.invokeDecisionProcedure( goal, self.edb, {}, self.DEBUG, sipCollection)) if not rt: askResult = False break return plugin.get('SPARQLQueryResult',QueryResult)(askResult) else: rt = TopEvaluate(queryObj, graph, initBindings, DEBUG=self.DEBUG, dataSetBase=dataSetBase, extensionFunctions=extensionFunctions) return plugin.get('SPARQLQueryResult',QueryResult)(rt)
def conjunctiveSipStrategy(self,goalsRemaining,factGraph,bindings=None): """ Given a conjunctive set of triples, invoke sip-strategy passing on intermediate solutions to facilitate 'join' behavior """ bindings = bindings if bindings else {} try: tp = goalsRemaining.next() assert isinstance(bindings,dict) dPred = self.derivedPredicateFromTriple(tp) if dPred is None: baseEDBQuery = EDBQuery([BuildUnitermFromTuple(tp)], self.edb, bindings=bindings) if self.DEBUG: print >>sys.stderr,"Evaluating TP against EDB: ",\ baseEDBQuery.asSPARQL() query,rt = baseEDBQuery.evaluate() # _vars = baseEDBQuery.returnVars for item in rt: bindings.update(item) for ansDict in self.conjunctiveSipStrategy( goalsRemaining, factGraph, bindings): yield ansDict else: queryLit = BuildUnitermFromTuple(tp) currentOp = GetOp(queryLit) queryLit.setOperator(currentOp) query=EDBQuery([queryLit], self.edb, bindings=bindings) if bindings: tp=first(query.formulae).toRDFTuple() if self.DEBUG: print >>sys.stderr,"Goal/Query: ", query.asSPARQL() SetupDDLAndAdornProgram( self.edb, self.idb, [tp], derivedPreds=self.derivedPredicates, ignoreUnboundDPreds = True, hybridPreds2Replace=self.hybridPredicates) if self.hybridPredicates: lit = BuildUnitermFromTuple(tp) op = GetOp(lit) if op in self.hybridPredicates: lit.setOperator(URIRef(op+u'_derived')) tp = lit.toRDFTuple() sipCollection=PrepareSipCollection(self.edb.adornedProgram) if self.DEBUG and sipCollection: for sip in SIPRepresentation(sipCollection): print >>sys.stderr,sip pprint(list(self.edb.adornedProgram),sys.stderr) elif self.DEBUG: print >> sys.stderr, "No SIP graph!" for nextAnswer,ns in self.invokeDecisionProcedure( tp, factGraph, bindings, self.DEBUG, sipCollection): nonGroundGoal = isinstance(nextAnswer,dict) if nonGroundGoal or nextAnswer: #Either we recieved bindings from top-down evaluation #or we (successfully) proved a ground query if not nonGroundGoal: #Attempt to prove a ground query, return the response rt = nextAnswer else: #Recieved solutions to 'open' query, merge with given bindings #and continue rt = mergeMappings1To2(bindings,nextAnswer) #either answers were provided (the goal wasn't grounded) or #the goal was ground and successfully proved for ansDict in self.conjunctiveSipStrategy( goalsRemaining, factGraph, rt): yield ansDict except StopIteration: yield bindings
def SipStrategy(query, sipCollection, factGraph, derivedPreds, bindings={}, processedRules=None, network=None, debug=False, buildProof=False, memoizeMemory=None, proofLevel=1): """ Accordingly, we define a sip-strategy for computing the answers to a query expressed using a set of Datalog rules, and a set of sips, one for each adornment of a rule head, as follows... Each evaluation uses memoization (via Python decorators) but also relies on well-formed rewrites for using semi-naive bottom up method over large SPARQL data. """ memoizeMemory = memoizeMemory and memoizeMemory or {} queryLiteral = BuildUnitermFromTuple(query) processedRules = processedRules and processedRules or set() if bindings: #There are bindings. Apply them to the terms in the query queryLiteral.ground(bindings) if debug: print >> sys.stderr, "%sSolving" % ('\t' * proofLevel), queryLiteral, bindings #Only consider ground triple pattern isomorphism with matching bindings goalRDFStatement = queryLiteral.toRDFTuple() if queryLiteral in memoizeMemory: if debug: print >> sys.stderr, "%sReturning previously calculated results for "%\ ('\t'*proofLevel), queryLiteral for answers in memoizeMemory[queryLiteral]: yield answers elif AlphaNode(goalRDFStatement).alphaNetworkHash( True, skolemTerms=bindings.values()) in\ [AlphaNode(r.toRDFTuple()).alphaNetworkHash(True, skolemTerms=bindings.values()) for r in processedRules if AdornLiteral(goalRDFStatement).adornment == \ r.adornment]: if debug: print >> sys.stderr, "%s Goal already processed..."%\ ('\t'*proofLevel) else: isGround = literalIsGround(queryLiteral) if buildProof: ns = NodeSet(goalRDFStatement, network=network, identifier=BNode()) else: ns = None adornedProgram = factGraph.adornedProgram queryPred = GetOp(queryLiteral) if sipCollection is None: rules = [] else: #For every rule head matching the query, we invoke the rule, #thus determining an adornment, and selecting a sip to follow rules = sipCollection.headToRule.get(queryPred, set()) if None in sipCollection.headToRule: #If there are second order rules, we add them #since they are a 'wildcard' rules.update(sipCollection.headToRule[None]) #maintained list of rules that haven't been processed before and #match the query validRules = [] #each subquery contains values for the bound arguments that are passed #through the sip arcs entering the node corresponding to that literal. For #each subquery generated, there is a set of answers. answers = [] variableMapping = {} #Some TBox queries can be 'joined' together into SPARQL queries against #'base' predicates via an RDF dataset #These atomic concept inclusion axioms can be evaluated together #using a disjunctive operator at the body of a horn clause #where each item is a query of the form uniPredicate(?X): #Or( uniPredicate1(?X1), uniPredicate2(?X), uniPredicate3(?X),..) #In this way massive, conjunctive joins can be 'mediated' #between the stated facts and the top-down solver @parameterizedPredicate([i for i in derivedPreds]) def IsAtomicInclusionAxiomRHS(rule, dPreds): """ This is an atomic inclusion axiom with a variable (or bound) RHS: uniPred(?ENTITY) """ bodyList = list(iterCondition(rule.formula.body)) body = first(bodyList) return GetOp(body) not in dPreds and \ len(bodyList) == 1 and \ body.op == RDF.type atomicInclusionAxioms = list(ifilter(IsAtomicInclusionAxiomRHS, rules)) if atomicInclusionAxioms and len(atomicInclusionAxioms) > 1: if debug: print >> sys.stderr, "\tCombining atomic inclusion axioms: " pprint(atomicInclusionAxioms, sys.stderr) if buildProof: factStep = InferenceStep(ns, source='some RDF graph') ns.steps.append(factStep) axioms = [rule.formula.body for rule in atomicInclusionAxioms] #attempt to exaustively apply any available substitutions #and determine if query if fully ground vars = [ v for v in GetArgs(queryLiteral, secondOrder=True) if isinstance(v, Variable) ] openVars,axioms,_bindings = \ normalizeBindingsAndQuery(vars, bindings, axioms) if openVars: mappings = {} #See if we need to do any variable mappings from the query literals #to the literals in the applicable rules query, rt = EDBQuery(axioms, factGraph, openVars, _bindings).evaluate( debug, symmAtomicInclusion=True) if buildProof: factStep.groundQuery = subquery for ans in rt: if buildProof: factStep.bindings.update(ans) memoizeMemory.setdefault(queryLiteral, set()).add( (prepMemiozedAns(ans), ns)) yield ans, ns else: #All the relevant derivations have been explored and the result #is a ground query we can directly execute against the facts if buildProof: factStep.bindings.update(bindings) query, rt = EDBQuery(axioms, factGraph, _bindings).evaluate( debug, symmAtomicInclusion=True) if buildProof: factStep.groundQuery = subquery memoizeMemory.setdefault(queryLiteral, set()).add( (prepMemiozedAns(rt), ns)) yield rt, ns rules = ifilter(lambda i: not IsAtomicInclusionAxiomRHS(i), rules) for rule in rules: #An exception is the special predicate ph; it is treated as a base #predicate and the tuples in it are those supplied for qb by unification. headBindings = getBindingsFromLiteral(goalRDFStatement, rule.formula.head) comboBindings = dict([(k, v) for k, v in itertools.chain( bindings.items(), headBindings.items())]) varMap = rule.formula.head.getVarMapping(queryLiteral) if headBindings and\ [term for term in rule.formula.head.getDistinguishedVariables(True) if varMap.get(term,term) not in headBindings]: continue subQueryAnswers = [] dontStop = True projectedBindings = comboBindings.copy() if debug: print >> sys.stderr, "%sProcessing rule"%\ ('\t'*proofLevel), rule.formula if debug and sipCollection: print >> sys.stderr, "Sideways Information Passing (sip) graph for %s: " % queryLiteral print >> sys.stdout, sipCollection.serialize(format='n3') for sip in SIPRepresentation(sipCollection): print >> sys.stderr, sip try: #Invoke the rule if buildProof: step = InferenceStep(ns, rule.formula) else: step = None for rt,step in\ invokeRule([headBindings], iter(iterCondition(rule.formula.body)), rule.sip, (proofLevel + 1, memoizeMemory, sipCollection, factGraph, derivedPreds, processedRules.union([ AdornLiteral(query)])), step=step, debug = debug): if rt: if isinstance(rt, dict): #We received a mapping and must rewrite it via #correlation between the variables in the rule head #and the variables in the original query (after applying #bindings) varMap = rule.formula.head.getVarMapping( queryLiteral) if varMap: rt = MakeImmutableDict( refactorMapping(varMap, rt)) if buildProof: step.bindings = rt else: if buildProof: step.bindings = headBindings validRules.append(rule) if buildProof: ns.steps.append(step) if isGround: yield True, ns else: memoizeMemory.setdefault(queryLiteral, set()).add( (prepMemiozedAns(rt), ns)) yield rt, ns except RuleFailure, e: #Clean up failed antecedents if buildProof: if ns in step.antecedents: step.antecedents.remove(ns) if not validRules: #No rules matching, query factGraph for answers successful = False if buildProof: factStep = InferenceStep(ns, source='some RDF graph') ns.steps.append(factStep) if not isGround: subquery, rt = EDBQuery([queryLiteral], factGraph, [ v for v in GetArgs(queryLiteral, secondOrder=True) if isinstance(v, Variable) ], bindings).evaluate(debug) if buildProof: factStep.groundQuery = subquery for ans in rt: successful = True if buildProof: factStep.bindings.update(ans) memoizeMemory.setdefault(queryLiteral, set()).add( (prepMemiozedAns(ans), ns)) yield ans, ns if not successful and queryPred not in derivedPreds: #Open query didn't return any results and the predicate #is ostensibly marked as derived predicate, so we have failed memoizeMemory.setdefault(queryLiteral, set()).add( (False, ns)) yield False, ns else: #All the relevant derivations have been explored and the result #is a ground query we can directly execute against the facts if buildProof: factStep.bindings.update(bindings) subquery, rt = EDBQuery([queryLiteral], factGraph, bindings).evaluate(debug) if buildProof: factStep.groundQuery = subquery memoizeMemory.setdefault(queryLiteral, set()).add( (prepMemiozedAns(rt), ns)) yield rt, ns
if len(conjGroundLiterals) > 1: #If there are literals to combine *and* a mapping from rule #builtins to SPARQL FILTER templates .. basePredicateVars = set( reduce( lambda x, y: x + y, map(lambda arg: list(GetVariables(arg, secondOrder=True)), conjGroundLiterals))) if projectedBindings: openVars = basePredicateVars.intersection(projectedBindings) else: #We don't have any given bindings, so we need to treat #the body as an open query openVars = basePredicateVars queryConj = EDBQuery( [copy.deepcopy(lit) for lit in conjGroundLiterals], factGraph, openVars, projectedBindings) query, answers = queryConj.evaluate(debug) if isinstance(answers, bool): combinedAnswers = {} rtCheck = answers else: if projectedBindings: combinedAnswers = (mergeMappings1To2(ans, projectedBindings, makeImmutable=True) for ans in answers) else: combinedAnswers = (MakeImmutableDict(ans) for ans in answers) combinedAnsLazyGenerator = lazyGeneratorPeek(combinedAnswers)
def invokeRule(priorAnswers, bodyLiteralIterator, sip, otherargs, priorBooleanGoalSuccess=False, step=None, debug=False, buildProof=False): """ Continue invokation of rule using (given) prior answers and list of remaining body literals (& rule sip). If prior answers is a list, computation is split disjunctively [..] By combining the answers to all these subqueries, we generate answers for the original query involving the rule head Can also takes a PML step and updates it as it navigates the top-down proof tree (passing it on and updating it where necessary) """ assert not buildProof or step is not None proofLevel, memoizeMemory, sipCollection, \ factGraph, derivedPreds, processedRules = otherargs remainingBodyList = [i for i in bodyLiteralIterator] lazyGenerator = lazyGeneratorPeek(priorAnswers, 2) if lazyGenerator.successful: # There are multiple answers in this step, we need to call invokeRule # recursively for each answer, returning the first positive attempt success = False rt = None _step = None ansNo = 0 for priorAns in lazyGenerator: ansNo += 1 try: if buildProof: newStep = InferenceStep(step.parent, step.rule, source=step.source) newStep.antecedents = [ant for ant in step.antecedents] else: newStep = None for rt, _step in\ invokeRule([priorAns], iter([i for i in remainingBodyList]), sip, otherargs, priorBooleanGoalSuccess, newStep, debug=debug, buildProof=buildProof): if rt: yield rt, _step except RuleFailure: pass if not success: # None of prior answers were successful # indicate termination of rule processing raise RuleFailure( "Unable to solve either of %s against remainder of rule: %s" % (ansNo, remainingBodyList)) # yield False, _InferenceStep(step.parent, step.rule, source=step.source) else: lazyGenerator = lazyGeneratorPeek(lazyGenerator) projectedBindings = lazyGenerator.successful and first( lazyGenerator) or {} # First we check if we can combine a large group of subsequent body literals # into a single query # if we have a template map then we use it to further # distinguish which builtins can be solved via # cumulative SPARQl query - else we solve # builtins one at a time def sparqlResolvable(literal): if isinstance(literal, Uniterm): return not literal.naf and GetOp(literal) not in derivedPreds else: return isinstance(literal, N3Builtin) and \ literal.uri in factGraph.templateMap def sparqlResolvableNoTemplates(literal): if isinstance(literal, Uniterm): return not literal.naf and GetOp(literal) not in derivedPreds else: return False conjGroundLiterals = list( itertools.takewhile( hasattr(factGraph, 'templateMap') and sparqlResolvable or \ sparqlResolvableNoTemplates, remainingBodyList)) bodyLiteralIterator = iter(remainingBodyList) if len(conjGroundLiterals) > 1: # If there are literals to combine *and* a mapping from rule # builtins to SPARQL FILTER templates .. basePredicateVars = set( reduce(lambda x, y: x + y, [ list(GetVariables(arg, secondOrder=True)) for arg in conjGroundLiterals ])) if projectedBindings: openVars = basePredicateVars.intersection(projectedBindings) else: # We don't have any given bindings, so we need to treat # the body as an open query openVars = basePredicateVars queryConj = EDBQuery( [copy.deepcopy(lit) for lit in conjGroundLiterals], factGraph, openVars, projectedBindings) query, answers = queryConj.evaluate(debug) if isinstance(answers, bool): combinedAnswers = {} rtCheck = answers else: if projectedBindings: combinedAnswers = (mergeMappings1To2(ans, projectedBindings, makeImmutable=True) for ans in answers) else: combinedAnswers = (MakeImmutableDict(ans) for ans in answers) combinedAnsLazyGenerator = lazyGeneratorPeek(combinedAnswers) rtCheck = combinedAnsLazyGenerator.successful if not rtCheck: raise RuleFailure("No answers for combined SPARQL query: %s" % query) else: # We have solved the previous N body literals with a single # conjunctive query, now we need to make each of the literals # an antecedent to a 'query' step. if buildProof: queryStep = InferenceStep(None, source='some RDF graph') queryStep.groundQuery = subquery queryStep.bindings = {} # combinedAnswers[-1] queryHash = URIRef( "tag:[email protected]:Queries#" + \ makeMD5Digest(subquery)) queryStep.identifier = queryHash for subGoal in conjGroundLiterals: subNs = NodeSet(subGoal.toRDFTuple(), identifier=BNode()) subNs.steps.append(queryStep) step.antecedents.append(subNs) queryStep.parent = subNs for rt, _step in invokeRule( isinstance(answers, bool) and [projectedBindings] or combinedAnsLazyGenerator, iter(remainingBodyList[len(conjGroundLiterals):]), sip, otherargs, isinstance(answers, bool), step, debug=debug, buildProof=buildProof): yield rt, _step else: # Continue processing rule body condition # one literal at a time try: bodyLiteral = next( bodyLiteralIterator ) if py3compat.PY3 else bodyLiteralIterator.next() # if a N3 builtin, execute it using given bindings for boolean answer # builtins are moved to end of rule when evaluating rules via sip if isinstance(bodyLiteral, N3Builtin): lhs = bodyLiteral.argument rhs = bodyLiteral.result lhs = isinstance( lhs, Variable) and projectedBindings[lhs] or lhs rhs = isinstance( rhs, Variable) and projectedBindings[rhs] or rhs assert lhs is not None and rhs is not None if bodyLiteral.func(lhs, rhs): if debug: print("Invoked %s(%s, %s) -> True" % (bodyLiteral.uri, lhs, rhs)) # positive answer means we can continue processing the rule body if buildProof: ns = NodeSet(bodyLiteral.toRDFTuple(), identifier=BNode()) step.antecedents.append(ns) for rt, _step in invokeRule([projectedBindings], bodyLiteralIterator, sip, otherargs, step, priorBooleanGoalSuccess, debug=debug, buildProof=buildProof): yield rt, _step else: if debug: print("Successfully invoked %s(%s, %s) -> False" % (bodyLiteral.uri, lhs, rhs)) raise RuleFailure( "Failed builtin invokation %s(%s, %s)" % (bodyLiteral.uri, lhs, rhs)) else: # For every body literal, subqueries are generated according # to the sip sipArcPred = URIRef(GetOp(bodyLiteral) + \ '_' + '_'.join(GetArgs(bodyLiteral))) assert len(list(IncomingSIPArcs(sip, sipArcPred))) < 2 subquery = copy.deepcopy(bodyLiteral) subquery.ground(projectedBindings) for N, x in IncomingSIPArcs(sip, sipArcPred): #That is, each subquery contains values for the bound arguments #that are passed through the sip arcs entering the node #corresponding to that literal #Create query out of body literal and apply sip-provided bindings subquery = copy.deepcopy(bodyLiteral) subquery.ground(projectedBindings) if literalIsGround(subquery): #subquery is ground, so there will only be boolean answers #we return the conjunction of the answers for the current #subquery answer = False ns = None answers = first( itertools.dropwhile( lambda item: not item[0], SipStrategy( subquery.toRDFTuple(), sipCollection, factGraph, derivedPreds, MakeImmutableDict(projectedBindings), processedRules, network=step is not None and \ step.parent.network or None, debug=debug, buildProof=buildProof, memoizeMemory=memoizeMemory, proofLevel=proofLevel))) if answers: answer, ns = answers if not answer and not bodyLiteral.naf or \ (answer and bodyLiteral.naf): #negative answer means the invokation of the rule fails #either because we have a positive literal and there #is no answer for the subgoal or the literal is #negative and there is an answer for the subgoal raise RuleFailure( "No solutions solving ground query %s" % subquery) else: if buildProof: if not answer and bodyLiteral.naf: ns.naf = True step.antecedents.append(ns) #positive answer means we can continue processing the rule body #either because we have a positive literal and answers #for subgoal or a negative literal and no answers for the #the goal for rt, _step in invokeRule([projectedBindings], bodyLiteralIterator, sip, otherargs, True, step, debug=debug): yield rt, _step else: _answers = \ SipStrategy(subquery.toRDFTuple(), sipCollection, factGraph, derivedPreds, MakeImmutableDict(projectedBindings), processedRules, network=step is not None and \ step.parent.network or None, debug=debug, buildProof=buildProof, memoizeMemory=memoizeMemory, proofLevel=proofLevel) # solve (non-ground) subgoal def collectAnswers(_ans): for ans, ns in _ans: if isinstance(ans, dict): try: map = mergeMappings1To2( ans, projectedBindings, makeImmutable=True) yield map except: pass combinedAnswers = collectAnswers(_answers) answers = lazyGeneratorPeek(combinedAnswers) if not answers.successful \ and not bodyLiteral.naf \ or (bodyLiteral.naf and answers.successful): raise RuleFailure( "No solutions solving ground query %s" % subquery) else: # Either we have a positive subgoal and answers # or a negative subgoal and no answers if buildProof: if answers.successful: goals = set([g for a, g in answers]) assert len(goals) == 1 step.antecedents.append(goals.pop()) else: newNs = NodeSet( bodyLiteral.toRDFTuple(), network=step.parent.network, identifier=BNode(), naf=True) step.antecedents.append(newNs) for rt, _step in invokeRule( answers, bodyLiteralIterator, sip, otherargs, priorBooleanGoalSuccess, step, debug=debug, buildProof=buildProof): yield rt, _step except StopIteration: #Finished processing rule if priorBooleanGoalSuccess: yield projectedBindings and projectedBindings or True, step elif projectedBindings: #Return the most recent (cumulative) answers and the given step yield projectedBindings, step else: raise RuleFailure( "Finished processing rule unsuccessfully")
def conjunctiveSipStrategy(self, goalsRemaining, factGraph, bindings=None): """ Given a conjunctive set of triples, invoke sip-strategy passing on intermediate solutions to facilitate 'join' behavior """ bindings = bindings if bindings else {} try: tp = next(goalsRemaining) assert isinstance(bindings, dict) dPred = self.derivedPredicateFromTriple(tp) if dPred is None: baseEDBQuery = EDBQuery([BuildUnitermFromTuple(tp)], self.edb, bindings=bindings) if self.DEBUG: _debug( "Evaluating TP against EDB: %s" % baseEDBQuery.asSPARQL()) query, rt = baseEDBQuery.evaluate() if isinstance(rt, bool) and rt: yield bindings elif not isinstance(rt, bool): rt = list(rt) remaining_goals = itertools.tee(goalsRemaining, len(rt)) for idx in range(len(rt)): item = {} item.update(rt[idx]) item.update(bindings) if self.DEBUG: _debug("Solution from EDB query: %s" % item) for ansDict in self.conjunctiveSipStrategy( remaining_goals[idx], factGraph, item): yield ansDict else: queryLit = BuildUnitermFromTuple(tp) currentOp = GetOp(queryLit) queryLit.setOperator(currentOp) query = EDBQuery([queryLit], self.edb, bindings=bindings) if bindings: tp = first(query.formulae).toRDFTuple() if self.DEBUG: _debug("Goal/Query: %s" % query.asSPARQL()) tp = self.hybridPredQueryPreparation(tp) SetupDDLAndAdornProgram( self.edb, self.idb, [tp], derivedPreds=self.derivedPredicates, ignoreUnboundDPreds=True) sipCollection = PrepareSipCollection(self.edb.adornedProgram) if self.DEBUG and sipCollection: for sip in SIPRepresentation(sipCollection): _debug(sip) _debug(pformat(list(self.edb.adornedProgram))) elif self.DEBUG: _debug("No SIP graph.") for nextAnswer, ns in self.invokeDecisionProcedure( tp, factGraph, bindings, self.DEBUG, sipCollection): if isinstance(nextAnswer, dict): # Received solutions to 'open' query, merge with given # bindings and continue for ansDict in self.conjunctiveSipStrategy( goalsRemaining, factGraph, mergeMappings1To2(bindings, nextAnswer)): yield ansDict elif nextAnswer: # we (successfully) proved a ground query, pass on # bindings assert isinstance(nextAnswer, bool) for ansDict in self.conjunctiveSipStrategy( goalsRemaining, factGraph, bindings): yield ansDict except StopIteration: yield bindings
def conjunctiveSipStrategy(self, goalsRemaining, factGraph, bindings=None): """ Given a conjunctive set of triples, invoke sip-strategy passing on intermediate solutions to facilitate 'join' behavior """ bindings = bindings if bindings else {} try: tp = next(goalsRemaining) assert isinstance(bindings, dict) dPred = self.derivedPredicateFromTriple(tp) if dPred is None: baseEDBQuery = EDBQuery([BuildUnitermFromTuple(tp)], self.edb, bindings=bindings) if self.DEBUG: print("Evaluating TP against EDB:%s" % baseEDBQuery.asSPARQL()) query, rt = baseEDBQuery.evaluate() # _vars = baseEDBQuery.returnVars for item in rt: bindings.update(item) for ansDict in self.conjunctiveSipStrategy( goalsRemaining, factGraph, bindings): yield ansDict else: queryLit = BuildUnitermFromTuple(tp) currentOp = GetOp(queryLit) queryLit.setOperator(currentOp) query = EDBQuery([queryLit], self.edb, bindings=bindings) if bindings: tp = first(query.formulae).toRDFTuple() if self.DEBUG: print("Goal/Query: ", query.asSPARQL()) SetupDDLAndAdornProgram( self.edb, self.idb, [tp], derivedPreds=self.derivedPredicates, ignoreUnboundDPreds=True, hybridPreds2Replace=self.hybridPredicates) if self.hybridPredicates: lit = BuildUnitermFromTuple(tp) op = GetOp(lit) if op in self.hybridPredicates: lit.setOperator(URIRef(op + u'_derived')) tp = lit.toRDFTuple() sipCollection = PrepareSipCollection(self.edb.adornedProgram) if self.DEBUG and sipCollection: for sip in SIPRepresentation(sipCollection): print(sip) pprint(list(self.edb.adornedProgram), sys.stderr) elif self.DEBUG: print("No SIP graph.") for nextAnswer, ns in self.invokeDecisionProcedure( tp, factGraph, bindings, self.DEBUG, sipCollection): nonGroundGoal = isinstance(nextAnswer, dict) if nonGroundGoal or nextAnswer: #Either we recieved bindings from top-down evaluation #or we (successfully) proved a ground query if not nonGroundGoal: #Attempt to prove a ground query, return the response rt = nextAnswer else: #Recieved solutions to 'open' query, merge with given bindings #and continue rt = mergeMappings1To2(bindings, nextAnswer) #either answers were provided (the goal wasn't grounded) or #the goal was ground and successfully proved for ansDict in self.conjunctiveSipStrategy( goalsRemaining, factGraph, rt): yield ansDict except StopIteration: yield bindings