def test_state_copy(self):
        system = DialogueSystem(TestDialogueState.domain)
        system.detach_module(ForwardPlanner)
        StatePruner.enable_reduction = False

        system.get_settings().show_gui = False
        system.start_system()

        initial_state = copy(system.get_state())

        rule_id = ""
        for id in system.get_state().get_node("u_u2").get_output_node_ids():
            if str(system.get_content(id)).find("+=HowAreYou") != -1:
                rule_id = id

        TestDialogueState.inference.check_prob(
            initial_state, rule_id, Effect.parse_effect("a_u2+=HowAreYou"),
            0.9)
        TestDialogueState.inference.check_prob(initial_state, rule_id,
                                               Effect.parse_effect("Void"),
                                               0.1)

        TestDialogueState.inference.check_prob(initial_state, "a_u2",
                                               "[HowAreYou]", 0.2)
        TestDialogueState.inference.check_prob(initial_state, "a_u2",
                                               "[Greet, HowAreYou]", 0.7)
        TestDialogueState.inference.check_prob(initial_state, "a_u2", "[]",
                                               0.1)

        StatePruner.enable_reduction = True
Exemple #2
0
    def get_prob_distrib(self, condition):
        """
        Fills the cache with the resulting table for the given condition

        :param condition: the condition for which to fill the cache
        """
        builder = CategoricalTableBuilder(self._base_var + self._primes)

        full_effects = list()
        for inputVal in condition.get_values():
            if isinstance(inputVal, Effect):
                full_effects.extend(inputVal.get_sub_effects())

        full_effect = Effect(full_effects)
        values = full_effect.get_values(self._base_var)
        if full_effect.is_non_exclusive(self._base_var):
            add_val = ValueFactory.create(list(values.keys()))
            builder.add_row(add_val, 1.0)
        elif len(values) > 0:
            total = 0.0
            for f in values.values():
                total += float(f)
            for v in values.keys():
                builder.add_row(v, values[v] / total)
        else:
            builder.add_row(ValueFactory.none(), 1.0)

        return builder.build()
Exemple #3
0
    def test_param_4(self):
        system = DialogueSystem(TestParameters.domain1)
        system.detach_module(ForwardPlanner)
        system.get_settings().show_gui = False
        system.start_system()

        rules = TestParameters.domain1.get_models()[1].get_rules()
        outputs = rules[0].get_output(Assignment("u_u", "my name is"))
        o = Effect(BasicEffect("u_u^p", "Pierre"))
        assert isinstance(outputs.get_parameter(o), SingleParameter)
        input = Assignment("theta_5", ValueFactory.create("[0.36, 0.24, 0.40]"))
        assert outputs.get_parameter(o).get_value(input) == pytest.approx(0.36, abs=0.01)

        system.get_state().remove_nodes(system.get_state().get_action_node_ids())
        system.get_state().remove_nodes(system.get_state().get_utility_node_ids())
        system.add_content("u_u", "my name is")

        system.get_state().remove_nodes(system.get_state().get_action_node_ids())
        system.get_state().remove_nodes(system.get_state().get_utility_node_ids())
        system.add_content("u_u", "Pierre")

        system.get_state().remove_nodes(system.get_state().get_action_node_ids())
        system.get_state().remove_nodes(system.get_state().get_utility_node_ids())
        system.add_content("u_u", "my name is")

        system.get_state().remove_nodes(system.get_state().get_action_node_ids())
        system.get_state().remove_nodes(system.get_state().get_utility_node_ids())
        system.add_content("u_u", "Pierre")

        assert system.get_state().query_prob("theta_5").to_continuous().get_function().get_mean()[0] == pytest.approx(0.3, abs=0.12)
Exemple #4
0
    def is_void(self):
        """
        Returns true if the case is void (empty or with a single void effect)

        :return: true if void, false otherwise
        """
        return (not self._effects) or (self._rule_type == RuleType.PROB
                                       and len(self._effects) == 1
                                       and Effect() in self._effects)
Exemple #5
0
    def test_outputs(self):
        effects = []

        assert Effect(effects) == Effect.parse_effect("Void")
        effects.append(BasicEffect("v1", "val1"))
        assert Effect(effects) == Effect.parse_effect("v1:=val1")

        effects.append(BasicEffect("v2", ValueFactory.create("val2"), 1, False, False))
        assert Effect(effects) == Effect.parse_effect("v1:=val1 ^ v2+=val2")

        effects.append(BasicEffect("v2", ValueFactory.create("val3"), 1, True, True))
        assert Effect(effects) == Effect.parse_effect("v1:=val1 ^ v2+=val2 ^ v2!=val3")
Exemple #6
0
    def add_void_effect(self):
        """
        Adds a void effect to the rule if the fixed mass is lower than 1.0 and a void
        effect is not already defined.
        """
        # case 1: if there are no effects, insert a void one with prob.1
        if len(self._effects) == 0:
            self.add_effect(Effect(), FixedParameter(1.0))
            return

        fixed_mass = 0
        for effect in self._effects.keys():
            # case 2: if there is already a void effect, do nothing
            if len(effect) == 0:
                return

            # sum up the fixed probability mass
            a_param = self._effects[effect]
            if isinstance(a_param, FixedParameter):
                fixed_mass += a_param.get_value()

        # case 3: if the fixed probability mass is = 1, do nothing
        if fixed_mass > 0.99:
            return

        # case 4: if the fixed probability mass is < 1, fill the remaining mass
        elif fixed_mass > 0.0:
            self.add_effect(Effect(), FixedParameter(1 - fixed_mass))

        # case 5: in case the rule output is structured via single or complex
        # parameters p1, p2,... pn, create a new complex effect = 1 - (p1+p2+...pn)
        # that fill the remaining probability mass
        else:
            params = []
            for value in self._effects.values():
                params.append(MathExpression(value.get_expression()))
            one = MathExpression("1")
            negation = one.combine('-', params)
            self.add_effect(Effect(), ComplexParameter(negation))
    def _get_full_effect(effect_node, priority):
        """
        Extracts a full effect from the XML specification.

        :param effect_node: the XML node
        :param priority: the rule priority
        :return: the corresponding effect
        """
        effects = list()

        for child_node in effect_node:
            if XMLUtils.has_content(child_node) and len(child_node.attrib) > 0:
                sub_effect = XMLRuleReader._get_sub_effect(child_node, priority)
                effects.append(sub_effect)

        return Effect(effects)
Exemple #8
0
    def add_output(self, new_case):
        """
        Adds a rule output to the current one. The result is a joint probability
        distribution in the output of a probability rule, and an addition of utility
        tables in the case of a utility rule.

        :param new_case: the new rule case to add
        """
        if self.is_void():
            self._effects = new_case._effects

        elif new_case.is_void() or hash(frozenset(
                self._effects.items())) == hash(
                    frozenset(new_case._effects.items())):
            return

        elif self._rule_type == RuleType.PROB:
            new_output = dict()

            for effect_1 in self._effects.keys():
                param_1 = self._effects[effect_1]

                for effect_2 in new_case.get_effects():
                    param_2 = new_case.get_parameter(effect_2)
                    new_effect = Effect([effect_1, effect_2])
                    new_param = RuleOutput.merge_parameters(
                        param_1, param_2, '*')

                    if new_effect in new_output:
                        new_param = RuleOutput.merge_parameters(
                            new_output[new_effect], new_param, '+')

                    new_output[new_effect] = new_param

            self._effects = new_output
            new_case.prune_effects()

        elif self._rule_type == RuleType.UTIL:
            for effect in new_case.get_effects():
                # TODO: Original code seems strange. a_param is not needed here.
                # a_param = new_case.get_parameter(effect)
                # if effect in self.effects:
                #    a_param = RuleOutput.merge_parameters(self.effects[effect], a_param, '+')
                self._effects[effect] = new_case.get_parameter(effect)
Exemple #9
0
    def test_param_5(self):
        system = DialogueSystem(TestParameters.domain2)
        system.detach_module(ForwardPlanner)
        system.get_settings().show_gui = False
        system.start_system()

        rules = TestParameters.domain2.get_models()[0].get_rules()
        outputs = rules[0].get_output(Assignment("u_u", "brilliant"))
        o = Effect(BasicEffect("a_u", "approval"))
        assert isinstance(outputs.get_parameter(o), ComplexParameter)
        input = Assignment([Assignment("theta_6", 2.1), Assignment("theta_7", 1.3)])
        assert outputs.get_parameter(o).get_value(input) == pytest.approx(0.74, abs=0.01)

        system.get_state().remove_nodes(system.get_state().get_action_node_ids())
        system.get_state().remove_nodes(system.get_state().get_utility_node_ids())
        system.add_content("u_u", "brilliant")

        assert system.get_state().query_prob("theta_6").to_continuous().get_function().get_mean()[0] == pytest.approx(1.0, abs=0.08)

        assert system.get_content("a_u").get_prob("approval") == pytest.approx(0.63, abs=0.08)
        assert system.get_content("a_u").get_prob("irony") == pytest.approx(0.3, abs=0.08)