예제 #1
0
    class Parent(KnowledgeEngine):
        @Rule(Fact(initial=L(True)))
        def shouldnot_run(self):
            # pytest.set_trace()
            print("Ran")
            executions.append(4)

        @Rule(Fact(inherited=L(True)))
        def inherited(self):
            executions.append(2)

        @Rule(NOT(Fact(not_inherited=L(True))))
        def not_inherited(self):
            executions.append(3)
예제 #2
0
    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')
예제 #3
0
def test_facts_produce_activations_that_are_Activations():
    """
    A fact produces activations that are Activation objects
    """
    from pyknow.fact import Fact, L
    from pyknow.factlist import FactList
    from pyknow.match import Capturation
    from pyknow.activation import Activation

    flist = FactList()
    flist.declare(Fact(a=L(1)))
    caps = list(Fact(a=L(1)).get_activations(flist, Capturation()))
    assert len(caps) == 1
    assert isinstance(caps[0], Activation)
    assert caps[0].facts == (0,)
예제 #4
0
def test_tree_NOT():
    """
        Test tree not
    """

    from pyknow.tree import KETree
    from pyknow.engine import KnowledgeEngine
    from pyknow.rule import Rule, NOT
    from pyknow.fact import Fact, L

    executions = []
    global executions

    class Child(KnowledgeEngine):
        @Rule(Fact(always_run=L(True)))
        def always_run(self):
            executions.append(1)
            self.parent.declare(Fact(inherited=L(True)))

    class Parent(KnowledgeEngine):
        @Rule(Fact(inherited=L(True)))
        def inherited(self):
            executions.append(2)

        @Rule(NOT(Fact(not_inherited=L(True))))
        def not_inherited(self):
            executions.append(3)

    tree_ = {
        'node':
        Parent(),
        'children': [{
            'node': Child(),
            'children': []
        }, {
            'node': Child(),
            'children': []
        }]
    }

    tree_['children'][0]['node'].deffacts(Fact(always_run=L(True)))

    # Parent does not inherit its children facts:
    tree_['children'][0]['node'].deffacts(Fact(not_inherited=L(True)))

    KETree(tree_).run_sequential()
    print(executions)
    assert len(executions) == 3
예제 #5
0
def test_ke_inheritance():
    from pyknow.rule import Rule
    from pyknow.fact import Fact, L
    from pyknow.engine import KnowledgeEngine

    executed = False

    class Person(Fact):
        pass

    class Base(KnowledgeEngine):
        @Rule(Person(name=L('pepe')))
        def is_pepe(self):
            self.declare(Person(drinks=L("coffee")))

    class Test(Base):
        @Rule(Person(drinks=L("coffee")))
        def drinks_coffee(self):
            nonlocal executed
            executed = True

    ke_ = Test()
    ke_.deffacts(Person(name=L('pepe')))
    ke_.reset()
    ke_.run()

    assert executed
예제 #6
0
def test_rules_are_executed_once(to_declare_random):
    from random import shuffle
    from pyknow.engine import KnowledgeEngine
    from pyknow.rule import Rule
    from pyknow.fact import Fact, L

    executions = []

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

        @Rule(Fact(something=L(3)))
        def rule2(self):
            nonlocal executions
            executions.append('rule2')

    ke = Test()

    to_declare = list(set(to_declare_random + [1, 2, 3]))
    shuffle(to_declare)
    print(to_declare)

    for i in to_declare:
        ke.deffacts(Fact(something=L(i)))

    ke.reset()
    ke.run()

    assert executions.count('rule1') == 1
    assert executions.count('rule2') == 1
예제 #7
0
def test_Rule_simple_testce():
    from pyknow.rule import Rule
    from pyknow.fact import Fact, T, L
    from pyknow.factlist import FactList

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

    fl = FactList()
    fl.declare(Fact(a=L("David")))
    fl.declare(Fact(a=L("Penelope")))

    activations = list(r.get_activations(fl))

    assert len(activations) == 1

    assert {0} == set(activations[0].facts)
예제 #8
0
def test_nested_declarations():
    from pyknow.rule import Rule
    from pyknow.fact import Fact, L
    from pyknow.engine import KnowledgeEngine

    class Person(Fact):
        pass

    executed = False

    class Person_KE(KnowledgeEngine):
        @Rule(Person(name=L("David")))
        def david(self):
            self.declare(Person(name=L("Pepe")))

        @Rule(Person(name=L("Pepe")))
        def pepe(self):
            nonlocal executed
            executed = True

    ke_ = Person_KE()
    ke_.deffacts(Person(name=L("David")))
    ke_.reset()
    ke_.run()
    assert executed
예제 #9
0
def test_matching_different_number_of_arguments():
    from pyknow.rule import Rule
    from pyknow.fact import Fact, L
    from pyknow.engine import KnowledgeEngine

    class Person(Fact):
        pass

    executed = False

    class Person_KE(KnowledgeEngine):
        @Rule(Person(name=L("David")))
        def david(self):
            self.declare(Person(name=L("Pepe"), apellido=L("stuff")))

        @Rule(Person(name=L("Pepe")))
        def pepe(self):
            nonlocal executed
            executed = True

    ke_ = Person_KE()
    ke_.deffacts(Person(name=L("David")))
    ke_.reset()
    ke_.run()
    assert executed
예제 #10
0
def test_or_notmatching_operator():
    """
        Test OR operator
    """
    from pyknow.engine import KnowledgeEngine
    from pyknow.rule import Rule, OR
    from pyknow.fact import Fact, L

    class Test(KnowledgeEngine):
        """ Test KE """
        @Rule(OR(Fact(something=L(1)),
              Fact(something=L(2))))
        def rule1(self):
            """ First rule, something=1 and something=2"""
            pass

    static = ((1, 3), (1, 3, 5))
    for test in static:
        ke_ = Test()
        ke_.reset()
        for val in test:
            ke_.deffacts(Fact(none=L(val)))
        ke_.reset()
        assert len(ke_.agenda.activations) == 0

    ke_.run()
예제 #11
0
def test_V_resolve():
    """ Test V Resolve """
    from pyknow.fact import Fact, V, L
    key = "key_test"
    context = {key: True}
    not_fact = V(key)
    against_fact = Fact(**{key: L(True)})
    assert not_fact.resolve(against_fact, key, context)
예제 #12
0
def test_N_resolve():
    """ Test N Resolve """
    from pyknow.fact import Fact, N, L
    key = "key_test"
    context = {key: True}
    not_fact = N(key)
    against_fact = Fact(**{key: L(False)})
    assert not_fact.resolve(against_fact, key, context)
예제 #13
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
예제 #14
0
def test_Rule_with_empty_Fact_matches_all_Facts():
    from pyknow.rule import Rule
    from pyknow.factlist import FactList
    from pyknow.fact import Fact, L
    from pyknow.activation import Activation

    r = Rule(Fact())
    fl = FactList()

    fl.declare(Fact(something=L(True)))
    fl.declare(Fact(something=L(False)))
    fl.declare(Fact(something=L(3)))

    activations = list(r.get_activations(fl))
    assert len(activations) == 3
    for i in range(3):
        assert Activation(None, (i, )) in activations
예제 #15
0
def test_match_with_W_True(kwargs):
    assume('something' not in kwargs)

    from pyknow.fact import Fact, W, L

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

    assert f1.matches(f0, {})
예제 #16
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
예제 #17
0
def test_matching_captured_different_facts_AND():
    from pyknow.rule import Rule
    from pyknow.fact import Fact, L, V, C
    from pyknow.engine import KnowledgeEngine

    class Person(Fact):
        pass

    executions = []

    class Person_KE(KnowledgeEngine):
        @Rule(Person(name=C("name")), Person(surname=V('name')))
        def same_name(self, name):
            nonlocal executions
            executions.append(name)

    ke_ = Person_KE()
    ke_.deffacts(Person(surname=L('surname'), name=L("NotAName")))
    ke_.deffacts(Person(name=L('name'), surname=L("NotAName")))
    ke_.reset()
    ke_.run()
    assert executions == ["NotAName"]
예제 #18
0
def test_and_N_negative():
    from pyknow.rule import Rule
    from pyknow.fact import Fact, L, N, C
    from pyknow.engine import KnowledgeEngine

    class Person(Fact):
        pass

    executions = []

    class Person_KE(KnowledgeEngine):
        @Rule(Person(name=L("name"), age=C('age')),
              Person(name=L("name"), age=N("age")))
        def same_name(self, age):
            nonlocal executions
            executions.append(age)

    ke_ = Person_KE()
    ke_.deffacts(Person(name=L("name"), age=L(18)))
    ke_.deffacts(Person(name=L('name'), age=L(18)))
    ke_.reset()
    ke_.run()
    assert executions == []
예제 #19
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
예제 #20
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
예제 #21
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
예제 #22
0
 class Base(KnowledgeEngine):
     @Rule(Person(name=L('pepe')))
     def is_pepe(self):
         self.declare(Person(drinks=L("coffee")))
예제 #23
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)
예제 #24
0
def test_not_aggreation():
    from pyknow.rule import Rule, NOT, AND
    from pyknow.fact import Fact, L, N, C
    from pyknow.engine import KnowledgeEngine

    class Person(Fact):
        pass

    class ConflictResolver(Fact):
        pass

    executions = []

    class Person_KE(KnowledgeEngine):
        @Rule(NOT(ConflictResolver(resolved=L(True))),
              AND(Person(name=L("name"), age=C('age')),
                  Person(name=L("name"), age=N("age"))))
        def same_name(self, age):
            nonlocal executions
            executions.append(age)

    ke_ = Person_KE()
    ke_.deffacts(Person(name=L("name"), age=L(18)))
    ke_.deffacts(Person(name=L('name'), age=L(19)))
    ke_.deffacts(ConflictResolver(resolved=L(True)))
    ke_.reset()
    ke_.run()
    assert executions == []

    executions = []

    ke_ = Person_KE()
    ke_.deffacts(Person(name=L("name"), age=L(18)))
    ke_.deffacts(Person(name=L('name'), age=L(19)))
    ke_.reset()
    ke_.run()
    assert executions == [19]
    executions = []

    ke_ = Person_KE()
    ke_.deffacts(Person(name=L("name"), age=L(18)))
    ke_.deffacts(Person(name=L('name'), age=L(18)))
    ke_.reset()
    ke_.run()
    assert executions == []

    ke_ = Person_KE()
    ke_.deffacts(Person(name=L("name"), age=L(18)))
    ke_.deffacts(Person(name=L('name'), age=L(18)))
    ke_.deffacts(ConflictResolver(resolved=L(True)))
    ke_.reset()
    ke_.run()
    assert executions == []
예제 #25
0
 class Person_KE(KnowledgeEngine):
     @Rule(Person(name=L("name"), age=C('age')),
           Person(name=L("name"), age=N("age")))
     def same_name(self, age):
         nonlocal executions
         executions.append(age)
예제 #26
0
 def david(self):
     self.declare(Person(name=L("Pepe"), apellido=L("stuff")))
예제 #27
0
 def david(self):
     self.declare(Person(name=L("Pepe")))
예제 #28
0
 class Test(Base):
     @Rule(Person(drinks=L("coffee")))
     def drinks_coffee(self):
         nonlocal executed
         executed = True
예제 #29
0
 def is_pepe(self):
     self.declare(Person(drinks=L("coffee")))
예제 #30
0
 class Test(KnowledgeEngine):
     # pylint: disable=too-few-public-methods
     @Rule(Fact(a=L(1)))
     def test(self):
         # pylint: disable=no-self-use
         pass