def build_path(self): if self.G is None: self.build_graph() self.path, _ = cpp(self.G) self.path = [(e1, e2) for e1, e2, _, _ in self.path] return self.path
def eulerCicle(graph): edgelist = nx.to_pandas_edgelist(graph, source='_node1', target='_node2') edgelist_file = create_mock_csv_from_dataframe(edgelist) circuit_cpp_req, _ = cpp(edgelist_file) print('Print the CPP solution:') # solve chinese postman problem on graph # result circuit_cpp_req is in the form ('6.0', '2.0', 0, {'distance': 1.05144, 'id': 6, 'augmented': True}) # node1_| |_node2 index # keep only the nodes circuit_edges = [] for e in circuit_cpp_req: circuit_edges.append((int(float(e[0])), int(float(e[1])))) return circuit_edges
def postman(osm_data): Settings = IngestSettings( max_distance=Distance(km=50), max_segments=300, max_concurrent=40, quality_settings=DefaultQualitySettings, location_filter=None, ) loader = OSMIngestor(Settings) loader.load_osm(osm_data, extra_links=[(885729040, 827103027)]) # s = datetime.now() # data = write_gpickle(loader.global_graph, 'test.pickle') #nx_yaml.write_yaml(loader.global_graph, 'test.yaml') # e = datetime.now() # print(e-s) # s = datetime.now() # graph = read_gpickle('test.pickle') # e = datetime.now() # print(e-s) # import pdb; pdb.set_trace() for i, network in enumerate(loader.trail_networks()): print(network.name, network.total_length().mi) print(network.trail_names()) gmap = gmplot.GoogleMapPlotter(42.385, -71.083, 13) edge_map = {} for segment in network.trail_segments(): segment.draw(gmap) edge_map[segment.id] = segment.nodes clean_name = (network.name or f'no-name-{i}').replace(' ', '').replace("\'", '') gmap.draw(f"{clean_name}-{i}.html") with open('edges.csv', 'w') as csv_file: writer = csv.DictWriter(csv_file, fieldnames=['start', 'end', 'id', 'distance']) writer.writeheader() for segment in network.trail_segments(): writer.writerow(dict(start=segment.nodes[0].id, end=segment.nodes[-1].id, id=segment.id, distance=segment.length_m())) try: s = datetime.now() circuit, graph = cpp('edges.csv') e = datetime.now() print(f'Time: {e-s}') for k, v in calculate_postman_solution_stats(circuit).items(): print(k, v) with open(f"{clean_name}-{i}.gpx", "w") as f: f.write(circuit_to_gpx(circuit, edge_map).to_xml()) except Exception as ex: print(ex)
def test_sleeping_giant_cpp_solution(): cpp_solution, graph = cpp(edgelist_filename=EDGELIST, start_node=START_NODE) # make number of edges in solution is correct assert len(cpp_solution) == 155 # make sure our total mileage is correct cpp_solution_distance = sum([edge[3]['distance'] for edge in cpp_solution]) assert math.isclose(cpp_solution_distance, 33.25) # make sure our circuit begins and ends at the same place assert cpp_solution[0][0] == cpp_solution[-1][1] == START_NODE # make sure original graph is properly returned assert len(graph.edges()) == 121 [e[2].get('augmented') for e in graph.edges(data=True)].count(True) == 35
def solvePostmanProblem(name, write=True, write_minimal=True): filename = "graphs_in_csv/" + name + ".csv" # find CPP solution circuit, graph = cpp(edgelist_filename=filename) if write: print(circuit) if write_minimal: print("\tNumber of edges walked: " + str(len(circuit))) """ # print solution route for e in circuit: print(e) """ if write: # print solution summary stats for k, v in calculate_postman_solution_stats(circuit).items(): print(k, v) createCsvFromCircuit(circuit, name)
def create_circuit(self, network_id: str, circuit_id: str): network = TrailNetwork.objects.get(id=network_id) circuit = Circuit.objects.get(id=circuit_id) circuit.status = InProgress circuit.error = "" circuit.save() try: graph = read_gpickle(BytesIO(network.graph.tobytes())) with NamedTemporaryFile(suffix='.csv', mode='w') as f: writer = csv.DictWriter( f, fieldnames=['start', 'end', 'id', 'distance']) writer.writeheader() edge_map = {} for segment in segments_for_graph(graph): writer.writerow( dict(start=segment.nodes[0].derived_id, end=segment.nodes[-1].derived_id, id=segment.id, distance=segment.length_m())) edge_map[segment.id] = segment.nodes f.flush() circuit_nodes, _ = solver.cpp(f.name) stats = calculate_postman_solution_stats(circuit_nodes) walked_twice = Distance(m=stats['distance_doublebacked']) walked_total = Distance(m=stats['distance_walked_required']) line_string = circuit_to_line_string(circuit_nodes, edge_map) circuit.route = line_string circuit.total_length = walked_total circuit.status = Complete circuit.error = "" except Exception as ex: circuit.status = Error circuit.error = ex raise finally: circuit.save()
from postman_problems.solver import cpp from postman_problems.stats import calculate_postman_solution_stats # find CPP solution circuit, graph = cpp(edgelist_filename='graph.csv', start_node='A') # print solution route for e in circuit: print(e) # print solution summary stats for k, v in calculate_postman_solution_stats(circuit).items(): print(k, v)
def main(): """Solve the RPP and save visualizations of the solution""" # PARAMS / DATA --------------------------------------------------------------------- # inputs START_NODE = 'a' N_NODES = 13 # filepaths CPP_REQUIRED_SVG_FILENAME = pkg_resources.resource_filename( 'postman_problems', 'examples/star/output/cpp_graph_req') CPP_OPTIONAL_SVG_FILENAME = pkg_resources.resource_filename( 'postman_problems', 'examples/star/output/cpp_graph_opt') RPP_SVG_FILENAME = pkg_resources.resource_filename( 'postman_problems', 'examples/star/output/rpp_graph') RPP_BASE_SVG_FILENAME = pkg_resources.resource_filename( 'postman_problems', 'examples/star/output/base_rpp_graph') PNG_PATH = pkg_resources.resource_filename('postman_problems', 'examples/star/output/png/') RPP_GIF_FILENAME = pkg_resources.resource_filename( 'postman_problems', 'examples/star/output/rpp_graph.gif') # setup logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # CREATE GRAPH ---------------------------------------------------------------------- logger.info('Solve RPP') graph_base = create_star_graph(N_NODES) edgelist = nx.to_pandas_edgelist(graph_base, source='_node1', target='_node2') # SOLVE CPP ------------------------------------------------------------------------- # with required edges only edgelist_file = create_mock_csv_from_dataframe(edgelist) circuit_cpp_req, graph_cpp_req = cpp(edgelist_file, start_node=START_NODE) logger.info('Print the CPP solution (required edges only):') for e in circuit_cpp_req: logger.info(e) # with required and optional edges as required edgelist_all_req = edgelist.copy() edgelist_all_req.drop(['required'], axis=1, inplace=True) edgelist_file = create_mock_csv_from_dataframe(edgelist_all_req) circuit_cpp_opt, graph_cpp_opt = cpp(edgelist_file, start_node=START_NODE) logger.info('Print the CPP solution (optional and required edges):') for e in circuit_cpp_opt: logger.info(e) # SOLVE RPP ------------------------------------------------------------------------- edgelist_file = create_mock_csv_from_dataframe( edgelist) # need to regenerate circuit_rpp, graph_rpp = rpp(edgelist_file, start_node=START_NODE) logger.info('Print the RPP solution:') for e in circuit_rpp: logger.info(e) logger.info('Solution summary stats:') for k, v in calculate_postman_solution_stats(circuit_rpp).items(): logger.info(str(k) + ' : ' + str(v)) # VIZ ------------------------------------------------------------------------------- try: from postman_problems.viz import plot_circuit_graphviz, plot_graphviz, make_circuit_images, make_circuit_video logger.info('Creating single SVG of base graph') plot_graphviz(graph=graph_base, filename=RPP_BASE_SVG_FILENAME, edge_label_attr='distance', format='svg', engine='circo', graph_attr={ 'label': 'Base Graph: Distances', 'labelloc': 't' }) logger.info( 'Creating single SVG of CPP solution (required edges only)') plot_circuit_graphviz( circuit=circuit_cpp_req, graph=graph_cpp_req, filename=CPP_REQUIRED_SVG_FILENAME, format='svg', engine='circo', graph_attr={ 'label': 'Base Graph: Chinese Postman Solution (required edges only)', 'labelloc': 't' }) logger.info( 'Creating single SVG of CPP solution (required & optional edges)') plot_circuit_graphviz( circuit=circuit_cpp_opt, graph=graph_cpp_opt, filename=CPP_OPTIONAL_SVG_FILENAME, format='svg', engine='circo', graph_attr={ 'label': 'Base Graph: Chinese Postman Solution (required & optional edges)', 'labelloc': 't' }) logger.info('Creating single SVG of RPP solution') plot_circuit_graphviz(circuit=circuit_rpp, graph=graph_rpp, filename=RPP_SVG_FILENAME, format='svg', engine='circo', graph_attr={ 'label': 'Base Graph: Rural Postman Solution', 'labelloc': 't' }) logger.info('Creating PNG files for GIF') make_circuit_images(circuit=circuit_rpp, graph=graph_rpp, outfile_dir=PNG_PATH, format='png', engine='circo') logger.info('Creating GIF') make_circuit_video(infile_dir_images=PNG_PATH, outfile_movie=RPP_GIF_FILENAME, fps=1) except FileNotFoundError(OSError) as e: print(e) print( "Sorry, looks like you don't have all the needed visualization dependencies." )
G.add_edges_from(edges) G.remove_nodes_from(list(nx.isolates(G))) # Get largest connected component G = max(nx.connected_component_subgraphs(G), key=len) # ### -------TEST --- # nodes = list(G.nodes()) # poses = [(x, 255 - y) for x, y in nodes] # pos = dict(zip(nodes, poses)) # ax = plt.axes(aspect='equal') # nx.draw_networkx(G, pos=pos, ax=ax, # with_labels=False, nodelist=[], node_size=15, # edge_color='black', width=2) # plt.show() # ### -- END TEST -- path, _ = cpp(G) path = [(e1, e2) for e1, e2, _, _ in path] ## ADD STOPS # Add start stops_nodes = [path[0][0]] dist = 0 for e in path: d = G.get_edge_data(e[0], e[1])[0]['distance'] dist += d if dist >= 300: stops_nodes.append(e[1]) dist = 0 # Remove last item if we are less than 150 from start if dist < 150:
def test_cpp_graph_1(GRAPH_1_EDGELIST_CSV): circuit, graph = cpp(GRAPH_1_EDGELIST_CSV, start_node='a') assert len(circuit) == 7 # Re-use the test for the summary_stats function to ensure CPP solution is correct test_stats_on_simple_graph_required_edges_only(circuit)
tmp = [] for e in g_tc.edges(data=True): tmpi = e[2].copy() # so we don't mess w original graph tmpi['start_node'] = e[0] tmpi['end_node'] = e[1] tmp.append(tmpi) # create dataframe with node1 and node2 in order eldf = pd.DataFrame(tmp) eldf = eldf[['start_node', 'end_node'] + list(set(eldf.columns) - {'start_node', 'end_node'})] # create edgelist mock CSV elfn = create_mock_csv_from_dataframe(eldf) circuit, graph = cpp(elfn, start_node='735393342') print("----------- CPP Solutions -----------") # print solution route for e in circuit: print(e) print("----------- CPP Summary -----------") # print solution summary stats for k, v in calculate_postman_solution_stats(circuit).items(): print(k, v) # convert 'path' from string back to list. Caused by `create_mock_csv_from_dataframe` for e in circuit: if type(e[3]['path']) == str: exec('e[3]["path"]=' + e[3]["path"])
def main(): """Solve the CPP and save visualizations of the solution""" # PARAMS / DATA --------------------------------------------------------------------- # inputs EDGELIST = pkg_resources.resource_filename( 'postman_problems', 'examples/sleeping_giant/edgelist_sleeping_giant.csv') NODELIST = pkg_resources.resource_filename( 'postman_problems', 'examples/sleeping_giant/nodelist_sleeping_giant.csv') START_NODE = "b_end_east" # outputs GRAPH_ATTR = {'dpi': '65'} EDGE_ATTR = {'fontsize': '20'} NODE_ATTR = { 'shape': 'point', 'color': 'black', 'width': '0.1', 'fixedsize': 'true' } PNG_PATH = pkg_resources.resource_filename( 'postman_problems', 'examples/sleeping_giant/output/png/') CPP_SVG_FILENAME = pkg_resources.resource_filename( 'postman_problems', 'examples/sleeping_giant/output/cpp_graph') CPP_GIF_FILENAME = pkg_resources.resource_filename( 'postman_problems', 'examples/sleeping_giant/output/cpp_graph.gif') # setup logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # SOLVE CPP ------------------------------------------------------------------------- logger.info('Solve CPP') circuit, graph = cpp(EDGELIST, START_NODE) logger.info('Print the CPP solution:') for e in circuit: logger.info(e) logger.info('Solution summary stats:') for k, v in calculate_postman_solution_stats(circuit).items(): logger.info(str(k) + ' : ' + str(v)) # VIZ ------------------------------------------------------------------------------- try: from postman_problems.viz import (add_pos_node_attribute, add_node_attributes, plot_circuit_graphviz, make_circuit_images, make_circuit_video) logger.info('Add node attributes to graph') nodelist_df = pd.read_csv(NODELIST) graph = add_node_attributes(graph, nodelist_df) # add attributes graph = add_pos_node_attribute( graph, origin='topleft') # add X,Y positions in format for graphviz logger.info('Creating single SVG of CPP solution') plot_circuit_graphviz(circuit=circuit, graph=graph, filename=CPP_SVG_FILENAME, format='svg', engine='neato', graph_attr=GRAPH_ATTR, edge_attr=EDGE_ATTR, node_attr=NODE_ATTR) except FileNotFoundError(OSError) as e: print(e) print( "Sorry, looks like you don't have all the needed visualization dependencies." )
def main(): """Solve the CPP and save visualizations of the solution""" # PARAMS / DATA --------------------------------------------------------------------- # inputs EDGELIST = pkg_resources.resource_filename( 'postman_problems', 'examples/seven_bridges/edgelist_seven_bridges.csv') START_NODE = 'D' # outputs PNG_PATH = pkg_resources.resource_filename( 'postman_problems', 'examples/seven_bridges/output/png/') CPP_VIZ_FILENAME = pkg_resources.resource_filename( 'postman_problems', 'examples/seven_bridges/output/cpp_graph') CPP_BASE_VIZ_FILENAME = pkg_resources.resource_filename( 'postman_problems', 'examples/seven_bridges/output/base_cpp_graph') CPP_GIF_FILENAME = pkg_resources.resource_filename( 'postman_problems', 'examples/seven_bridges/output/cpp_graph.gif') # setup logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # SOLVE CPP ------------------------------------------------------------------------- logger.info('Solve CPP') circuit, graph = cpp(edgelist_filename=EDGELIST, start_node=START_NODE) logger.info('Print the CPP solution:') for e in circuit: logger.info(e) logger.info('Solution summary stats:') for k, v in calculate_postman_solution_stats(circuit).items(): logger.info(str(k) + ' : ' + str(v)) # VIZ ------------------------------------------------------------------------------- try: from postman_problems.viz import plot_circuit_graphviz, make_circuit_images, make_circuit_video logger.info('Creating single SVG of base graph') plot_circuit_graphviz(circuit=circuit, graph=graph, filename=CPP_BASE_VIZ_FILENAME, edge_label_attr='distance', format='svg', engine='circo', graph_attr={ 'label': 'Base Graph: Distances', 'labelloc': 't' }) logger.info('Creating single SVG of CPP solution') plot_circuit_graphviz(circuit=circuit, graph=graph, filename=CPP_VIZ_FILENAME, format='svg', engine='circo', graph_attr={ 'label': 'Base Graph: Chinese Postman Solution', 'labelloc': 't' }) logger.info('Creating PNG files for GIF') make_circuit_images(circuit=circuit, graph=graph, outfile_dir=PNG_PATH, format='png', engine='circo', graph_attr={ 'label': 'Base Graph: Chinese Postman Solution', 'labelloc': 't' }) logger.info('Creating GIF') video_message = make_circuit_video(infile_dir_images=PNG_PATH, outfile_movie=CPP_GIF_FILENAME, fps=0.5) logger.info(video_message) logger.info("and that's a wrap, checkout the output!") except FileNotFoundError(OSError) as e: print(e) print( "Sorry, looks like you don't have all the needed visualization dependencies." )
def chinese_postman(csv): # find CPP solution circuit, graph = cpp(edgelist_filename=csv, start_node='0') return circuit
for node, deg in G.degree(): if deg > 0: x, y = node img[y, x] = 255 return img from postman_problems.solver import cpp for e in list(G.edges()): G.remove_edge(*e) G.add_edge(*e, distance=1, id=str(e)) G.remove_nodes_from(list(nx.isolates(G))) c, g = cpp(G) edgelist = [(e1, e2) for e1, e2, _, _ in c] #TODO: somehow avoid the last stop being too close to the first one? stops = [n1 for n1, n2 in edgelist[::60]] # pos is {(0,0): (0,255), (0,1): (0,254), (0,2): (0,253), ..., # (255,254): (255,1), (255,255): (255,0)} # Need to reverse order of y in the positions since img has origin top left # and pyplot has origin bottom left # nodes = list(G.nodes()) # poses = [(x, 255-y) for x,y in nodes] # pos = dict(zip(nodes, poses))#list(product(range(w), range(h)[::-1])))) # nx.draw_networkx(G, pos=pos, with_labels=False, node_size=1, node_color='w', width=2) # nx.draw_networkx(G, pos=pos, edgelist=c, with_labels=False, node_size=1, node_color='w', edge_color ='r', width=2) # #plt.show()
# -*- coding: utf-8 -*- """ Created on Thu Jun 21 19:17:20 2018 @author: weing """ import postman_problems from postman_problems.solver import cpp from postman_problems.stats import calculate_postman_solution_stats # find CPP solution circuitSmall, graphSmall = cpp( edgelist_filename='component-connections-edgelist-reduced-degree-2.csv', start_node='1') circuit, graph = cpp(edgelist_filename='component-connections-edgelist.csv', start_node='1') # print solution route for e in circuit: print(e) # print solution route for e in circuitSmall: print(e) # print solution summary stats for k, v in calculate_postman_solution_stats(circuitSmall).items(): print(k, v) for k, v in calculate_postman_solution_stats(circuit).items():