在深度首次搜索有向图时跟踪时间

时间:2013-12-09 20:47:55

标签: python depth-first-search

我尝试对有向图进行深度优先搜索,在这样做的同时,我也尝试跟踪有关图的数据。首先,这是我用来构建有向图的类。

class Node(object):
   def __init__(self, name):
       self.name = str(name)
   def getName(self):
       return self.name
   def __str__(self):
       return self.name
   def __repr__(self):
      return self.name
   def __eq__(self, other):
      return self.name == other.name
   def __ne__(self, other):
      return not self.__eq__(other)

class Edge(object):
   def __init__(self, src, dest,distance,distance_out):
       self.src = src
       self.dest = dest
       self.distance = distance
       self.distance_out = distance_out
   def getSource(self):
       return self.src
   def getDestination(self):
       return self.dest
   def getDistance(self):
      return self.distance
   def getDistance_Outdoors(self):
      return self.distance_out
   def __str__(self):
       return str(self.src) + '--'+'Total Distance:(' +str(self.distance)+')' + ' '+ 'Outside Distance:('+str(self.distance_out)+')'+'-->' + str(self.dest)


class Digraph(object):
   """
   A directed graph
   """
   def __init__(self):
       self.nodes = set([])
       self.edges = {}
   def addNode(self, node):
       if node in self.nodes:
           raise ValueError('Duplicate node')
       else:
           self.nodes.add(node)
           self.edges[node] = []
   def addEdge(self, edge):
       src = edge.getSource()
       dest = edge.getDestination()
       distance = edge.getDistance()
       distance_out = edge.distance_out
       if not(src in self.nodes and dest in self.nodes):
           raise ValueError('Node not in graph')
       self.edges[src].append([dest,[distance,distance_out]])
   def childrenOf(self, node):
       return self.edges[node]
   def hasNode(self, node):
       return node in self.nodes
   def testDict(self):
      return self.edges
   def __str__(self):
       res = ''
       for k in self.edges:
           for d in self.edges[k]:
               res = res + str(k) + '->' + str(d[0]) + str(d[1])+ '\n' 
       return res[:-1]

我目前正在处理的有向图有37个节点和129个边。

这是我搜索功能的代码。

import string
from graph import Digraph, Edge, Node
def depthFirstSearchVisit(digraph, time, node,discovered, undiscovered ,
                          explored , nodes , hierarchy ):
    time = time + 1 #While vertex has just been discovered
    nodes[node].append(time) ##Mark the discovery time for the node in the nodes dictionary
    discovered.append(node)##Mark the node as discovered
    if node in undiscovered: ## Remove node from undiscovered after it's discovery
        undiscovered.remove(node)
    for adjacent_node in digraph.childrenOf(node):##Explore edge (node, adjacent_node)
        if adjacent_node[0] in undiscovered: ##The adjacent node is a predecessor of the node
            hierarchy[node].append(adjacent_node[0])##Mark it as such in the hierarchy dictionary
            depthFirstSearchVisit(digraph,time,adjacent_node[0],discovered,
                                  undiscovered,explored,nodes,hierarchy)##Then recursively visit that adjacent_node
    explored.append(node) ##After exploring all of the nodes adjacent
    nodes[node].append(time)
    return nodes
def depthFirstSearch(digraph,time, discovered = [], undiscovered = [],
                     explored = [], nodes = {}, hierarchy = {}):

    if len(nodes) == 0: ## If nodes is empty
        for i in digraph.nodes: ##Initialize a dictionary where nodes are the keys and 
            nodes[i] = [] ##An empty list for values, so they can be filled with discovery and exploration times
    for key in nodes: ##For each node in the digraph mark them all as undiscovered.
        undiscovered.append(key)
    for key2 in nodes:##Construct hierarchy dict for later use in DepthFirstSearchVisit
        hierarchy[key2] = []
    ##Time initialized to zero in parameter call
    for node in nodes:
        if node in undiscovered:
            depthFirstSearchVisit(digraph,time,node,discovered, undiscovered, explored,nodes,hierarchy)
    return nodes

现在我正在测试字典节点是否正在输出正确的信息。这是节点字典的结构。

{node: [time of discovery, time of exploration]} 

发现的时间是DepthFirsTSearchVisit首次遇到节点,探索的时间是所有发现的节点的后代等等。

以下是我的输出结果:

{32: [1, 1], 48: [4, 4], 50: [9, 9], 37: [17, 17], 13: [15, 15], 10: [25, 25], 64: [9, 9], 35: [18, 18], 5: [22, 22], 24: [14, 14], 6: [10, 10], 57: [2, 2], 9: [20, 20], 68: [6, 6], 39: [16, 16], 1: [23, 23], 38: [16, 16], 62: [8, 8], 4: [12, 12], 16: [4, 4], 34: [15, 15], 2: [9, 9], 54: [7, 7], 7: [21, 21], 66: [8, 8], 56: [5, 5], 46: [3, 3], 76: [7, 7], 18: [6, 6], 3: [24, 24], 36: [2, 2], 12: [13, 13], 33: [19, 19], 14: [8, 8], 8: [11, 11], 26: [3, 3], 31: [18, 18]}

我认为我应该得到什么输出:时间值不应该相同。发现和探索之间应该存在很大差异。

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

您正在将时间视为传递参考。它不是 - 它是通过价值。这是因为python int是不可变的。所以当你这样做时:

def depthFirstSearchVisit(digraph, time, node,discovered, undiscovered ,
                          explored , nodes , hierarchy ):
    time = time + 1 #While vertex has just been discovered
    ...

这创建了一个本地调用时间,它指向与输入时间相同的int。然后你递增它,现在时间指向函数本地的新整数。然后,当你这样做时:

depthFirstSearchVisit(digraph,time,adjacent_node[0],discovered,
     undiscovered,explored,nodes,hierarchy)

看起来期望子功能在它存在时增加时间,然后当它返回时,我传递的时间将被修改。但实际上,它不会。

Python变量传递对于来自其他语言的程序员来说可能有点混乱,因为它并没有真正通过引用OR值,至少不是C ++风格。你有一个名字,它指向一个对象。当您调用函数时,该函数将获取一个新的本地名称,但它指向同一个对象。只要你不重新分配这个名字,那就像是通过引用传递。但是一旦你重新分配它,你的本地名称现在指向一个新对象,不再共享。

正如评论所说,你最好只在顶部和底部拨打time.time()

最后一个补充:如果你真的想要整数时间,那就很容易使用itertools.count。它必须是一个全球性的:

from itertools import count
gtime = count(0)

#Note: Removed time, as it's useless now
def depthFirstSearchVisit(digraph, node,discovered, undiscovered ,
                          explored , nodes , hierarchy ):
     starttime = gtime.next()
     # Call some functions...
     # ....
     # Those also increment global time
     endtime = gtime.next()