示例#1
0
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
示例#2
0
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
示例#3
0
    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
示例#4
0
 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
示例#5
0
文件: trails.py 项目: casotto/gfl
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
示例#6
0
 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("")
         
示例#7
0
    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)])
示例#9
0
    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)])
示例#10
0
    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)]
示例#11
0
    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)])
示例#12
0
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
示例#13
0
    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
示例#14
0
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
示例#15
0
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
示例#16
0
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
示例#17
0
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
示例#18
0
    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)
示例#19
0
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
示例#20
0
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)
示例#21
0
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)
示例#22
0
    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)
示例#23
0
    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
示例#24
0
 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
示例#25
0
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
示例#26
0
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
示例#27
0
 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))
示例#28
0
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
示例#29
0
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
示例#30
0
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
示例#31
0
文件: tsp.py 项目: MurielMauch/Grafos
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
示例#32
0
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
示例#34
0
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
示例#35
0
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
示例#36
0
文件: etc.py 项目: hnishi/ortoolpy
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)),
    )
示例#37
0
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
示例#38
0
 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
示例#39
0
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
示例#40
0
文件: postman.py 项目: wallarelvo/TVD
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
示例#41
0
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
示例#42
0
文件: graph.py 项目: msanders/bio
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] ]
示例#43
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)])
示例#44
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)])
示例#45
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)
示例#46
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
示例#47
0
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
示例#50
0
文件: euler.py 项目: eah13/bioalgo
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()
示例#51
0
 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
示例#52
0
 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
示例#53
0
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)
示例#54
0
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
示例#55
0
文件: tsp.py 项目: huevosabio/windopt
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
示例#56
0
文件: trails.py 项目: casotto/gfl
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
示例#57
0
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(";", "")
示例#58
0
  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()
示例#59
0
 def test_not_eulerian(self):
     f=list(eulerian_circuit(nx.complete_graph(4)))