예제 #1
0
파일: engine.py 프로젝트: fly2mars/TO
    def reset(self, **kwargs):
        """
        Performs a reset as per CLIPS behaviour (resets the
        agenda and factlist and declares InitialFact())

        Any keyword argument passed to `reset` will be passed to @DefFacts
        which have those arguments on their signature.

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

        self.agenda = Agenda()
        self.facts = FactList()

        self.matcher.reset()

        deffacts = []
        for deffact in self.get_deffacts():
            signature = inspect.signature(deffact)
            if not any(p.kind == inspect.Parameter.VAR_KEYWORD
                       for p in signature.parameters.values()):
                # There is not **kwargs defined. Pass only the defined
                # names.
                args = set(signature.parameters.keys())
                deffacts.append(
                    deffact(**{k: v
                               for k, v in kwargs.items() if k in args}))
            else:
                deffacts.append(deffact(**kwargs))

        # Declare all facts yielded by deffacts
        self.__declare(*chain.from_iterable(deffacts))

        self.running = False
def test_factlist_declare_raises_valueError():
    """ declare raises valueerror if not ``Fact`` object providen """

    from pyknow.factlist import FactList
    import pytest

    with pytest.raises(ValueError):
        FactList().declare("Foo")
예제 #3
0
def test_Rule_empty_doesnt_match_empty_factlist():
    from pyknow.rule import Rule
    from pyknow.factlist import FactList

    r = Rule()
    fl = FactList()

    assert tuple(r.get_activations(fl)) == tuple()
예제 #4
0
 def __init__(self):
     self.context = Context()
     self._fixed_facts = []
     self.facts = FactList()
     self.running = False
     self.agenda = Agenda()
     self.strategy = self.__strategy__()
     self._parent = False
     self.shared_attributes = {}
def test_factlist_declare():
    """ Test declare method adds to factlist and updates index """
    from pyknow.factlist import FactList
    from pyknow import Fact
    flist = FactList()
    assert getattr(flist, "last_index") == 0
    assert not flist
    flist.declare(Fact())
    assert getattr(flist, "last_index") == 1
    assert isinstance(flist[0], Fact)
예제 #6
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
예제 #7
0
def test_facts_produce_activations_without_capturation():
    """
    A fact produces activations if no capturations are provided
    """
    from pyknow.fact import Fact, L
    from pyknow.factlist import FactList
    from pyknow.match import Capturation

    flist = FactList()
    flist.declare(Fact(a=L(1)))
    caps = list(Fact(a=L(1)).get_activations(flist, Capturation()))
    assert len(caps) == 1
def test_factlist_raises_valueerror_on_invalid_fact():
    from pyknow.factlist import FactList
    from pyknow import Fact, Field

    class MockFact(Fact):
        must_be_string = Field(str, mandatory=True)

    flist = FactList()
    f0 = MockFact(must_be_string=0)

    with pytest.raises(ValueError):
        flist.declare(f0)
예제 #9
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()))
def test_factlist_retract():
    """ Test retract method """

    from pyknow.factlist import FactList
    from pyknow import Fact
    flist = FactList()
    assert getattr(flist, "last_index") == 0
    assert not flist
    flist.declare(Fact())
    assert getattr(flist, "last_index") == 1
    assert isinstance(flist[0], Fact)
    assert flist.retract(0) == 0
    assert not flist
예제 #11
0
def test_Rule_multiple_criteria_generates_activation_with_matching_facts():
    from pyknow.rule import Rule
    from pyknow.factlist import FactList
    from pyknow.fact import Fact, L

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

    activations = list(r.get_activations(fl))
    assert len(activations) == 1
    assert {0, 1} == set(activations[0].facts)
예제 #12
0
def test_factlist_retract_matching():
    """ Test retract_matching 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_matching(Fact()) == [0]
    assert not flist.facts
예제 #13
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())
예제 #14
0
def test_Rule_and_AND_nesting():
    from pyknow.rule import Rule, AND
    from pyknow.factlist import FactList
    from pyknow.fact import Fact, L

    r = Rule(AND(Fact(a=L(2)), Fact(b=L(1))))

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

    activations = list(r.get_activations(fl))
    assert len(activations) == 1
    assert {0, 1} == set(activations[0].facts)
예제 #15
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
예제 #16
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,)
예제 #17
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)
def test_factlist_changes():
    """ Test factlist changes """

    from pyknow.factlist import FactList
    from pyknow import Fact

    flist = FactList()

    f0 = flist.declare(Fact(a=1))
    assert flist.changes[0] == [f0]

    f1 = flist.declare(Fact(b=1))
    assert flist.changes[0] == [f1]

    flist.retract(f1)
    assert flist.changes[1] == [f1]
예제 #19
0
파일: engine.py 프로젝트: fly2mars/TO
    def __init__(self):
        self.running = False
        self.facts = FactList()
        self.agenda = Agenda()

        if (isinstance(self.__matcher__, type)
                and issubclass(self.__matcher__, abstract.Matcher)):
            self.matcher = self.__matcher__(self)
        else:
            raise TypeError("__matcher__ must be a subclass of Matcher")

        if (isinstance(self.__strategy__, type)
                and issubclass(self.__strategy__, abstract.Strategy)):
            self.strategy = self.__strategy__()
        else:
            raise TypeError("__strategy__ must be a subclass of Strategy")
예제 #20
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
예제 #21
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
def test_DepthStrategy_update_agenda_asertion_order_affects_agenda_order_3():
    """

    From Clips docs on Depth Strategy::

      Newly activated rules are placed above all rules of the same salience.
      For example, given that facta activates rule1 and rule2 and factb
      activates rule3 and rule4, then if facta is asserted before factb, rule3
      and rule4 will be above rule1 and rule2 on the agenda. However, the
      position of rule1 relative to rule2 and rule3 relative to rule4 will be
      arbitrary.

    """
    from pyknow.strategies import DepthStrategy
    from pyknow.activation import Activation
    from pyknow import Rule
    from pyknow.agenda import Agenda
    from pyknow import Fact
    from pyknow.factlist import FactList

    fl = FactList()

    f1 = Fact(1)
    fl.declare(f1)

    f2 = Fact(2)
    fl.declare(f2)

    act1 = Activation(rule=Rule(), facts=(f1, ))
    act2 = Activation(rule=Rule(), facts=(f1, ))
    act3 = Activation(rule=Rule(), facts=(f2, ))
    act4 = Activation(rule=Rule(), facts=(f2, ))

    a = Agenda()

    st = DepthStrategy()

    st.update_agenda(a, [act1, act2, act3, act4], [])
    order = list(a.activations)

    assert (order.index(act4) > order.index(act1)
            and order.index(act4) > order.index(act2))
    assert (order.index(act3) > order.index(act1)
            and order.index(act3) > order.index(act2))
예제 #23
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.matcher.reset()

        # Declare all deffacts
        for deffact in self.get_deffacts():
            for fact in deffact():
                self.__declare(fact)

        self.running = False
예제 #24
0
def test_DepthStrategy_update_agenda_different_salience():
    from random import shuffle

    from pyknow.strategies import DepthStrategy
    from pyknow.activation import Activation
    from pyknow import Rule
    from pyknow import Fact
    from pyknow.agenda import Agenda
    from pyknow.factlist import FactList

    flist = FactList()

    f1 = Fact(1)
    flist.declare(f1)

    f2 = Fact(2)
    flist.declare(f2)

    f3 = Fact(3)
    flist.declare(f3)

    f4 = Fact(4)
    flist.declare(f4)

    act1 = Activation(rule=Rule(salience=1), facts=(f1, ))
    act2 = Activation(rule=Rule(salience=2), facts=(f2, ))
    act3 = Activation(rule=Rule(salience=3), facts=(f3, ))
    act4 = Activation(rule=Rule(salience=4), facts=(f4, ))

    acts = [act1, act2, act3, act4]
    shuffle(acts)

    st = DepthStrategy()
    a = Agenda()

    for act in acts:
        st.update_agenda(a, acts, [])

    order = list(a.activations)
    assert (order.index(act4) < order.index(act3) < order.index(act2) <
            order.index(act1))
예제 #25
0
def test_DepthStrategy_update_agenda_assertion_order_affects_agenda_order_1():
    from pyknow.strategies import DepthStrategy
    from pyknow.activation import Activation
    from pyknow import Rule
    from pyknow.agenda import Agenda
    from pyknow import Fact
    from pyknow.factlist import FactList

    fl = FactList()

    f1 = Fact(1)
    fl.declare(f1)

    f2 = Fact(2)
    fl.declare(f2)

    f3 = Fact(3)
    fl.declare(f3)

    f4 = Fact(4)
    fl.declare(f4)

    act1 = Activation(rule=Rule(), facts=(f1, ))
    act2 = Activation(rule=Rule(), facts=(f2, ))
    first = [act1, act2]

    act3 = Activation(rule=Rule(), facts=(f3, ))
    act4 = Activation(rule=Rule(), facts=(f4, ))
    second = [act3, act4]

    a = Agenda()

    st = DepthStrategy()

    oldact = a.activations
    st.update_agenda(a, first, [])
    assert list(a.activations) == list(reversed(first))

    st.update_agenda(a, second, first)
    assert list(a.activations) == list(reversed(second))
예제 #26
0
def test_DepthStrategy_update_agenda_activations_to_agenda():
    from pyknow.strategies import DepthStrategy
    from pyknow.activation import Activation
    from pyknow import Rule
    from pyknow.agenda import Agenda
    from pyknow import Fact
    from pyknow.factlist import FactList

    fl = FactList()
    f1 = Fact(1)
    fl.declare(f1)
    f2 = Fact(2)
    fl.declare(f2)

    act1 = Activation(rule=Rule(), facts=(f1, ))
    act2 = Activation(rule=Rule(), facts=(f2, ))

    a = Agenda()

    st = DepthStrategy()
    st.update_agenda(a, [act1, act2], [])

    assert act1 in a.activations
    assert act2 in a.activations
예제 #27
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)
예제 #28
0
def test_factlist_facts_are_ordereddict():
    """ Fact list on FactList object is an OrderedDict """

    from pyknow.factlist import FactList
    from collections import OrderedDict
    assert isinstance(getattr(FactList(), "facts"), OrderedDict)
예제 #29
0
def test_factlist_has_facts():
    """ Factlist object has a fact list """
    from pyknow.factlist import FactList
    assert hasattr(FactList(), "facts")
def test_factlist_facts_idx_starts_zero():
    """ Factlist idx starts at zero """

    from pyknow.factlist import FactList
    assert getattr(FactList(), "last_index") == 0