def test_conflictsetchange_valid_adds_to_memory():
    from pyknow.fact import Fact
    from pyknow.matchers.rete.nodes import ConflictSetNode
    from pyknow.matchers.rete.token import Token, TokenInfo
    from pyknow.rule import Rule

    csn = ConflictSetNode(Rule())

    f = Fact(test='data')
    f.__factid__ = 1

    csn.activate(Token.valid(f, {'mycontextdata': 'data'}))

    assert TokenInfo([f], {'mycontextdata': 'data'}) in csn.memory
Exemple #2
0
def test_notnode_left_activate_valid_non_matching(TestNode):
    from pyknow.matchers.rete.nodes import NotNode
    from pyknow.matchers.rete.token import Token
    from pyknow.fact import Fact

    nn = NotNode(lambda l, r: False)
    nn.right_memory.append(Token.valid(Fact(test='data1')).to_info())
    nn.right_memory.append(Token.valid(Fact(test='data2')).to_info())

    tn1 = TestNode()
    tn2 = TestNode()

    nn.add_child(tn1, tn1.activate)
    nn.add_child(tn2, tn2.activate)

    token = Token.valid(Fact(test='data'))
    nn.activate_left(token)

    assert tn1.added == [token]
    assert tn2.added == [token]
    assert nn.left_memory[token.to_info()] == 0
Exemple #3
0
def test_notnode_right_activate_valid_match_just_one(TestNode):
    from pyknow.matchers.rete.nodes import NotNode
    from pyknow.matchers.rete.token import Token
    from pyknow.fact import Fact

    nn = NotNode(lambda l, r: True)
    tn1 = TestNode()
    tn2 = TestNode()

    nn.add_child(tn1, tn1.activate)
    nn.add_child(tn2, tn2.activate)

    token = Token.valid(Fact(test='data'))

    nn.left_memory[token.to_info()] = 0

    nn.activate_right(token)

    assert Token.invalid(Fact(test='data')) in tn1.added
    assert Token.invalid(Fact(test='data')) in tn2.added
    assert nn.left_memory[token.to_info()] == 1
Exemple #4
0
def test_token_initialization_types():
    """
    Token.tag must be a Tag
    Token.data can be:
        - A Fact
        - An interable of Facts

    """
    from pyknow.matchers.rete.token import Token
    from pyknow.fact import Fact

    with pytest.raises(TypeError):
        Token(None, Fact())

    with pytest.raises(TypeError):
        Token(Token.TagType.VALID, None)

    with pytest.raises(TypeError):
        Token(Token.TagType.VALID, [Fact(), None])

    with pytest.raises(TypeError):
        Token(Token.TagType.VALID, [Fact()], [])

    # THIS MUST NOT RAISE
    Token(Token.TagType.VALID, Fact(), {})
    Token(Token.TagType.VALID, [Fact(), Fact()], {})
Exemple #5
0
def test_conflictsetchange_get_activations_data():
    from pyknow.matchers.rete.nodes import ConflictSetNode
    from pyknow.matchers.rete.token import Token
    from pyknow.rule import Rule
    from pyknow.fact import Fact

    rule = Rule()
    csn = ConflictSetNode(rule)

    f = Fact(first=1)
    f.__factid__ = 1

    csn.activate(Token.valid(f, {'data': 'test'}))

    added, removed = csn.get_activations()

    assert len(added) == 1
    assert len(removed) == 0

    assert list(added)[0].rule is rule
    assert f in list(added)[0].facts
    assert list(added)[0].context == {'data': 'test'}
Exemple #6
0
def test_factlist_retract():
    """ Test retract method """

    from pyknow.factlist import FactList
    from pyknow.fact import Fact
    flist = FactList()
    assert getattr(flist, "_fidx") == 0
    assert not flist.facts
    flist.declare(Fact())
    assert getattr(flist, "_fidx") == 1
    assert isinstance(flist.facts[0], Fact)
    assert flist.retract(0) == 0
    assert not flist.facts
Exemple #7
0
def test_ordinarymatchnode_left_activate_invalid_remove_from_left_memory():
    from pyknow.matchers.rete.nodes import OrdinaryMatchNode
    from pyknow.matchers.rete.token import Token
    from pyknow.fact import Fact

    omn = OrdinaryMatchNode(lambda l, r: True)

    fact = Fact(test='data')
    token = Token.valid(fact)
    omn.left_memory.append(token.to_info())

    omn.activate_left(Token.invalid(fact))

    assert not omn.left_memory
Exemple #8
0
def test_default_is_and():
    """
        Test that AND is the default operator
    """
    from collections import defaultdict
    from pyknow.engine import KnowledgeEngine
    from pyknow.rule import Rule
    from pyknow.fact import Fact, L

    executions = []

    class Test(KnowledgeEngine):
        """ Test KE """
        @Rule(Fact(something=L(1)),
              Fact(something=L(2)))
        def rule1(self):
            """ First rule, something=1 and something=2"""
            nonlocal executions
            executions.append('rule1')

        @Rule(Fact(something=L(3)))
        def rule2(self):
            """ Second rule, only something=3 """
            nonlocal executions
            executions.append('rule2')

    ke_ = Test()

    to_declare = []

    for i in range(1, 10):
        to_declare.append(L(i))

    to_declare = dict(enumerate(to_declare))

    for k, n in to_declare.items():
        ke_.deffacts(Fact(something=n))

    ke_.reset()
    results = defaultdict(list)
    for activation in ke_.agenda.activations:
        results[''.join([str(to_declare[a - 1].resolve())
                         for a in activation.facts])].append(1)

    assert dict(results) == {'3': [1], '12': [1]}
    assert len(ke_.agenda.activations) == 2
    ke_.run()

    assert executions.count('rule1') == 1
    assert executions.count('rule2') == 1
Exemple #9
0
def test_featuretesternode_pass_fact_to_matcher():
    from pyknow.matchers.rete.nodes import FeatureTesterNode
    from pyknow.matchers.rete.token import Token
    from pyknow.fact import Fact

    fact = Fact(this_is_my_fact=True)

    def _matcher(f):
        nonlocal fact
        assert f is fact

    ftn = FeatureTesterNode(_matcher)

    ftn.activate(Token.valid(fact))
Exemple #10
0
def test_ordinarymatchnode_left_activate_valid_store_in_left_memory():
    from pyknow.matchers.rete.nodes import OrdinaryMatchNode
    from pyknow.matchers.rete.token import Token, TokenInfo
    from pyknow.fact import Fact

    omn = OrdinaryMatchNode(lambda l, r: True)

    assert not omn.left_memory

    fact = Fact(test='data')
    token = Token.valid(fact)
    omn.activate_left(token)

    assert TokenInfo({fact}, {}) in omn.left_memory
Exemple #11
0
def test_match_if_all_defined_is_present(kwargs):
    from pyknow.fact import Fact, L
    kwargs['ATLEAST1'] = 'VALUE'
    kwsuperset = kwargs.copy()
    kwsuperset.update({'OTHER1': 'VALUE'})

    f0 = Fact(**{a: L(b) for a, b in kwargs.items()})
    f1 = Fact(**{a: L(b) for a, b in kwsuperset.items()})

    assert not f1.matches(f0, {})
    assert f0.matches(f1, {})
Exemple #12
0
def test_KnowledgeEngine_get_activations_returns_activations():
    from pyknow.engine import KnowledgeEngine
    from pyknow.rule import Rule
    from pyknow.fact import Fact, L

    class Test(KnowledgeEngine):
        # pylint: disable=too-few-public-methods
        @Rule(Fact(a=L(1)))
        def test(self):
            # pylint: disable=no-self-use
            pass

    ke = Test()
    ke.deffacts(Fact(a=L(1)))
    ke.reset()
    activations = list(ke.get_activations())
    assert len(activations) == 1
Exemple #13
0
def test_featuretesternode_pass_when_callable_fail(TestNode):
    from pyknow.matchers.rete.nodes import FeatureTesterNode
    from pyknow.matchers.rete.token import Token
    from pyknow.fact import Fact

    ftn = FeatureTesterNode(lambda f: False)
    tn1 = TestNode()
    tn2 = TestNode()

    token = Token.valid(Fact(test=True))

    ftn.add_child(tn1, tn1.activate)
    ftn.add_child(tn2, tn2.activate)

    ftn.activate(token)

    assert tn1.added == tn2.added == []
Exemple #14
0
def test_featuretesternode_pass_when_callable_modify_context(TestNode):
    from pyknow.matchers.rete.nodes import FeatureTesterNode
    from pyknow.matchers.rete.token import Token
    from pyknow.fact import Fact

    ftn = FeatureTesterNode(lambda f: {'something': True})
    tn1 = TestNode()
    tn2 = TestNode()

    token = Token.valid(Fact(test=True), {'something': False})

    ftn.add_child(tn1, tn1.activate)
    ftn.add_child(tn2, tn2.activate)

    ftn.activate(token)

    newtoken = token.copy()
    newtoken.context['something'] = True

    assert tn1.added == tn2.added == []
Exemple #15
0
def test_token_initialization_conversions():
    """
    Token.data is modified in this way:
        - If is a Fact: Converted to a Set containing this Fact.
        - An interable of Facts: Converter to a set of Facts.

    """
    from pyknow.matchers.rete.token import Token
    from pyknow.fact import Fact

    t1 = Token(Token.TagType.VALID, Fact())
    assert t1.data == {Fact()}

    t2 = Token(Token.TagType.VALID, [Fact(a=1), Fact(b=2)])
    assert t2.data == {Fact(a=1), Fact(b=2)}
Exemple #16
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
Exemple #17
0
 class Child(KnowledgeEngine):
     @Rule(Fact(always_run=L(True)))
     def always_run(self):
         executions.append(1)
         self.parent.retract_matching(Fact(initial=L(True)))
         self.parent.declare(Fact(inherited=L(True)))
Exemple #18
0
def test_T_resolve():
    """ Test T Resolve """
    from pyknow.fact import Fact, T, L
    assert T(lambda c, x: x).resolve(Fact(foo=L("foo")), "foo", {}) == "foo"
Exemple #19
0
 class Test(KnowledgeEngine):
     # pylint: disable=too-few-public-methods
     @Rule(Fact(a=L(1)))
     def test(self):
         # pylint: disable=no-self-use
         pass
def test_fact_freeze_mutable_values():
    f = Fact([1, 2, 3])
    assert f[0] == (1, 2, 3)
Exemple #21
0
def test_empty_fact_match_all(kwargs):
    """ Empty fact matches against all. InitialFact should be this case """
    from pyknow.fact import Fact, L
    fact = Fact(**{a: L(b) for a, b in kwargs.items()})
    assert Fact().matches(fact, {})
def test_fact_setitem_does_not_raise_before_declare():
    f = Fact()
    f[0] = 1

    assert f[0] == 1
Exemple #23
0
def test_ordinarymatchnode_left_activate_invalid_build_new_tokens(TestNode):
    from pyknow.matchers.rete.nodes import OrdinaryMatchNode
    from pyknow.matchers.rete.token import Token
    from pyknow.fact import Fact

    omn = OrdinaryMatchNode(lambda l, r: True)
    tn1 = TestNode()
    tn2 = TestNode()
    omn.add_child(tn1, tn1.activate)
    omn.add_child(tn2, tn2.activate)

    rt1 = Token.valid(Fact(rightdata='rightdata1'))
    rt2 = Token.valid(Fact(rightdata='rightdata2'))
    omn.right_memory.append(rt1.to_info())
    omn.right_memory.append(rt2.to_info())

    token = Token.invalid(Fact(leftdata='leftdata'))
    omn.activate_left(token)

    assert tn1.added == [Token.invalid([Fact(leftdata='leftdata'),
                                        Fact(rightdata='rightdata1')]),
                         Token.invalid([Fact(leftdata='leftdata'),
                                        Fact(rightdata='rightdata2')])]

    assert tn2.added == [Token.invalid([Fact(leftdata='leftdata'),
                                        Fact(rightdata='rightdata1')]),
                         Token.invalid([Fact(leftdata='leftdata'),
                                        Fact(rightdata='rightdata2')])]
Exemple #24
0
 def always_run(self):
     executions.append(1)
     self.parent.declare(Fact(inherited=L(True)))
Exemple #25
0
def test_Rule_nesting_issubclass():
    """
        This actually tests that nesting a Rule is permitted.
        Rule nesting can be useful for meta-stuff, and
    """
    from pyknow.rule import Rule
    from pyknow.factlist import FactList
    from pyknow.fact import Fact, L

    r1 = Rule(Fact(a=L(1)), Fact(b=L(2)), Fact(c=L(3)))
    r2 = Rule(Fact(a=L(1)), Rule(Fact(b=L(2)), Fact(c=L(3))))
    r3 = Rule(Fact(a=L(1)), Rule(Fact(b=L(2)), Rule(Fact(c=L(3)))))
    r4 = Rule(Rule(Fact(a=L(1))), Rule(Fact(b=L(2))), Rule(Fact(c=L(3))))
    r5 = Rule(Rule(Fact(a=L(1)), Fact(b=L(2)), Fact(c=L(3))))

    fl = FactList()
    fl.declare(Fact(a=L(1)))
    fl.declare(Fact(b=L(2)))
    fl.declare(Fact(c=L(3)))

    for r in (r1, r2, r3, r4, r5):
        activations = list(r.get_activations(fl))
        assert len(activations) == 1
        assert {0, 1, 2} == set(activations[0].facts)
Exemple #26
0
 def always_run(self):
     executions.append(1)
     self.parent.retract_matching(Fact(initial=L(True)))
     self.parent.declare(Fact(inherited=L(True)))