예제 #1
0
    def _get_full_condition(condition_node):
        """
        Extracting the condition associated with an XML specification.

        :param condition_node: the XML node
        :return: the associated condition
        """
        sub_conditions = list()

        for child_node in condition_node:
            if XMLUtils.has_content(child_node):
                sub_condition = XMLRuleReader._get_sub_condition(child_node)
                sub_conditions.append(sub_condition)

        if len(sub_conditions) == 0:
            return VoidCondition()

        operator_str = None
        if 'operator' in condition_node.keys():
            operator_str = condition_node.attrib['operator'].lower().strip()

        if operator_str is not None:
            if operator_str == 'and':
                return ComplexCondition(sub_conditions, BinaryOperator.AND)
            elif operator_str == 'or':
                return ComplexCondition(sub_conditions, BinaryOperator.OR)
            elif operator_str == 'neg' or operator_str == 'not':
                negated_condition = sub_conditions[0] if len(sub_conditions) == 1 else ComplexCondition(sub_conditions, BinaryOperator.AND)
                return NegatedCondition(negated_condition)
            else:
                raise ValueError()

        return sub_conditions[0] if len(sub_conditions) == 1 else ComplexCondition(sub_conditions, BinaryOperator.AND)
예제 #2
0
    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)
예제 #3
0
    def _create_model(node):
        """
        Given an XML node, extracts the rule-based model that corresponds to it.

        :param node: the XML node
        :return: the corresponding model
        """
        model = Model()
        for child in node:
            if child.tag == 'rule':
                rule = XMLRuleReader.get_rule(child)
                model.add_rule(rule)
            elif XMLUtils.has_content(child):
                if child.tag == '#text':
                    raise ValueError()

        if 'trigger' in node.keys():
            trigger_str = node.attrib['trigger']
            matcher_list = re.compile(
                r'([\w\*\^_\-\[\]\{\}]+(?:\([\w\*,\s\^_\-\[\]\{\}]+\))?)[\w\*\^_\-\[\]\{\}]*'
            ).findall(trigger_str)
            for matcher in matcher_list:
                model.add_trigger(matcher)

        if 'blocking' in node.keys():
            if node.attrib['blocking'].lower() == 'true':
                blocking = True
            elif node.attrib['blocking'].lower() == 'false':
                blocking = False
            else:
                raise ValueError()
            model.set_blocking(blocking)

        if 'id' in node.keys():
            model.set_id(node.attrib['id'])

        if 'planning-only' in node.keys():
            model.planning_only = node.attrib['planning-only'].lower(
            ) == 'true'

        return model
예제 #4
0
    def get_rule(node):
        """
        Extracts the rule corresponding to the XML specification.

        :param node: topNode the XML node
        :return: the corresponding rule
        """

        # extracting the rule type
        rule_type = RuleType.PROB
        if 'util=' in XMLUtils.serialize(node):
            rule_type = RuleType.UTIL

        # setting the rule identifier
        try:
            rule_id = node.attrib['id']
        except:
            rule_id = 'rule' + str(XMLRuleReader._id_counter)
            XMLRuleReader._id_counter += 1

        # creating the rule
        rule = Rule(rule_id, rule_type)

        priority = 1
        if 'priority' in node.keys():
            priority = int(node.attrib['priority'])

        # extracting the rule cases
        for child_node in node:
            if child_node.tag == 'case':
                condition = XMLRuleReader._get_condition(child_node)
                output = XMLRuleReader._get_output(child_node, rule_type, priority)
                rule.add_case(condition, output)
            elif XMLUtils.has_content(node):
                if node.tag == '#text':
                    raise ValueError()

        return rule
예제 #5
0
    def extract_partial_domain(main_node, domain, root_path, full_extract):
        """
        Extracts a partially specified domain from the XML node and add its content to
        the dialogue domain.

        :param main_node: main XML node
        :param domain: dialogue domain
        :param root_path: root path (necessary to handle references)
        :param full_extract: whether to extract the full domain or only the files
        :return: the augmented dialogue domain
        """
        tag = main_node.tag

        if tag == 'domain':
            # extracting rule-based probabilistic model
            for child in main_node:
                domain = XMLDomainReader.extract_partial_domain(
                    child, domain, root_path, full_extract)
        elif tag == 'import':
            # extracting imported references
            try:
                file_name = main_node.attrib['href']
                file_path = str(root_path) + os.sep + file_name
                fl = Path(file_path)
                domain.add_imported_files(fl)
                sub_document = XMLUtils.get_xml_document(file_path)
                domain = XMLDomainReader.extract_partial_domain(
                    XMLUtils.get_main_node(sub_document), domain, root_path,
                    full_extract)
            except:
                raise ValueError()

        if not full_extract:
            return domain

        if tag == 'settings':
            # extracting settings
            settings = XMLUtils.extract_mapping(main_node)
            domain.get_settings().fill_settings(settings)
        if tag == 'function':
            # extracting custom functions
            # try:
            domain_function_name = main_node.attrib['name'].strip()

            module_name, actual_function_name = main_node.text.rsplit('.', 1)
            mod = importlib.import_module(module_name)
            func = getattr(mod, actual_function_name)

            domain.get_settings().add_function(domain_function_name, func)
            # except:
            #     raise ValueError()
        if tag == 'initialstate':
            # extracting initial state
            state = XMLStateReader.get_bayesian_network(main_node)
            domain.set_initial_state(DialogueState(state))
        if tag == 'model':
            # extracting rule-based probabilistic model
            model = XMLDomainReader._create_model(main_node)
            domain.add_model(model)
        if tag == 'parameters':
            # extracting parameters
            parameters = XMLStateReader.get_bayesian_network(main_node)
            domain.set_parameters(parameters)
        if XMLUtils.has_content(main_node):
            if main_node == '#text':  # TODO: main_node -> main_node.tag ??
                raise ValueError()

        return domain
예제 #6
0
    def _get_sub_condition(node):
        """
        Extracting a partial condition from a rule specification

        :param node: the XML node
        :return: the corresponding condition
        """
        # extracting a basic condition
        if node.tag == 'if':
            if 'var' not in node.keys():
                raise ValueError()

            variable_name = node.attrib['var']
            template = Template.create(variable_name)

            if template.is_under_specified():
                template = Template.create(str(template).replace('*', '{' + str(random.randint(1, 99)) + '}'))

            value_str = None
            if 'value' in node.keys():
                value_str = node.attrib['value']

            if value_str is not None:
                relation = XMLRuleReader._get_relation(node)
                condition = BasicCondition(variable_name, value_str, relation)
            else:
                if 'var2' not in node.keys():
                    raise ValueError()

                second_variable = node.attrib['var2']
                relation = XMLRuleReader._get_relation(node)
                condition = BasicCondition(variable_name, '{' + second_variable + '}', relation)

            for attrib_key in node.attrib.keys():
                if attrib_key not in ['var', 'var2', 'value', 'relation']:
                    raise ValueError()

            return condition

        # extracting a conjunction or disjunction
        if node.tag == 'or' or node.tag == 'and':
            conditions = list()

            for child_node in node:
                if XMLUtils.has_content(child_node):
                    conditions.append(XMLRuleReader._get_sub_condition(child_node))

            return ComplexCondition(conditions, BinaryOperator.OR if node.tag == 'or' else BinaryOperator.AND)

        # extracting a negated conjunction
        if node.tag == 'neg' or node.tag == 'not':
            conditions = list()

            for child_node in node:
                if XMLUtils.has_content(child_node):
                    conditions.append(XMLRuleReader._get_sub_condition(child_node))

            return conditions[0] if len(conditions) == 1 else ComplexCondition(conditions, BinaryOperator.AND)

        if XMLUtils.has_content(node):
            raise ValueError()

        return VoidCondition()