【问题标题】:How to partially compare two graphs如何部分比较两个图表
【发布时间】:2012-11-24 02:28:05
【问题描述】:

例如,这两个图被认为是完美的部分匹配:

0 - 1

1 - 2

2 - 3

3 - 0

0 - 1

1 - 2

这两个被认为是不匹配

0 - 1

1 - 2

2 - 3

3 - 0

0 - 1

1 - 2

2 - 0

数字不一定要匹配,只要这些节点之间的关系可以完美匹配即可。

【问题讨论】:

  • 你的意思是在可能的重命名之后,第二个图是第一个图的子图?
  • @DanielFischer 是的!正是这样。

标签: algorithm


【解决方案1】:

这是子图同构问题:http://en.wikipedia.org/wiki/Subgraph_isomorphism_problem

由于 Ullmann,文章中提到了一种算法。

Ullmann 算法是深度优先搜索的扩展。深度优先搜索的工作方式如下:

def search(graph,subgraph,assignments):
  i=len(assignments)

  # Make sure that every edge between assigned vertices in the subgraph is also an
  # edge in the graph.
  for edge in subgraph.edges:
    if edge.first<i and edge.second<i:
      if not graph.has_edge(assignments[edge.first],assignments[edge.second]):
        return False

  # If all the vertices in the subgraph are assigned, then we are done.
  if i==subgraph.n_vertices:
    return True

  # Otherwise, go through all the possible assignments for the next vertex of
  # the subgraph and try it.
  for j in possible_assignments[i]:
    if j not in assignments:
      assignments.append(j)
      if search(graph,subgraph,assignments):
        # This worked, so we've found an isomorphism.
        return True
      assignments.pop()

def find_isomorphism(graph,subgraph):
  assignments=[]
  if search(graph,subgraph,assignments):
    return assignments
  return None

对于基本算法,possible_assignments[i] = range(0,graph.n_vertices)。也就是说,所有的顶点都是一种可能性。

Ullmann 通过缩小可能性扩展了这个基本算法:

def update_possible_assignments(graph,subgraph,possible_assignments):
  any_changes=True
  while any_changes:
    any_changes = False
    for i in range(0,len(subgraph.n_vertices)):
      for j in possible_assignments[i]:
        for x in subgraph.adjacencies(i):
          match=False
          for y in range(0,len(graph.n_vertices)):
            if y in possible_assignments[x] and graph.has_edge(j,y):
              match=True
          if not match:
            possible_assignments[i].remove(j)
            any_changes = True

这个想法是,如果子图的节点 i 可能匹配图的节点 j,那么对于子图中与节点 i 相邻的每个节点 x,必须有可能找到相邻的节点 y到图中的节点 j。这个过程的帮助远不止一目了然,因为每次我们消除一个可能的分配,这可能会导致其他可能的分配被消除,因为它们是相互依赖的。

那么最后的算法是:

def search(graph,subgraph,assignments,possible_assignments):
  update_possible_assignments(graph,subgraph,possible_assignments)

  i=len(assignments)

  # Make sure that every edge between assigned vertices in the subgraph is also an
  # edge in the graph.
  for edge in subgraph.edges:
    if edge.first<i and edge.second<i:
      if not graph.has_edge(assignments[edge.first],assignments[edge.second]):
        return False

  # If all the vertices in the subgraph are assigned, then we are done.
  if i==subgraph.n_vertices:
    return True

  for j in possible_assignments[i]:
    if j not in assignments:
      assignments.append(j)

      # Create a new set of possible assignments, where graph node j is the only 
      # possibility for the assignment of subgraph node i.
      new_possible_assignments = deep_copy(possible_assignments)
      new_possible_assignments[i] = [j]

      if search(graph,subgraph,assignments,new_possible_assignments):
        return True

      assignments.pop()
    possible_assignments[i].remove(j)
    update_possible_assignments(graph,subgraph,possible_assignments)

def find_isomorphism(graph,subgraph):
  assignments=[]
  possible_assignments = [[True]*graph.n_vertices for i in range(subgraph.n_vertices)]
  if search(graph,subgraph,assignments,possible_assignments):
    return assignments
  return None

【讨论】:

  • 感谢您的详细解答。真的很不错。
  • 这是您的原始代码吗?如果没有,你能给我指个参考吗?
  • @PrateekAgrawal: assignments[A] 是图的顶点,对应于子图的顶点 A。
猜你喜欢
  • 1970-01-01
  • 2013-03-27
  • 1970-01-01
  • 1970-01-01
  • 2012-08-02
  • 2017-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多