Exemplo n.º 1
0
    class Test(KnowledgeEngine):
        @Rule(InitialFact())
        def rule1(self):
            pass

        @Rule(InitialFact())
        def rule2(self):
            pass
Exemplo n.º 2
0
def _(exp):
    dnf_rule = dnf(exp)
    prep_rule = dnf_rule.new_conditions(*[prepare_rule(e) for e in dnf_rule])
    if not prep_rule:
        return prep_rule.new_conditions(InitialFact())
    elif isinstance(prep_rule[0], NOT) or len(extract_facts(prep_rule)) == 0:
        return prep_rule.new_conditions(InitialFact(), *prep_rule)
    else:
        return dnf(prep_rule)
Exemplo n.º 3
0
 def __init__(self, *conds, salience=0):
     if not conds:
         conds = (InitialFact(), )
     self.__fn = None
     self._conds = conds
     self.salience = salience
     RULE_WATCHER.debug("Initialized rule with conds %s", conds)
Exemplo n.º 4
0
def _(exp):
    or_exp = []
    for e in exp:
        if isinstance(e, NOT):
            or_exp.append(AND(InitialFact(), e))
        elif isinstance(e, AND):
            or_exp.append(prepare_rule(e))
        else:
            or_exp.append(e)
    return OR(*or_exp)
Exemplo n.º 5
0
def test_Rule_with_only_one_NOT_match_InitialFact_if_fact_is_not_present():
    from pyknow.rule import NOT, Rule
    from pyknow.factlist import FactList
    from pyknow.fact import Fact, InitialFact, L
    from pyknow.match import Capturation

    r = Rule(NOT(Fact(something=L(True))))
    fl = FactList()
    fl.declare(InitialFact())

    assert next(r.get_activations(fl, Capturation()), None) is not None
Exemplo n.º 6
0
def test_Rule_empty_matches_with_initial_fact():
    from pyknow.rule import Rule
    from pyknow.factlist import FactList
    from pyknow.fact import InitialFact
    from pyknow.activation import Activation
    from pyknow.match import Capturation

    r = Rule()
    fl = FactList()
    fl.declare(InitialFact())
    assert Activation(None,
                      (0, )) in list(r.get_activations(fl, Capturation()))
Exemplo n.º 7
0
    def reset(self):
        """
        Performs a reset as per CLIPS behaviour (resets the
        agenda and factlist and declares InitialFact())

        .. note:: If persistent facts have been added, they'll be
                  re-declared.
        """

        self.agenda = Agenda()
        self.facts = FactList()
        self.__declare(InitialFact())
        self.load_initial_facts()
        self.strategy.update_agenda(self.agenda, self.get_activations())
Exemplo n.º 8
0
def test_Rule_and_NOT_nesting():
    from pyknow.rule import Rule, NOT
    from pyknow.factlist import FactList
    from pyknow.fact import Fact, InitialFact, L

    r = Rule(Fact(a=L(1)), NOT(Fact(b=L(2))))
    fl = FactList()
    fl.declare(InitialFact())
    fl.declare(Fact(a=L(1)))

    activations = list(r.get_activations(fl))
    assert len(activations) == 1

    assert {0, 1} == set(activations[0].facts)
Exemplo n.º 9
0
def test_rule_with_NOT_testce():
    from pyknow.rule import Rule, NOT
    from pyknow.factlist import FactList
    from pyknow.fact import Fact, InitialFact, L, T

    r = Rule(Fact(a=L(1)), NOT(Fact(b=T(lambda c, x: x.startswith('D')))))

    fl = FactList()
    fl.declare(InitialFact())
    fl.declare(Fact(a=L(1)))

    activations = r.get_activations(fl)
    assert len(list(activations)) == 1

    fl.declare(Fact(b=L('David')))
    activations = r.get_activations(fl)
    assert len(list(activations)) == 0

    fl = FactList()
    fl.declare(InitialFact())
    fl.declare(Fact(a=L(1)))
    fl.declare(Fact(b=L('Penelope')))
    activations = r.get_activations(fl)
    assert len(list(activations)) == 1
Exemplo n.º 10
0
    def _(elem):
        # Create new nodes
        condition_node = _wire_rule(elem[0])
        initial_fact_node = _wire_rule(InitialFact())
        not_node_1 = NotNode(SameContextCheck())
        not_node_2 = NotNode(SameContextCheck())

        # NotNode1
        condition_node.add_child(not_node_1, not_node_1.activate_right)
        initial_fact_node.add_child(not_node_1, not_node_1.activate_left)

        # NotNode2
        initial_fact_node.add_child(not_node_2, not_node_2.activate_left)
        not_node_1.add_child(not_node_2, not_node_2.activate_right)

        return not_node_2
Exemplo n.º 11
0
def test_Rule_with_NOT_DEFINED():
    from pyknow.rule import Rule, NOT
    from pyknow.factlist import FactList
    from pyknow.fact import Fact, InitialFact, L, W

    r = Rule(Fact(a=L(1)), NOT(Fact(b=W(True))))

    fl = FactList()
    fl.declare(InitialFact())
    fl.declare(Fact(a=L(1)))

    activations = r.get_activations(fl)
    assert len(list(activations)) == 1

    fl.declare(Fact(b=L('SOMETHING')))
    activations = r.get_activations(fl)
    assert len(list(activations)) == 0
Exemplo n.º 12
0
    def _(elem):
        leader = elem[0]
        followers = elem[1:]

        initial_fact_node = _wire_rule(InitialFact())
        leader_node = _wire_rule(leader)
        followers_node = _wire_rule(AND(*followers))
        not_node_1 = NotNode(SameContextCheck())
        not_node_2 = NotNode(SameContextCheck())

        # NotNode1
        followers_node.add_child(not_node_1, not_node_1.activate_right)
        leader_node.add_child(not_node_1, not_node_1.activate_left)

        # NotNode2
        not_node_1.add_child(not_node_2, not_node_2.activate_right)
        initial_fact_node.add_child(not_node_2, not_node_2.activate_left)

        return not_node_2
Exemplo n.º 13
0
def _(exp):
    if isinstance(exp[0], NOT):
        return AND(InitialFact(), *exp)
    else:
        return exp
Exemplo n.º 14
0
 def _declare_initial_fact(self):
     yield InitialFact()
Exemplo n.º 15
0
    def build_alpha_part(ruleset, root_node):
        """
        Given a set of already adapted rules, build the alpha part of
        the RETE network starting at `root_node`.

        """
        # Adds a dummy rule with InitialFact as LHS for always generate
        # the alpha part matching InitialFact(). This is needed for the
        # CE using InitialFact
        ruleset = ruleset.copy()
        ruleset.add(Rule(InitialFact()))

        # Generate a dictionary with rules and the set of facts of the
        # rule.
        rule_facts = {rule: extract_facts(rule) for rule in ruleset}

        # For each fact build a list of checker function capable of
        # check for each part in the fact.
        fact_checks = {
            fact: set(generate_checks(fact))
            for fact in chain.from_iterable(rule_facts.values())
        }

        # Make a ranking of the most used checks
        check_rank = Counter(chain.from_iterable(fact_checks.values()))

        def weighted_check_sort(check):
            """Sort check by its type and number of times seen."""
            if isinstance(check, TypeCheck):
                return (float('inf'), hash(check))
            elif isinstance(check, FactCapture):
                return (float('-inf'), hash(check))
            elif isinstance(check, FeatureCheck):
                return (check_rank[check], hash(check))
            else:
                raise TypeError("Unknown check type.")  # pragma: no cover

        def weighted_rule_sort(rule):
            """Sort rules by the average weight of its checks."""
            total = 0
            for fact in rule_facts[rule]:
                for check in fact_checks[fact]:
                    total += check_rank[check]
            return total / len(rule_facts[rule])

        sorted_rules = sorted(ruleset, key=weighted_rule_sort, reverse=True)

        fact_terminal_nodes = dict()
        # For rule in rank order and for each rule fact also in rank
        # order, build the alpha brank looking for an existing node
        # first.
        for rule in sorted_rules:
            for fact in rule_facts[rule]:
                current_node = root_node
                fact_sorted_checks = sorted(fact_checks[fact],
                                            key=weighted_check_sort,
                                            reverse=True)

                for check in fact_sorted_checks:
                    # Look for a child node with the given check in the
                    # current parent node.
                    for child in current_node.children:
                        if child.node.matcher is check:
                            current_node = child.node
                            break
                    else:
                        # Create a new node and append as child
                        new_node = FeatureTesterNode(check)
                        current_node.add_child(new_node, new_node.activate)
                        current_node = new_node

                fact_terminal_nodes[fact] = current_node

        # Return this dictionary containing the last alpha node for each
        # fact.
        return fact_terminal_nodes