2015-06-29 5 views
1

Я использую функцию от here:NetworkX/Python_igraph: Все пути между двумя узлами, ограниченный списком узлов

def find_all_paths(graph, start, end, mode = 'OUT', maxlen = None): 
def find_all_paths_aux(adjlist, start, end, path, maxlen = None): 
    path = path + [start] 
    if start == end: 
     return [path] 
    paths = [] 
    if maxlen is None or len(path) <= maxlen: 
     for node in adjlist[start] - set(path): 
      paths.extend(find_all_paths_aux(adjlist, node, end, path, maxlen)) 
    return paths 
adjlist = [set(graph.neighbors(node, mode = mode)) \ 
    for node in xrange(graph.vcount())] 
all_paths = [] 
start = start if type(start) is list else [start] 
end = end if type(end) is list else [end] 
for s in start: 
    for e in end: 
     all_paths.extend(find_all_paths_aux(adjlist, s, e, [], maxlen)) 
return all_paths 

найти все пути между двумя узлами.

Альтернативная функция является один here:

def find_all_paths(graph, start, end): 
path = [] 
paths = [] 
queue = [(start, end, path)] 
while queue: 
    start, end, path = queue.pop() 
    print 'PATH', path 

    path = path + [start] 
    if start == end: 
     paths.append(path) 
    for node in set(graph[start]).difference(path): 
     queue.append((node, end, path)) 
return paths 

Я хотел бы выразить одну из функций, чтобы сделать еще один аргумент, который будет список «via_nodes».

Если путь имеет один из этих сквозных путей между его концом и стартовым узлом, его не следует возвращать.

Было бы легко сначала вычислить все пути с помощью функции, как она есть сейчас, а затем исключить пути, встречающиеся выше условия, но для того, чтобы сделать его более эффективным, я хотел бы, чтобы он остановил поиск пути, как только он встретится via_node на более раннем этапе.

Любые идеи?

ответ

0

Хорошо, я отвечу на себя, но буду рад тестированию и комментариям: взяв вторую функцию сверху (адаптированную для работы с python-igraph и networkx), я добавил аргумент vn, поэтому поиск пути останавливается, если достигнут узел vn:

import igraph as ig 

def find_all_paths2(graph, start, end, vn = []): 
     """ 
     Finds all paths between nodes start and end in graph. 
     If any node on such a path is within vn, the path is not   
     returned. 
     !! start and end node can't be in the vn list !! 

     Params: 
     -------- 

     G : igraph graph 

     start: start node index 

     end : end node index 

     vn : list of via- or stop-nodes indices 

     Returns: 
     -------- 

     A list of paths (node index lists) between start and end node 
     """ 

    vn = vn if type(vn) is list else [vn] 
    path = [] 
    paths = [] 
    queue = [(start, end, path)] 
    while queue: 
     start, end, path = queue.pop() 
     #print 'PATH', path 
     path = path + [start] 
     #print 'PATH after adding start ', path 

     if start in vn: 
      print start,' is in vianodes ',str(vn) 
      pass#paths.append(path) 

     if start == end: 
      print 'end' 
      paths.append(path) 
     #print graph.neighbors(start) 
     if start not in vn: 
      print start,' not in vianodes ',str(vn) 
      for node in set(graph.neighbors(start)).difference(path): 
       queue.append((node, end, path)) 
    return paths 

G = ig.Graph() 
G.add_vertices(14) 
G.add_edges([(13,10),(12,13),(11,12),(10,11),(9,10),(2,9),(0,1), (1,2),(2,3),(3,0),(0,4),(4,5),(5,6),(6,7),(7,8),(8,6)])#,(0,0)]) 
#G = G.as_directed() 


for p in find_all_paths2(G,0,12,[]): 
    print 'path: ',p 

path: [0, 3, 2, 9, 10, 13, 12] 
path: [0, 3, 2, 9, 10, 11, 12] 
path: [0, 1, 2, 9, 10, 13, 12] 
path: [0, 1, 2, 9, 10, 11, 12] 

for p in find_all_paths2(G,0,12,[13]): 
     print 'path: ',p 


path: [0, 3, 2, 9, 10, 11, 12] 
path: [0, 1, 2, 9, 10, 11, 12] 
0

Удалите узлы из графика, прежде чем вы переходите по длинным дорожкам.

Верните их, когда закончите.

Это занимает меньше памяти в высокосвязанных графах.

import networkx 
G = networkx.Graph() 
G.add_node(14) 
G.add_edges_from([(13,10),(12,13),(11,12),(10,11),(9,10),(2,9),(0,1),(1,2),(2,3),(3,0),(0,4),(4,5),(5,6),(6,7),(7,8),(8,6)]) 


def simple_paths_with_node_exclusion(G, source, target, exclude_nodes): 
     edge_list = [] 
     edge_list.extend(G.edges_iter(exclude_nodes)) 
     G.remove_nodes_from(exclude_nodes) 
     value = networkx.all_simple_paths(G, source, target) 
     G.add_nodes_from(edge_list) 
     return value 

print(list(simple_paths_with_node_exclusion(G,0,12,[13]))) 
  • если вы делаете время или тесты памяти я бы с удовольствием слушать о результатах с реальными данными в комментариях ниже.