def create_pes(): global mvp pattern = em.EmbPattern() vertices = [ world_space_to_screen_space(vert) for vert in scene.vertices ] def to_i4(l): return l[0] | l[1] << 8 | l[2] << 16 | l[3] << 24 im = list(face_fbo.read(components=1, dtype='i4')) visible_faces = Counter([ to_i4(im[k:k+4]) for k in range(0,len(im),4) ]) del visible_faces[0xFFFFFFFF] # TODO count pixels of visible faces and prune any with fewer than some number print(visible_faces) # faces = visible_faces threshold = 10 faces = [ f for f,cnt in visible_faces.items() if cnt >= threshold ] G = nx.Graph() # go through all things in scene indices for idx in faces: face = scene.mesh_list[0].faces[idx] verts = [ tuple(vertices[p]) for p in face ] edges = list(zip(verts, islice(cycle(verts), 1, None))) G.add_edges_from(edges) stitches = [] for C in [ G.subgraph(c) for c in nx.connected_components(G) ]: for (p0, p1) in nx.eulerian_circuit(nx.eulerize(C)): # needs to be at least 2 for t in np.linspace(0, 1, 2): stitches.append(((1-t)*p0[0] + t*p1[0], (1-t)*p0[1] + t*p1[1])) stitches = [ k for k,g in groupby(stitches) ] for (x, y) in stitches: pattern.add_stitch_absolute(em.STITCH, x, y) # create dst format (pes doesn't work?) print("Saving file...") em.write_dst(pattern, 'file.dst') em.write_pes(pattern, 'file.pes') em.write_txt(pattern, 'file.txt') print("Done.")
''' TEST ON A SIMPLE TOY ''' print("\nHierholzer eulerian path test on toy example") toy = nx.Graph() toy.add_nodes_from(['A', 'B', 'C', 'D', 'E']) # graph with 2 triangles toy.add_edges_from([('A', 'B'), ('A', 'C'), ('B', 'C'), ('C', 'D'), ('C', 'E'), ('D', 'E')]) print(nx.is_eulerian(toy), nx.has_eulerian_path(toy)) print(hierholzer(toy)) ''' Eulerian Path test i made the test on R and on a toy example because eulerian path on graph of provinces dosen't exist because the graph of provinces in not strongly connected''' time_eulerian = [] time_eulerian_nx = [] num_node = [3, 9, 19, 29, 39, 49] for test in range(len(num_node)): toy = nx.complete_graph(num_node[test]) toy = nx.eulerize(toy) # print(nx.is_eulerian(toy)) # print(nx.has_eulerian_path(toy)) # print(nx.has_eulerian_path(R)) # print(nx.has_eulerian_path(P)) '''EULERIAN PATH ON A TOY EXAMPLE USING NETWORKX''' start = time.time() path = nx.eulerian_path(toy) # print(list(path)) end = time.time() time_eulerian_nx.append(end - start) '''EULERIAN PATH ON A TOY EXAMPLE USING IMPLEMENTED FUNCTIONS''' start = time.time() path = hierholzer(toy) # print(path) end = time.time()
print("h) R =", vertex_cover.min_weighted_vertex_cover(G)) print() # i) Minimum edge cover print("i) F =", covering.min_edge_cover(G)) print() # j) Shortest closed path (circuit) that visits every vertex print("j) W =", end=" ") for i in range(len(tournament.hamiltonian_path(D))): print(tournament.hamiltonian_path(D)[i], "-", end=" ") print(tournament.hamiltonian_path(D)[0]) print() # k) Shortest closed path (circuit) that visits every edge H = nx.eulerize(G) c = list(n for (n, d) in nx.eulerian_circuit(H)) print("k) U =", end=" ") for i in range(len(c)): print(c[i], "-", end=" ") print(c[0]) print() # m) 2-edge-connected components print("m) ", list(edge_kcomponents.bridge_components(G))) print() # o) MST MST = nx.Graph(mst.minimum_spanning_tree(G)) print("o) MST = ", MST.nodes) print("Weight =", sum(c for (a, b, c) in (MST.edges.data('weight'))))
def test_on_complete_graph(self): G = nx.complete_graph(4) assert_true(nx.is_eulerian(nx.eulerize(G))) assert_true(nx.is_eulerian(nx.eulerize(nx.MultiGraph(G))))
def test_on_eulerian_multigraph(self): G = nx.MultiGraph(nx.cycle_graph(3)) G.add_edge(0, 1) H = nx.eulerize(G) assert_true(nx.is_eulerian(H))
def _order_edges_in_block(self, block_data, drop_augmented): """Produce an edge sequence for all edges in the component. Parameters ---------- block_data : pandas.DataFrame A DataFrame representing all the edges within a single block. drop_augmented : bool Whether or not to keep any edges that needed to be added to the source edges in order to navigate the network. Returns ------- edges : pandas.DataFrame The same edges that were input with the edge order and route type as new columns. """ logger.debug("order_edges_by_block started") logger.debug("Received edge data of shape %s", block_data.shape) # Sort the DataFrame to load right hand arcs into NetworkX first. # Note that Eulerian paths work in reverse order. block_data = block_data.sort_values(self.leftrightflag_field, ascending=False) block_g = nx.from_pandas_edgelist(block_data, source=self.source_field, target=self.target_field, edge_attr=True, create_using=self.graph_type) logger.debug("Block contains %s edges and %s nodes", block_g.number_of_edges(), block_g.number_of_nodes()) # if the graph is empty it means there is a problem with the source data # an error is logged, but other blocks are still processed if nx.is_empty(block_g): logger.error("Block contains no edges and cannot be sequenced") return # Scale nodes that are mid-segment by looking for duplicated ngd_str_uid values logger.debug( "Looking for nodes that fall in the middle of a road segment") block_data['same_ngd_str_uid'] = block_data.duplicated( subset=[self.struid_field], keep=False) mid_arc_start_nodes = set( block_data.loc[block_data['same_ngd_str_uid'] == True, self.source_field]) mid_arc_end_nodes = set( block_data.loc[block_data['same_ngd_str_uid'] == True, self.target_field]) mid_arc_nodes = mid_arc_start_nodes.intersection(mid_arc_end_nodes) if mid_arc_nodes: logger.debug("Found mid-segment nodes: %s", mid_arc_nodes) self._apply_node_scaling_factor(mid_arc_nodes, factor=-0.5) # initialize the edge sequence counter edge_sequence = 0 # record what type of path was used to determine the circuit path_indicator_name = self.path_indicator path_indicator_edges = {} # blocks don't necessarily form fully connected graphs, so cycle through the components logger.debug("Block contains %s connected components", nx.number_weakly_connected_components(block_g)) for block_comp in sorted(nx.weakly_connected_components(block_g), key=len, reverse=True): logger.debug( "Creating subgraph from connected component with %s nodes", len(block_comp)) block_g_comp = block_g.subgraph(block_comp) # determine the preferred start node for this block component preferred_sp = self._get_preferred_start_node(block_g_comp.nodes) logger.debug("Preferred start node for this block: %s", preferred_sp) logger.debug("Component contains %s edges and %s nodes", block_g_comp.number_of_edges(), len(block_g_comp)) # Need to pick an approach to processing this component depending on what type of circuit it forms. # Ideally things are a Eulerian circuit that can be walked and return to start, but not all blocks form # these nice circuits. If no good circuit can be found, then sequence numbers are just applied but may # not form a logical order. # Track the sequence value in case the enumeration method needs to be reset. This gets used when using # the preferred start point fails, and also controls if the start node for this component is marked as a # point we want to cluster on. seq_val_at_start = edge_sequence # the preferred option is a Eulerian circuit, so try that first # logger.debug("Available edges: %s", block_g_comp.edges) if nx.is_eulerian(block_g_comp): logger.debug("Block component is eulerian.") # record all these edges as being eulerian indicator = dict( zip(block_g_comp.edges, ['circuit'] * block_g_comp.size())) path_indicator_edges.update(indicator) # enumerate the edges and order them directly logger.debug("Creating Eulerian circuit from node %s", preferred_sp) for u, v, k in nx.eulerian_circuit(block_g_comp, source=preferred_sp, keys=True): edge_sequence += 1 block_g.edges[u, v, k][self.eo_name] = edge_sequence # logger.debug("Sequence applied: (%s, %s, %s) = %s", u, v, k, edge_sequence) # next best option is a path that stops at a different location from the start point elif nx.has_eulerian_path(block_g_comp): logger.debug("Block component forms Eulerian path") # record all these edges as being a eulerian path indicator = dict( zip(block_g_comp.edges, ['path'] * block_g_comp.size())) path_indicator_edges.update(indicator) try: logger.debug( "Trying to create path from preferred start node %s", preferred_sp) for u, v, k in nx.eulerian_path(block_g_comp, source=preferred_sp, keys=True): edge_sequence += 1 # check if the start point is actually in the first edge if edge_sequence == 1 and not (preferred_sp == u or preferred_sp == v): logger.debug( "Preferred start point not present on starting edge, throwing KeyError." ) raise KeyError("Invalid starting edge") # Sometimes the preferred start point means walking over the same edge twice, which will leave # a data gap (the previous edge order value will be overwritten). If this happens, throw a # KeyError if block_g.edges[u, v, k].get(self.eo_name): logger.debug("Edge already sequenced.") raise KeyError( "Preferred start point results in backtracking." ) block_g.edges[u, v, k][self.eo_name] = edge_sequence # logger.debug("Sequence applied: (%s, %s, %s) = %s", u, v, k, edge_sequence) if edge_sequence < block_g_comp.number_of_edges(): logger.debug("It looks like some edges got missed") raise KeyError("Missing edges on path") logger.debug( "Path was created from desired start point %s", preferred_sp) except KeyError: # preferred start point failed; let networkx pick and start over logger.debug( "Preferred start node did not create a path. Trying a different one." ) # reset the path listing since a new point will be picked logger.debug("Reset edge_sequence value to %s", seq_val_at_start) edge_sequence = seq_val_at_start for u, v, k in nx.eulerian_path(block_g_comp, keys=True): edge_sequence += 1 block_g.edges[u, v, k][self.eo_name] = edge_sequence # logger.debug("Sequence applied: (%s, %s, %s) = %s", u, v, k, edge_sequence) # No good path exists, which means someone will have to backtrack else: logger.debug( "Non-eulerian block is not easily traversable. Eulerizing it." ) # Record all these edges as being augmented. indicator = dict( zip(block_g_comp.edges, ['augmented'] * block_g_comp.size())) path_indicator_edges.update(indicator) # Send this data to the anomaly folder so that it can be investigated later. It could have addressable # issues that operations can correct for the next run. logger.debug("Writing anomaly set for this block") bf_uid_set = list( nx.get_edge_attributes( block_g_comp, self.edge_uid_field).values()).pop() anomaly_file_name = f"anomaly_block_component.{bf_uid_set}.yaml" nx.write_yaml(block_g_comp, (self.anomaly_folder / anomaly_file_name).as_posix()) # You cannot eulerize a directed graph, so create an undirected one logger.debug("Creating MultiGraph from directed graph.") temp_graph = nx.MultiGraph() for u, v, data in block_g_comp.edges(data=True): key = temp_graph.add_edge(u, v, **data) # logger.debug("Adding edge (%s, %s, %s) to temporary graph.", u, v, key) logger.debug("Created temporary MultiGraph with %s edges", temp_graph.number_of_edges()) # Convert the temporary graph to a proper Euler circuit so that it can be traversed. logger.debug("Eulerizing MultiGraph") euler_block = nx.eulerize(temp_graph) logger.debug("Added %s edges to the block", (euler_block.size() - temp_graph.size())) logger.debug("Number of vertices in eulerized graph: %s", euler_block.number_of_nodes()) # As we try to traverse the undirected graph, we need to keep track of places already visited to make # sure arcs are not skipped. visited_edges = Counter() # augmented edges will throw the node weights off, so don't bother trying the preferred start node logger.debug("Generating path through augmented block") for u, v, k in nx.eulerian_circuit(euler_block, preferred_sp, keys=True): # augmented edges have no attributes, so look for one and skip the edge if nothing is returned if drop_augmented and not euler_block.edges[u, v, k].get( self.edge_uid_field): logger.debug("Ignoring augmented edge (%s, %s, %s)", u, v, k) continue # Increment the sequence value for each edge we see. edge_sequence += 1 # Since we formed an undirected MultiGraph we need to check the orientation of the nodes on the # edge to assign the sequence back to the directed graph. start_node = u end_node = v available_edge_count = block_g.number_of_edges( start_node, end_node) # If no edges exist, invert the nodes and check again. # This also checks to see if we've already encountered all the edges between these nodes, indicating # we need to process the inverse of the start and end values if available_edge_count == 0 or ( ((start_node, end_node) in visited_edges) and (available_edge_count == visited_edges[(start_node, end_node)])): logger.debug( "Nothing to process between (%s, %s), inverting nodes.", start_node, end_node) start_node = v end_node = u available_edge_count = block_g.number_of_edges( start_node, end_node) logger.debug( "Number of edges available between (%s, %s): %s", start_node, end_node, available_edge_count) # Apply the edge_sequence to the first edge that hasn't received one yet for ki in range(available_edge_count): if not block_g.edges[start_node, end_node, ki].get( self.eo_name): logger.debug( "Edge sequence applied: (%s, %s, %s) = %s", start_node, end_node, ki, edge_sequence) block_g.edges[start_node, end_node, ki][self.eo_name] = edge_sequence visited_edges[(start_node, end_node)] += 1 break # At this point every edge should be accounted for, but in case something somehow slips through the cracks # it needs to be given a sequence label. The label almost certainly won't make much sense in terms of a # logical ordering, but this is just trying ot make sure it is counted. logger.debug("Looking for any missed edges in block component") for u, v, k in block_g_comp.edges: if not block_g.edges[u, v, k].get(self.eo_name): edge_sequence += 1 block_g.edges[u, v, k][self.eo_name] = edge_sequence logger.warning( "Applied out of order sequence to component edge (%s, %s, %s): %s", u, v, k, edge_sequence) # just log the last sequence value to make tracing easier logger.debug("Final edge sequence value for component: %s", edge_sequence) # apply a sequence value to all the edges that were discovered logger.debug("Edge order results: %s", nx.get_edge_attributes(block_g_comp, self.eo_name)) # To help cluster the start nodes, mark which node was used as the start point in this block if seq_val_at_start == 1: self._mark_chosen_start_node(block_g_comp, preferred_sp) logger.debug("Finished processing component") # record that block processing is finished logger.debug("Block processing complete") # nx.set_edge_attributes(block_g, block_sequence_labels, self.eo_name) nx.set_edge_attributes(block_g, path_indicator_edges, path_indicator_name) # check to see if the counts line up if not block_g.number_of_edges() == edge_sequence: logger.debug( "Edge sequence (%s) and edge count (%s) do not match in block", edge_sequence, block_g.number_of_edges()) # help start point clustering by apply a scaling factor to all nodes that were touched logger.debug( "Applying scaling factor to nodes in this block, except start point" ) nodes_in_block = set(block_g.nodes()) nodes_in_block.remove( preferred_sp) # don't scale the preferred start point self._apply_node_scaling_factor(nodes_in_block) logger.debug("Final node data for block: %s", self.graph.subgraph(block_g.nodes).nodes(data=True)) logger.debug("Returning pandas DataFrame from block graph.") return nx.to_pandas_edgelist(block_g, source=self.source_field, target=self.target_field)
def test_on_eulerian_multigraph(self): G = nx.MultiGraph(nx.cycle_graph(3)) G.add_edge(0, 1) H = nx.eulerize(G) assert nx.is_eulerian(H)
def test_on_empty_graph(self): with pytest.raises(nx.NetworkXError): nx.eulerize(nx.empty_graph(3))
def test_null_graph(self): nx.eulerize(nx.Graph())
def test_disconnected(self): G = nx.from_edgelist([(0, 1), (2, 3)]) nx.eulerize(G)
n = ps[0] m = ps[1] graph = nx.Graph() for i in range(0, m): s = f.readline() ps = [float(i) for i in s.split()] v = int(ps[0]) u = int(ps[1]) graph.add_edge(v, u, weight = 1) f.close() f = open("outputPy.txt", "w") f.write("maximum stable set = " + str(approximation.independent_set.maximum_independent_set(graph)) + '\n') f.write("maximum matching = " + str(nx.max_weight_matching(graph)) + '\n') f.write("minimum vertex cover = " + str(approximation.vertex_cover.min_weighted_vertex_cover(graph)) + '\n') f.write("minimum edge cover = " + str(nx.min_edge_cover(graph))) f.write("minimum path that visits every edge: " + str(list(nx.eulerian_circuit(nx.eulerize(graph))))) dists = dict(nx.all_pairs_shortest_path_length(graph)) paths = dict(nx.all_pairs_shortest_path(graph)) distsArr = [] listsCnt = 0 for i in range(1, n + 1): if i == 9 or i == 27 or i == 19 or i == 46 or i == 18: continue distsArr.append([]) listsCnt += 1 for j in range(1, n + 1): if j == 9 or j == 27 or j == 19 or j == 46 or j == 18: continue distsArr[listsCnt - 1].append(dists[i][j]) vertexes = [] for i in range(1, n + 1):
pos, edgelist=esmall, width=2, alpha=0.5, edge_color='b', style='dashed') # labels nx.draw_networkx_labels(G, pos, font_size=11, font_family='sans-serif', font_color='blue') nx.draw_networkx_edge_labels(G, pos=nx.spectral_layout(G), font_size=5) nx.eulerize(G) plt.axis('off') plt.savefig("weighted_graph.png") # save as png plt.tight_layout(True) plt.suptitle('Eulerized Graph, Distance Model (miles)') plt.show() # display print( startGreen + '------------- Algorithmic Path Experiments post-Eulerian Graph' + ' -------------' + endColor, '\n') print( startBlue + '\nShortest path from Pensacola to Phoenix, Eulerized Graph:\n' + endColor,
fin_country = open("europe.txt") fin_edges = open("distances.txt") country = [] # список стран edges = [] # список рёбер G = nx.Graph() # граф matrix = [[0] * V for i in range(V)] for i in range(V): pars_one = fin_country.readline().split('.') if i != V - 1: num, name = pars_one[0], pars_one[1][:-1] else: num, name = pars_one[0], pars_one[1] country.append(name) for i in range(E): pars_two = fin_edges.readline().split() a, b = int(pars_two[0]), int(pars_two[1]) matrix[a][b] = matrix[b][a] = 1 edges.append([a, b]) # создадим граф for i in range(E): a, b = edges[i] G.add_edge(country[a], country[b]) # Построим кратчайший замкнутый путь, с помощью функции либы networkx a = list(nx.eulerian_circuit(nx.eulerize(G))) for i in a: v1, v2 = i print('(', v1, '-->', v2, end=') ')
def test_disconnected(self): with pytest.raises(nx.NetworkXError): G = nx.from_edgelist([(0, 1), (2, 3)]) nx.eulerize(G)
def test_null_multigraph(self): nx.eulerize(nx.MultiGraph())
def test_null_multigraph(self): with pytest.raises(nx.NetworkXPointlessConcept): nx.eulerize(nx.MultiGraph())
def test_on_empty_graph(self): nx.eulerize(nx.empty_graph(3))
def test_on_eulerian(self): G = nx.cycle_graph(3) H = nx.eulerize(G) assert nx.is_isomorphic(G, H)
def test_on_eulerian(self): G = nx.cycle_graph(3) H = nx.eulerize(G) assert_true(nx.is_isomorphic(G, H))
def test_on_complete_graph(self): G = nx.complete_graph(4) assert nx.is_eulerian(nx.eulerize(G)) assert nx.is_eulerian(nx.eulerize(nx.MultiGraph(G)))
G.add_edge('B', 'G', weight=35) G.add_edge('C', 'D', weight=70) G.add_edge('C', 'F', weight=28) G.add_edge('D', 'E', weight=80) G.add_edge('E', 'F', weight=62) G.add_edge('F', 'G', weight=40) posicoes = { 'A': (0, 3), 'B': (3, 2), 'C': (6, 1), 'D': (10, 0), 'E': (9, 5), 'F': (7, 3), 'G': (2, 5) } # rotulos = nx.get_edge_attributes(G, 'weight') nx.draw(G, posicoes, with_labels=True) # nx.draw_networkx_edge_labels(G, posicoes, edge_labels=rotulos) print("É Euleriano?", nx.is_eulerian(G)) print("Arestas:", G.edges(data=True)) print("# de arestas:", G.number_of_edges()) print("Soma total dos pesos:", G.size(weight='weight')) G_eulerizado = nx.eulerize(G) print("\nÉ Euleriano?", nx.is_eulerian(G_eulerizado)) print("Arestas:", G_eulerizado.edges(data=True)) print("# de arestas:", G_eulerizado.number_of_edges()) print("Soma total dos pesos:", G_eulerizado.size(weight='weight'))