Example #1
0
def get_edges():
    '''
    <Graph>.edges AND <Graph>.edges() return the SAME EdgeView of the edges in the graph
    - An EdgeView is a strange data structure
        - It require a tuple index to access
            - What's really going on? Just look at the library code. It's simple really
        - At each tuple index, it stores a Python dict
        - This syntax makes more sense than the v1.11 syntax
    - Edges are stored as 2-tuples (which are immutable)
    - 
    '''
    g = Graph([(1, 5), [5, 5]])
    print(type(g.edges)) # <class 'networkx.classes.reportviews.EdgeView'>
    print(type(g.edges())) # <class 'networkx.classes.reportviews.EdgeView'>
    print(g.edges()) # [(1, 5), (5, 5)]
    # Invalid syntax
    #print(g.edges[1]) # TypeError: 'int' object is not iterable
    # Missing keys
    #print(g.edges[0, 1]) # KeyError: 1
    #print(g.edges[1, 2]) # KeyError: 2
    # Correct syntax
    print(type(g.edges[1, 5])) # <class 'dict'>
    print(g.edges[1, 5]) # {}
    # I can view the 2-tuples but can't modify them
    for e in g.edges():
        pass
Example #2
0
def examine_node_attributes():
    '''
    A node can contain arbitrary attributes
    - The <Graph>.node attribute is a regular Python dict whose key-value pairs are node identifiers and Python dicts
        - The documentation says that nodes cannot be added to the graph through <Graph>.node, but the code shows they can!
            - However, doing this can mess up the structure of the graph. The newly added node might not have its own Python dict if the update was
              done incorrectly
            - "Warning: adding a node to G.node does not add it to the graph." Listen to the documentation and never try to add nodes via <Graph>.node
    '''
    g = Graph([(1, 5), (5, 5)])
    print(g.nodes())  # [1, 5]
    print(g.edges())  # [(1, 5), (5, 5)]
    print(type(g.node))  # <class 'dict'>
    # Get the dict of an arbitrary node, but not the node itself (annoying)
    print(type(g.node[5]))  # <class 'dict'>
    print(g.node[5])  # {}
    g.node[5]['pet'] = 'cat'
    print(g.node[5])  # {'pet': 'cat'}
    ## NEVER DO THIS
    # This is how to mess up the graph
    g.node[6] = 'psych'
    # The node exists, but are there underlying problems I'm not aware of?
    print(g.nodes())  # [1, 5, 6]
    # Here's the first problem. This should be a dict, but it's a str
    print(type(g.node[6]))  # <class 'str'>
    # This error occurs because of the abuse of the API
    #g.add_node(6) # AttributeError: 'str' object has no attribute 'update'
    # This is how to "correctly" add a node via <Graph>.node, but never do this
    g.node[6] = {'psych': 'psych'}
    g.add_node(6)
    print(g.nodes())  # [1, 5, 6]
Example #3
0
def get_edges():
    '''<Graph>.edges() returns a Python list of tuples, where each 2-tuple represents an edge between two nodes'''
    g = Graph([(1, 5), (5, 5)])
    #print(type(g.edges())) # <class 'list'>
    #print(g.edges()) # [(1, 5), (5, 5)]
    # Iterate over 2-tuples
    for e in g.edges():
        print(e)  # (1, 5)\n(5, 5)
Example #4
0
def add_edges():
    '''Including an arbitrary attribute with newly added edges will add that attribute to all of the new edges'''
    g = Graph([(1, 5), (5, 5)])
    g.add_edges_from([[4, 6], (7, 8)], win='yes')
    print(g.nodes())  # [1, 5, 4, 6, 7, 8]
    print(g.edges())  # [(1, 5), (5, 5), (4, 6), (7, 8)]
    print(
        g.edge
    )  # {1: {5: {}}, 5: {1: {}, 5: {}}, 4: {6: {'win': 'yes'}}, 6: {4: {'win': 'yes'}}, 7: {8: {'win': 'yes'}}, 8: {7: {'win': 'yes'}}}
Example #5
0
def create_graph_from_edges():
    '''
    - Don't use this strategy alone to copy a graph
    - None of the arbitrary attributes from nodes, edges, or the graph are copied
    - When a new graph is created from the edges of an existing graph, the nodes that form each edge are also created
        - Thus, creating a copy from edges is almost a true copy
            - It is NOT a true copy because any nodes without edges are not copied!
    '''
    g = Graph([(1, 5), (5, 5)])
    g.add_node(6)
    g.edge[1][5]['foo'] = 'bar'
    print(g.edge[1][5])  # {'foo': 'bar'}
    print(g.nodes())  # [1, 5, 6]
    h = Graph()
    # Yes, this is the required syntax to do this
    h.add_edges_from(g.edges())
    print(h.edge[1][5])  # {}
    print(h.nodes())  # [1, 5]
    print(h.edges())  # [(1, 5), (5, 5)]
Example #6
0
def create_graph_from_graph():
    '''Passing another graph object appears to have the same net result as <Graph>.copy()'''
    g = Graph([(1, 5), (5, 5)])
    g.add_node(6)
    h = Graph(g)
    print(h.nodes())  # [1, 5, 6]
    print(h.edges())  # [(1, 5), (5, 5)]
    g.node[1]['color'] = 'black'
    print(g.node[1])  # {'color': 'black'}
    print(h.node[1])  # {}
Example #7
0
def create_graph_from_nodes():
    '''
    The net result is the same as in v1.11: the new graph gets all new nodes that are copies of the original nodes
    - No edges are copied
    - No arbitrary attributes are copied
    '''
    g = Graph([(1, 5), (5, 5)])
    g.graph['baz'] = 'boo'
    g.add_node(6)
    print(g.nodes())  # [1, 5, 6]
    print(g.edges())  # [(1, 5), (5, 5)]
    g.nodes[5]['foo'] = 'bar'
    print(g.nodes[5])  # {'foo': 'bar'}
    h = Graph()
    h.add_nodes_from(g)
    print(h.graph)  # {}
    print(h.nodes())  # [1, 5, 6]
    print(h.edges())  # {}
    print(h.nodes[5])  # {}
Example #8
0
def create_graph_from_nodes():
    '''
    - Don't use this strategy alone to copy a graph
    - None of the arbitrary attributes from nodes, edges, or the graph are copied
    - If the nodes of a graph object are used to create a new graph object:
        - No edges are created in the new graph.
    '''
    g = Graph([(1, 5), (5, 5)])
    g.graph['baz'] = 'boo'
    g.add_node(6)
    print(g.nodes())  # [1, 5, 6]
    print(g.edges())  # [(1, 5), (5, 5)]
    g.node[5]['foo'] = 'bar'
    print(g.node[5])  # {'foo': 'bar'}
    h = Graph()
    h.add_nodes_from(g)
    print(h.graph)  # {}
    print(h.nodes())  # [1, 5, 6]
    print(h.edges())  # {}
    print(h.node[5])  # {}
Example #9
0
def construct(G: Graph, weight="weight"):
    e_weight = {}
    adj, radj = {}, {}
    edges = G.edges()
    for e in edges:
        e_weight[e] = edges[e][weight]
        if e[0] not in adj:
            adj[e[0]] = []
        adj[e[0]].append(e[1])
        if e[1] not in radj:
            radj[e[1]] = []
        radj[e[1]].append(e[0])
    return e_weight, [adj, radj]
Example #10
0
def examine_node_attributes():
    '''
    The v2.4 API is slightly different because it uses <Graph>.nodes (or <Graph>.nodes()) while <Graph>.node doesn't exist
    - Even though the NodeView is new, the underlying Python dicts that store attributes are the same as v1.11
    '''
    g = Graph([(1, 5), (5, 5)])
    g.add_node(5)
    print(g.nodes())  # [1, 5]
    print(g.edges())  # [(1, 5), (5, 5)]
    #print(g.node[5]) # AttributeError: 'Graph' object has no attribute 'node'
    print(g.nodes[5])  # {}
    g.nodes[5]['foo'] = 'bar'
    print(g.nodes[5])  # {'foo': 'bar'}
Example #11
0
def create_graph_with_new_data():
    '''
    - Parallel edges are not allowed
    - The data can be:
        - An edge list
        - Any NetworkX graph object
    - The data cannot be a flat list of nodes!
        - It can't be a list of nodes because a bunch of unconnected nodes don't compose a very interesting graph
            - Nodes can be any hashable object. Recall that immutable objects are implicitly hashable: int, string, tuple, etc.
    '''
    # Create with edge list. Since this is an undirected graph, there is only one edge between 1 and 3
    g = Graph([(1, 'foo'), (1, 3), (3, 1)])
    g.add_node(6)
    # Create with another graph
    print(g.nodes())  # [1, 'foo', 3, 6]
    print(g.edges())  # [(1, 'foo'), (1, 3)]