计算元组列表中元素的可达性

时间:2018-08-23 08:38:12

标签: python python-3.x reachability

我有一个这样的元组列表。

a = [(1,2),(1,3),(1,4),(2,5),(6,5),(7,8)]

在此列表中,1与2有关,然后2与5有关,而5与6有关,因此1与6有关。类似地,我需要找到元组中其他元素之间的关系。我需要一个采用输入值和输出的函数,如下所示:

input = (1,6) #output = True
input = (5,3) #output = True
input = (2,8) #output = False

我不了解itertools或map函数。它们可以用来解决这类问题吗? 并且出于好奇和兴趣,我在哪里可以找到这些类型的问题来解决,以及在现实生活中遇到的这些类型的问题在哪里?

2 个答案:

答案 0 :(得分:6)

可以通过将元组视为图形中的边来轻松完成此操作。然后将问题简化为检查两个节点之间是否存在路径。

为此存在许多不错的库,请参见例如networkx

import networkx as nx

a = [(1,2),(1,3),(1,4),(2,5),(6,5),(7,8)]

G = nx.Graph(a)

nx.has_path(G, 1, 6)  # True
nx.has_path(G, 5, 3)  # True
nx.has_path(G, 2, 8)  # False

答案 1 :(得分:2)

这个答案here很好地将您的问题表示为图问题,其中每次您需要运行算法时,都需要检查输入顶点之间是否存在路径。然后,每个查询的时间复杂度取决于基础图的大小,顺序,直径和程度。

但是,如果您打算使用同一数组a多次运行此算法,则可能值得对输入图进行一些预处理以首先找到连接的组件(Wikipedia : connected components)。在这种情况下,您可以为每个查询获取恒定时间。这是我建议的代码:

# NOTE : tested using python 3.6.1
# WARNING : no input sanitization

a = [(1,2),(1,3),(1,4),(2,5),(6,5),(7,8)]
n = 8 # order of the underlying graph

# prepare graph as lists of neighbors for every vertex, i.e. adjacency lists (extra unused vertex '0', just to match the value range of the problem)
graph = [[] for i in range(n+1)]
for edge in a:
  graph[edge[0]].append(edge[1])
  graph[edge[1]].append(edge[0])
print( "graph : " + str(graph) )

# list of unprocessed vertices : contains all of them at the beginning
unprocessed_vertices = {i for i in range(1,n+1)}

# subroutine to discover the connected component of a vertex
def build_component():
  component = [] # current connected component
  curr_vertices = {unprocessed_vertices.pop()} # locally unprocessed vertices, initialize with one of the globally unprocessed vertices
  while len(curr_vertices) > 0:
    curr_vertex = curr_vertices.pop() # vertex to be processed
    # add unprocessed neighbours of current vertex to the set of vertices to process
    for neighbour in graph[curr_vertex]:
      if neighbour in unprocessed_vertices:
        curr_vertices.add(neighbour)
        unprocessed_vertices.remove(neighbour)
    component.append(curr_vertex)
  return component

# main algorithm : graph traversal on multiple connected components
components = []
while len(unprocessed_vertices) > 0:
  components.append( build_component() )
print( "components : " + str(components) )

# assign a number to each component
component_numbers = [None] * (n+1)
curr_number = 1
for comp in components:
  for vertex in comp:
    component_numbers[vertex] = curr_number
  curr_number += 1
print( "component_numbers : " + str(component_numbers) )

# main functionality
def is_connected( pair ):
  return component_numbers[pair[0]] == component_numbers[pair[1]]

# run main functionnality on inputs : every call is executed in constant time now, regardless of the size of the graph
print( is_connected( (1,6) ) )
print( is_connected( (5,3) ) )
print( is_connected( (2,8) ) )

我真的不知道最有可能遇到此问题的情况,但是我想它可以在应用程序中执行一些群集任务,或者也许您是否想知道是否可以从一个地方转到另一个地方。另一个。如果图形的边缘表示模块之间的依赖关系,则此问题将告诉您两个部分是否相互依赖,因此可能在编译或管理大型项目时有一些潜在的应用程序。潜在的问题是“连接组件”问题,这是我们知道的多项式算法中的问题。

使用图对这类问题建模通常非常有用,因为这些对象的结构非常简单,并且在大多数情况下,我们可以将原始问题简化为图上众所周知的问题。