Exemple #1
0
    def to_undirected(self, reciprocal=False):
        """Return an undirected representation of the digraph.

        Parameters
        ----------
        reciprocal : bool (optional)
          If True only keep edges that appear in both directions
          in the original digraph.

        Returns
        -------
        G : Graph
            An undirected graph with the same name and nodes and
            with edge (u,v,data) if either (u,v,data) or (v,u,data)
            is in the digraph.  If both edges exist in digraph and
            their edge data is different, only one edge is created
            with an arbitrary choice of which edge data to use.
            You must check and correct for this manually if desired.

        Notes
        -----
        If edges in both directions (u,v) and (v,u) exist in the
        graph, attributes for the new undirected edge will be a combination of
        the attributes of the directed edges.  The edge data is updated
        in the (arbitrary) order that the edges are encountered.  For
        more customized control of the edge attributes use add_edge().

        This returns a "deepcopy" of the edge, node, and
        graph attributes which attempts to completely copy
        all of the data and references.

        This is in contrast to the similar G=DiGraph(D) which returns a
        shallow copy of the data.

        See the Python copy module for more information on shallow
        and deep copies, http://docs.python.org/library/copy.html.

        Warning: If you have subclassed DiGraph to use dict-like objects 
        in the data structure, those changes do not transfer to the Graph
        created by this method.
        """
        H = Graph()
        H.name = self.name
        H.add_nodes_from(self)
        if reciprocal is True:
            H.add_edges_from((u, v, deepcopy(d))
                             for u, nbrs in self.adjacency()
                             for v, d in nbrs.items() if v in self.pred[u])
        else:
            H.add_edges_from((u, v, deepcopy(d))
                             for u, nbrs in self.adjacency()
                             for v, d in nbrs.items())
        H.graph = deepcopy(self.graph)
        H.node = deepcopy(self.node)
        return H
Exemple #2
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])  # {}
Exemple #3
0
def get_neighbors():
    '''
    Unlike v1.11, <Graph>.neighbors(<v>) returns an iterator over the keys of nodes that are neighbors of <v>, as opposed to a list
    - Iterating over the dict_keyiterators returns the keys of neighboring nodes
    '''
    g = Graph([(1, 2), (2, 3)])
    n = g.neighbors(2)
    print(type(n)) # <class 'dict_keyiterator'>
    print(n) # <dict_keyiterator object at 0x1030d9228>
    for x in n:
        print(x) # 1\n3
Exemple #4
0
def add_nodes():
    '''Multiple nodes can be added at the same time from any container'''
    g = Graph([(1, 5), (5, 5)])
    # If a kwarg is included, every added node will get the kwarg as an attribute
    g.add_nodes_from(['a', 'b'], price='$10')
    print(g.nodes())  # [1, 5, 'a', 'b']
    print(g.node['a'])  # {'price': '$10'}
    print(g.node['b'])  # {'price': '$10'}
    # A dictionary can be used as a source of nodes, but the dict values are not incorporated into the graph
    g.add_nodes_from({'greeting': 'aloha'})
    print(g.nodes())  # [1, 5, 'a', 'b', 'greeting']
    print(g.node['greeting'])  # {}
Exemple #5
0
def edges_():
    '''
    edges(<Graph>, [<nbunch>]) returns Python list of edges incident to nodes in nbunch
    - If <nbunch> is not provided or None, return all edges in <Graph>
    '''
    g = Graph([(1, 5), (5, 5)])
    g.add_edge(2, 4)
    g.add_edge(1, 2)
    # 2 is connected to 4 and 1, so return those edges
    print(function.edges(g, 2))  # [(2, 4), (2, 1)]
    # With no <nbunch>, return all edges
    print(function.edges(g))  # [(1, 5), (1, 2), (5, 5), (2, 4)]
Exemple #6
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'}
Exemple #7
0
def get_nodes():
    '''
    <Graph>.nodes() returns a new list that contains the unique identifiers that represent nodes in the graph
    - Modifying this list does nothing to the original graph
    - I can only access nodes by index, not key
    '''
    g = Graph([(1, 5), (5, 5)])
    g.add_node(5)
    print(type(g.nodes()))  # <class 'list'>
    print(g.nodes())  # [1, 5]
    print(g.nodes()[0])  # 1
    g.nodes().append(6)
    print(g.nodes())  # [1, 5]
Exemple #8
0
 def __init__(self, data=None, **kwds):
     Graph.__init__(self, **kwds)
     if data is not None:
         try:  # build a graph
             G = Graph()
             G = convert.from_whatever(data, create_using=G)
         except:
             raise NetworkXError, "Data %s is not a tree" % data
         # check if it is a tree.
         if G.order()==G.size()+1 and \
                component.number_connected_components(G)==1:
             self.adj = G.adj.copy()
             del G
         else:
             raise NetworkXError, "Data %s is not a tree" % data
Exemple #9
0
def add_edge_():
    '''
    - <Graph>.edge[<u>][<v>] no longer exists, so use <Graph>.edges[<u>, <v>]
    - Unlike v1.11 which accepted a dict as a third argument, only additionals kwargs are accepted after <u> and <v>
    - The rules for arbitrary attributes are the same as v1.11 (see notes below)
    '''
    g = Graph([(1, 5), (5, 5)])
    g.edges[1, 5]['foo'] = 'bar'
    #g.add_edge(1, 5, {}) # TypeError
    # This is wrong. Don't do this!
    #g.add_edge(1, 5, attr_dict={})
    #print(g.edges[1, 5]) # {'foo': 'bar', 'attr_dict': {}}
    # A duplciate edge cannot remove existing arbitrary edge attributes
    g.add_edge(1, 5)
    print(g.edges[1, 5]) # {'foo': 'bar'}
Exemple #10
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)]
Exemple #11
0
 def to_undirected(self):
     """Return an undirected representation of the digraph.
 
     A new graph is returned with the same name and nodes and
     with edge (u,v,data) if either (u,v,data) or (v,u,data) 
     is in the digraph.  If both edges exist in digraph and
     their edge data is different, only one edge is created
     with an arbitrary choice of which edge data to use.  
     You must check and correct for this manually if desired.
     
     """
     H = Graph()
     H.name = self.name
     H.add_nodes_from(self)
     H.add_edges_from([(v, u, d)
                       for (u, v, d) in self.edges_iter(data=True)])
     return H
Exemple #12
0
def add_edge():
    '''
    - Adding an edge with nonexistent nodes creates those nodes
    - Adding a duplicate edge can update the arbitrary attribute data for that edge (see below)
        - The rules for updating arbitrary attributes are the same as those for adding a duplicate node
    '''
    g = Graph([(1, 5), (5, 5)])
    g.edge[1][5]['foo'] = 'bar'
    # A duplciate edge cannot remove existing arbitrary edge attributes.
    # - Also, {} and attr_dict={} are equivalent
    #g.add_edge(1, 5, attr_dict={})
    #g.add_edge(1, 5, {})
    #print(g.edge[1][5]) # {'foo': 'bar'}
    # A duplicate edge can overwrite existing arbitrary edge attributes
    #g.add_edge(1, 5, attr_dict={'foo': 'fru'})
    g.add_edge(1, 5, foo='fru')
    print(g.edge[1][5])  # {'foo': 'fru'}
Exemple #13
0
def examine_edge_attributes():
    '''
    Although the tuple indexing syntax is new, what's unchanged from v1.11 is that every edge key stores a regular dict
    - As before, edge attributes are distinct from node attributes and undirected graphs can only have one edge between vertices
    '''
    g = Graph([(1, 5), (5, 5)])
    print(type(g.edges[1, 5]))  # <class 'dict'>
    print(g.edges[1, 5])  # {}
    g.edges[5, 1]['foo'] = 'bar'
    print(g.nodes[1])  # {}
    print(g.nodes[5])  # {}
    print(g.edges[1, 5])  # {'foo': 'bar'}
    print(g.edges[1, 5] is g.edges[5, 1])  # True
    # The legacy edge attribute access via <Graph>[<u>][<v>] is (confusingly) preserved
    print(g[1][5])  # {'foo': 'bar'}
    #print(g.edges[1][5]) # TypeError
    print(g.edges[1, 5])  # {'foo': 'bar'}
    print(g[1][5] is g.edges[1, 5])  # True
Exemple #14
0
def get_nodes_and_data():
    '''
    The <Graph>.nodes() method accepts an optional kwarg "data" that, regardless of value, is interpreted as a truthy or falsy value
    - If truthy, a list of 2-tuples is returned. Each 2-tuple consists of (<key>, <attr dict>)
    - If falsy, a list of keys is returned
    In v1.11 that's all that happens. It's very simple
    '''
    g = Graph()
    g.add_nodes_from(['a', 'b'], data='quack')
    g.add_node('c', data=False)
    g.add_node('d')
    print(g.nodes())  # ['a', 'b', 'c', 'd']
    print(g.nodes(data=False))  # ['a', 'b', 'c', 'd']
    print(
        g.nodes(data=True)
    )  # [('a', {'data': 'quack'}), ('b', {'data': 'quack'}), ('c', {'data': False}), ('d', {})]
    print(
        g.nodes(data='no')
    )  # [('a', {'data': 'quack'}), ('b', {'data': 'quack'}), ('c', {'data': False}), ('d', {})]
Exemple #15
0
def create_true_graph_copy():
    '''
    - <Graph>.copy() returns a true copy of the original graph
        - == operator for graph objects is useless, or perhaps __eq__ isn't implemented so it falls back to "is" behavior
    - This is NOT what I want if I don't want to copy attributes
    '''
    g = Graph([(1, 5), (5, 5)])
    g.add_node(6)
    g.graph['pie'] = 'apple'
    g.node[1]['pet'] = 'fish'
    g.edge[5][5]['sound'] = 'clink'
    h = g.copy()
    print(h.nodes())  # [1, 5, 6]
    print(h.edges())  # [(1, 5), (5, 5)]
    print(h.graph)  # {'pie': 'apple'}
    print(h.node)  # {1: {'pet': 'fish'}, 5: {}, 6: {}}
    print(h.edge)  # {1: {5: {}}, 5: {1: {}, 5: {'sound': 'clink'}}, 6: {}}
    print(h is g)  # False
    print(h == g)  # False
Exemple #16
0
def make_nonmultigraph(multigraph):
    """
        Removes duplicate edges. Instead of having multiple edges going from the same source to the same target,
        this function adds one edge with a weight attribute,
        Parameters:
            multigraph: The multi-graph with multi-edges
        Return:
            G: A new graph which is equivalent to the multi-graph.
    """
    G = Graph()
    for node in multigraph.nodes_iter():
        G.add_node(node)
    for edge in multigraph.edges_iter():
        for existing_edge in G.edges_iter():
            if existing_edge[0] == edge[0] and existing_edge[1] == edge[
                    1]:  #If the edge is already in the existing edge list...
                G.edge[edge[0]][edge[1]][
                    'weight'] += 1  # the existing edge's weight is incremented
        G.add_edge(edge[0], edge[1], weight=1)
    return G
Exemple #17
0
    def to_undirected(self):
        """Return an undirected representation of the digraph.

        Returns
        -------
        G : Graph
            An undirected graph with the same name and nodes and
            with edge (u,v,data) if either (u,v,data) or (v,u,data)
            is in the digraph.  If both edges exist in digraph and
            their edge data is different, only one edge is created
            with an arbitrary choice of which edge data to use.
            You must check and correct for this manually if desired.

        Notes
        -----
        If edges in both directions (u,v) and (v,u) exist in the
        graph, attributes for the new undirected edge will be a combination of
        the attributes of the directed edges.  The edge data is updated
        in the (arbitrary) order that the edges are encountered.  For
        more customized control of the edge attributes use add_edge().

        This returns a "deepcopy" of the edge, node, and
        graph attributes which attempts to completely copy
        all of the data and references.

        This is in contrast to the similar G=DiGraph(D) which returns a
        shallow copy of the data.

        See the Python copy module for more information on shallow
        and deep copies, http://docs.python.org/library/copy.html.

        """
        H = Graph()
        H.name = self.name
        H.add_nodes_from(self)
        H.add_edges_from((u, v, deepcopy(d))
                         for u, nbrs in self.adjacency_iter()
                         for v, d in nbrs.items())
        H.graph = deepcopy(self.graph)
        H.node = deepcopy(self.node)
        return H
Exemple #18
0
def get_node_attributes_():
    '''
    get_node_attributes(<Graph>, <attribute key>) returns a dict 
    - The <attribute key> can be anything that could be a key (i.e. any immutable object), but in most cases it will be a string. Multiple keys cannot
      be specified
    - The returned dict's keys are node identifiers who have the desired attribute key
    '''
    g = Graph([(1, 5), (5, 5)])
    g.node[5]['foo'] = 'bar'
    g.node[1]['foo'] = 'boo'
    # Works as expected
    #d = function.get_node_attributes(g, 'foo')
    #print(type(d)) # <class 'dict'>
    #print(len(d)) # 2
    #print(d) # {1: 'boo', 5: 'bar'}
    # Does not work. There is no object with the literal attribute key ('foo', 'hi')
    g.node[1]['hi'] = 'bye'
    d = function.get_node_attributes(g, ('foo', 'hi'))
    print(d)  # {}
    g.node[1][('foo', 'hi')] = 'lmao'
    print(function.get_node_attributes(g, ('foo', 'hi')))  # {1: 'lmao'}
    def _check_cycle(mode_declarations):
        g = Graph().to_directed()

        for decl in mode_declarations:
            input_args = decl.input_arguments()
            output_args = decl.output_arguments()

            for o in output_args:
                g.add_node(o.name)

            for i in input_args:
                g.add_node(i.name)

                for o in output_args:
                    g.add_edge(i.name, o.name)

        try:
            res = find_cycle(g)
        except NetworkXNoCycle:
            return

        raise CheckFailed('Cycle found: %s' % str(res))
Exemple #20
0
def get_nodes_and_data():
    '''
    <Graph>.nodes() is completely different in v2.4
    - The "data" kwarg can do three things:
        - If data==True, return all node keys and all their data
        - If data==False, return just a list of node keys
        - If data==<attribute key>, return all node keys with the attribute key, along with the value of the attribute
    - In combination with "data", the "default" kwarg will substitute <value> for every node that doesn't have the searched-for attribute key
    '''
    g = Graph()
    g.add_nodes_from(['a', 'b'], data='quack', size='tiny')
    g.add_node('c', data=False)
    g.add_node('d')
    print(g.nodes()) # ['a', 'b', 'c', 'd']
    # Get no node attribute values
    print(g.nodes(data=False)) # ['a', 'b', 'c', 'd']
    # Get all node attribute key-value pairs
    print(g.nodes(data=True)) # [('a', {'data': 'quack', 'size': 'tiny'}), ('b', {'data': 'quack', 'size': 'tiny'}), ('c', {'data': False}), ('d', {})]
    # Get all node keys and attribute values for the given attribute key
    print(g.nodes(data='size')) # [('a', 'tiny'), ('b', 'tiny'), ('c', None), ('d', None)]
    # Substitute a value for nodes that don't have the key
    print(g.nodes(data='size', default='purple')) # [('a', 'tiny'), ('b', 'tiny'), ('c', 'purple'), ('d', 'purple')]
Exemple #21
0
def examine_edge_attributes():
    '''
    <Graph>.edge[<n>] is a Python dict
    - This dict has keys that represent every other node that <n> is connected to
    - The values in the dict are themselves dicts. Each dict is associated with a node, but each dict is NOT the same dict that would be found via
      <Graph>.node
      - Thus, to look up an attribute of the edge between 5 and 5 (self loop), I would use <Graph>.edge[5][5], which is quite natural syntax actually
        - Don't worry. Every edge, regardless of how it was accessed, has exactly one Python dict for attributes
    '''
    g = Graph([(1, 5), (5, 5)])
    print(type(g.edge))  # <class 'dict'>
    print(type(g.edge[5]))  # # <class 'dict'>
    g.node[5]['foo'] = 'bar'
    print(g.node[5])  # {'foo': 'bar'}
    # If the node dicts and edge dicts were the same, foo and bar would be shown below
    print(g.edge[5])  # {1: {}, 5: {}}
    g.edge[5][5]['friend'] = 'homie'
    print(g.node[5])  # {'foo': 'bar'}
    print(g.edge[5])  # {1: {}, 5: {'friend': 'homie'}}
    print(g.edge[1][5] is g.edge[5][1])  # True
    # Edge attributes can be accessed directly on the graph object
    print(g[5][5])  # {'friend': 'homie'}
    print(g[5][5] is g.edge[5][5])  # True
Exemple #22
0
    def add_snapshot(self, ebunch=None, graph=None, start=None, end=None, time=None):
        """Add a snapshot with a bunch of edge values.

        Parameters
        ----------
        ebunch : container of edges, optional (default= None)
            Each edge in the ebunch list will be included to all added graphs.
        graph : networkx graph object, optional (default= None)
            networkx graph to be inserted into snapshot graph.
        start: start timestamp, inclusive
        end: end timestamp, exclusive
        time: timestamp for impulses, cannot be used together with (start, end)

        Returns
        -------
        None

        Examples
        --------
        >>> G = dnx.SnapshotGraph()
        >>> G.add_snapshot([(1, 4), (1, 3)], start=0, end=3)
        """
        if not graph:
            g = Graph()
            g.add_edges_from(ebunch)
        else:
            g = graph

        if time is not None and (start or end):
            raise ValueError('Time and (start or end) cannot both be specified.')
        elif time is not None:
            self.insert(g, time=time)
        elif start is None and end is None:
            raise ValueError('Either time or both start and end must be specified.')
        else:
            self.insert(g, start=start, end=end)
Exemple #23
0
    def add_snapshot(self, ebunch=None, graph=None, num_in_seq=None):
        """Add a snapshot with a bunch of edge values.

        Parameters
        ----------
        ebunch : container of edges, optional (default= None)
            Each edge in the ebunch list will be included to all added graphs.
        graph : networkx graph object, optional (default= None)
            networkx graph to be inserted into snapshot graph.
        num_in_seq : integer, optional (default= None)
            Time slot to begin insertion at.

        Returns
        -------
        None

        Examples
        --------
        >>> G = dnx.SnapshotGraph()
        >>> G.add_snapshot([(1, 4), (1, 3)])

        """
        if not graph:
            g = Graph()
            g.add_edges_from(ebunch)
        else:
            g = graph

        if (not num_in_seq) or (num_in_seq == len(self.snapshots) + 1):
            self.snapshots.append(g)

        elif num_in_seq > len(self.snapshots):
            while num_in_seq > len(self.snapshots):
                self.snapshots.append(g)
        else:
            self.insert(g, snap_len=1, num_in_seq=num_in_seq)
Exemple #24
0
def neighbors_():
    '''Functional equivalent to <Graph>.neighbors(<v>)'''
    g = Graph([(1, 2), (2, 3)])
    print(function.neighbors(g, 2))  # [1, 3]
Exemple #25
0
def get_neighbors():
    '''Get a Python list of neighbors connected to <v> via <Graph>.neighbors(<v>)'''
    g = Graph([(1, 2), (2, 3)])
    n = g.neighbors(2)
    print(type(n))  # <class 'list'>
    print(n)  # [1, 3]
Exemple #26
0
 def __init__(self):
     super().__init__()
     self._table = {self.url: self.url}
     self._graph = Graph()
Exemple #27
0
    def to_undirected(self, reciprocal=False, as_view=False):
        """Returns an undirected representation of the digraph.

        Parameters
        ----------
        reciprocal : bool (optional)
          If True only keep edges that appear in both directions
          in the original digraph.
        as_view : bool (optional, default=False)
          If True return an undirected view of the original directed graph.

        Returns
        -------
        G : Graph
            An undirected graph with the same name and nodes and
            with edge (u, v, data) if either (u, v, data) or (v, u, data)
            is in the digraph.  If both edges exist in digraph and
            their edge data is different, only one edge is created
            with an arbitrary choice of which edge data to use.
            You must check and correct for this manually if desired.

        See Also
        --------
        Graph, copy, add_edge, add_edges_from

        Notes
        -----
        If edges in both directions (u, v) and (v, u) exist in the
        graph, attributes for the new undirected edge will be a combination of
        the attributes of the directed edges.  The edge data is updated
        in the (arbitrary) order that the edges are encountered.  For
        more customized control of the edge attributes use add_edge().

        This returns a "deepcopy" of the edge, node, and
        graph attributes which attempts to completely copy
        all of the data and references.

        This is in contrast to the similar G=DiGraph(D) which returns a
        shallow copy of the data.

        See the Python copy module for more information on shallow
        and deep copies, https://docs.python.org/2/library/copy.html.

        Warning: If you have subclassed DiGraph to use dict-like objects
        in the data structure, those changes do not transfer to the
        Graph created by this method.

        Examples
        --------
        >>> G = nx.path_graph(2)   # or MultiGraph, etc
        >>> H = G.to_directed()
        >>> list(H.edges)
        [(0, 1), (1, 0)]
        >>> G2 = H.to_undirected()
        >>> list(G2.edges)
        [(0, 1)]
        """
        graph_class = self.to_undirected_class()
        if as_view is True:
            return nx.graphviews.generic_graph_view(self, Graph)
        # deepcopy when not a view
        G = Graph()
        G.graph.update(deepcopy(self.graph))
        G.add_nodes_from((n, deepcopy(d)) for n, d in self._node.items())
        if reciprocal is True:
            G.add_edges_from((u, v, deepcopy(d))
                             for u, nbrs in self._adj.items()
                             for v, d in nbrs.items() if v in self._pred[u])
        else:
            G.add_edges_from((u, v, deepcopy(d))
                             for u, nbrs in self._adj.items()
                             for v, d in nbrs.items())
        return G
Exemple #28
0
    def to_subgraph(self,
                    begin,
                    end,
                    multigraph=False,
                    edge_data=False,
                    edge_interval_data=False,
                    node_data=False):
        """Return a networkx Graph or MultiGraph which includes all the nodes and
        edges which have overlapping intervals with the given interval.

        Parameters
        ----------
        begin: integer
            Inclusive beginning time of the edge appearing in the interval graph.
            Must be bigger than begin.
        end: integer
            Non-inclusive ending time of the edge appearing in the interval graph.
        multigraph: bool, optional (default= False)
            If True, a networkx MultiGraph will be returned. If False, networkx Graph.
        edge_data: bool, optional (default= False)
            If True, edges will keep their attributes.
        edge_interval_data: bool, optional (default= False)
            If True, each edge's attribute will also include its begin and end interval data.
            If `edge_data= True` and there already exist edge attributes with names begin and end,
            they will be overwritten.
        node_data : bool, optional (default= False)
            if True, each node's attributes will be included.

        See Also
        --------
        to_snapshots : divide the interval graph to snapshots

        Notes
        -----
        If multigraph= False, and edge_data=True or edge_interval_data=True,
        in case there are multiple edges, only one will show with one of the edge's attributes.

        Note: nodes with no edges will not appear in any subgraph.

        Examples
        --------
        >>> G = dnx.IntervalGraph()
        >>> G.add_edges_from([(1, 2, 3, 10), (2, 4, 1, 11), (6, 4, 12, 19), (2, 4, 8, 15)])
        >>> H = G.to_subgraph(4, 12)
        >>> type(H)
        <class 'networkx.classes.graph.Graph'>
        >>> list(H.edges(data=True))
        [(1, 2, {}), (2, 4, {})]

        >>> H = G.to_subgraph(4, 12, edge_interval_data=True)
        >>> type(H)
        <class 'networkx.classes.graph.Graph'>
        >>> list(H.edges(data=True))
        [(1, 2, {'end': 10, 'begin': 3}), (2, 4, {'end': 15, 'begin': 8})]

        >>> M = G.to_subgraph(4, 12, multigraph=True, edge_interval_data=True)
        >>> type(M)
        <class 'networkx.classes.multigraph.MultiGraph'>
        >>> list(M.edges(data=True))
        [(1, 2, {'end': 10, 'begin': 3}), (2, 4, {'end': 11, 'begin': 1}), (2, 4, {'end': 15, 'begin': 8})]
        """

        if end <= begin:
            raise NetworkXError(
                "IntervalGraph: subgraph duration must be strictly bigger than zero: "
                "begin: {}, end: {}.".format(begin, end))

        iedges = self.tree[begin:end]

        if multigraph:
            G = MultiGraph()
        else:
            G = Graph()

        if edge_data and edge_interval_data:
            G.add_edges_from((iedge.data[0], iedge.data[1],
                              dict(self._adj[iedge.data[0]][iedge],
                                   begin=iedge.begin,
                                   end=iedge.end)) for iedge in iedges)
        elif edge_data:
            G.add_edges_from((iedge.data[0], iedge.data[1],
                              self._adj[iedge.data[0]][iedge].copy())
                             for iedge in iedges)
        elif edge_interval_data:
            G.add_edges_from((iedge.data[0], iedge.data[1], {
                'begin': iedge.begin,
                'end': iedge.end
            }) for iedge in iedges)
        else:
            G.add_edges_from(
                (iedge.data[0], iedge.data[1]) for iedge in iedges)

        # include node attributes
        if node_data:
            G.add_nodes_from((n, self._node[n].copy()) for n in G.nodes)

        return G
Exemple #29
0
def bad_create_graph():
    '''NetworkX does not view a flat list as a list of edges'''
    g = Graph([
        1, 2
    ])  # networkx.exception.NetworkXError: Input is not a valid edge list
Exemple #30
0
def create_empty_graph():
    '''Create an empty graph with no nodes or edges'''
    g = Graph()
    print(type(g))  # <class 'networkx.classes.graph.Graph'>