def increment_un(G, X, UN_X, v): """Compute UN of X|v, based on the UN of X""" U = set() for S in UN_X: U.add(subtract(S, v)) U.add(subtract(S, v) | (G.neighborhoods[v] & (G.vertices - (X | v)))) return U
def heuristic(graph): subset = 0 while is_independent(graph, subset): # Find valid vertex with the least new neighbors existing_neighbors = graph(subset) min_new_neighbors = Infinity new_vertex = None for v in iterate(subtract(graph.vertices, subset)): if not graph(v) & subset: new_neighbors = subtract(graph(v), existing_neighbors) if size(new_neighbors) < min_new_neighbors: min_new_neighbors = size(new_neighbors) new_vertex = v if new_vertex == None: return subset else: subset |= new_vertex
def bfs(graph, root): """Return vertices of a component of graph in some bfs order, starting with root.""" done = 0 front = root while front: v = first(front) yield v done |= v front |= graph.neighborhoods[v] front = subtract(front, done)
def trivial_case(N, left, right, v): # No neighbors if contains(left, N[v]): return True # Twins for u in iterate(left): if N[v] & right == subtract(N[u], v) & right: return True return False
def is_word_in_graph(word: str, graph, last_vertex=0, forbidden_vertices=0): if not word: return True letter = word[0] candidates = graph.letters_to_vertices[letter] | graph.letters_to_vertices['.'] candidates = subtract(candidates, forbidden_vertices) if last_vertex: candidates &= graph.neighborhoods[last_vertex] return any(is_word_in_graph(word[1:], graph, v, forbidden_vertices | v) for v in iterate(candidates))
def incremental_un_heuristic(G): lboolw_components = [] decomposition_components = [] for component in components(G): best_lboolw = Infinity best_decomposition = None for i, start in enumerate([first(component)]): #for i, start in enumerate(iterate(component)): print('{}th starting vertex'.format(i)) right = subtract(component, start) left = start un_left = increment_un(G, 0, {0}, start) booldim_left = 1 decomposition = [start] lboolw = len(un_left) for _ in range(size(component) - 1): best_vertex, best_un, _ = greedy_step(G, left, right, un_left, booldim_left, {}, Infinity) booldim_left = len(best_un) lboolw = max(lboolw, booldim_left) un_left = best_un decomposition.append(best_vertex) right = subtract(right, best_vertex) left = left | best_vertex if lboolw < best_lboolw: best_lboolw = lboolw best_decomposition = decomposition lboolw_components.append(best_lboolw) decomposition_components.append(best_decomposition) total_lboolw = max(lboolw_components) total_decomposition = [v for part in decomposition_components for v in part] return total_lboolw, total_decomposition
def check_decomposition(G, decomposition): un = {0} lboolw = 1 left = 0 right = G.vertices for v in decomposition: un = increment_un(G, left | v, v, un) lboolw = max(lboolw, len(un)) left = left | v right = subtract(right, v) return lboolw
def recurse(word: str, graph, last_vertex, forbidden): if not word: return True letter = word[0] if letter not in graph.letters_to_vertices: return False candidates = subtract(graph.letters_to_vertices[letter] & graph.neighborhoods[last_vertex], forbidden) if not candidates: return False return any(recurse(word[1:], graph, v, forbidden | v) for v in iterate(candidates))