Exemple #1
0
 def sparqlResolvableNoTemplates(literal):
     predTerm = GetOp(literal)
     if isinstance(literal, Uniterm):
         return not literal.naf and (predTerm not in derivedPreds or
                                     (predTerm in hybridPredicates and
                                      not predTerm.find('_derived') + 1))
     else:
         return False
Exemple #2
0
 def sparqlResolvableNoTemplates(literal):
     predTerm = GetOp(literal)
     if isinstance(literal,Uniterm):
         return not literal.naf and (
             predTerm not in derivedPreds or 
             ( predTerm in hybridPredicates and
               not predTerm.find('_derived') + 1 ))
     else:
         return False
Exemple #3
0
 def sparqlResolvable(literal):
     predTerm = GetOp(literal)
     if not isinstance(literal, AdornedUniTerm) and isinstance(
             literal, Uniterm):
         return not literal.naf and (predTerm not in derivedPreds or
                                     (predTerm in hybridPredicates and
                                      not predTerm.find('_derived') + 1))
     else:
         return isinstance(literal, N3Builtin) and \
                literal.uri in factGraph.templateMap
Exemple #4
0
 def sparqlResolvable(literal):
     predTerm = GetOp(literal)
     if not isinstance(literal,
                       AdornedUniTerm) and isinstance(literal,
                                                      Uniterm):
         return not literal.naf and (
             predTerm not in derivedPreds or
             ( predTerm in hybridPredicates and
               not predTerm.find('_derived') + 1 ))
     else:
         return isinstance(literal,N3Builtin) and \
                literal.uri in factGraph.templateMap
Exemple #5
0
def compareAdornedPredToRuleHead(aPred, head, hybridPreds2Replace):
    """
    If p_a is an unmarked adorned predicate, then for each rule that has p in its head, ..
    """
    headPredicateTerm = GetOp(head)
    aPredTerm = GetOp(aPred)
    assert isinstance(head, Uniterm)
    if head.getArity() == aPred.getArity():
        return headPredicateTerm == aPredTerm or isinstance(
            headPredicateTerm,
            Variable) or (IsHybridPredicate(aPred, hybridPreds2Replace)
                          and aPredTerm[:-8] == headPredicateTerm)
    return False
Exemple #6
0
def buildMagicBody(N, prevPredicates, adornedHead, derivedPreds, noMagic=[]):
    unboundHead = 'b' in adornedHead.adornment
    if unboundHead:
        body = [adornedHead.makeMagicPred()]
    else:
        # If there are no bound argument positions to pass magic values with,
        # we propagate values in the full relation
        body = []
    for prevAPred in prevPredicates:
        op = GetOp(prevAPred)
        if op in N or isinstance(op, Variable):
            # If qj, j<i, is in N, we add qj to the body of the magic rule
            # Note, if the atom has a variable for the predicate, treat it as a base
            # predicate occurrence
            body.append(prevAPred)
        if op in derivedPreds \
            and isinstance(prevAPred, AdornedUniTerm) \
            and prevAPred.adornment.count('b') > 0:
            # If qj is a derived predicate and its adornment contains at least
            # one b, we also add the corresponding magic predicate to the body
            if op in noMagic:
                body.append(prevAPred)
            else:
                body.append(prevAPred.makeMagicPred())
    return body
Exemple #7
0
def RDFTuplesToSPARQL(conjunct,
                      edb,
                      isGround=False,
                      vars=[],
                      symmAtomicInclusion=False):
    """
    Takes a conjunction of Horn literals and returns the
    corresponding SPARQL query
    """
    queryType = isGround and "ASK" or "SELECT %s" % (' '.join(
        [v.n3() for v in vars]))

    queryShell = len(conjunct) > 1 and "%s {\n%s\n}" or "%s { %s }"

    if symmAtomicInclusion:
        if vars:
            var = vars.pop()
            prefix = "%s a ?KIND" % var.n3()
        else:

            prefix = "%s a ?KIND" % first(
                [first(iterCondition(lit)).arg[0].n3() for lit in conjunct])
        conjunct = (i.formulae[0] if isinstance(i, And) else i
                    for i in conjunct)

        subquery = queryShell % (
            queryType, "%s\nFILTER(%s)" % (prefix, ' ||\n'.join(
                ['?KIND = %s' % edb.qname(GetOp(lit)) for lit in conjunct])))
    else:
        subquery = queryShell % (queryType, ' .\n'.join(
            ['\t' + tripleToTriplePattern(edb, lit) for lit in conjunct]))
    return subquery
Exemple #8
0
 def unprocessedPreds(aPredCol):
     rt = []
     for p in aPredCol:
         if not p.marked:
             rt.append(p)
         if p not in goalDict:
             goalDict.setdefault(GetOp(p), set()).add(p)
     return rt
Exemple #9
0
def SetupMetaInterpreter(tBoxGraph, goal, useThingRule=True):
    from FuXi.LP.BackwardFixpointProcedure import BackwardFixpointProcedure
    from FuXi.Rete.Magic import SetupDDLAndAdornProgram
    from FuXi.Horn.PositiveConditions import BuildUnitermFromTuple
    from FuXi.Rete.TopDown import PrepareSipCollection
    from FuXi.DLP import LloydToporTransformation, makeRule
    from FuXi.Rete.SidewaysInformationPassing import GetOp

    owlThingAppears = False
    if useThingRule and OWL.Thing in tBoxGraph.all_nodes():
        owlThingAppears = True
    completionRules = HornFromN3(StringIO(RULES))
    if owlThingAppears:
        completionRules.formulae.extend(
            HornFromN3(StringIO(CONDITIONAL_THING_RULE)))
    reducedCompletionRules = set()
    for rule in completionRules:
        for clause in LloydToporTransformation(rule.formula):
            rule = makeRule(clause, {})
            # log.debug(rule)
            # PrettyPrintRule(rule)
            reducedCompletionRules.add(rule)

    network = SetupRuleStore(makeNetwork=True)[-1]
    SetupDDLAndAdornProgram(
        tBoxGraph,
        reducedCompletionRules,
        [goal],
        derivedPreds=derivedPredicates,
        ignoreUnboundDPreds=True,
        hybridPreds2Replace=hybridPredicates)

    lit = BuildUnitermFromTuple(goal)
    op = GetOp(lit)
    lit.setOperator(URIRef(op + u'_derived'))
    goal = lit.toRDFTuple()

    sipCollection = PrepareSipCollection(reducedCompletionRules)
    tBoxGraph.templateMap = {}
    bfp = BackwardFixpointProcedure(
        tBoxGraph,
        network,
        derivedPredicates,
        goal,
        sipCollection,
        hybridPredicates=hybridPredicates,
        debug=True)
    bfp.createTopDownReteNetwork(True)
    log.debug(reducedCompletionRules)
    rt = bfp.answers(debug=True)
    log.debug(rt)
    log.debug(bfp.metaInterpNetwork)
    bfp.metaInterpNetwork.reportConflictSet(True, sys.stderr)
    for query in bfp.edbQueries:
        log.debug("Dispatched query against dataset: ", query.asSPARQL())
    log.debug(list(bfp.goalSolutions))
Exemple #10
0
 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
Exemple #11
0
def PrepareSipCollection(adornedRuleset):
    """
    Takes adorned ruleset and returns an RDF dataset
    formed from the sips associated with each adorned
    rule as named graphs.  Also returns a mapping from
    the head predicates of each rule to the rules that match
    it - for efficient retrieval later
    """
    headToRule = {}
    graphs = []
    secondOrderRules = set()

    for rule in adornedRuleset:
        ruleHead = GetOp(rule.formula.head)

        if isinstance(ruleHead, Variable):
            #We store second order rules (i.e., rules whose head is a
            #predicate occurrence whose predicate symbol is a variable) aside
            secondOrderRules.add(rule)

        headToRule.setdefault(ruleHead, set()).add(rule)

        if hasattr(rule, 'sip'):
            graphs.append(rule.sip)

    # Second order rules are mapped from a None key (in order
    # to indicate they are wildcards)

    headToRule[None] = secondOrderRules

    if not graphs:
        return

    graph = ReadOnlyGraphAggregate(graphs)
    graph.headToRule = headToRule

    return graph
Exemple #12
0
def DerivedPredicateIterator(factsOrBasePreds,
                             ruleset,
                             strict=DDL_STRICTNESS_FALLBACK_DERIVED,
                             defaultPredicates=None):
    if not defaultPredicates:
        defaultPredicates = [], []
    defaultBasePreds, defaultDerivedPreds = defaultPredicates
    basePreds = [
        GetOp(buildUniTerm(fact)) for fact in factsOrBasePreds
        if fact[1] != LOG.implies
    ]
    processed = {True: set(), False: set()}
    derivedPreds = set()
    uncertainPreds = set()
    ruleBodyPreds = set()
    ruleHeads = set()
    for rule in ruleset:
        if rule.formula.body:
            for idx, term in enumerate(
                    itertools.chain(iterCondition(rule.formula.head),
                                    iterCondition(rule.formula.body))):
                # iterate over terms from head to end of body
                op = GetOp(term)
                if op not in processed[idx > 0]:
                    # not processed before
                    if idx > 0:
                        # body literal
                        ruleBodyPreds.add(op)
                    else:
                        # head literal
                        ruleHeads.add(op)
                    if strict in DDL_MUST_CHECK and \
                        not (op not in basePreds or idx > 0):
                        # checking DDL well formedness and
                        # op is a base predicate *and* a head literal (derived)
                        if strict in DDL_FALLBACK:
                            mark = strict == DDL_STRICTNESS_FALLBACK_DERIVED and \
                            'derived' or 'base'
                            if strict == DDL_STRICTNESS_FALLBACK_DERIVED and \
                                op not in defaultBasePreds:
                                # a clashing predicate is marked as derived due
                                # to level of strictness
                                derivedPreds.add(op)
                            elif strict == DDL_STRICTNESS_FALLBACK_BASE and \
                                op not in defaultDerivedPreds:
                                # a clashing predicate is marked as base dur
                                # to level of strictness
                                defaultBasePreds.append(op)
                            import warnings
                            warnings.warn(
                                "predicate symbol of %s is in both IDB and EDB. Marking as %s"
                                % (term, mark))
                        else:
                            raise SyntaxError(
                                "%s is a member of a derived predicate and a base predicate."
                                % term)
                    if op in basePreds:
                        # base predicates are marked for later validation
                        uncertainPreds.add(op)
                    else:
                        if idx == 0 and not isinstance(op, Variable):
                            # head literal with proper predicate symbol
                            # identify as a derived predicate
                            derivedPreds.add(op)
                        elif not isinstance(op, Variable):
                            # body literal with proper predicate symbol
                            # mark for later validation
                            uncertainPreds.add(op)
                    processed[idx > 0].add(op)
    for pred in uncertainPreds:
        # for each predicate marked as 'uncertain'
        # do further checking
        if (pred not in ruleBodyPreds and not isinstance(pred, Variable)) or\
           pred in ruleHeads:
            # pred is not in a body literal and is a proper predicate symbol
            # or it is a rule head -> mark as a derived predicate
            derivedPreds.add(pred)
    for pred in derivedPreds:
        if not pred in defaultBasePreds:
            yield pred
Exemple #13
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
Exemple #14
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 \
          _expr.name == 'BGP':
            # 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(sip)
                        pprint(list(self.edb.adornedProgram))
                    elif self.DEBUG:
                        print("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)
Exemple #15
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("%sSolving" % ('\t' * proofLevel), queryLiteral, bindings)
    # Only consider ground triple pattern isomorphism with matching bindings
    goalRDFStatement = queryLiteral.toRDFTuple()

    if queryLiteral in memoizeMemory:
        if debug:
            print("%sReturning previously calculated results for " % \
                        ('\t' * proofLevel), queryLiteral)
        for answers in memoizeMemory[queryLiteral]:
            yield answers
    elif AlphaNode(goalRDFStatement).alphaNetworkHash(
                                      True,
                                      skolemTerms=list(bindings.values())) in \
        [AlphaNode(r.toRDFTuple()).alphaNetworkHash(True,
                                                    skolemTerms=list(bindings.values()))
            for r in processedRules
                if AdornLiteral(goalRDFStatement).adornment == \
                   r.adornment]:
        if debug:
            print("%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(filter(IsAtomicInclusionAxiomRHS, rules))
        if atomicInclusionAxioms and len(atomicInclusionAxioms) > 1:
            if debug:
                print("\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 = filter(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("%sProcessing rule" % \
                            ('\t' * proofLevel), rule.formula)
                if debug and sipCollection:
                    print("Sideways Information Passing (sip) graph for %s: " %
                          queryLiteral)
                    print(sipCollection.serialize(format='n3'))
                    for sip in SIPRepresentation(sipCollection):
                        print(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:
                # 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
Exemple #16
0
        def sparqlResolvableNoTemplates(literal):

            if isinstance(literal, Uniterm):
                return not literal.naf and GetOp(literal) not in derivedPreds
            else:
                return False
Exemple #17
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")
Exemple #18
0
 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
Exemple #19
0
def IdentifyDerivedPredicates(ddlMetaGraph, tBox, ruleset=None):
    """
    See: http://code.google.com/p/fuxi/wiki/DataDescriptionLanguage#
    """
    dPreds = set()
    basePreds = set()
    DDL = Namespace(
        'http://code.google.com/p/fuxi/wiki/DataDescriptionLanguage#')

    if ruleset:
        for rule in ruleset:
            dPreds.add(GetOp(rule.formula.head))

    for derivedClassList in ddlMetaGraph.subjects(predicate=RDF.type,
                                                  object=DDL.DerivedClassList):
        dPreds.update(Collection(ddlMetaGraph, derivedClassList))
    for derivedClassList in ddlMetaGraph.subjects(
            predicate=RDF.type, object=DDL.DerivedPropertyList):
        dPreds.update(Collection(ddlMetaGraph, derivedClassList))
    derivedPropPrefixes = []
    basePropPrefixes = []
    for derivedPropPrefixList in ddlMetaGraph.subjects(
            predicate=RDF.type, object=DDL.DerivedPropertyPrefix):
        derivedPropPrefixes.extend(
            Collection(ddlMetaGraph, derivedPropPrefixList))
    for basePropPrefixList in ddlMetaGraph.subjects(
            predicate=RDF.type, object=DDL.BasePropertyPrefix):
        basePropPrefixes.extend(Collection(ddlMetaGraph, basePropPrefixList))

    for prop in tBox.query(OWL_PROPERTIES_QUERY):
        if first(filter(lambda prefix: prop.startswith(prefix),
                                   derivedPropPrefixes)) and \
                       (prop, RDF.type, OWL_NS.AnnotationProperty) not in tBox:
            dPreds.add(prop)
        if first(filter(lambda prefix: prop.startswith(prefix),
                                   basePropPrefixes)) and \
                       (prop, RDF.type, OWL_NS.AnnotationProperty) not in tBox and \
                       prop not in dPreds:
            basePreds.add(prop)

    derivedClassPrefixes = []
    for derivedClsPrefixList in ddlMetaGraph.subjects(
            predicate=RDF.type, object=DDL.DerivedClassPrefix):
        derivedClassPrefixes.extend(
            Collection(ddlMetaGraph, derivedClsPrefixList))
    baseClassPrefixes = []
    for baseClsPrefixList in ddlMetaGraph.subjects(predicate=RDF.type,
                                                   object=DDL.BaseClassPrefix):
        baseClassPrefixes.extend(Collection(ddlMetaGraph, baseClsPrefixList))
    for cls in tBox.subjects(predicate=RDF.type, object=OWL_NS.Class):
        if first(
                filter(lambda prefix: cls.startswith(prefix),
                       baseClassPrefixes)):
            if cls not in dPreds:
                basePreds.add(cls)
        if first(
                filter(lambda prefix: cls.startswith(prefix),
                       derivedClassPrefixes)):
            if cls not in basePreds:
                dPreds.add(cls)

    nsBindings = dict([(prefix, nsUri) for prefix, nsUri in itertools.chain(
        tBox.namespaces(), ddlMetaGraph.namespaces()) if prefix])
    for queryNode in ddlMetaGraph.subjects(predicate=RDF.type,
                                           object=DDL.DerivedClassQuery):
        query = first(ddlMetaGraph.objects(queryNode, RDF.value))
        for cls in tBox.query(query, initNs=nsBindings):
            dPreds.add(cls)

    for baseClsList in ddlMetaGraph.subjects(predicate=RDF.type,
                                             object=DDL.BaseClassList):
        basePreds.update(Collection(ddlMetaGraph, baseClsList))

    dPreds.difference_update(basePreds)
    return dPreds
Exemple #20
0
def SetupDDLAndAdornProgram(factGraph,
                            rules,
                            GOALS,
                            derivedPreds=None,
                            strictCheck=DDL_STRICTNESS_FALLBACK_DERIVED,
                            defaultPredicates=None,
                            ignoreUnboundDPreds=False,
                            hybridPreds2Replace=None):
    if not defaultPredicates:
        defaultPredicates = [], []
    # _dPredsProvided = bool(derivedPreds)
    if not derivedPreds:
        _derivedPreds = DerivedPredicateIterator(
            factGraph,
            rules,
            strict=strictCheck,
            defaultPredicates=defaultPredicates)
        if not isinstance(derivedPreds, (set, list)):
            derivedPreds = list(_derivedPreds)
        else:
            derivedPreds.extend(_derivedPreds)
    hybridPreds2Replace = hybridPreds2Replace or []
    adornedProgram = AdornProgram(factGraph,
                                  rules,
                                  GOALS,
                                  derivedPreds,
                                  ignoreUnboundDPreds,
                                  hybridPreds2Replace=hybridPreds2Replace)
    if adornedProgram != set([]):
        rt = reduce(lambda l, r: l + r, [
            list(iterCondition(clause.formula.body))
            for clause in adornedProgram
        ])
    else:
        rt = set()
    for hybridPred, adornment in [
        (t, a) for t, a in set([(URIRef(GetOp(term).split('_derived')[0]
                                        ) if GetOp(term).find('_derived') +
                                 1 else GetOp(term), ''.join(term.adornment))
                                for term in rt
                                if isinstance(term, AdornedUniTerm)])
            if t in hybridPreds2Replace
    ]:
        #If there are hybrid predicates, add rules that derived their IDB counterpart
        #using information from the adorned queries to determine appropriate arity
        #and adornment
        hybridPred = URIRef(hybridPred)
        hPred = URIRef(hybridPred + u'_derived')
        if len(adornment) == 1:
            # p_derived^{a}(X) :- p(X)
            body = BuildUnitermFromTuple((Variable('X'), RDF.type, hybridPred))
            head = BuildUnitermFromTuple((Variable('X'), RDF.type, hPred))
        else:
            # p_derived^{a}(X, Y) :- p(X, Y)
            body = BuildUnitermFromTuple(
                (Variable('X'), hybridPred, Variable('Y')))
            head = BuildUnitermFromTuple((Variable('X'), hPred, Variable('Y')))
        _head = AdornedUniTerm(head, list(adornment))
        rule = AdornedRule(Clause(And([body]), _head.clone()))
        rule.sip = Graph()
        adornedProgram.add(rule)

    if factGraph is not None:
        factGraph.adornedProgram = adornedProgram
    return adornedProgram
Exemple #21
0
def MagicSetTransformation(factGraph,
                           rules,
                           GOALS,
                           derivedPreds=None,
                           strictCheck=DDL_STRICTNESS_FALLBACK_DERIVED,
                           noMagic=None,
                           defaultPredicates=None):
    """
    Takes a goal and a ruleset and returns an iterator
    over the rulest that corresponds to the magic set
    transformation:
    """
    noMagic = noMagic and noMagic or []
    magicPredicates = set()
    # replacement = {}
    adornedProgram = SetupDDLAndAdornProgram(
        factGraph,
        rules,
        GOALS,
        derivedPreds=derivedPreds,
        strictCheck=strictCheck,
        defaultPredicates=defaultPredicates)
    newRules = []
    for rule in adornedProgram:
        if rule.isSecondOrder():
            import warnings
            warnings.warn("Second order rule no supported by GMS: %s" % rule,
                          RuntimeWarning)

        magicPositions = {}
        #Generate magic rules
        for idx, pred in enumerate(iterCondition(rule.formula.body)):
            # magicBody = []
            if isinstance(pred,
                          AdornedUniTerm):  # and pred not in magicPredicates:
                # For each rule r in Pad, and for each occurrence of an adorned
                # predicate p a in its body, we generate a magic rule defining magic_p a
                prevPreds = [
                    item for _idx, item in enumerate(rule.formula.body)
                    if _idx < idx
                ]
                if 'b' not in pred.adornment:
                    import warnings
                    warnings.warn(
                        "adorned predicate w/out any bound arguments (%s in %s)"
                        % (pred, rule.formula), RuntimeWarning)
                if GetOp(pred) not in noMagic:
                    magicPred = pred.makeMagicPred()
                    magicPositions[idx] = (magicPred, pred)
                    inArcs = [(N, x) for (
                        N,
                        x) in IncomingSIPArcs(rule.sip, getOccurrenceId(pred))
                              if not set(x).difference(GetArgs(pred))]
                    if len(inArcs) > 1:
                        # If there are several arcs entering qi, we define the
                        # magic rule defining magic_qi in two steps. First,
                        # for each arc Nj --> qi with label cj , we define a
                        # rule with head label_qi_j(cj ). The body of the rule
                        # is the same as the body of the magic rule in the
                        # case where there is a single arc entering qi
                        # (described above). Then the magic rule is defined as
                        # follows. The head is magic_q(0). The body contains
                        # label_qi_j(cj) for all j (that is, for all arcs
                        # entering qi ).
                        #
                        # We combine all incoming arcs into a single list of
                        # (body) conditions for the magic set
                        PrettyPrintRule(rule)
                        SIPRepresentation(rule.sip)
                        print(pred, magicPred)
                        _body = []
                        additionalRules = []
                        for idxSip, (N, x) in enumerate(inArcs):
                            newPred = pred.clone()
                            SetOp(newPred,
                                  URIRef('%s_label_%s' % (newPred.op, idxSip)))
                            ruleBody = And(
                                buildMagicBody(N, prevPreds, rule.formula.head,
                                               derivedPreds))
                            additionalRules.append(
                                Rule(Clause(ruleBody, newPred)))
                            _body.extend(newPred)
                            # _body.extend(ruleBody)
                        additionalRules.append(
                            Rule(Clause(And(_body), magicPred)))
                        newRules.extend(additionalRules)
                        for i in additionalRules:
                            print(i)
                        raise NotImplementedError()
                    else:
                        for idxSip, (N, x) in enumerate(inArcs):
                            ruleBody = And(
                                buildMagicBody(N, prevPreds, rule.formula.head,
                                               derivedPreds, noMagic))
                            newRule = Rule(Clause(ruleBody, magicPred))
                            newRules.append(newRule)
                    magicPredicates.add(magicPred)
        # Modify rules
        # we modify the original rule by inserting
        # occurrences of the magic predicates corresponding
        # to the derived predicates of the body and to the head
        # If there are no bound arguments in the head, we don't modify the rule
        idxIncrement = 0
        newRule = copy.deepcopy(rule)
        for idx, (magicPred, origPred) in list(magicPositions.items()):
            newRule.formula.body.formulae.insert(idx + idxIncrement, magicPred)
            idxIncrement += 1
        if 'b' in rule.formula.head.adornment and GetOp(
                rule.formula.head) not in noMagic:
            headMagicPred = rule.formula.head.makeMagicPred()
            if isinstance(newRule.formula.body, Uniterm):
                newRule.formula.body = And(
                    [headMagicPred, newRule.formula.body])
            else:
                newRule.formula.body.formulae.insert(0, headMagicPred)
        newRules.append(newRule)

    if not newRules:
        newRules.extend(AdditionalRules(factGraph))
    for rule in newRules:
        if rule.formula.body:
            yield rule
Exemple #22
0
 def termHash(term):
     return GetOp(term), \
            reduce(lambda x, y: x + y, term.adornment)
Exemple #23
0
def AdornRule(derivedPreds,
              clause,
              newHead,
              ignoreUnboundDPreds=False,
              hybridPreds2Replace=None):
    """
    Adorns a horn clause using the given new head and list of
    derived predicates
    """
    assert len(list(iterCondition(clause.head))) == 1
    hybridPreds2Replace = hybridPreds2Replace or []
    adornedHead = AdornedUniTerm(clause.head, newHead.adornment)
    sip = BuildNaturalSIP(clause,
                          derivedPreds,
                          adornedHead,
                          hybridPreds2Replace=hybridPreds2Replace,
                          ignoreUnboundDPreds=ignoreUnboundDPreds)
    bodyPredReplace = {}

    def adornment(arg, headArc, x):
        if headArc:
            # Sip arc from head
            # don't mark bound if query has no bound/distinguished terms
            return (arg in x and
                    arg in adornedHead.getDistinguishedVariables(True)) \
                        and 'b' or 'f'
        else:
            return arg in x and 'b' or 'f'

    for literal in iterCondition(sip.sipOrder):
        op = GetOp(literal)
        args = GetArgs(literal)
        if op in derivedPreds or (op in hybridPreds2Replace
                                  if hybridPreds2Replace else False):
            for N, x in IncomingSIPArcs(sip, getOccurrenceId(literal)):
                headArc = len(N) == 1 and N[0] == GetOp(newHead)
                if not set(x).difference(args):
                    # A binding
                    # for q is useful, however, only if it is a binding for an argument of q.
                    bodyPredReplace[literal] = AdornedUniTerm(
                        NormalizeUniterm(literal),
                        [adornment(arg, headArc, x) for arg in args],
                        literal.naf)
                # For a predicate occurrence with no incoming
                # arc, the adornment contains only f. For our purposes here,
                # we do not distinguish between a predicate with such an
                # adornment and an unadorned predicate (we do in order to support open queries)
            if literal not in bodyPredReplace and ignoreUnboundDPreds:
                bodyPredReplace[literal] = AdornedUniTerm(
                    NormalizeUniterm(literal),
                    ['f' for arg in GetArgs(literal)], literal.naf)
    if hybridPreds2Replace:
        atomPred = GetOp(adornedHead)
        if atomPred in hybridPreds2Replace:
            adornedHead.setOperator(URIRef(atomPred + u'_derived'))
        for bodAtom in [
                bodyPredReplace.get(p, p) for p in iterCondition(sip.sipOrder)
        ]:
            bodyPred = GetOp(bodAtom)
            if bodyPred in hybridPreds2Replace:
                bodAtom.setOperator(URIRef(bodyPred + u'_derived'))
    rule = AdornedRule(
        Clause(
            And([
                bodyPredReplace.get(p, p) for p in iterCondition(sip.sipOrder)
            ]), adornedHead))
    rule.sip = sip
    return rule
Exemple #24
0
def AdornProgram(factGraph,
                 rs,
                 goals,
                 derivedPreds=None,
                 ignoreUnboundDPreds=False,
                 hybridPreds2Replace=None):
    """
    The process starts from the given query. The query determines bindings for q, and we replace
    q by an adorned version, in which precisely the positions bound in the query are designated as
    bound, say q e . In general, we have a collection of adorned predicates, and as each one is processed,
    we will mark it, so that it will not be processed again. If p a is an unmarked adorned
    predicate, then for each rule that has p in its head, we generate an adorned version for the rule
    and add it to Pad; then p is marked as processed.

    The adorned version of a rule contains additional
    adorned predicates, and these are added to the collection, unless they already appear
    there. The process terminates when no unmarked adorned predicates are left.

    """
    from FuXi.DLP import LloydToporTransformation
    from collections import deque
    goalDict = {}
    hybridPreds2Replace = hybridPreds2Replace or []
    adornedPredicateCollection = set()
    for goal, nsBindings in NormalizeGoals(goals):
        adornedPredicateCollection.add(AdornLiteral(goal, nsBindings))
    if not derivedPreds:
        derivedPreds = list(DerivedPredicateIterator(factGraph, rs))

    def unprocessedPreds(aPredCol):
        rt = []
        for p in aPredCol:
            if not p.marked:
                rt.append(p)
            if p not in goalDict:
                goalDict.setdefault(GetOp(p), set()).add(p)
        return rt

    toDo = deque(unprocessedPreds(adornedPredicateCollection))
    adornedProgram = set()
    while len(toDo):
        term = toDo.popleft()
        #check if there is a rule with term as its head
        for rule in rs:
            for clause in LloydToporTransformation(rule.formula):
                head = isinstance(
                    clause.head, Exists) and clause.head.formula or clause.head
                # headPredicate = GetOp(head)
                if compareAdornedPredToRuleHead(term, head,
                                                hybridPreds2Replace):
                    #for each rule that has p in its head, we generate an adorned version for the rule
                    adornedRule = AdornRule(
                        derivedPreds,
                        clause,
                        term,
                        ignoreUnboundDPreds=ignoreUnboundDPreds,
                        hybridPreds2Replace=hybridPreds2Replace)
                    adornedProgram.add(adornedRule)
                    #The adorned version of a rule contains additional adorned
                    #predicates, and these are added
                    for pred in iterCondition(adornedRule.formula.body):
                        if isinstance(pred, N3Builtin):
                            aPred = pred
                        else:
                            aPred = not isinstance(pred, AdornedUniTerm) and \
                                        AdornLiteral(pred.toRDFTuple(),
                                                     nsBindings,
                                                     pred.naf) or pred
                        op = GetOp(pred)
                        if (op in derivedPreds or
                            (op in hybridPreds2Replace
                             if hybridPreds2Replace else False)
                            ) and aPred not in adornedPredicateCollection:
                            adornedPredicateCollection.add(aPred)
        term.marked = True
        toDo.extendleft(unprocessedPreds(adornedPredicateCollection))

    factGraph.queryAtoms = goalDict
    return adornedProgram
Exemple #25
0
def IsHybridPredicate(pred, hybridPreds2Replace):
    op = GetOp(pred)
    return op[-7:] == 'derived' and op[:-8] in hybridPreds2Replace