例如,以下两个图被认为是完美的部分匹配:
0-1
1-2
2-3
3-0
和
这两个被认为是不匹配的
2-0
数字不必匹配,只要这些节点之间的关系可以完全匹配即可。
这是子图同构问题:http : //en.wikipedia.org/wiki/Subgraph_isomorphism_problem
由于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)。也就是说,所有顶点都是可能的。
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,必须找到与节点j相邻的节点y。在图中。这个过程的帮助比最初显而易见的要多,因为每次我们消除一个可能的分配时,这可能会导致其他可能的分配被消除,因为它们是相互依赖的。
最终的算法是:
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