예제 #1
0
    def query_prob(self, query):
        """
        Queries the probability distribution encoded in the Bayesian Network, given a
        set of query variables, and some evidence.

        :param query: the full query result
        :return: the corresponding multivariate table failed
        """
        network = query.get_network()
        query_vars = set(query.get_query_vars())
        evidence = query.get_evidence()

        full_joint = NaiveInference.get_full_joint(network, False)

        # TODO: Do I have to use TreeMap(Java) like data-structure? ... OrderedDict is not same with TreeMap
        query_values = OrderedDict()
        for node in network.get_chance_nodes():
            if node.get_id() in query_vars:
                query_values[node.get_id()] = node.get_values()

        query_assignments = InferenceUtils.get_all_combinations(query_values)

        query_result = MultivariateTableBuilder()

        for query_assignment in query_assignments:
            sum = 0.
            for assignment in full_joint.keys():
                if assignment.contains(
                        query_assignment) and assignment.contains(evidence):
                    sum += full_joint[assignment]

            query_result.add_row(query_assignment, sum)

        query_result.normalize()
        return query_result.build()
예제 #2
0
    def get_ranking(self, input, min_diff):
        """
        Returns the ranking of the given input sorted by utility

        :param input: the input to rank
        :param min_diff: the minimum difference between utilities
        :return: the rank of the given assignment in the utility table
        """
        return InferenceUtils.get_ranking(self.get_table(), input, min_diff)
예제 #3
0
    def get_n_best(self, n_best):
        """
        Creates a table with a subset of the utility values, namely the N-best highest ones.

        :param n_best: the number of values to keep in the filtered table
        :return: the table of values, of size nbest
        """
        filtered_table = InferenceUtils.get_n_best(self.get_table(), n_best)
        return UtilityTable(filtered_table)
예제 #4
0
    def get_n_best(self, n_best):
        """
        Returns a subset of the N values in the table with the highest probability.

        :param n_best: the number of values to select
        :return: the distribution with the subset of values
        """

        return MultivariateTable(
            self._head_vars, InferenceUtils.get_n_best(self._table, n_best))
예제 #5
0
    def __str__(self):
        """
        Returns a string representation for the distribution

        :return: the string representation for the table.
        """
        sorted_table = InferenceUtils.get_n_best(self.get_table(),
                                                 len(self._table))

        result = []
        for key, value in sorted_table.items():
            result.append('U(%s):=%f\n' % (str(key), value))

        return ''.join(result)[:-1] if len(result) > 0 else ''
예제 #6
0
    def __str__(self):
        """
        Returns a string representation of the probability table

        :return: the string representation
        """
        sorted_table = InferenceUtils.get_n_best(self._table,
                                                 max(len(self._table), 1))

        result = []
        for key, value in sorted_table.items():
            result.append('P(%s):=%f\n' % (str(key), value))

        return ''.join(result)[:-1] if len(result) > 0 else ''
예제 #7
0
    def prune_values(self, threshold):
        """
        Prunes all table values that have a probability lower than the threshold.

        :param threshold: the threshold
        :return: true if at least one value has been pruned, false otherwise
        """

        new_table = dict()
        changed = False
        for key in self._table.keys():
            prob = self._table[key]
            if prob >= threshold:
                new_table[key] = prob
            else:
                changed = True

        if changed:
            InferenceUtils.normalize(new_table)
            self._table = new_table

        self._intervals = None
        return changed
예제 #8
0
    def __str__(self):
        """
        Returns a string representation of the probability table

        :return: the string representation
        """
        sorted_table = InferenceUtils.get_n_best(self._table,
                                                 max(len(self._table), 1))

        result = ''
        for key, value in sorted_table.items():
            result += 'P(%s=%s):=%f\n' % (self._variable, key, value)

        return result[:-1] if len(result) > 0 else result
예제 #9
0
    def linearize(self):
        """
        Extracts all alternative assignments of values for the variables in the range.
        This operation can be computational expensive, use with caution.

        :return: the set of alternative assignments
        """
        if len(self._range) == 1:
            item_key = list(self._range.keys())[0]
            result = set()
            for item_value in self._range[item_key]:
                result.add(Assignment(item_key, item_value))
            return result

        return InferenceUtils.get_all_combinations(self._range)
예제 #10
0
    def get_n_best(self, n_best):
        """
        Returns a subset of the N values in the table with the highest probability.

        :param n_best: the number of values to select
        :return: the distribution with the subset of values
        """
        n_table = InferenceUtils.get_n_best(self._table, n_best)

        from bn.distribs.distribution_builder import CategoricalTableBuilder
        builder = CategoricalTableBuilder(self._variable)
        for v in n_table.keys():
            builder.add_row(v, n_table[v])

        return builder.build().to_discrete()
예제 #11
0
    def query_util(self, query):
        """
        Computes the utility distribution for the Bayesian network, depending on the
        value of the action variables given as parameters.

        :param query: the full query
        :return: the corresponding utility table
        """
        network = query.get_network()
        query_vars = set(query.get_query_vars())
        evidence = query.get_evidence()

        full_joint = NaiveInference.get_full_joint(network, True)

        # TODO: Do I have to use TreeMap(Java) like data-structure? ... OrderedDict is not same with TreeMap
        action_values = OrderedDict()
        for node in network.get_nodes():
            if node.get_id() in query_vars:
                action_values[node.get_id()] = node.get_values()

        action_assignments = InferenceUtils.get_all_combinations(action_values)
        table = UtilityTable()

        for action_assignment in action_assignments:
            total_utility = 0.
            total_prob = 0.

            for joint_assignment in full_joint.keys():
                if not joint_assignment.contains(evidence):
                    continue

                total_utility_for_assignment = 0.
                state_and_action_assignment = Assignment(
                    [joint_assignment, action_assignment])

                for value_node in network.get_utility_nodes():
                    utility = value_node.get_utility(
                        state_and_action_assignment)
                    total_utility_for_assignment += utility

                total_utility += (total_utility_for_assignment *
                                  full_joint.get(joint_assignment))
                total_prob += full_joint.get(joint_assignment)

            table.set_util(action_assignment, total_utility / total_prob)

        return table
예제 #12
0
    def reduce(self, query):
        """
        Reduces the Bayesian network to a subset of its variables. This reduction
        operates here by generating the possible conditional assignments for every
        retained variables, and calculating the distribution for each assignment.

        :param query: the reduction query
        :return: the reduced network
        """
        network = query.get_network()
        query_vars = set(query.get_query_vars())
        evidence = query.get_evidence()

        original_sorted_node_ids = network.get_sorted_node_ids()
        sorted_node_ids = list()
        for node_id in original_sorted_node_ids:
            if node_id in query_vars:
                sorted_node_ids.append(node_id)

        sorted_node_ids = list(reversed(sorted_node_ids))
        reduced_network = BNetwork()
        for variable_id in sorted_node_ids:
            direct_ancestors = network.get_node(variable_id).get_ancestor_ids(
                query_vars)

            input_values = dict()
            for direct_ancestor in direct_ancestors:
                input_values[direct_ancestor] = network.get_node(
                    variable_id).get_values()

            assignments = InferenceUtils.get_all_combinations(input_values)

            builder = ConditionalTableBuilder(variable_id)
            for assignment in assignments:
                new_evidence = Assignment([evidence, assignment])
                result = self.query_prob(network, variable_id, new_evidence)
                builder.add_rows(assignment, result.get_table())

            chance_node = ChanceNode(variable_id, builder.build())
            for ancestor in direct_ancestors:
                chance_node.add_input_node(reduced_network.get_node(ancestor))

            reduced_network.add_node(chance_node)

        return reduced_network
예제 #13
0
    def generate_xml(self):
        """
        Generates the XML representation for the table, for the document doc.

        :param doc: the XML document for which to generate the XML.
        :return: XML reprensetation
        """
        var = Element("variable")
        var.set("id", self._variable.replace("'", ""))
        for v in InferenceUtils.get_n_best(self._table,
                                           len(self._table)).keys():
            if v != ValueFactory.none():
                value_node = Element("value")
                if self._table[v] < 0.99:
                    value_node.set("prob",
                                   StringUtils.get_short_form(self._table[v]))
                value_node.text = str(v)
                var.append(value_node)

        return var
예제 #14
0
    def get_values_linearise(self):
        """
        Calculates the possible values for the output distribution via linearisation
        (more costly operation, but necessary in case of add effects).

        :return: the set of possible output values
        """
        table = dict()
        for i in range(len(self._input_rules)):
            table[str(i)] = self._input_rules[i].get_effects()

        combinations = InferenceUtils.get_all_combinations(table)

        values = set()
        for cond in combinations:
            values.update(self.get_prob_distrib(cond).get_values())

        if len(values) == 0:
            values.add(ValueFactory.none())

        return values
예제 #15
0
    def get_full_joint(network, include_actions):
        """
        Computes the full joint probability distribution for the Bayesian Network

        :param network: the Bayesian network
        :param include_actions: whether to include action nodes or not
        :return: the resulting joint distribution
        """
        # TODO: Do I have to use TreeMap(Java) like data-structure? ... OrderedDict is not same with TreeMap
        all_values = OrderedDict()
        for chance_node in network.get_chance_nodes():
            all_values[chance_node.get_id()] = chance_node.get_values()

        if include_actions:
            for action_node in network.get_action_nodes():
                all_values[action_node.get_id()] = action_node.get_values()

        full_assignments = InferenceUtils.get_all_combinations(all_values)
        result = dict()
        for assignment in full_assignments:
            joint_log_prob = 0.
            for chance_node in network.get_chance_nodes():
                trimmed_condition = assignment.get_trimmed(
                    chance_node.get_input_node_ids())
                joint_log_prob += math.log10(
                    chance_node.get_prob(
                        trimmed_condition,
                        assignment.get_value(chance_node.get_id())))

            if include_actions:
                for action_node in network.get_action_nodes():
                    joint_log_prob += math.log10(
                        action_node.get_prob(
                            assignment.get_value(action_node.get_id())))

            result[assignment] = pow(10, joint_log_prob)

        return result