Пример #1
0
 def sample_global(self, global_state, variable, allowed_values):
     '''
     This method can be used to sample from the density according to a global
     state containing values for all other variables that this node belongs to.
     @param global_state: A Dict (node -> value) that must hold a value for
         all variables that this density depends on. Except for the variable
         that it is directly associated with.
     @param variable: The variable that this density is directly associated
         with.
     @param allowed_values: A list of values that are allowed to be sampled.
         This is necessary because external evidence may restrict the value
         range.
     @returns: The sampled value.
     '''
     node_value_pairs=[(node,global_state[node]) for node in self.variables if node != variable]
     probabilities=[self.get_probability(node_value_pairs+[(variable,value)]) for value in allowed_values]
     idx=weighted_random(probabilities)
     return allowed_values[idx]
Пример #2
0
def weighted_sample(network, evidence = {}):
    '''
    Each nonevidence variable is sampled according to the conditional
    distribution given the values already sampled for the variable's parents,
    while a weight isaccumulated based on the likelihood for each evidence
    variable.

    See "Artificial Intelligence: A Modern Approach (Third edition)" by
    Stuart Russell and Peter Norvig (p. 534)

    Keyword arguments:
    network -- a Bayesian network
    evidence -- a dict of observed values

    Returns a new sample as tuple of state and weight (state, w).
    '''
    w = 1.0
    state = {}
    if not isinstance(network, primo.networks.BayesianNetwork):
        raise Exception("The given network is not an instance of BayesNet.")

    nodes = network.get_nodes_in_topological_sort()
    for node in nodes:
        #reduce this node's cpd
        parents = network.get_parents(node)
        if parents:
            evidence_tmp = [(parent, state[parent]) for parent in parents]
            reduced_cpd = node.get_cpd_reduced(evidence_tmp)
        else:
            reduced_cpd = node.get_cpd()

        # (re-)calulate weight
        if node in evidence:
            w *= reduced_cpd.get_table()[node.get_value_range().index(evidence[node])]
            state[node] = node.get_value_range().index(evidence[node])
        else:
            # sample state
            new_state = weighted_random(reduced_cpd.get_table())
            state[node] = node.get_value_range()[new_state]

    return (state, w)
Пример #3
0
def weighted_sample(network, evidence = {}):
    '''
    Each nonevidence variable is sampled according to the conditional
    distribution given the values already sampled for the variable's parents,
    while a weight isaccumulated based on the likelihood for each evidence
    variable.

    See "Artificial Intelligence: A Modern Approach (Third edition)" by
    Stuart Russell and Peter Norvig (p. 534)

    Keyword arguments:
    network -- a Bayesian network
    evidence -- a dict of observed values

    Returns a new sample as tuple of state and weight (state, w).
    '''
    w = 1.0
    state = {}
    if not isinstance(network, primo.networks.BayesianNetwork):
        raise Exception("The given network is not an instance of BayesNet.")

    nodes = network.get_nodes_in_topological_sort()
    for node in nodes:
        #reduce this node's cpd
        parents = network.get_parents(node)
        if parents:
            evidence_tmp = [(parent, state[parent]) for parent in parents]
            reduced_cpd = node.get_cpd_reduced(evidence_tmp)
        else:
            reduced_cpd = node.get_cpd()

        # (re-)calulate weight
        if node in evidence:
            w *= reduced_cpd.get_table()[node.get_value_range().index(evidence[node])]
            state[node] = node.get_value_range().index(evidence[node])
        else:
            # sample state
            new_state = weighted_random(reduced_cpd.get_table())
            state[node] = node.get_value_range()[new_state]

    return (state, w)
Пример #4
0
    def transition(self, network, state, extern_evidence):
        '''
        Does one single state transition.
        @param network: A BayesNet.
        @param state: The current state of the BayesNet. Given as a Dict from
            RandomNode to Value
        @param extern_evidence: Evidence that is given by the user. This is a
            Dict from Node to Evidence.
        '''
        nodes = network.get_nodes([])
        nodes_to_resample = [
            n for n in nodes if not n in extern_evidence.keys()
            or extern_evidence[n].get_unique_value() == None
        ]

        for node in nodes_to_resample:
            parents = network.get_parents(node)
            if parents:
                evidence = [(parent, state[parent]) for parent in parents]
                reduced_cpd = node.get_cpd_reduced(evidence)
            else:
                reduced_cpd = node.get_cpd()

            #reduce the children's cpds
            children = network.get_children(node)
            for child in children:

                #reduce this node's cpd
                parents = network.get_parents(child)
                evidence = [(parent, state[parent]) for parent in parents
                            if parent != node]
                evidence.append((child, state[child]))
                reduced_child_cpd = child.get_cpd_reduced(evidence)

                reduced_cpd = reduced_cpd.multiplication(reduced_child_cpd)

            new_state = weighted_random(reduced_cpd.get_table())
            state[node] = node.get_value_range()[new_state]

        return state
Пример #5
0
 def sample_global(self, global_state, variable, allowed_values):
     '''
     This method can be used to sample from the density according to a global
     state containing values for all other variables that this node belongs to.
     @param global_state: A Dict (node -> value) that must hold a value for
         all variables that this density depends on. Except for the variable
         that it is directly associated with.
     @param variable: The variable that this density is directly associated
         with.
     @param allowed_values: A list of values that are allowed to be sampled.
         This is necessary because external evidence may restrict the value
         range.
     @returns: The sampled value.
     '''
     node_value_pairs = [(node, global_state[node])
                         for node in self.variables if node != variable]
     probabilities = [
         self.get_probability(node_value_pairs + [(variable, value)])
         for value in allowed_values
     ]
     idx = weighted_random(probabilities)
     return allowed_values[idx]
Пример #6
0
    def transition(self, network, state, extern_evidence):
        '''
        Does one single state transition.
        @param network: A BayesNet.
        @param state: The current state of the BayesNet. Given as a Dict from
            RandomNode to Value
        @param extern_evidence: Evidence that is given by the user. This is a
            Dict from Node to Evidence.
        '''
        nodes = network.get_nodes([])
        nodes_to_resample=[n for n in nodes if not n in extern_evidence.keys() or extern_evidence[n].get_unique_value() == None]

        for node in nodes_to_resample:
            parents=network.get_parents(node)
            if parents:
                evidence=[(parent,state[parent]) for parent in parents]
                reduced_cpd = node.get_cpd_reduced(evidence)
            else:
                reduced_cpd = node.get_cpd()

            #reduce the children's cpds
            children = network.get_children(node)
            for child in children:

                #reduce this node's cpd
                parents=network.get_parents(child)
                evidence=[(parent,state[parent]) for parent in parents if parent != node]
                evidence.append((child,state[child]))
                reduced_child_cpd = child.get_cpd_reduced(evidence)

                reduced_cpd = reduced_cpd.multiplication(reduced_child_cpd)

            new_state=weighted_random(reduced_cpd.get_table())
            state[node]=node.get_value_range()[new_state]

        return state