Пример #1
0
    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))
Пример #2
0
 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")
Пример #3
0
 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")
Пример #4
0
    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
Пример #5
0
    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
Пример #6
0
    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)
Пример #7
0
    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
Пример #8
0
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")
Пример #9
0
    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
Пример #10
0
    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)
Пример #11
0
    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
Пример #12
0
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
Пример #13
0
 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)
Пример #14
0
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")
Пример #15
0
    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
Пример #16
0
    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