示例#1
0
    def test_call_returns_empty_numdict_when_no_rules_exist(self):

        rules = Rules(max_conds=1)

        inputs = {
            chunks(1):
            nd.NumDict(
                {
                    chunk("Condition A"): .7,
                    chunk("Condition B"): .2,
                    chunk("Condition C"): .6,
                    chunk("Condition D"): .5,
                    chunk("Condition E"): .3
                },
                default=0)
        }

        action_rules = ActionRules(
            source=chunks(1),
            rules=rules,
            temperature=1  # high temperature to ensure variety
        )
        strengths = action_rules.call(inputs)

        self.assertEqual(len(strengths), 0, msg="Unexpected items in output.")
示例#2
0
    def test_rule_selection_follows_boltzmann_distribution(self):

        rules = Rules(max_conds=1)
        rules.define(rule("A"), chunk("Action 1"), chunk("Condition A"))
        rules.define(rule("B"), chunk("Action 1"), chunk("Condition B"))
        rules.define(rule("C"), chunk("Action 1"), chunk("Condition C"))
        rules.define(rule("D"), chunk("Action 2"), chunk("Condition D"))
        rules.define(rule("E"), chunk("Action 2"), chunk("Condition E"))

        inputs = {
            chunks(1):
            nd.NumDict(
                {
                    chunk("Condition A"): .7,
                    chunk("Condition B"): .2,
                    chunk("Condition C"): .6,
                    chunk("Condition D"): .5,
                    chunk("Condition E"): .3
                },
                default=0)
        }

        get_rule = lambda c: rule(c.cid[-1])

        action_rules = ActionRules(
            source=chunks(1),
            rules=rules,
            temperature=.1  # relatively high temperature to ensure variety
        )

        expected = nd.transform_keys(inputs[chunks(1)], func=get_rule)
        expected = nd.boltzmann(expected, t=.1)
        expected = nd.with_default(expected, default=None)

        N = 100

        selected = []
        is_rule = lambda sym: sym.ctype in ConstructType.rule
        for _ in range(N):
            strengths = action_rules.call(inputs)
            s = nd.keep(strengths, func=is_rule)
            s = nd.threshold(s, th=0)
            s = s.constant(val=1)
            s = nd.with_default(s, default=0)
            selected.append(s)

        counts = nd.ew_sum(*selected)
        terms = ((counts - (N * expected))**2) / (N * expected)
        chi_square_stat = nd.val_sum(terms)
        critical_value = 9.488  # for chi square w/ 4 df @ alpha = .05

        self.assertFalse(critical_value < chi_square_stat,
                         msg="Chi square test significant at alpha = .05.")
示例#3
0
    def test_call_activates_unique_action_and_rule_pair(self):

        rules = Rules(max_conds=1)
        rules.define(rule("A"), chunk("Action 1"), chunk("Condition A"))
        rules.define(rule("B"), chunk("Action 1"), chunk("Condition B"))
        rules.define(rule("C"), chunk("Action 1"), chunk("Condition C"))
        rules.define(rule("D"), chunk("Action 2"), chunk("Condition D"))
        rules.define(rule("E"), chunk("Action 2"), chunk("Condition E"))

        inputs = {
            chunks(1):
            nd.NumDict(
                {
                    chunk("Condition A"): .7,
                    chunk("Condition B"): .2,
                    chunk("Condition C"): .6,
                    chunk("Condition D"): .5,
                    chunk("Condition E"): .3
                },
                default=0)
        }

        action_rules = ActionRules(
            source=chunks(1),
            rules=rules,
            temperature=1  # high temperature to ensure variety
        )
        strengths = action_rules.call(inputs)
        above_zero = nd.threshold(strengths, th=0.0)

        self.assertEqual(
            len(above_zero),
            2,
            msg="Expected at most two items above zero activation.")
        if chunk("Action 1") in above_zero:
            self.assertTrue(rule("A") in above_zero or rule("B") in above_zero
                            or rule("C") in above_zero,
                            msg="Unexpected rule paired with Action 1.")
        if chunk("Action 2") in above_zero:
            self.assertTrue(rule("D") in above_zero or rule("E") in above_zero,
                            msg="Unexpected rule paired with Action 2.")
示例#4
0
                                         interface=alice.assets.wm_interface))

        # This terminus controls the agent's speech actions.

        Construct(name=terminus("speech"),
                  process=ActionSelector(
                      source=features("main"),
                      temperature=.01,
                      interface=alice.assets.speech_interface))

    nacs = Structure(name=subsystem("nacs"), assets=Assets(chunks=nacs_cdb))

    with nacs:

        Construct(
            name=chunks("in"),
            process=MaxNodes(
                sources=[buffer("stimulus"), buffer("wm")]))

        Construct(name=flow_tb("main"),
                  process=TopDown(source=chunks("in"),
                                  chunks=nacs.assets.chunks))

        Construct(
            name=features("main"),
            process=MaxNodes(
                sources=[buffer("stimulus"),
                         buffer("wm"),
                         flow_tb("main")]))

        Construct(name=flow_bt("main"),
示例#5
0
    nacs = Structure(name=subsystem("nacs"), assets=Assets(chunk_db=chunk_db))

    with nacs:

        # Although the entry point for the NACS are chunks, in this example we
        # start with features as there are no constructs that initially
        # activate chunks in the NACS activation cycle.

        Construct(name=features("main"),
                  process=MaxNodes(sources=[buffer("stimulus")]))

        Construct(name=flow_bt("main"),
                  process=BottomUp(source=features("main"),
                                   chunks=nacs.assets.chunk_db))

        Construct(name=chunks("main"),
                  process=MaxNodes(sources=[flow_bt("main")]))

        # Termini

        # In addition to introducting chunk extraction, this example
        # demonstrates the use of two temrmini in one single subsytem. We
        # include one terminus for the output of the top level and one for the
        # bottom level.

        # The top level terminus is basically the same as the one used in the
        # free association example. It randomly selects a chunk through a
        # competitive process which involves sampling chunks from a boltzmann
        # distribution constructed from their respective strength values. This
        # terminus is relevant for the quizzing/querying section of the
        # simulation.
示例#6
0
    with nacs:

        # The first instance of gating in this example is on the stimulus. We
        # do not gate the stimulus buffer. Instead, we create a flow_in
        # construct, which repeats the output of the stimulus buffer, and we
        # gate that. This allows us to gate the stimulus buffer in the NACS
        # independently from other subsystems. To implement the gate, we
        # initialize a `Gated` object which wraps the activation repeater.

        Construct(name=flow_in("stimulus"),
                  process=Gated(base=Repeater(source=buffer("stimulus")),
                                controller=buffer("gate"),
                                interface=gate_interface,
                                pidx=0))

        Construct(name=chunks("in"),
                  process=MaxNodes(sources=[flow_in("stimulus")]))

        Construct(name=flow_tb("main"),
                  process=TopDown(source=chunks("in"), chunks=nacs.assets.cdb))

        Construct(name=features("main"),
                  process=MaxNodes(sources=[flow_tb("main")]))

        Construct(name=flow_tt("associations"),
                  process=Gated(base=AssociativeRules(
                      source=chunks("in"), rules=nacs.assets.rule_db),
                                controller=buffer("gate"),
                                interface=gate_interface,
                                pidx=1))
示例#7
0
        # chunk and feature pools are used. These pools handle computing the 
        # strengths of chunk and feature nodes in bulk.

        # This design offers a number of advantages: it is flexible (we do not 
        # need to explicitly declare new chunk or feature nodes to the system), 
        # efficient (all chunk and feature node activations are computed by one 
        # single object in one pass), simple (it reduces bookeeping requirements
        # when adding and removing nodes) and more intelligible (nodes do not 
        # cause clutter in large models). 

        # One downside to this approach is that we have to be careful about 
        # tracking the feature domain. This is why it is good to define the 
        # (initial) feature domain explicitly prior to agent assembly. 

        Construct(
            name=chunks("in"),
            process=MaxNodes(sources=[buffer("stimulus")])
        )

        # Next up is a top-down activation flow, where activations flow from 
        # chunk nodes to linked feature nodes.

        Construct(
            name=flow_tb("main"), 
            process=TopDown(
                source=chunks("in"),
                chunks=nacs.assets.cdb
            ) 
        )

        # In this simulation, because there are no bottom-level flows (i.e.,