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
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()
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)
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)
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")
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)
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)
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)