贝叶斯网络的拓扑排序

2024-04-24 23:07:52 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图通过遵循https://en.wikipedia.org/wiki/Topological_sorting中的伪代码来实现贝叶斯网络的拓扑排序

运行我的代码时,我得到错误:

for child in children:

TypeError: 'Variable' object is not iterable 

当我无法循环到某个节点的子节点时,我不知道如何更新该节点的传入边数。需要更改代码的帮助,以便在不提示错误消息的情况下正确更新节点的in degree计数。Im实现的函数是类定义底部的排序的_节点函数


class BayesianNetwork:
    """
    Class representing a Bayesian network.
    Nodes can be accessed through self.variables['variable_name'].
    Each node is a Variable.

    Edges are stored in a dictionary. A node's children can be accessed by
    self.edges[variable]. Both the key and value in this dictionary is a Variable.
    """
    def __init__(self):
        self.edges = defaultdict(lambda: [])  # All nodes start out with 0 edges
        self.variables = {}                   # Dictionary of "name":TabularDistribution

    def add_variable(self, variable):
        """
        Adds a variable to the network.
        """
        if not isinstance(variable, Variable):
            raise TypeError(f"Expected {Variable}; got {type(variable)}.")
        self.variables[variable.name] = variable

    def add_edge(self, from_variable, to_variable):
        """
        Adds an edge from one variable to another in the network. Both variables must have
        been added to the network before calling this method.
        """
        if from_variable not in self.variables.values():
            raise ValueError("Parent variable is not added to list of variables.")
        if to_variable not in self.variables.values():
            raise ValueError("Child variable is not added to list of variables.")
        self.edges[from_variable].append(to_variable)

    def sorted_nodes(self):
        """
        TODO: Implement Kahn's algorithm (or some equivalent algorithm) for putting
              variables in lexicographical topological order.


        Returns: List of sorted variable names.
        """
        inDegree = {n : 0 for n in self.variables.values()}
        L = [] #Empty list that will contain the sorted nodes
        S = [] #List of nodes with 0 incoming edges (in-degree = 0)

        for edgelist in self.edges.values(): #If edgelist contains a node, that node has +1 incoming edges
            for node in edgelist:
                inDegree[node] += 1

        #Find nodes with 0 in-degree
        for node in inDegree:
            if (inDegree[node] == 0):
                S.append(node)

        #Process nodes with in-degree = 0

        while S:
            node = S.pop()
            L.append(node)

        #Update in-degree. The children of the node we removed from S now have one less in-degree

            for children in self.edges[node]:
                for child in children:
                    inDegree[child] -= 1
                if inDegree[child] == 0:
                    L.append(child)

        #Print error if graph has edges (not acyclic), otherwise return L
        if any(node for node in inDegree.values()):
            print("Error: Graph has cycles")
        else:
            return L