def _simplify_graph(g: nx.MultiDiGraph, check_lanes):
    for n, _ in tqdm(list(g.adjacency()), desc="simplifying oneways"):
        if g.out_degree(n) == 1 and g.in_degree(n) == 1:  # oneways
            simplify_oneways(n, g, check_lanes)

    for n, _ in tqdm(list(g.adjacency()), desc="simplifying bidirectional"):
        if g.out_degree(n) == 2 and g.in_degree(
                n) == 2:  # both directions in highway
            simplify_twoways(n, g, check_lanes)
def simplify_graph(g: nx.MultiDiGraph, check_lanes):
    for n, _ in list(g.adjacency()):
        if g.out_degree(n) == 1 and g.in_degree(n) == 1:  # oneways
            simplify_oneways(n, g, check_lanes)

    for n, _ in list(g.adjacency()):
        if g.out_degree(n) == 2 and g.in_degree(
                n) == 2:  # both directions in highway
            simplify_twoways(n, g, check_lanes)
Example #3
0
def convert_multidi_to_weighted_undir_graph(in_graph: nx.MultiDiGraph,
                                            agg_function: Any) -> nx.Graph:
    """Convert a graph with multiple edges to a graph with no multiple edges.

  Arguments:
    in_graph: graph with (potentially) multiple directed edges per node pair.
    agg_function: a function that takes an iterable of floats and returns
      a number. Applied to weights on multiple edges to produce one weight.
  Returns:
    out_graph: graph with weighted undirected edges.
  """
    edges = collections.defaultdict(dict)
    for node, neighbor_dict in in_graph.adjacency():
        for neighbor, edges_dict in neighbor_dict.items():
            id_pair = tuple(sorted([node, neighbor]))
            if 'weight' not in edges[id_pair]:
                edges[id_pair]['weight'] = []
            for _, edge_data in edges_dict.items():
                # Some input edges have artificially high weight [1] in to prevent
                # an agent from visiting the center of a POI. So, the input is also
                # given a "true_length" attribute [2] so that the graph construction
                # can use the actual distance.
                # [1] See cabby.geo.map_processing.map_structure.ADD_POI_DISTANCE
                # [2] See cabby.geo.map_processing.edge
                if 'true_length' in edge_data:
                    weight = edge_data['true_length']
                else:
                    weight = edge_data['length']
                edges[id_pair]['weight'].append(weight)
    for id_pair in edges:
        edges[id_pair]['weight'] = agg_function(edges[id_pair]['weight'])
    out_graph = nx.Graph()
    out_graph.add_edges_from(
        [id_pair + (data, ) for id_pair, data in edges.items()])
    return out_graph
def _get_max_id_in_graph(g: nx.MultiDiGraph) -> int:
    max_id = -1
    for n, nbrdict in g.adjacency():
        for nbr, attrs in nbrdict.items():
            for i in range(len(attrs)):
                if max_id < attrs[i]['id']:
                    max_id = attrs[i]['id']
    return max_id
def create_digraph(graph: nx.MultiDiGraph) -> nx.DiGraph:
    if not _is_multidigraph(graph):
        return nx.DiGraph(graph)

    # id_counter = _get_max_id_in_graph(graph) + 1
    new_graph = nx.DiGraph()
    for n, nbrdict in graph.adjacency():
        for nbr, attributes in nbrdict.items():
            if not type(attributes) is dict:
                id_counter = 0
                for i in range(len(attributes)):
                    if attributes[i]['others'] == [[]]:
                        new_graph.add_edge(n,
                                           nbr,
                                           id='{}_{}'.format(
                                               attributes[i]['id'],
                                               id_counter),
                                           lanes=attributes[i]['lanes'],
                                           others=attributes[i]['others'])
                        id_counter += 1
                    else:
                        temp_nbr = get_node(attributes[i]['others'][0])
                        new_graph.add_edge(n,
                                           temp_nbr,
                                           id='{}_{}'.format(
                                               attributes[i]['id'],
                                               id_counter),
                                           lanes=attributes[i]['lanes'],
                                           others=[[]])
                        id_counter += 1
                        new_graph.add_edge(temp_nbr,
                                           nbr,
                                           id='{}_{}'.format(
                                               attributes[i]['id'],
                                               id_counter),
                                           lanes=attributes[i]['lanes'],
                                           others=attributes[i]['others'][1:])
                        id_counter += 1

            else:
                new_graph.add_edge(n,
                                   nbr,
                                   id=attributes['id'],
                                   lanes=attributes['lanes'],
                                   others=attributes['others'])
    return new_graph
def graph_from_prov_networkx_graph(prov_graph: nx.MultiDiGraph):
    graph_object = dict()
    node_labels = dict()
    edge_labels = dict()

    renamed_nodes = {node: i for i, node in enumerate(prov_graph.nodes)}

    for n, nbrsdict in prov_graph.adjacency():
        u = renamed_nodes[n]
        graph_object[u] = dict()
        node_labels[u] = str(n.get_type())
        for nbr, keydict in nbrsdict.items():
            v = renamed_nodes[nbr]
            for key, eattr in keydict.items():
                if v not in graph_object[u]:
                    # only add the first edge
                    graph_object[u][v] = 1.0
                    edge_labels[(u, v)] = str(eattr["relation"].get_type())

    return (graph_object, node_labels, edge_labels)
Example #7
0
def plot_graph(graph: nx.MultiDiGraph) -> None:
    """
    Plot the Multiple Directed graph using the plotly library.
    """
    # Choosing the spring layout to position the vertices of the graph.
    pos = nx.spring_layout(graph)

    # Creating the edge trace.
    edge_x = []
    edge_y = []

    xtext = []
    ytext = []
    edge_values_text = []
    for edge in graph.edges():
        # Determine the start and end coordinates of the edge on the graph.
        x0, y0 = pos[edge[0]]
        x1, y1 = pos[edge[1]]

        # Add all x coordinates to list of x_edge data.
        edge_x.append(x0)
        edge_x.append(x1)
        edge_x.append(None)

        # Add all y coordinates to list of y_edge data.
        edge_y.append(y0)
        edge_y.append(y1)
        edge_y.append(None)

        # Add x midpoint coordinates to list of xtext data.
        xtext.append((x0 + x1) / 2)

        # Add y midpoint coordinates to list of ytext data.
        ytext.append((y0 + y1) / 2)

        # Add transaction value to list of edge_values data.
        value = graph.get_edge_data(edge[0], edge[1])[0]['weight']
        edge_values_text.append(f"Transaction Value: {value}")

    # Plotting the edges.
    edge_trace = go.Scatter(x=edge_x,
                            y=edge_y,
                            line=dict(width=1, color='black'),
                            mode='lines')

    # Plotting the edge transaction text.
    edge_values_trace = go.Scatter(x=xtext,
                                   y=ytext,
                                   mode='none',
                                   text=edge_values_text,
                                   textposition='top center',
                                   hovertemplate='%{text}<extra></extra>')

    # Creating the node trace.
    node_x = []
    node_y = []
    node_size = []
    for node in graph.nodes():
        # Determine the coordinates of each node (using the spring layout defined earlier)
        x, y = pos[node]
        node_x.append(x)
        node_y.append(y)

        size = 10
        if graph.nodes[node] != {}:
            size = graph.nodes[node]['size']

        node_size.append(size)

    node_trace = go.Scatter(x=node_x,
                            y=node_y,
                            mode='markers',
                            hoverinfo='text',
                            marker=dict(showscale=True,
                                        colorscale='Hot',
                                        color=[],
                                        size=node_size,
                                        colorbar=dict(
                                            thickness=10,
                                            title='# of Transactions (degree)',
                                            xanchor='left',
                                            titleside='right'),
                                        line_width=2))

    # Setting the text of each node to its address.
    node_text = []
    for node in graph.nodes():
        node_desc = f"Address: {node}"

        # If the account doesn't have an empty representation
        # in the graph, get its balance.
        if graph.nodes[node] != {}:
            balance = graph.nodes[node]['balance']
            node_desc = f"Address: {node}\nBalance: {balance}"

        # Add the description of the node to the list (which
        # will get added to the trace, updating it).
        node_text.append(node_desc)

    # Update the text and size attributes of the node trace.
    node_trace.text = node_text

    node_neighbours = []
    for node in graph.adjacency():
        # To find the neighbours of this node (accounts who either
        # sent or received transactions from this current account)
        # we must access the second item of a tuple, which contains
        # a dictionary representation of its neighbours (addresses
        # mapped to
        neighbours = len(node[1])
        node_neighbours.append(neighbours)

    node_trace.marker.color = node_neighbours

    # Setting up the layout here.
    layout = go.Layout(
        title='Ethereum Transaction Graph',
        showlegend=False,
        hovermode='closest',
        xaxis=dict(showgrid=False, zeroline=False),
        yaxis=dict(showgrid=False, zeroline=False),
        margin=dict(b=20, l=15, r=15,
                    t=50),  # Setting up the margins around the graph
    )

    # Plot the graph figure.
    fig = go.Figure(data=[edge_trace, node_trace, edge_values_trace],
                    layout=layout)

    # update layout
    fig.update_layout(title_font_size=15)

    fig.show()
def _is_multidigraph(g: nx.MultiDiGraph) -> bool:
    for node, nbrdict in g.adjacency():
        for nbr, attributes in nbrdict.items():
            if len(attributes) > 1:
                return True
    return False