微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何找到图形的所有路径

如何解决如何找到图形的所有路径

更新 感谢一些社区成员的评论,我意识到存在一些类似的问题,但它们可能有点不同,请允许我进一步解释。 我其实希望在一个实际问题中使用相同的方法,所以简单地说:

  1. 完全允许重复使用不同路径中的边
  2. 从 A 到 B 的唯一(或新)路径被定义为具有任何不同顶点的顶点集合。

让我使用 Bradley .N Miller 和 David L. Ranum 来自 Python 数据结构和算法分析的测验来解释我的问题。

问题: 考虑将单词 FOOL 转换为 SAGE 的任务,也称为单词阶梯问题。在解决 在单词阶梯问题中,一次只能替换一个字母,每一步的结果必须是一个单词,不能不存在。

输入:

FOUL
FOOL
FOIL
FAIL
COOL
FALL
POOL
PALL
POLL
POLE
PALE
PAGE
SALE
POPE
POPE
SAGE

我们可以很容易地找到从 FOOL 到 SAGE 的路径,正如 Bradley 所示: enter image description here

我使用广度优先搜索(BFS)来解决问题:

class Vertex: 
def __init__(self,key,value = None):
    self.id = key
    self.connectedTo = {}
    self.color = 'white'
    self.dist = sys.maxsize
    self.pred = []
    self.disc = 0
    self.fin = 0
    self.value = value,#self.GraphBulided = False
    self.traverseIndex = 0
    self.prednum = 0

def addNeighbor(self,nbr,weight=0): 
    self.connectedTo[nbr] = weight

def __str__(self): 
    return '{} connectedTo: {}'.format(self.id,\
    str([x.id for x in self.connectedTo]))

def setColor(self,color):
    self.color = color
    
def setdistance(self,d): 
    self.dist = d

#I want store all  Pred for next traverse so I use a list to do it
def setPred(self,p,list = False): 
    if not list: 
        self.pred = p
    else: 
        self.pred.append(p)
        self.prednum += 1
    
def setdiscovery(self,dtime):
    self.disc = dtime
    
def setFinish(self,ftime):
    self.fin = ftime
    
#def setGraphBulided(self,tag = True): 
#    self.GraphBulided = tag
    
def getFinish(self):
    return self.fin
    
def getdiscovery(self):
    return self.disc
    
def getPred(self):
    if isinstance(self.pred,list):
        if self.traverseIndex < self.prednum:
            return self.pred[self.traverseIndex]
        else: 
            return self.pred[-1]
    else: 
        return self.pred

def __hash__(self):
    return hash(self.id)

def getPredById(self): 
    if self.traverseIndex < self.prednum and isinstance(self.pred,list): 
        pred = self.pred[self.traverseIndex]
        self.traverseIndex += 1
        print("vertix {}: {} of {} preds".format(self.id,self.traverseIndex,self.prednum))
        return [pred,self.traverseIndex]
    else: 
        pred =  None
        return [pred,None]
    
def getCurrPredStaus(self): 
    #if not self.pred: 
    #    return None
    return self.prednum - self.traverseIndex
    
    
def getdistance(self):
    return self.dist
    
def getColor(self):
    return self.color   
    
def getConnections(self): 
    return self.connectedTo.keys()

def getId(self): 
    return self.id

def getWeight(self,nbr): 
    return self.connectedTo[nbr]

def getValue(self): 
    return self.value

def findpath(self,dest): 
    pass


class Graph: 
def __init__(self):  
    self.vertList = {}
    self.numVertics = 0
    self.verticsInSerach = set()
    self.GraphBulided = False

def addVertex(self,value = None): 
    self.numVertics = self.numVertics + 1
    newVertex = Vertex(key,value=value)
    self.vertList[key] = newVertex
    return newVertex

def getVertex(self,n): 
    if n in self.vertList: 
        return self.vertList[n]
    else: 
        return None
    
def __contains__(self,n): 
    return n in self.vertList

def addEdge(self,f,t,cost = 0,fvalue = None,tvalue = None): 
    if f not in self.vertList:
        nv = self.addVertex(f,fvalue)
    if t not in self.vertList: 
        nv = self.addVertex(t,tvalue)
    self.vertList[f].addNeighbor(self.vertList[t],cost)

def setGraphBulided(self,tag = True): 
    self.GraphBulided = tag

def getVertices(self): 
    return self.vertList.keys()

def setGraphBulided(self,tag = True): 
    self.GraphBulided = tag
    
def setSerachedVertixs(self,vertix): 
    self.verticsInSerach.add(vertix)

def getGraphBulided(self): 
    return self.GraphBulided

def getSerachedVertixs(self): 
    return self.verticsInSerach

def __iter__(self): 
    return iter(self.vertList.values())

def __hash__(self):
    hashids = [x for x in self.getVertices()]
    if len(hashids) > 0 and hashids[0]: 
        return hash(','.join(hashids))
    else: 
        return None

这里有一些用于构建图表的附加功能

def buildGraph(wordFile,DFSgraph = False): 
d = {}
g = Graph()
if DFSgraph: 
    g = DFSGraph()
wfile = open(wordFile)
for line in wfile: 
    word = line[:-1]
    for i in range(len(word)):
        bucket = word[:i] + '_' + word[i+1:]
        if bucket in d: 
            d[bucket].append(word)
        else:
            d[bucket] = [word]
for bucket in d.keys(): 
    for word1 in d[bucket]:
        for word2 in d[bucket]: 
            if word1 != word2: 
                g.addEdge(word1,word2) 
wfile.close()   
return g



class Queue:
def __init__(self):
    self.items = []

def isEmpty(self):
    return self.items == []

def enqueue(self,item):
    self.items.insert(0,item)

def dequeue(self):
    return self.items.pop()

def size(self):
    return len(self.items)

def bfs(g,start,listpred = False): 
start.setdistance(0)
start.setPred(None)
vertQueue = Queue()
vertQueue.enqueue(start)
while (vertQueue.size() > 0): 
    currentVert = vertQueue.dequeue()
    if currentVert.getConnections(): 
        g.setSerachedVertixs(currentVert)
    for nbr in currentVert.getConnections(): 
        #print('sreach {}'.format(currentVert.getId()))
        if (nbr.getColor() == 'white' or nbr.getColor() == 'gray'):
            nbr.setColor('gray')
            nbr.setdistance(currentVert.getdistance() + 1)
            if nbr.prednum > 0 and currentVert.getId() not in [x.getId() for x in nbr.pred]: 
                nbr.setPred(currentVert,listpred)
            elif nbr.prednum == 0: 
                nbr.setPred(currentVert,listpred)
            vertQueue.enqueue(nbr)
    currentVert.setColor('black')

因此,我们可以轻松找到所需的最短路径(如果我们只为一个顶点存储一个 pred)。

wordGraph = buildGraph('fourletterwords1.txt',DFSgraph=False)    
    bfs(wordGraph,wordGraph.getVertex('FOOL'),listpred=True) 
    def traverse(y): 
        x=y 
        while(x.getPred()):
            print(x.getPred())
            x = x.getPred()
        print(x.getId())    
    traverse(wordGraph.getVertex('SAGE'))

但是,我仍然不知道如何正确跟踪所有路径,您能给我一些建议吗?

解决方法

FIND path from src to dst ( Dijkstra algorithm )
ADD path to list of paths
LOOP P over list of paths
    LOOP V over vertices in P
        IF V == src OR V == dst
            CONTINUE to next V
        COPY graph to working graph
        REMOVE V from working graph
        FIND path from src to dst in working graph( Dijkstra algorithm )
        IF path found
            IF path not in list of paths
                ADD path to list of paths

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。