Beispiel #1
0
def NormalizeDisjunctions(disj,
                          clause,
                          ruleset,
                          network,
                          constructNetwork,
                          negativeStratus,
                          ignoreNegativeStratus):
    """
    Removes disjunctions from logic programs (if possible)
    """
    from FuXi.DLP import breadth_first, breadth_first_replace
    # disj = [i for i in breadth_first(clause.body) if isinstance(i,Or)]
    while len(disj) > 1:
        ApplyDemorgans(clause)
        if HasBreadthFirstNestedConj(clause.body):
            FlattenConjunctions(clause.body)
        disj = [i for i in breadth_first(clause.body) if isinstance(i, Or)]
        assert len(disj) < 2, "Unable to effectively reduce disjunctions"
    if len(disj) == 1:
        # There is one disjunction in the body, we can reduce from:
        # H :- B1 V B2  to H : - B1 and H :- B2
        origDisj = disj[0]
        for item in origDisj:
            # First we want to replace the entire disjunct with an item within
            # it
            list(breadth_first_replace(
                clause.body, candidate=origDisj, replacement=item))
            clause_clone = copy.deepcopy(clause)
            disj = [i for i in breadth_first(clause_clone.body)
                    if isinstance(i, Or)]
            if len(disj) > 0:
                # If the formula has disjunctions of it's own, we handle them
                # recursively
                NormalizeDisjunctions(disj,
                                      clause_clone,
                                      ruleset,
                                      network,
                                      constructNetwork,
                                      negativeStratus,
                                      ignoreNegativeStratus)
            else:
                if HasBreadthFirstNestedConj(clause_clone.body):
                    FlattenConjunctions(clause_clone.body)
                # Otherwise handle normally
                HandleNonDisjunctiveClauses(
                    ruleset, network, constructNetwork,
                    negativeStratus, ignoreNegativeStratus, clause_clone)
            # restore the replaced term (for the subsequent iteration)
            list(breadth_first_replace(
                clause.body, candidate=item, replacement=origDisj))
    else:
        # The disjunction has been handled by normal form transformation,
        # we just need to handle normally
        if HasBreadthFirstNestedConj(clause_clone.body):
            FlattenConjunctions(clause_clone.body)
        HandleNonDisjunctiveClauses(
            ruleset, network, constructNetwork,
            negativeStratus, ignoreNegativeStratus, clause)
Beispiel #2
0
def NormalizeDisjunctions(disj, clause, ruleset, network, constructNetwork,
                          negativeStratus, ignoreNegativeStratus):
    """
    Removes disjunctions from logic programs (if possible)
    """
    from FuXi.DLP import breadth_first, breadth_first_replace
    #    disj = [i for i in breadth_first(clause.body) if isinstance(i,Or)]
    while len(disj) > 1:
        ApplyDemorgans(clause)
        if HasBreadthFirstNestedConj(clause.body):
            FlattenConjunctions(clause.body)
        disj = [i for i in breadth_first(clause.body) if isinstance(i, Or)]
        assert len(disj) < 2, "Unable to effectively reduce disjunctions"
    if len(disj) == 1:
        # There is one disjunction in the body, we can reduce from:
        # H :- B1 V B2  to H : - B1 and H :- B2
        origDisj = disj[0]
        for item in origDisj:
            # First we want to replace the entire disjunct with an item within
            # it
            list(
                breadth_first_replace(clause.body,
                                      candidate=origDisj,
                                      replacement=item))
            clause_clone = copy.deepcopy(clause)
            disj = [
                i for i in breadth_first(clause_clone.body)
                if isinstance(i, Or)
            ]
            if len(disj) > 0:
                # If the formula has disjunctions of it's own, we handle them
                # recursively
                NormalizeDisjunctions(disj, clause_clone, ruleset, network,
                                      constructNetwork, negativeStratus,
                                      ignoreNegativeStratus)
            else:
                if HasBreadthFirstNestedConj(clause_clone.body):
                    FlattenConjunctions(clause_clone.body)
                # Otherwise handle normally
                HandleNonDisjunctiveClauses(ruleset, network, constructNetwork,
                                            negativeStratus,
                                            ignoreNegativeStratus,
                                            clause_clone)
            # restore the replaced term (for the subsequent iteration)
            list(
                breadth_first_replace(clause.body,
                                      candidate=item,
                                      replacement=origDisj))
    else:
        # The disjunction has been handled by normal form transformation, we just need to
        # handle normally
        if HasBreadthFirstNestedConj(clause_clone.body):
            FlattenConjunctions(clause_clone.body)
        HandleNonDisjunctiveClauses(ruleset, network, constructNetwork,
                                    negativeStratus, ignoreNegativeStratus,
                                    clause)
Beispiel #3
0
def ApplyDemorgans(clause):
    """
    >>> from FuXi.DLP import Clause
    >>> EX_NS = Namespace('http://example.com/')
    >>> ns = {'ex' : EX_NS}
    >>> pred1 = PredicateExtentFactory(EX_NS.somePredicate,newNss=ns)
    >>> pred2 = PredicateExtentFactory(EX_NS.somePredicate2,newNss=ns)
    >>> pred3 = PredicateExtentFactory(EX_NS.somePredicate3,binary=False,newNss=ns)
    >>> pred4 = PredicateExtentFactory(EX_NS.somePredicate4,binary=False,newNss=ns)
    >>> clause = Clause(And([pred1[(Variable('X'),Variable('Y'))],
    ...                      Or([pred2[(Variable('X'),EX_NS.individual1)],
    ...                          pred3[(Variable('Y'))]],naf=True)]),
    ...                 pred4[Variable('X')])
    >>> clause
    ex:somePredicate4(?X) :- And( ex:somePredicate(?X ?Y) not Or( ex:somePredicate2(?X ex:individual1) ex:somePredicate3(?Y) ) )
    >>> ApplyDemorgans(clause)
    >>> clause
    ex:somePredicate4(?X) :- And( ex:somePredicate(?X ?Y) And( not ex:somePredicate2(?X ex:individual1) not ex:somePredicate3(?Y) ) )
    >>> FlattenConjunctions(clause.body)
    >>> clause
    ex:somePredicate4(?X) :- And( ex:somePredicate(?X ?Y) not ex:somePredicate2(?X ex:individual1) not ex:somePredicate3(?Y) )
    """
    from FuXi.DLP import breadth_first, breadth_first_replace
    replacementMap = {}
    for negDisj in [i for i in breadth_first(clause.body)
                    if isinstance(i, Or) and i.naf]:
        replacementList = []
        for innerTerm in negDisj:
            assert isinstance(negDisj, Uniterm), negDisj
            innerTerm.naf = not innerTerm.naf
            replacementList.append(innerTerm)
        replacementMap[negDisj] = And(replacementList)
    for old, new in list(replacementMap.items()):
        list(breadth_first_replace(
            clause.body, candidate=old, replacement=new))
Beispiel #4
0
def FlattenConjunctions(condition, isNested=False):
    from FuXi.DLP import breadth_first
    if isNested or HasNestedConjunction(condition):
        flattenHelper(condition)
    for nestedConj in [i for i in breadth_first(condition)
                       if isinstance(i, And) and HasNestedConjunction(i)]:
        FlattenConjunctions(nestedConj, isNested=True)
Beispiel #5
0
def ApplyDemorgans(clause):
    """
    >>> from FuXi.DLP import Clause
    >>> EX_NS = Namespace('http://example.com/')
    >>> ns = {'ex' : EX_NS}
    >>> pred1 = PredicateExtentFactory(EX_NS.somePredicate,newNss=ns)
    >>> pred2 = PredicateExtentFactory(EX_NS.somePredicate2,newNss=ns)
    >>> pred3 = PredicateExtentFactory(EX_NS.somePredicate3,binary=False,newNss=ns)
    >>> pred4 = PredicateExtentFactory(EX_NS.somePredicate4,binary=False,newNss=ns)
    >>> clause = Clause(And([pred1[(Variable('X'),Variable('Y'))],
    ...                      Or([pred2[(Variable('X'),EX_NS.individual1)],
    ...                          pred3[(Variable('Y'))]],naf=True)]),
    ...                 pred4[Variable('X')])
    >>> clause
    ex:somePredicate4(?X) :- And( ex:somePredicate(?X ?Y) not Or( ex:somePredicate2(?X ex:individual1) ex:somePredicate3(?Y) ) )
    >>> ApplyDemorgans(clause)
    >>> clause
    ex:somePredicate4(?X) :- And( ex:somePredicate(?X ?Y) And( not ex:somePredicate2(?X ex:individual1) not ex:somePredicate3(?Y) ) )
    >>> FlattenConjunctions(clause.body)
    >>> clause
    ex:somePredicate4(?X) :- And( ex:somePredicate(?X ?Y) not ex:somePredicate2(?X ex:individual1) not ex:somePredicate3(?Y) )
    """
    from FuXi.DLP import breadth_first, breadth_first_replace
    replacementMap = {}
    for negDisj in [i for i in breadth_first(clause.body) 
                        if isinstance(i,Or) and i.naf]:
        replacementList = []
        for innerTerm in negDisj:
            assert isinstance(i,Uniterm)
            innerTerm.naf = not innerTerm.naf
            replacementList.append(innerTerm)
        replacementMap[negDisj] = And(replacementList)
    for old,new in replacementMap.items():
        list(breadth_first_replace(clause.body,candidate=old,replacement=new))
Beispiel #6
0
def FlattenConjunctions(condition,isNested=False):
    from FuXi.DLP import breadth_first
    if isNested or HasNestedConjunction(condition):
        flattenHelper(condition)
    for nestedConj in [i for i in breadth_first(condition) 
                       if isinstance(i,And) and HasNestedConjunction(i)]:
        FlattenConjunctions(nestedConj, isNested=True)    
Beispiel #7
0
    def __init__(self, formulae=None, n3Rules=None, nsMapping=None):
        from FuXi.Rete.RuleStore import N3Builtin
        self.nsMapping = nsMapping and nsMapping or {}
        self.formulae = formulae and formulae or []
        if n3Rules:
            from FuXi.DLP import breadth_first
            # Convert a N3 abstract model (parsed from N3) into a RIF BLD
            for lhs, rhs in n3Rules:
                allVars = set()
                for ruleCondition in [lhs, rhs]:
                    for stmt in ruleCondition:
                        if isinstance(stmt, N3Builtin):
                            ExternalFunction(stmt, newNss=self.nsMapping)
                            # print(stmt)
                            # raise
                        allVars.update(
                            [term for term in stmt if isinstance(term, (BNode, Variable))])
                body = [isinstance(term, N3Builtin) and term or
                        Uniterm(list(term)[1], [list(term)[0], list(term)[-1]],
                                newNss=nsMapping) for term in lhs]
                body = len(body) == 1 and body[0] or And(body)
                head = [Uniterm(p, [s, o], newNss=nsMapping)
                        for s, p, o in rhs]
                head = len(head) == 1 and head[0] or And(head)

                # first we identify body variables
                bodyVars = set(reduce(lambda x, y: x + y,
                                      [list(extractVariables(i, existential=False))
                                       for i in iterCondition(body)]))
                # then we identify head variables
                headVars = set(reduce(lambda x, y: x + y,
                                      [list(extractVariables(i, existential=False))
                                       for i in iterCondition(head)]))

                # then we identify those variables that should (or should not)
                # be converted to skolem terms
                updateDict = dict([(var, BNode())
                                   for var in headVars if var not in bodyVars])

                for uniTerm in iterCondition(head):
                    def updateUniterm(uterm):
                        newArg = [updateDict.get(i, i) for i in uniTerm.arg]
                        uniTerm.arg = newArg
                    if isinstance(uniTerm, Uniterm):
                        updateUniterm(uniTerm)
                    else:
                        for u in uniTerm:
                            updateUniterm(u)

                exist = [list(extractVariables(i))
                         for i in breadth_first(head)]
                e = Exists(formula=head,
                           declare=set(reduce(lambda x, y: x + y, exist, [])))
                if reduce(lambda x, y: x + y, exist):
                    head = e
                    assert e.declare, exist

                self.formulae.append(Rule(Clause(body, head), declare=allVars))
Beispiel #8
0
def HasBreadthFirstNestedConj(condition):
    from FuXi.DLP import breadth_first
    return HasNestedConjunction(condition) \
        or [i for i in breadth_first(condition)
            if isinstance(i, And) and HasNestedConjunction(i)]
Beispiel #9
0
    def __init__(self, formulae=None, n3Rules=None, nsMapping=None):
        from FuXi.Rete.RuleStore import N3Builtin
        self.nsMapping = nsMapping and nsMapping or {}
        self.formulae = formulae and formulae or []
        if n3Rules:
            from FuXi.DLP import breadth_first
            # Convert a N3 abstract model (parsed from N3) into a RIF BLD
            for lhs, rhs in n3Rules:
                allVars = set()
                for ruleCondition in [lhs, rhs]:
                    for stmt in ruleCondition:
                        if isinstance(stmt, N3Builtin):
                            ExternalFunction(stmt, newNss=self.nsMapping)
                            # print(stmt)
                            # raise
                        allVars.update([
                            term for term in stmt
                            if isinstance(term, (BNode, Variable))
                        ])
                body = [
                    isinstance(term, N3Builtin) and term
                    or Uniterm(list(term)[1],
                               [list(term)[0], list(term)[-1]],
                               newNss=nsMapping) for term in lhs
                ]
                body = len(body) == 1 and body[0] or And(body)
                head = [
                    Uniterm(p, [s, o], newNss=nsMapping) for s, p, o in rhs
                ]
                head = len(head) == 1 and head[0] or And(head)

                # first we identify body variables
                bodyVars = set(
                    reduce(lambda x, y: x + y, [
                        list(extractVariables(i, existential=False))
                        for i in iterCondition(body)
                    ]))
                # then we identify head variables
                headVars = set(
                    reduce(lambda x, y: x + y, [
                        list(extractVariables(i, existential=False))
                        for i in iterCondition(head)
                    ]))

                # then we identify those variables that should (or should not)
                # be converted to skolem terms
                updateDict = dict([(var, BNode()) for var in headVars
                                   if var not in bodyVars])

                for uniTerm in iterCondition(head):

                    def updateUniterm(uterm):
                        newArg = [updateDict.get(i, i) for i in uniTerm.arg]
                        uniTerm.arg = newArg

                    if isinstance(uniTerm, Uniterm):
                        updateUniterm(uniTerm)
                    else:
                        for u in uniTerm:
                            updateUniterm(u)

                exist = [
                    list(extractVariables(i)) for i in breadth_first(head)
                ]
                e = Exists(formula=head,
                           declare=set(reduce(lambda x, y: x + y, exist, [])))
                if reduce(lambda x, y: x + y, exist):
                    head = e
                    assert e.declare, exist

                self.formulae.append(Rule(Clause(body, head), declare=allVars))
Beispiel #10
0
def HasBreadthFirstNestedConj(condition):
    from FuXi.DLP import breadth_first
    return HasNestedConjunction(condition) or\
           [i for i in breadth_first(condition)
                if isinstance(i,And) and HasNestedConjunction(i)]