def calc_euler_tour(g, start, end): '''Calculates an Euler tour over the graph g from vertex start to vertex end. Assumes start and end are odd-degree vertices and that there are no other odd-degree vertices.''' even_g = nx.subgraph(g, g.nodes()) if end in even_g.neighbors(start): # If start and end are neighbors, remove the edge even_g.remove_edge(start, end) comps = list(nx.connected_components(even_g)) # If the graph did not split, just find the euler circuit if len(comps) == 1: trail = list(nx.eulerian_circuit(even_g, start)) trail.append((start, end)) elif len(comps) == 2: subg1 = nx.subgraph(even_g, comps[0]) subg2 = nx.subgraph(even_g, comps[1]) start_subg, end_subg = ( subg1, subg2) if start in subg1.nodes() else (subg2, subg1) trail = list(nx.eulerian_circuit(start_subg, start)) + [ (start, end) ] + list(nx.eulerian_circuit(end_subg, end)) else: raise Exception( 'Unknown edge case with connected components of size {0}:\n{1}' .format(len(comps), comps)) else: # If they are not neighbors, we add an imaginary edge and calculate the euler circuit even_g.add_edge(start, end) circ = list(nx.eulerian_circuit(even_g, start)) try: trail_start = circ.index((start, end)) except: trail_start = circ.index((end, start)) trail = circ[trail_start + 1:] + circ[:trail_start] return trail
def get_eulerian(edict): G = nx.DiGraph(edict) if (not nx.is_eulerian(G)): out_degrees = G.out_degree([node for node in G]) in_degrees = G.in_degree([node for node in G]) ds = [out_degrees, in_degrees] d = {} out_degree_dict = dict(out_degrees) for k in out_degree_dict.keys(): d[k] = tuple(d[k] for d in ds) for key in d: d[key] = d[key][0] - d[key][1] extra_out = [key for (key, value) in d.items() if value == 1][0] extra_in = [key for (key, value) in d.items() if value == -1][0] G.add_edge(extra_in, extra_out) euler = list(nx.eulerian_circuit(G, source=extra_out)) index = euler.index((extra_in, extra_out)) blah = euler[index + 1:] + euler[:index] path = [] path = blah[0][0] + sign + blah[0][1] for line in blah[1:]: path = path + (sign + line[1]) else: eulerian = list(nx.eulerian_circuit(G)) path = eulerian[0][0] + sign + eulerian[0][1] for line in eulerian[1:]: path = path + (sign + line[1]) return path
def _run_diffusion_process(self, node): """ Generating a diffusion tree from a given source node and linearizing it with a directed Eulerian tour. Arg types: * **node** *(int)* - The source node of the diffusion. Return types: * **euler** *(list of strings)* - The list of nodes in the walk. """ infected = [node] sub_graph = nx.DiGraph() sub_graph.add_node(node) infected_counter = 1 while infected_counter < self.diffusion_cover: end_point = random.sample(infected, 1)[0] nebs = [node for node in self.graph.neighbors(end_point)] sample = random.choice(nebs) if sample not in infected: infected_counter = infected_counter + 1 infected = infected + [sample] sub_graph.add_edges_from([(end_point, sample), (sample, end_point)]) if infected_counter == self.diffusion_cover: break euler = [ str(u) for u, v in nx.eulerian_circuit(sub_graph, infected[0]) ] if len(euler) == 0: euler = [ str(u) for u, v in nx.eulerian_circuit(graph, infected[0]) ] return euler
def run_diffusion_process(self, node): """ Generating a diffusion tree from a given source node. Linearizing it with an Eulerian tour. :param node: Source of diffusion. :return euler: Eulerian linear node sequence. """ infected = [node] sub_graph = nx.DiGraph() sub_graph.add_node(node) infected_counter = 1 while infected_counter < self.number_of_nodes: end_point = random.sample(infected, 1)[0] nebs = [node for node in self.graph.neighbors(end_point)] sample = random.sample(nebs, 1)[0] if sample not in infected: infected_counter = infected_counter + 1 infected = infected + [sample] sub_graph.add_edges_from([(end_point, sample), (sample, end_point)]) if infected_counter == self.number_of_nodes: break euler = [ str(u) for u, v in nx.eulerian_circuit(sub_graph, infected[0]) ] if len(euler) == 0: euler = [ str(u) for u, v in nx.eulerian_circuit(graph, infected[0]) ] return euler
def calc_euler_tour(g, start, end): '''Calculates an Euler tour over the graph g from vertex start to vertex end. Assumes start and end are odd-degree vertices and that there are no other odd-degree vertices.''' even_g = nx.subgraph(g, g.nodes()) if end in even_g.neighbors(start): # If start and end are neighbors, remove the edge even_g.remove_edge(start, end) comps = list(nx.connected_components(even_g)) # If the graph did not split, just find the euler circuit if len(comps) == 1: trail = list(nx.eulerian_circuit(even_g, start)) trail.append((start, end)) elif len(comps) == 2: subg1 = nx.subgraph(even_g, comps[0]) subg2 = nx.subgraph(even_g, comps[1]) start_subg, end_subg = (subg1, subg2) if start in subg1.nodes() else (subg2, subg1) trail = list(nx.eulerian_circuit(start_subg, start)) + [(start, end)] + list(nx.eulerian_circuit(end_subg, end)) else: raise Exception('Unknown edge case with connected components of size {0}:\n{1}'.format(len(comps), comps)) else: # If they are not neighbors, we add an imaginary edge and calculate the euler circuit even_g.add_edge(start, end) circ = list(nx.eulerian_circuit(even_g, start)) try: trail_start = circ.index((start, end)) except: trail_start = circ.index((end, start)) trail = circ[trail_start+1:] + circ[:trail_start] return trail
def eulerian_Detector(self): """ Для неориентированного графа if self._edges_value > 0: graph = copy.deepcopy(self._edges) # Буферный граф odd = [ vertex for vertex in graph.keys() if len(graph[vertex]) & 1 ] keys = [] for key in graph.keys(): keys.append(key) odd.append(keys[0]) if len(odd) > 3: print("Граф не содержит Эйлерова цикла") print("") return stack = [ odd[0] ] path = [] # Цикл обхода графа while stack: vertex = stack[-1] if graph[vertex]: jertex = graph[vertex][0] stack.append(jertex) del graph[jertex][ graph[jertex].index(vertex) ] del graph[vertex][0] else: path.append(stack.pop()) print("Эйлеров цикл в введенном графе: ") print (str(path)) print("") return path else: print("Граф пуст") print("") """ # Для всех типов графов: if self._edges_value > 0: G = nx.DiGraph() for vertex in self._edges.keys(): values = self._edges[vertex] for value in values: G.add_edge(vertex, value) if nx.is_eulerian(G): print("Граф содержит Эйлеров цикл") print("Эйлеров цикл в введенном графе: ") print (str(list(nx.eulerian_circuit(G)))) print("") return list(nx.eulerian_circuit(G)) else: print("Граф не содержит Эйлеров цикл") print("") else: print("Граф пуст") print("")
def test_eulerian_circuit_cycle(self): G = nx.cycle_graph(4) edges = list(eulerian_circuit(G, source=0)) nodes = [u for u, v in edges] assert_equal(nodes, [0, 1, 2, 3]) assert_equal(edges, [(0, 1), (1, 2), (2, 3), (3, 0)]) edges = list(eulerian_circuit(G, source=1)) nodes = [u for u, v in edges] assert_equal(nodes, [1, 0, 3, 2]) assert_equal(edges, [(1, 0), (0, 3), (3, 2), (2, 1)])
def test_eulerian_circuit_cycle(self): G=nx.cycle_graph(4) edges=list(eulerian_circuit(G,source=0)) nodes=[u for u,v in edges] assert_equal(nodes,[0,1,2,3]) assert_equal(edges,[(0,1),(1,2),(2,3),(3,0)]) edges=list(eulerian_circuit(G,source=1)) nodes=[u for u,v in edges] assert_equal(nodes,[1,0,3,2]) assert_equal(edges,[(1,0),(0,3),(3,2),(2,1)])
def test_eulerian_circuit_digraph(self): G = nx.DiGraph() G.add_cycle([0, 1, 2, 3]) edges = list(eulerian_circuit(G, source=0)) nodes = [u for u, v in edges] assert_equal(nodes, [0, 1, 2, 3]) assert_equal(edges, [(0, 1), (1, 2), (2, 3), (3, 0)]) edges = list(eulerian_circuit(G, source=1)) nodes = [u for u, v in edges] assert_equal(nodes, [1, 2, 3, 0]) assert_equal(edges, [(1, 2), (2, 3), (3, 0), (0, 1)])
def test_eulerian_circuit_digraph(self): G = nx.DiGraph() nx.add_cycle(G, [0, 1, 2, 3]) edges = list(nx.eulerian_circuit(G, source=0)) nodes = [u for u, v in edges] assert nodes == [0, 1, 2, 3] assert edges == [(0, 1), (1, 2), (2, 3), (3, 0)] edges = list(nx.eulerian_circuit(G, source=1)) nodes = [u for u, v in edges] assert nodes == [1, 2, 3, 0] assert edges == [(1, 2), (2, 3), (3, 0), (0, 1)]
def test_eulerian_circuit_digraph(self): G=nx.DiGraph() nx.add_cycle(G, [0, 1, 2, 3]) edges=list(eulerian_circuit(G,source=0)) nodes=[u for u,v in edges] assert_equal(nodes,[0,1,2,3]) assert_equal(edges,[(0,1),(1,2),(2,3),(3,0)]) edges=list(eulerian_circuit(G,source=1)) nodes=[u for u,v in edges] assert_equal(nodes,[1,2,3,0]) assert_equal(edges,[(1,2),(2,3),(3,0),(0,1)])
def tsp_mstheuristic( graph, depot ) : # the simple MST heurisitc, should exhibit the right rate of growth at least mst = nx.minimum_spanning_tree( graph, weight='weight' ) gg = nx.MultiGraph() gg.add_edges_from( mst.edges_iter() ) gg.add_edges_from( mst.edges_iter() ) circuit = nx.eulerian_circuit( gg, depot ) tour = [] for i,j in nx.eulerian_circuit( gg, depot ) : if i not in tour : tour.append( i ) tour.append( depot ) return tour
def create_path_description(self, graph): """ Creating a random Eulerian walk on the diffusion tree. :param graph: Original graph of interest. """ self.euler = [ u for u, v in nx.eulerian_circuit(self.sub_graph, self.start_node) ] if len(self.euler) == 0: self.euler = [ u for u, v in nx.eulerian_circuit(graph, self.start_node) ] return self.euler
def eulerian_path(g, algorithm='Fleury'): """Return a Eulerian path for the semi-eulerian graph ``g``. Parameters ---------- g : nx.DiGraph, nx.MultiDiGraph The input graph. The graph must be semi-Eulerian. algorithm : {'Fleury', 'Hierholzer'}, optional Which algorithm to use to find the path. Hierholzer is faster but has the distinct disadvantage that I haven't implemented it yet. =P Returns ------- edges_iter : iterator of edges An Eulerian path of ``g``. Notes ----- An Eulerian path is one that visits every edge in a graph exactly once. """ source, sink = _source_and_sink(g) g.add_edge(sink, source) edges_iter = nx.eulerian_circuit(g, source=source) return edges_iter
def twice_around(G, origin=0): H = nx.minimum_spanning_tree(G) # Encontra a MST de G H = nx.MultiGraph(H) Haux = H.copy() # Fazendo uma cópia de H para utilizar no loop for u, v in Haux.edges(): # Duplica as arestas da MST H.add_edge(u, v) euleraux = list(nx.eulerian_circuit(H, origin)) # Encontra circuito Euleriano I = nx.Graph() aux = [] for u, v in euleraux: # Adiciona em aux todos os vertices do circuito Euleriano aux.append(u) aux.append(v) h = [] for i in aux: # Adiciona os h os vértices de aux sem repeticoes if (i not in h): h.append(i) h.append(origin) # Adiciona a origem for i in range(30): # Coloca em I.add_edge(h[i], h[i + 1]) I[h[i]][h[i + 1]]['weight'] = G[h[i]][h[i + 1]]['weight'] return I # Retorna I
def christofides(graph_x, subset_graph): t0 = time.clock() subset_n = neighbours(subset_graph) graph_comp = makecomplete(subset_n, graph_x) newEdges = missing_edges(subset_n) simp = simplify_complete(graph_comp,newEdges) perfect_matching = call_blossom(subset_n,simp) subset_plus_comp = subset_n.copy() allGraph = nx.MultiGraph(subset_plus_comp) for edge in perfect_matching: allGraph.add_weighted_edges_from([(edge[0],edge[1], graph_comp[edge[0]][edge[1]]['weight'])]) mst_edges = match_components(subset_n,simp,graph_x) final = allGraph.copy() for edge in mst_edges: final.add_weighted_edges_from([(edge[0],edge[1], graph_comp[edge[0]][edge[1]]['weight'])]) final.add_weighted_edges_from([(edge[0],edge[1], graph_comp[edge[0]][edge[1]]['weight'])]) tour = list(nx.eulerian_circuit(final)) t1 = time.clock() results = list() results.append(tour_cost(tour, graph_comp)) runtime = t1 - t0 results.append(runtime) results.append(tour_cost(tour, graph_comp)) results.append(runtime) results.append(check_solution(tour,graph_x,subset_graph)) print(tour) print(results) return results
def eulerian_path(g, algorithm="Fleury"): """Return a Eulerian path for the semi-eulerian graph ``g``. Parameters ---------- g : nx.DiGraph, nx.MultiDiGraph The input graph. The graph must be semi-Eulerian. algorithm : {'Fleury', 'Hierholzer'}, optional Which algorithm to use to find the path. Hierholzer is faster but has the distinct disadvantage that I haven't implemented it yet. =P Returns ------- edges_iter : iterator of edges An Eulerian path of ``g``. Notes ----- An Eulerian path is one that visits every edge in a graph exactly once. """ source, sink = _source_and_sink(g) g.add_edge(sink, source) edges_iter = nx.eulerian_circuit(g, source=source) return edges_iter
def twice_around(self, source=None): if source is None: source = np.random.choice(self.graph.nodes()) T = self.extract_mst(TSP.MST.PRIM) T = nx.MultiGraph(T) T.add_edges_from(T.edges(data=True)) eulerian_circuit = nx.eulerian_circuit(T, source) visited = [] hamiltonian_path = [] for u,v in eulerian_circuit: if u not in visited: visited.append(u) hamiltonian_path.append(u) hamiltonian_path.append(hamiltonian_path[0]) hamiltonian_graph = nx.create_empty_copy(self.graph) for i in range(len(hamiltonian_path)-1): edge = (hamiltonian_path[i], hamiltonian_path[i+1]) hamiltonian_graph.add_edge(*edge, self.graph.get_edge_data(*edge)) return (hamiltonian_graph, hamiltonian_path)
def kTours(SubGraph, OriginalGraph): LamdaGraph = nx.Graph(OriginalGraph) hamiltonian_path_edges = [] hamiltonian_path_nodes = [] hamiltonian_path_edges_with_duplicates = [] if nx.number_of_nodes(SubGraph) == 1: nodes = nx.nodes(SubGraph) hamiltonian_path_nodes.append(nodes[0]) min_objective_value = 0 else: # Duplicate graph edges -- create a multigraph multiGraph = duplicateGraphEdges(SubGraph) # Create Eulerian Circuit -- using networkx euler algorithm node_list = multiGraph.nodes(data=False) if isinstance(node_list, int): node = node_list else: node = node_list[0] (euler_circuit) = nx.eulerian_circuit(multiGraph, source=node) hamiltonian_path_edges, hamiltonian_path_nodes = removeRepeatedNodes( euler_circuit, node, LamdaGraph) hamiltonian_path_edges_with_duplicates = retrieveOriginEdges( hamiltonian_path_edges, LamdaGraph, SubGraph) return hamiltonian_path_nodes, hamiltonian_path_edges, hamiltonian_path_edges_with_duplicates
def getOutputValues(vertices, edges, dropoffs, weight, loc_len, start_index): actual_vertices = [i for i in range(loc_len) if vertices[i].x == 1] # new_start_index = actual_vertices.index(start_index) # g = Graph(len(actual_vertices)) # [g.addEdge(i,j) for j in range(len(actual_vertices)) for i in range(len(actual_vertices)) if edges[actual_vertices[i], actual_vertices[j]].x == 1] # print(g.isEulerianCycle()) # adj = [0] * len(actual_vertices) for i in range(len(actual_vertices)): adj[i] = [] # [adj[i].append(j) for j in range(len(actual_vertices)) for i in range(len(actual_vertices)) if edges[actual_vertices[i], actual_vertices[j]].x == 1] # print(printCircuit(adj, actual_vertices, new_start_index)) new_start_index = actual_vertices.index(start_index) adj_matrix = [[ weight[actual_vertices[i], actual_vertices[j]] if edges[actual_vertices[i], actual_vertices[j]].x == 1 else 'x' for j in range(len(actual_vertices)) ] for i in range(len(actual_vertices))] # for i in range(len(actual_vertices)): # for j in range(len(actual_vertices)): # print(adj_matrix[i][j], end = ' ') # print() G = adjacency_matrix_to_graph(adj_matrix)[0] circuit = list(nx.eulerian_circuit(G, source=new_start_index)) new_circuit = [(actual_vertices[i], actual_vertices[j]) for i, j in circuit] print(new_circuit)
def plot_puzzle_graph(G, pos, diff_degree=2., amp=1., scale=1.5, steps=100, **params): """ Turn graph into puzzle, by making a line for each edge if the edge has an attribute for 'invisible_line' set to True skip it and if the edge has an attrible for 'straight_line' set to True, don't make a nub """ # add matching on odd degree nodes (with 'blank' as a hacky vtx in # the middle to make sure the degree really increases odd_nodes = [v for v in G if len(G[v])%2 == 1] for u,v in zip(odd_nodes[::2], odd_nodes[1::2]): midpt = 'mid_%s_%s' % (u,v) G.add_edge(u, midpt, invisible_line=True) G.add_edge(midpt, v, invisible_line=True) for u, v in nx.eulerian_circuit(G): if G[u][v].get('invisible_line'): continue if G[u][v].get('straight_line'): plot_line(pos[u], pos[v], **params) else: if random.random() > .5: plot_nub(pos[u], pos[v], diff_degree, amp, scale, steps, **params) else: plot_nub(pos[v], pos[u], diff_degree, amp, scale, steps, **params)
def twice_around(self, source=None): if source is None: source = np.random.choice(self.graph.nodes()) T = self.extract_mst(TSP.MST.PRIM) T = nx.MultiGraph(T) T.add_edges_from(T.edges(data=True)) eulerian_circuit = nx.eulerian_circuit(T, source) visited = [] hamiltonian_path = [] for u, v in eulerian_circuit: if u not in visited: visited.append(u) hamiltonian_path.append(u) hamiltonian_path.append(hamiltonian_path[0]) hamiltonian_graph = nx.create_empty_copy(self.graph) for i in range(len(hamiltonian_path) - 1): edge = (hamiltonian_path[i], hamiltonian_path[i + 1]) hamiltonian_graph.add_edge(*edge, self.graph.get_edge_data(*edge)) return (hamiltonian_graph, hamiltonian_path)
def solve(self, problem_graph): solution = [] cost = 0 mst = self.get_mst(problem_graph) odd_graph = self.build_graph_with_odd_vertex(problem_graph, mst) matching_edges = nx.algorithms.matching.max_weight_matching(odd_graph) mst_extended = self.join_mst_and_matching_edges( problem_graph, mst, matching_edges) walk = list(nx.eulerian_circuit(mst_extended)) solution = self.fast_hamiltonian_circuit_from_euler_circuit(walk) for i in range(len(solution)): u = solution[i] v = solution[(i + 1) % len(solution)] weight = problem_graph[u][v]['weight'] cost += weight return solution, cost
def get_euler(edges, source=None): sub_graph = nx.DiGraph() sub_graph.add_edges_from(edges) if source is None: source = edges[0][0] euler = (u for u, v in nx.eulerian_circuit(sub_graph, source)) yield from euler
def _create_eulerian_path(eulerianGraph: nx.MultiGraph, start: int): """ オイラーグラフからオイラー路を生成する Parameters ---------- eulerianGraph : networkx.MultiGraph オイラーグラフ start : int オイラー路のスタート地点 Returns ------- eulerianPath : list オイラー路を辿る頂点の順番のリスト """ # オイラー路の辺リストを生成 eulerianEdges = list(nx.eulerian_circuit(eulerianGraph, start)) # オイラー路を辿る頂点の順番のリストを生成 eulerianPath = [edge[0] for edge in eulerianEdges] # オイラー路のスタート地点とゴール地点を一致させる eulerianPath.append(eulerianEdges[len(eulerianEdges) - 1][1]) return eulerianPath
def create_eulerian_circuit(graph_augmented, graph_original, starting_node=None): """Create the eulerian path using only edges from the original graph.""" euler_circuit = [] naive_circuit = list( nx.eulerian_circuit(graph_augmented, source=starting_node)) for edge in naive_circuit: edge_data = graph_augmented.get_edge_data(edge[0], edge[1]) if edge_data[0]['trail'] != 'augmented': # If `edge` exists in original graph, grab the edge attributes and add to eulerian circuit. edge_att = graph_original[edge[0]][edge[1]] euler_circuit.append((edge[0], edge[1], edge_att)) else: aug_path = nx.shortest_path(graph_original, edge[0], edge[1], weight='distance') aug_path_pairs = list(zip(aug_path[:-1], aug_path[1:])) print('Filling in edges for augmented edge: {}'.format(edge)) print('Augmenting path: {}'.format(' => '.join(aug_path))) print('Augmenting path pairs: {}\n'.format(aug_path_pairs)) # If `edge` does not exist in original graph, find the shortest path between its nodes and # add the edge attributes for each link in the shortest path. for edge_aug in aug_path_pairs: edge_aug_att = graph_original[edge_aug[0]][edge_aug[1]] euler_circuit.append((edge_aug[0], edge_aug[1], edge_aug_att)) return euler_circuit
def solve(self): "*** YOUR CODE HERE ***" self.length = dict(nx.all_pairs_dijkstra_path_length(self.nxG)) self.allPairsLengths = list(nx.all_pairs_dijkstra_path_length( self.nxG)) self.mst = nx.minimum_spanning_tree(self.nxG) self.perfect_matching = self._compute_min_perfect_matching(self.mst) """ print("size", self.perfect_matching.size()) for i in self.perfect_matching.nodes: print(len(self.perfect_matching.__getitem__(i)), i) """ self.eulerian_tour = list(nx.eulerian_circuit(self.perfect_matching)) self.tour_list = [u for u, v in self.eulerian_tour ] # + [list(self.eulerian_tour)[-1][1]] #print("tour list", self.tour_list) self.incomplete_path = self.add_back_removed_nodes( self.tour_list, self.remove_nodes) #print(self.incomplete_path) self.complete_path = self.reorganize_list(self.incomplete_path, self.graph.start) #print(self.complete_path) self.hamiltonian_path = self.create_hamiltonian_path( self.complete_path) #print(self.hamiltonian_path) #for i in range(len(self.hamiltonian_path) - 1): #if self.nxG.has_edge(self.hamiltonian_path[i], self.hamiltonian_path[i+1]) == False: #print(self.hamiltonian_path[i], self.hamiltonian_path[i+1]) #for i in self.nxG.nodes: #if i not in self.hamiltonian_path: #print(i, "False") return smartOutput(self.graph, self.hamiltonian_path, self.allPairsLengths, list(self.homes))
def make_one_permut(spanning_tree, source=None): """Creates a path from the spanning tree. For M nodes, there can be any number of possible Eulerian paths, ranging from 1 to (M - 1)!. TODO: Christofide's algorithm can be used here for the spanning tree to Eulerian path reduction. """ G = nx.MultiGraph() # Adding two copies of the edges to 'G' to make it Eulerian. G.add_edges_from(spanning_tree) G.add_edges_from(spanning_tree) permut = [None] * (len(spanning_tree) + 1) permut_idx = 0 handled_nodes = set() for (u, v) in nx.eulerian_circuit(G, source=source): if u not in handled_nodes: handled_nodes.add(u) permut[permut_idx] = u permut_idx += 1 if v not in handled_nodes: handled_nodes.add(v) permut[permut_idx] = v permut_idx += 1 return permut
def transformToBoundaryLine(lines): """ tries to find an euler circuit for each components (based on all lines/line segments) returns a tuple (number of boundary lines (= number of polygons), list of the boundary lines) """ graph = nx.Graph() # init graph for line in lines: points = [tuple(p) for p in line["coordinates"]] for p in points: graph.add_node(p) for start, end in zip(points, points[1:]): graph.add_edge(start, end) # each subgraph is one boundary line subgraphs = list(nx.connected_component_subgraphs(graph)) lines = [] for graph in subgraphs: try: edges = list(nx.eulerian_circuit(graph)) startpoint = edges[0][0] points = [start for start, end in edges] # add startpoint, as polygon rings have to end, where they started points.append(startpoint) lines.append(points) except nx.NetworkXError: # TODO: allow partly lines and partly polygons logging.debug("One of the boundary lines was not an euler train .. a very weird shape this one has") return 0, None return len(lines), lines
def twArr(G, src): H = nx.Graph() T = nx.MultiGraph(Prim(G, src).copy()) for e in list(T.edges): T.add_edge(e[0], e[1], weight=G[e[0]][e[1]]['weight']) L = np.array(list(nx.eulerian_circuit(T, src))) LNodes = list() LNoRepeat = list() for u, v in L: LNodes.append(u) LNodes.append(v) for vk in LNodes: if ((vk not in LNoRepeat) or (len(LNoRepeat) == 0)): LNoRepeat.append(vk) for v in range(len(LNoRepeat)): if (v is not len(LNoRepeat) - 1): H.add_edge(LNoRepeat[v], LNoRepeat[v + 1], weight=G[LNoRepeat[v]][LNoRepeat[v + 1]]['weight']) else: H.add_edge(LNoRepeat[v], LNoRepeat[0], weight=G[LNoRepeat[v]][LNoRepeat[0]]['weight']) return H
def twice_around(G, origin=0): H = nx.minimum_spanning_tree(G) # gero a mst a partir do grafo original H = nx.MultiGraph(H) # como somente multigrafos aceitam arestas paralelas for u, v in H.edges(): H.add_edge(u, v) #duplico arestas da mst euleraux = list(nx.eulerian_circuit(H, origin)) # gero um circuito euleriano #inicializa o grafo e cria uma lista auxiliar I = nx.Graph() aux = [] #salva o circuito euleriano na lista auxiliar for u, v in euleraux: aux.append(u) aux.append(v) h = [] for i in aux: if (i not in h): # elimino repetições h.append(i) h.append(origin) for i in range(30): I.add_edge(h[i], h[i + 1]) # gero grafo resultante I[h[i]][h[i + 1]]['weight'] = G[h[i]][h[i + 1]][ 'weight'] # copiando também o peso return I
def create_eulerian_circuit(graph_augmented, graph_original, starting_node = None): euler_circuit = [] aug_path = () aug_path_pairs = [] naive_circuit = [] naive_circuit = list(nx.eulerian_circuit(graph_augmented, source = starting_node)) # print("ddddd", naive_circuit) for edge in naive_circuit: edge_data = graph_augmented.get_edge_data(edge[0], edge[1]) if edge_data[0]['trail'] != 'augmented': edge_att = graph_original[edge[0]][edge[1]] euler_circuit.append((edge[0], edge[1], edge_att)) else: aug_path = nx.shortest_path(graph_original, edge[0], edge[1], weight = 'distance') aug_path_pairs = list(zip(aug_path[:-1], aug_path[1:])) for edge_aug in aug_path_pairs: edge_aug_att = graph_original[edge_aug[0]][edge_aug[1]] euler_circuit.append((edge_aug[0], edge_aug[1], edge_aug_att)) return euler_circuit
def set_of_edges_to_superstring(graph): cycle = nx.eulerian_circuit(graph, 'eps') superstring = '' for cur, next in cycle: if next != 'eps' and (cur == 'eps' or len(next) > len(cur)): superstring += next[-1] return superstring
def christofides(g, points): n = g.number_of_nodes() S = nx.MultiGraph() T = nx.minimum_spanning_tree(g); S.add_nodes_from(T.nodes) S.add_edges_from(T.edges) nbunch = [] for i in range(0, n): if T.degree(i) % 2 == 1: nbunch.append(i) M = nx.Graph() M.add_nodes_from(nbunch) for i in range(0, len(nbunch)-1): for j in range(i+1, len(nbunch)): M.add_edge(nbunch[i],nbunch[j], weight=-(length(points[nbunch[i]], points[nbunch[j]]))) aristas = nx.max_weight_matching(M, maxcardinality = True) for arista in aristas: S.add_edge(arista[0], arista[1], weight=length(points[arista[0]], points[arista[1]])) aristas = [u for u, v in nx.eulerian_circuit(S)] circuito = [] for arista in aristas: if arista not in circuito: circuito.append(arista) return circuito
def twiceAround(G, ini=0): F = nx.minimum_spanning_tree(G) #Gera uma MST do grafo G F = nx.MultiGraph(F) #Define um MultiGrafo for u, v in list(F.edges()): #Dublica aresta da mst F.add_edge(u, v) #Gera o caminho de euler euler = list(nx.eulerian_circuit(F, ini)) #Inicializa o grafo e cria um auxiliar caminho = nx.Graph() Aux = [] #Salva o ciclo Euleriano no Aux for u, v in euler: Aux.append(u) Aux.append(v) fila = [] for i in Aux: #Elimina as repetições if (i not in fila): fila.append(i) fila.append(ini) for i in range(Tam): #Grafo resultante caminho.add_edge(fila[i], fila[i + 1]) #Copia os pesos caminho[fila[i]][fila[i + 1]]['weight'] = G[fila[i]][fila[i + 1]]['weight'] return caminho
def chinese_postman(g, weight="weight"): """ 中国人郵便配達問題 入力 g: 無向グラフ weight: 重みの属性文字 出力 距離と頂点リスト """ import networkx as nx from itertools import combinations assert not g.is_directed() g = nx.MultiGraph(g) subnd = [nd for nd, dg in g.degree() if dg % 2 == 1] # 奇数次数ノード群 dd = nx.floyd_warshall(g, weight=weight) # 完全距離表 mx = max(d for dc in dd.values() for d in dc.values()) # 最大距離 h = nx.Graph() for i, j in combinations(subnd, 2): h.add_edge(i, j, weight=mx - dd[i][j]) for i, j in nx.max_weight_matching(h, True): # 最大重み最大マッチング問題 g.add_edge(i, j, weight=dd[i][j]) return ( sum(d[weight] for (i, j, _), d in g.edges.items()), list(nx.eulerian_circuit(g)), )
def _sort_nodes(graph): """ NetworkX does not preserve any node order for edges in MultiDiGraphs. Given a graph (component) where all nodes are of degree 1 or 2, this calculates the sequence of nodes from one node to the next. If the component has any nodes with degree 1, it must have exactly two nodes of degree 1 by this constraint (long road, strung out like a line). One of the 1-degree nodes are chosen as the start-node. If all nodes have degree 2, we have a loop and the start/end node is chosen arbitrarily. Args: graph (networkx graph): Returns: list of node ids that constitute a direct path (tour) through each node. """ edge_type = is_graph_line_or_circle(graph) degree1_nodes = [n[0] for n in graph.degree() if n[1] == 1] if edge_type == 'line': start_node, end_node = degree1_nodes nodes = spm.dijkstra_path(graph, start_node, end_node) elif edge_type == 'circle': nodes = [n[0] for n in list(nx.eulerian_circuit(graph))] else: raise RuntimeError('Unrecognized edge_type') assert len(nodes) == len(graph.nodes()) return nodes
def POSTPROCESS(cls, digraph_eul, A ) : """ This implementation is different than what is specified in FHK. It simply returns an ordering of arcs in A. The process of moving from arc to arc by shortest paths should be straightforward. (Nevertheless, the steps of FHK are written below in comments.) """ # Step 1: Given a set of arcs and edges with associated direction, # from which a tour can be constructed, find the tour. # Step 2: For any series of two or more consecutive edges in the tour, # replace them with one edge, thus eliminating intermediate vertices. (???) # Step 3: For any two vertices vi and vj anchoring an edge in the tour, # insert any vertices that would create a shorter path between vi and vj. # (Undo Step 2 of PREPROCESS.) # Step 4: List the tour beginning at vs, the initial vertex, and finishing at vf, # the terminal vertex. # Alternative Method: arcs = {} for arc in A.edges( keys=True ) : arcs.setdefault( arc[:2], [] ).append( arc ) new_walk = [] for edge in nx.eulerian_circuit( digraph_eul ) : if edge in arcs : longver = arcs[edge] new_walk.append( longver.pop(0) ) if len( longver ) <= 0 : del arcs[edge] return new_walk
def generatePath(G): even_v = [] MST = nx.minimum_spanning_tree(G) for v in MST.nodes(): if len(MST.neighbors(v)) % 2 == 0: even_v.append(v) O = G.copy() for v in even_v: O.remove_node(v) matching = [] while len(O.edges()) > 1: minEdge = findMinEdge(O) O.remove_node(minEdge[0]) O.remove_node(minEdge[1]) matching.append(minEdge) MST = nx.MultiGraph(MST) MST.add_weighted_edges_from(matching) eulerTour = list(nx.eulerian_circuit(MST)) MST = nx.Graph(MST) maxEdge = findMaxEdge(MST) rudrataPath = findEulerPath(maxEdge, eulerTour) #eulerPath swap = nx.Graph() swap.add_nodes_from(MST.nodes(data=True)) swap.add_weighted_edges_from([(u, v, G[u][v]['weight']) for (u, v) in rudrataPath]) if len(swap.nodes()) > 4: swap = double_edge_swap(G, swap, nswap=2000, max_tries=10000) path = edgesToPath(swap.edges()) problems = pathCheck(G, path) if problems > 0: path = CHEAT(G) TSP = '' for v in path: TSP += str(v) + ' ' return TSP[:-1] # gets rid of final space
def eulerian_circuit(graph): circuit = list(nx.eulerian_circuit(graph)) nodes = [] for u, v in circuit: nodes.append(u) # Close the loop nodes.append(circuit[0][0]) return nodes
def ROUTEINSPECTION( graph, weight_attr='length' ) : """ input graph should be a roadmap, i.e., a weighted multi-digraph; however, the algorithm assumes no one-way roads """ workgraph = nx.MultiGraph() # add an original copy of every edge to the workgraph for u, v, key in graph.edges_iter( keys=True ) : workgraph.add_edge( u, v, (ORIGINAL,key) ) # if non-Eulerian, add joining paths between odd-degree vertices T = ODDNODES( graph ) # metric graph met = nx.Graph() for s in T : for t in T : if t == s : continue path = nx.shortest_path( graph, s, t, weight=weight_attr ) pathlen = PATHLEN( path, graph, weight_attr ) # use weight attribute for matching, want min cost! met.add_edge( s, t, weight=-pathlen, path=path ) match = nx.max_weight_matching( met, maxcardinality=True ) extras = itertools.count() while len( match ) > 0 : s, t = match.iteritems().next() del match[s] del match[t] # have to kill both ends path = met.get_edge_data(s,t).get('path') for u,v in zip( path[:-1], path[1:] ) : #edgekey = SHORTESTEDGE(u,v, graph, weight_attr ) #idx = len( extras ) #extras.append(edgekey) idx = extras.next() workgraph.add_edge(u,v, (EXTRA,idx) ) #return workgraph # traverse walk = [] for u, v in nx.eulerian_circuit( workgraph ) : edge_data = workgraph.get_edge_data(u,v) which, key = datakey = edge_data.iterkeys().next() workgraph.remove_edge(u,v, datakey ) if which == ORIGINAL : edge_key = key elif which == EXTRA : edge_key = SHORTESTEDGE(u,v, graph, weight_attr ) if not len( walk ) > 0 : walk.append(u) walk.extend([edge_key,v]) return walk
def euler_path(graph: nx.DiGraph, func=genome_path_string) -> list: edge = balance_graph(graph) if not nx.is_eulerian(graph): raise ValueError("Not Eulerian: {0}".format(graph)) circuit = list(nx.eulerian_circuit(graph, edge[1])) #print("asdf {0}".format(circuit)) #return [ func(x) for x in circuit ] return [x[0] for x in circuit] + [ circuit[0][0] ]
def test_eulerian_circuit_multigraph(self): G=nx.MultiGraph() nx.add_cycle(G, [0, 1, 2, 3]) G.add_edge(1,2) G.add_edge(1,2) edges=list(eulerian_circuit(G,source=0)) nodes=[u for u,v in edges] assert_equal(nodes,[0,3,2,1,2,1]) assert_equal(edges,[(0,3),(3,2),(2,1),(1,2),(2,1),(1,0)])
def test_multigraph_with_keys(self): G = nx.MultiGraph() nx.add_cycle(G, [0, 1, 2, 3]) G.add_edge(1, 2) G.add_edge(1, 2) edges = list(eulerian_circuit(G, source=0, keys=True)) nodes = [u for u, v, k in edges] assert_equal(nodes, [0, 3, 2, 1, 2, 1]) assert_equal(edges[:2], [(0, 3, 0), (3, 2, 0)]) assert_count_equal(edges[2:5], [(2, 1, 0), (1, 2, 1), (2, 1, 2)]) assert_equal(edges[5:], [(1, 0, 0)])
def eulerian_circuit_verbose( multidigraph, source=None ) : registry = dict() for u,v,key in multidigraph.edges_iter( keys=True ) : pair = u,v id = u,v,key if not pair in registry : registry[pair] = [] registry[ pair ].append( id ) for pair in nx.eulerian_circuit( multidigraph, source ) : options = registry[ pair ] yield options.pop(0)
def christofides(graph_x, subset_graph): t0 = time.clock() # ******* PHASE 1 ******** # Make graph_x complete with shortest path between nodes for missing edges graph_comp = make_complete(subset_graph, graph_x) new_edges = missing_edges(subset_graph) simplified = simplify_complete(graph_comp,new_edges) # ******* PHASE 2 ******* matching_edges = match_components(subset_graph, simplified, graph_x) # Add component matching edges to Gr subset_plus_comp = subset_graph.copy() for edge in matching_edges: subset_plus_comp.add_weighted_edges_from([(edge[0],edge[1], simplified[edge[0]][edge[1]]['weight'])]) perfect_matching = call_blossom(subset_plus_comp,graph_x) final = nx.MultiGraph(subset_plus_comp) for edge in perfect_matching: # If edge exists in original graph: if graph_x.has_edge(*edge): final.add_weighted_edges_from([(edge[0],edge[1], graph_x[edge[0]][edge[1]]['weight'])]) # Else get shortest path between them and replace else: final.add_weighted_edges_from(shortest_path_edges(edge[0],edge[1],graph_x)) if nx.is_eulerian(final): tour = list(nx.eulerian_circuit(final)) t1 = time.clock() results = list() results.append(tour_cost(tour, graph_comp)) runtime = t1 - t0 results.append(runtime) results.append(tour_cost(tour, graph_comp)) results.append(runtime) results.append(check_solution(tour,graph_x,subset_graph)) print(tour) print(results) else: results = list() t1 = time.clock() results.append(0) runtime = t1 - t0 results.append(runtime) results.append(0) results.append(runtime) results.append(False) return results
def eulerian_circuit(graph): """ Given an Eulerian graph, find one eulerian circuit. Returns the circuit as a list of nodes, with the first and last node being the same. """ circuit = list(nx.eulerian_circuit(graph)) nodes = [] for u, v in circuit: nodes.append(u) # Close the loop nodes.append(circuit[0][0]) return nodes
def DOUBLETOUR( roadnet ) : eulerian = nx.MultiDiGraph() for u,v, road in roadnet.edges_iter( keys=True ) : eulerian.add_edge( u,v, label=traversal( road, True ) ) eulerian.add_edge( v,u, label=traversal( road, False ) ) tour = [] walk = [ u for u in nx.eulerian_circuit( eulerian ) ] for u, v in walk : edges = eulerian.edge[u][v] key = edges.keys()[0] # get key of the some (e.g., first) edge from u, v data = eulerian.get_edge_data( u, v, key ) tour.append( data.get('label') ) eulerian.remove_edge( u, v, key ) return tour
def twice_around(G): mst = mst_prim(G) di_mst = mst.to_directed() euler = nx.eulerian_circuit(di_mst,random.randint(0, len(G.nodes())-1)) # o problema está aqui edges = list(euler) weight = 0 for i in edges: weight += G.edge[i[0]][i[1]]['weight'] path = [] for i in list(edges): if i[0] not in path: path.append(i[0]) if i[1] not in path: path.append(i[1]) return weight, path
def euler(Graph): global start global finish find_balance(Graph) path=[] if nx.is_eulerian(Graph): circuit=list(nx.eulerian_circuit(Graph, start)) for edge in circuit: current=Graph.edge[edge[0]][edge[1]]['label'] if current != None: path.append(current) if unbalanced==0: finish=circuit.pop()[1] answer=start, path, finish print answer else: none()
def TSP(cls, graph, weight_attr='weight' ) : assert not graph.is_multigraph() cls.graph = graph # Step 1: Find a minimum cost spanning tree for the nodes {ni} MST = nx.algorithms.minimum_spanning_tree( graph, weight=weight_attr ) cls.MST = MST # Step 2: Identify nodes of odd degree in the spanning tree, # and perform a minimum cost matching on these nodes. ODD_NODES = [ u for ( u, deg ) in MST.degree_iter() if deg % 2 == 1 ] oddnode_graph = graph.subgraph( ODD_NODES ) # want a *minimum* weight matching match_graph = nx.Graph() cls.match_graph = match_graph for u, v, data in oddnode_graph.edges_iter( data=True ) : weight = -data[weight_attr] match_graph.add_edge( u, v, weight=weight ) #oddnode_graph = graph.subgraph( ODD_NODES ).copy() #for u, v, data in oddnode_graph.edges_iter( data=True ) : data[weight_attr] *= -1 MATCH = max_weight_matching( oddnode_graph, weight='weight', maxcardinality=True ) cls.MATCH = MATCH # Step 3: Define Ett as the multiset of spanning and matching edges. eulerian_graph = nx.MultiGraph() cls.eulerian_graph = eulerian_graph eulerian_graph.add_edges_from( MST.edges_iter() ) eulerian_graph.add_edges_from( MATCH.edges_iter() ) # Step 4: Form a Hamiltonian cycle circuit = nx.eulerian_circuit( eulerian_graph ) walk = [ edge for edge in circuit ] # flatten cls.walk = walk #cls.circuit = circuit # Step 5: Make the cycle Hamiltonian by shortcutting. tour = [] for u, v in walk : if u not in tour : tour.append( u ) return tour
def find_euler_tour(self, nx_euler=False): h = nx.MultiGraph() h.add_edges_from(self.mst.edges()) h.add_edges_from(self.m.edges()) if not nx.is_eulerian(h): raise ValueError('h must be eulerian') print "find euler tour" t1 = time.time() if nx_euler: euler_edges = nx.eulerian_circuit(h) self.euler_path = [e for e in euler_edges] else: self.euler_path = self.build_euler_tour(h) t2 = time.time() print "took %s" % (t2-t1) print "euler path: ", self.euler_path print '#edges:', len(self.euler_path), '#nodes:', len(h.nodes()) self.plot_edges(self.euler_path,'c--',2) self.h = h
def print_cycle(G, source=None): """Print an Eulerian cycle in G. Args: G: A Graph. source: Starting node for circuit. Returns: None """ skills = nx.get_edge_attributes(G, 'skill') try: for i in nx.eulerian_circuit(G, source): if i in skills: skill = skills[i] else: skill = skills[(i[1], i[0])] print(f'{i} {skill}') except nx.NetworkXError as ex: print(ex)
def chinese_postman_paths(graph, n=5): """ Given a graph, return a list of node id's forming the shortest chinese postman path. """ # Find all the nodes with an odd degree, and create a graph containing only them odd = odd_graph(graph) # Find the best matching of pairs of odd nodes matchings = find_matchings(odd, n) paths = [] for cost, matching in matchings[:n]: # Copy the original graph to a multigraph (so we can add more edges between the same nodes) eulerian_graph = nx.MultiGraph(graph) # For each matched pair of odd vertices, connect them with the shortest path between them for u, v in matching.items(): if v <= u: # Each matching occurs twice in the matchings: (u => v) and (v => u). We only count those where v > u continue edge = odd[u][v] path = edge['path'] # The shortest path between the two nodes, calculated in odd_graph() # Add each segment in this path to the graph again for p, q in pairs(path): eulerian_graph.add_edge(p, q, weight=graph[p][q]['weight']) # Now that we have an eulerian graph, we can calculate the eulerian circuit circuit = list(nx.eulerian_circuit(eulerian_graph)) nodes = [] for u, v in circuit: nodes.append(u) # Close the loop nodes.append(circuit[0][0]) paths.append((eulerian_graph, nodes)) return paths
def tsp_ca(siteGraph): mst = nx.minimum_spanning_tree(siteGraph,weight='weight') odds = nx.Graph() for key, value in mst.degree().iteritems(): if value % 2 != 0: odds.add_node(key) for node in odds: if node == key: continue odds.add_edge(node,key,weight=-siteGraph[node][key]['weight']) matches = nx.max_weight_matching(odds, maxcardinality=True) perfectMatch = nx.Graph() for node in odds: perfectMatch.add_node(node) for key, value in matches.iteritems(): perfectMatch.add_edge(key,value,weight=siteGraph[key][value]['weight']) eGraph = nx.MultiGraph() eGraph.add_nodes_from(mst.nodes()) eGraph.add_edges_from(mst.edges()) eGraph.add_edges_from(perfectMatch.edges()) eulerianpath = list(nx.eulerian_circuit(eGraph)) #remove repetition crossed = [] path = [] for t in eulerianpath: if 'previous' not in locals(): previous = t[0] continue if t[0] not in crossed: path.append((previous,t[0])) crossed.append(t[0]) previous = t[0] solution = nx.DiGraph() solution.add_edges_from(path) for edge in solution.edges(): solution[edge[0]][edge[1]]['weight'] = siteGraph[edge[0]][edge[1]]['weight'] return solution
def decompose_graph(g, heuristic='tour', max_odds=20, verbose=0): '''Decompose a graph into a set of non-overlapping trails.''' # Get the connected subgraphs subgraphs = [nx.subgraph(g, x) for x in nx.connected_components(g)] chains = [] num_subgraphs = len(subgraphs) step = 0 while num_subgraphs > 0: if verbose: print 'Step #{0} ({1} subgraphs)'.format(step, num_subgraphs) for i in xrange(num_subgraphs-1, -1, -1): subg = subgraphs[i] # Get all odd-degree nodes odds = [x for x,y in nx.degree(subg).iteritems() if y % 2 == 1] if verbose > 1: if len(odds) == 0: print '\t\tNo odds' elif len(odds) == 2: print '\t\tExactly 2 odds' else: print '\t\t{0} odds'.format(len(odds)) # If there are no odd-degree edges, we can find an euler circuit if len(odds) == 0: trails = [list(nx.eulerian_circuit(subg))] elif len(odds) == 2: # If there are only two odd-degree edges, we can find an euler tour trails = [calc_euler_tour(subg, odds[0], odds[1])] elif heuristic in ['min', 'max', 'median', 'any']: trails = select_odd_degree_trail(subg, odds, max_odds, heuristic, verbose) elif heuristic == 'random': trails = select_random_trail(subg, verbose) elif heuristic == 'mindegree': trails = select_min_degree_trail(subg, max_odds, verbose) elif heuristic == 'ones': trails = select_single_edge_trails(subg, verbose) elif heuristic == 'tour': trails = pseudo_tour_trails(subg, odds, verbose) if verbose > 2: print '\t\tTrails: {0}'.format(len(trails)) # Remove the trail for trail in trails: subg.remove_edges_from(trail) # Add it to the list of chains chains.extend(trails) # If the subgraph is empty, remove it from the list if subg.number_of_edges() == 0: del subgraphs[i] else: comps = list(nx.connected_components(subg)) # If the last edge split the graph, add the new subgraphs to the list of subgraphs if len(comps) > 1: for x in comps: compg = nx.subgraph(subg, x) if compg.number_of_edges() > 0: subgraphs.append(compg) del subgraphs[i] # Update the count of connected subgraphs num_subgraphs = len(subgraphs) step += 1 return chains
call(["./blossom4","-3", "-x","data.dat", "-w", "output.dat"], stdout=fh) fh.close() result = genfromtxt('output.dat', delimiter=' ', usecols = (0, 1)) result = result[1:] #MINMAXMATCHING END H = MultiGraph() H.add_nodes_from(T.nodes()) H.add_edges_from(T.edges()) for (key, value) in result: H.add_edge(N[int(key)], N[int(value)]) f = open("data.dat", "wb") t = Set() for (i, j) in eulerian_circuit(H): if i in t: continue t.add(i) f.write(str(i) + " ") f.close() fh = open("trash.dat", "w") call(["./exe", 'input.dat'], stdout = fh) fh.close() #the result is t f = open("result.dat", "rb") s = f.read() f.close() s = s.replace(";", "")
if G.in_degree(n) > G.out_degree(n): n1 = n found +=1 if G.out_degree(n) > G.in_degree(n): n2 = n found +=1 if found>=2: break G.add_edge(n1,n2) print n2 + "->" + n1 if nx.is_eulerian(G): nodes = [] temp_nodes = [] start = False for u,v in nx.eulerian_circuit(G,source=n1): if (u == n1) and (v == n2): start = True if start: nodes.append(v) else: temp_nodes.append(v) nodes += temp_nodes print >>out, "->".join(str(n) for n in nodes) print >> sys.stderr, "Finished!" else: print "Not Eulerian" print G.edges()
def test_not_eulerian(self): f=list(eulerian_circuit(nx.complete_graph(4)))