PK_Gíd z!z!#networkx-networkx-1.10/gallery.html Gallery — NetworkX 1.10 documentation

Click on any image to see source code


Read the Docs v: networkx-1.10
Versions
latest
stable
networkx-1.10
Downloads
pdf
htmlzip
epub
On Read the Docs
Project Home
Builds

Free document hosting provided by Read the Docs.
PK_G0 +f f !networkx-networkx-1.10/index.html NetworkX 1.10 documentation

NetworkX documentation

Release:1.10
Date:October 31, 2015

Tutorial [PDF]

Reference [PDF]

Tutorial+Reference [HTML zip]

Overview

NetworkX is a Python language software package for the creation, manipulation, and study of the structure, dynamics, and function of complex networks.

With NetworkX you can load and store networks in standard and nonstandard data formats, generate many types of random and classic networks, analyze network structure, build network models, design new network algorithms, draw networks, and much more.

Who uses NetworkX?

The potential audience for NetworkX includes mathematicians, physicists, biologists, computer scientists, and social scientists. Good reviews of the state-of-the-art in the science of complex networks are presented in Albert and Barabási [BA02], Newman [Newman03], and Dorogovtsev and Mendes [DM03]. See also the classic texts [Bollobas01], [Diestel97] and [West01] for graph theoretic results and terminology. For basic graph algorithms, we recommend the texts of Sedgewick, e.g. [Sedgewick01] and [Sedgewick02] and the survey of Brandes and Erlebach [BE05].

Goals

NetworkX is intended to provide

  • tools for the study of the structure and dynamics of social, biological, and infrastructure networks,
  • a standard programming interface and graph implementation that is suitable for many applications,
  • a rapid development environment for collaborative, multidisciplinary projects,
  • an interface to existing numerical algorithms and code written in C, C++, and FORTRAN,
  • the ability to painlessly slurp in large nonstandard data sets.

The Python programming language

Python is a powerful programming language that allows simple and flexible representations of networks, and clear and concise expressions of network algorithms (and other algorithms too). Python has a vibrant and growing ecosystem of packages that NetworkX uses to provide more features such as numerical linear algebra and drawing. In addition Python is also an excellent “glue” language for putting together pieces of software from other languages which allows reuse of legacy code and engineering of high-performance algorithms [Langtangen04].

Equally important, Python is free, well-supported, and a joy to use.

In order to make the most out of NetworkX you will want to know how to write basic programs in Python. Among the many guides to Python, we recommend the documentation at http://www.python.org and the text by Alex Martelli [Martelli03].

Free software

NetworkX is free software; you can redistribute it and/or modify it under the terms of the BSD License. We welcome contributions from the community. Information on NetworkX development is found at the NetworkX Developer Zone at Github https://github.com/networkx/networkx

History

NetworkX was born in May 2002. The original version was designed and written by Aric Hagberg, Dan Schult, and Pieter Swart in 2002 and 2003. The first public release was in April 2005.

Many people have contributed to the success of NetworkX. Some of the contributors are listed in the credits.

What Next

Installing

Before installing NetworkX, you need to have setuptools installed.

Quick install

Get NetworkX from the Python Package Index at http://pypi.python.org/pypi/networkx

or install it with

pip install networkx

and an attempt will be made to find and install an appropriate version that matches your operating system and Python version.

You can install the development version (at github.com) with

pip install git://github.com/networkx/networkx.git#egg=networkx

More download file options are at http://networkx.github.io/download.html.

Installing from source

You can install from source by downloading a source archive file (tar.gz or zip) or by checking out the source files from the Mercurial source code repository.

NetworkX is a pure Python package; you don’t need a compiler to build or install it.

Source archive file

  1. Download the source (tar.gz or zip file) from https://pypi.python.org/pypi/networkx/ or get the latest development version from https://github.com/networkx/networkx/
  2. Unpack and change directory to the source directory (it should have the files README.txt and setup.py).
  3. Run python setup.py install to build and install
  4. (Optional) Run nosetests to execute the tests if you have nose installed.

GitHub

  1. Clone the networkx repostitory

(see https://github.com/networkx/networkx/ for other options)

  1. Change directory to networkx
  2. Run python setup.py install to build and install
  3. (Optional) Run nosetests to execute the tests if you have nose installed.

If you don’t have permission to install software on your system, you can install into another directory using the --user, --prefix, or --home flags to setup.py.

For example

python setup.py install --prefix=/home/username/python

or

python setup.py install --home=~

or

python setup.py install --user

If you didn’t install in the standard Python site-packages directory you will need to set your PYTHONPATH variable to the alternate location. See http://docs.python.org/2/install/index.html#search-path for further details.

Requirements

Python

To use NetworkX you need Python 2.7, 3.2 or later.

The easiest way to get Python and most optional packages is to install the Enthought Python distribution “Canopy”.

There are several other distributions that contain the key packages you need for scientific computing. See http://scipy.org/install.html for a list.

Optional packages

The following are optional packages that NetworkX can use to provide additional functions.

NumPy

Provides matrix representation of graphs and is used in some graph algorithms for high-performance matrix computations.

SciPy

Provides sparse matrix representation of graphs and many numerical scientific tools.

Matplotlib

Provides flexible drawing of graphs.

GraphViz

In conjunction with either

provides graph drawing and graph layout algorithms.

PyYAML

http://pyyaml.org/

Required for YAML format reading and writing.

Other packages

These are extra packages you may consider using with NetworkX

Tutorial

Start here to begin working with NetworkX.

Creating a graph

Create an empty graph with no nodes and no edges.

>>> import networkx as nx
>>> G=nx.Graph()

By definition, a Graph is a collection of nodes (vertices) along with identified pairs of nodes (called edges, links, etc). In NetworkX, nodes can be any hashable object e.g. a text string, an image, an XML object, another Graph, a customized node object, etc. (Note: Python’s None object should not be used as a node as it determines whether optional function arguments have been assigned in many functions.)

Nodes

The graph G can be grown in several ways. NetworkX includes many graph generator functions and facilities to read and write graphs in many formats. To get started though we’ll look at simple manipulations. You can add one node at a time,

>>> G.add_node(1)

add a list of nodes,

>>> G.add_nodes_from([2,3])

or add any nbunch of nodes. An nbunch is any iterable container of nodes that is not itself a node in the graph. (e.g. a list, set, graph, file, etc..)

>>> H=nx.path_graph(10)
>>> G.add_nodes_from(H)

Note that G now contains the nodes of H as nodes of G. In contrast, you could use the graph H as a node in G.

>>> G.add_node(H)

The graph G now contains H as a node. This flexibility is very powerful as it allows graphs of graphs, graphs of files, graphs of functions and much more. It is worth thinking about how to structure your application so that the nodes are useful entities. Of course you can always use a unique identifier in G and have a separate dictionary keyed by identifier to the node information if you prefer. (Note: You should not change the node object if the hash depends on its contents.)

Edges

G can also be grown by adding one edge at a time,

>>> G.add_edge(1,2)
>>> e=(2,3)
>>> G.add_edge(*e) # unpack edge tuple*

by adding a list of edges,

>>> G.add_edges_from([(1,2),(1,3)])

or by adding any ebunch of edges. An ebunch is any iterable container of edge-tuples. An edge-tuple can be a 2-tuple of nodes or a 3-tuple with 2 nodes followed by an edge attribute dictionary, e.g. (2,3,{‘weight’:3.1415}). Edge attributes are discussed further below

>>> G.add_edges_from(H.edges())

One can demolish the graph in a similar fashion; using Graph.remove_node(), Graph.remove_nodes_from(), Graph.remove_edge() and Graph.remove_edges_from(), e.g.

>>> G.remove_node(H)

There are no complaints when adding existing nodes or edges. For example, after removing all nodes and edges,

>>> G.clear()

we add new nodes/edges and NetworkX quietly ignores any that are already present.

>>> G.add_edges_from([(1,2),(1,3)])
>>> G.add_node(1)
>>> G.add_edge(1,2)
>>> G.add_node("spam")       # adds node "spam"
>>> G.add_nodes_from("spam") # adds 4 nodes: 's', 'p', 'a', 'm'

At this stage the graph G consists of 8 nodes and 2 edges, as can be seen by:

>>> G.number_of_nodes()
8
>>> G.number_of_edges()
2

We can examine them with

>>> G.nodes()
['a', 1, 2, 3, 'spam', 'm', 'p', 's']
>>> G.edges()
[(1, 2), (1, 3)]
>>> G.neighbors(1)
[2, 3]

Removing nodes or edges has similar syntax to adding:

>>> G.remove_nodes_from("spam")
>>> G.nodes()
[1, 2, 3, 'spam']
>>> G.remove_edge(1,3)

When creating a graph structure by instantiating one of the graph classes you can specify data in several formats.

>>> H=nx.DiGraph(G)   # create a DiGraph using the connections from G
>>> H.edges()
[(1, 2), (2, 1)]
>>> edgelist=[(0,1),(1,2),(2,3)]
>>> H=nx.Graph(edgelist)

What to use as nodes and edges

You might notice that nodes and edges are not specified as NetworkX objects. This leaves you free to use meaningful items as nodes and edges. The most common choices are numbers or strings, but a node can be any hashable object (except None), and an edge can be associated with any object x using G.add_edge(n1,n2,object=x).

As an example, n1 and n2 could be protein objects from the RCSB Protein Data Bank, and x could refer to an XML record of publications detailing experimental observations of their interaction.

We have found this power quite useful, but its abuse can lead to unexpected surprises unless one is familiar with Python. If in doubt, consider using convert_node_labels_to_integers() to obtain a more traditional graph with integer labels.

Accessing edges

In addition to the methods Graph.nodes(), Graph.edges(), and Graph.neighbors(), iterator versions (e.g. Graph.edges_iter()) can save you from creating large lists when you are just going to iterate through them anyway.

Fast direct access to the graph data structure is also possible using subscript notation.

Warning

Do not change the returned dict–it is part of the graph data structure and direct manipulation may leave the graph in an inconsistent state.

>>> G[1]  # Warning: do not change the resulting dict
{2: {}}
>>> G[1][2]
{}

You can safely set the attributes of an edge using subscript notation if the edge already exists.

>>> G.add_edge(1,3)
>>> G[1][3]['color']='blue'

Fast examination of all edges is achieved using adjacency iterators. Note that for undirected graphs this actually looks at each edge twice.

>>> FG=nx.Graph()
>>> FG.add_weighted_edges_from([(1,2,0.125),(1,3,0.75),(2,4,1.2),(3,4,0.375)])
>>> for n,nbrs in FG.adjacency_iter():
...    for nbr,eattr in nbrs.items():
...        data=eattr['weight']
...        if data<0.5: print('(%d, %d, %.3f)' % (n,nbr,data))
(1, 2, 0.125)
(2, 1, 0.125)
(3, 4, 0.375)
(4, 3, 0.375)

Convenient access to all edges is achieved with the edges method.

>>> for (u,v,d) in FG.edges(data='weight'):
...     if d<0.5: print('(%d, %d, %.3f)'%(n,nbr,d))
(1, 2, 0.125)
(3, 4, 0.375)

Adding attributes to graphs, nodes, and edges

Attributes such as weights, labels, colors, or whatever Python object you like, can be attached to graphs, nodes, or edges.

Each graph, node, and edge can hold key/value attribute pairs in an associated attribute dictionary (the keys must be hashable). By default these are empty, but attributes can be added or changed using add_edge, add_node or direct manipulation of the attribute dictionaries named G.graph, G.node and G.edge for a graph G.

Graph attributes

Assign graph attributes when creating a new graph

>>> G = nx.Graph(day="Friday")
>>> G.graph
{'day': 'Friday'}

Or you can modify attributes later

>>> G.graph['day']='Monday'
>>> G.graph
{'day': 'Monday'}

Node attributes

Add node attributes using add_node(), add_nodes_from() or G.node

>>> G.add_node(1, time='5pm')
>>> G.add_nodes_from([3], time='2pm')
>>> G.node[1]
{'time': '5pm'}
>>> G.node[1]['room'] = 714
>>> G.nodes(data=True)
[(1, {'room': 714, 'time': '5pm'}), (3, {'time': '2pm'})]

Note that adding a node to G.node does not add it to the graph, use G.add_node() to add new nodes.

Edge Attributes

Add edge attributes using add_edge(), add_edges_from(), subscript notation, or G.edge.

>>> G.add_edge(1, 2, weight=4.7 )
>>> G.add_edges_from([(3,4),(4,5)], color='red')
>>> G.add_edges_from([(1,2,{'color':'blue'}), (2,3,{'weight':8})])
>>> G[1][2]['weight'] = 4.7
>>> G.edge[1][2]['weight'] = 4

The special attribute ‘weight’ should be numeric and holds values used by algorithms requiring weighted edges.

Directed graphs

The DiGraph class provides additional methods specific to directed edges, e.g. DiGraph.out_edges(), DiGraph.in_degree(), DiGraph.predecessors(), DiGraph.successors() etc. To allow algorithms to work with both classes easily, the directed versions of neighbors() and degree() are equivalent to successors() and the sum of in_degree() and out_degree() respectively even though that may feel inconsistent at times.

>>> DG=nx.DiGraph()
>>> DG.add_weighted_edges_from([(1,2,0.5), (3,1,0.75)])
>>> DG.out_degree(1,weight='weight')
0.5
>>> DG.degree(1,weight='weight')
1.25
>>> DG.successors(1)
[2]
>>> DG.neighbors(1)
[2]

Some algorithms work only for directed graphs and others are not well defined for directed graphs. Indeed the tendency to lump directed and undirected graphs together is dangerous. If you want to treat a directed graph as undirected for some measurement you should probably convert it using Graph.to_undirected() or with

>>> H = nx.Graph(G) # convert G to undirected graph

Multigraphs

NetworkX provides classes for graphs which allow multiple edges between any pair of nodes. The MultiGraph and MultiDiGraph classes allow you to add the same edge twice, possibly with different edge data. This can be powerful for some applications, but many algorithms are not well defined on such graphs. Shortest path is one example. Where results are well defined, e.g. MultiGraph.degree() we provide the function. Otherwise you should convert to a standard graph in a way that makes the measurement well defined.

>>> MG=nx.MultiGraph()
>>> MG.add_weighted_edges_from([(1,2,.5), (1,2,.75), (2,3,.5)])
>>> MG.degree(weight='weight')
{1: 1.25, 2: 1.75, 3: 0.5}
>>> GG=nx.Graph()
>>> for n,nbrs in MG.adjacency_iter():
...    for nbr,edict in nbrs.items():
...        minvalue=min([d['weight'] for d in edict.values()])
...        GG.add_edge(n,nbr, weight = minvalue)
...
>>> nx.shortest_path(GG,1,3)
[1, 2, 3]

Graph generators and graph operations

In addition to constructing graphs node-by-node or edge-by-edge, they can also be generated by

  1. Applying classic graph operations, such as:

    subgraph(G, nbunch)      - induce subgraph of G on nodes in nbunch
    union(G1,G2)             - graph union
    disjoint_union(G1,G2)    - graph union assuming all nodes are different
    cartesian_product(G1,G2) - return Cartesian product graph
    compose(G1,G2)           - combine graphs identifying nodes common to both
    complement(G)            - graph complement
    create_empty_copy(G)     - return an empty copy of the same graph class
    convert_to_undirected(G) - return an undirected representation of G
    convert_to_directed(G)   - return a directed representation of G
    
  2. Using a call to one of the classic small graphs, e.g.

>>> petersen=nx.petersen_graph()
>>> tutte=nx.tutte_graph()
>>> maze=nx.sedgewick_maze_graph()
>>> tet=nx.tetrahedral_graph()
  1. Using a (constructive) generator for a classic graph, e.g.
>>> K_5=nx.complete_graph(5)
>>> K_3_5=nx.complete_bipartite_graph(3,5)
>>> barbell=nx.barbell_graph(10,10)
>>> lollipop=nx.lollipop_graph(10,20)
  1. Using a stochastic graph generator, e.g.
>>> er=nx.erdos_renyi_graph(100,0.15)
>>> ws=nx.watts_strogatz_graph(30,3,0.1)
>>> ba=nx.barabasi_albert_graph(100,5)
>>> red=nx.random_lobster(100,0.9,0.9)
  1. Reading a graph stored in a file using common graph formats, such as edge lists, adjacency lists, GML, GraphML, pickle, LEDA and others.
>>> nx.write_gml(red,"path.to.file")
>>> mygraph=nx.read_gml("path.to.file")

Details on graph formats: Reading and writing graphs

Details on graph generator functions: Graph generators

Analyzing graphs

The structure of G can be analyzed using various graph-theoretic functions such as:

>>> G=nx.Graph()
>>> G.add_edges_from([(1,2),(1,3)])
>>> G.add_node("spam")       # adds node "spam"
>>> nx.connected_components(G)
[[1, 2, 3], ['spam']]
>>> sorted(nx.degree(G).values())
[0, 1, 1, 2]
>>> nx.clustering(G)
{1: 0.0, 2: 0.0, 3: 0.0, 'spam': 0.0}

Functions that return node properties return dictionaries keyed by node label.

>>> nx.degree(G)
{1: 2, 2: 1, 3: 1, 'spam': 0}

For values of specific nodes, you can provide a single node or an nbunch of nodes as argument. If a single node is specified, then a single value is returned. If an nbunch is specified, then the function will return a dictionary.

>>> nx.degree(G,1)
2
>>> G.degree(1)
2
>>> G.degree([1,2])
{1: 2, 2: 1}
>>> sorted(G.degree([1,2]).values())
[1, 2]
>>> sorted(G.degree().values())
[0, 1, 1, 2]

Details on graph algorithms supported: Algorithms

Drawing graphs

NetworkX is not primarily a graph drawing package but basic drawing with Matplotlib as well as an interface to use the open source Graphviz software package are included. These are part of the networkx.drawing package and will be imported if possible. See Drawing for details.

Note that the drawing package in NetworkX is not yet compatible with Python versions 3.0 and above.

First import Matplotlib’s plot interface (pylab works too)

>>> import matplotlib.pyplot as plt

You may find it useful to interactively test code using “ipython -pylab”, which combines the power of ipython and matplotlib and provides a convenient interactive mode.

To test if the import of networkx.drawing was successful draw G using one of

>>> nx.draw(G)
>>> nx.draw_random(G)
>>> nx.draw_circular(G)
>>> nx.draw_spectral(G)

when drawing to an interactive display. Note that you may need to issue a Matplotlib

>>> plt.show()

command if you are not using matplotlib in interactive mode: (See Matplotlib FAQ )

To save drawings to a file, use, for example

>>> nx.draw(G)
>>> plt.savefig("path.png")

writes to the file “path.png” in the local directory. If Graphviz and PyGraphviz, or pydot, are available on your system, you can also use

>>> nx.draw_graphviz(G)
>>> nx.write_dot(G,'file.dot')

Details on drawing graphs: Drawing

What Next

Now that you have an idea of what the NetworkX package provides, you should investigate the parts of the package most useful for you.

Reference Section provides details on NetworkX.

/examples/index provides some example programs written using NetworkX.

Reference

Release:1.10
Date:October 31, 2015

Introduction

NetworkX provides data structures for graphs (or networks) along with graph algorithms, generators, and drawing tools.

The structure of NetworkX can be seen by the organization of its source code. The package provides classes for graph objects, generators to create standard graphs, IO routines for reading in existing datasets, algorithms to analyse the resulting networks and some basic drawing tools.

Most of the NetworkX API is provided by functions which take a graph object as an argument. Methods of the graph object are limited to basic manipulation and reporting. This provides modularity of code and documentation. It also makes it easier for newcomers to learn about the package in stages. The source code for each module is meant to be easy to read and reading this Python code is actually a good way to learn more about network algorithms, but we have put a lot of effort into making the documentation sufficient and friendly. If you have suggestions or questions please contact us by joining the NetworkX Google group.

Classes are named using CamelCase (capital letters at the start of each word). functions, methods and variable names are lower_case_underscore (lowercase with an underscore representing a space between words).

NetworkX Basics

After starting Python, import the networkx module with (the recommended way)

>>> import networkx as nx

To save repetition, in the documentation we assume that NetworkX has been imported this way.

If importing networkx fails, it means that Python cannot find the installed module. Check your installation and your PYTHONPATH.

The following basic graph types are provided as Python classes:

Graph
This class implements an undirected graph. It ignores multiple edges between two nodes. It does allow self-loop edges between a node and itself.
DiGraph
Directed graphs, that is, graphs with directed edges. Operations common to directed graphs, (a subclass of Graph).
MultiGraph
A flexible graph class that allows multiple undirected edges between pairs of nodes. The additional flexibility leads to some degradation in performance, though usually not significant.
MultiDiGraph
A directed version of a MultiGraph.

Empty graph-like objects are created with

>>> G=nx.Graph()
>>> G=nx.DiGraph()
>>> G=nx.MultiGraph()
>>> G=nx.MultiDiGraph()

All graph classes allow any hashable object as a node. Hashable objects include strings, tuples, integers, and more. Arbitrary edge attributes such as weights and labels can be associated with an edge.

The graph internal data structures are based on an adjacency list representation and implemented using Python dictionary datastructures. The graph adjaceny structure is implemented as a Python dictionary of dictionaries; the outer dictionary is keyed by nodes to values that are themselves dictionaries keyed by neighboring node to the edge attributes associated with that edge. This “dict-of-dicts” structure allows fast addition, deletion, and lookup of nodes and neighbors in large graphs. The underlying datastructure is accessed directly by methods (the programming interface “API”) in the class definitions. All functions, on the other hand, manipulate graph-like objects solely via those API methods and not by acting directly on the datastructure. This design allows for possible replacement of the ‘dicts-of-dicts’-based datastructure with an alternative datastructure that implements the same methods.

Graphs

The first choice to be made when using NetworkX is what type of graph object to use. A graph (network) is a collection of nodes together with a collection of edges that are pairs of nodes. Attributes are often associated with nodes and/or edges. NetworkX graph objects come in different flavors depending on two main properties of the network:

  • Directed: Are the edges directed? Does the order of the edge pairs (u,v) matter? A directed graph is specified by the “Di” prefix in the class name, e.g. DiGraph(). We make this distinction because many classical graph properties are defined differently for directed graphs.
  • Multi-edges: Are multiple edges allowed between each pair of nodes? As you might imagine, multiple edges requires a different data structure, though tricky users could design edge data objects to support this functionality. We provide a standard data structure and interface for this type of graph using the prefix “Multi”, e.g. MultiGraph().

The basic graph classes are named: Graph, DiGraph, MultiGraph, and MultiDiGraph

Nodes and Edges

The next choice you have to make when specifying a graph is what kinds of nodes and edges to use.

If the topology of the network is all you care about then using integers or strings as the nodes makes sense and you need not worry about edge data. If you have a data structure already in place to describe nodes you can simply use that structure as your nodes provided it is hashable. If it is not hashable you can use a unique identifier to represent the node and assign the data as a node attribute.

Edges often have data associated with them. Arbitrary data can associated with edges as an edge attribute. If the data is numeric and the intent is to represent a weighted graph then use the ‘weight’ keyword for the attribute. Some of the graph algorithms, such as Dijkstra’s shortest path algorithm, use this attribute name to get the weight for each edge.

Other attributes can be assigned to an edge by using keyword/value pairs when adding edges. You can use any keyword except ‘weight’ to name your attribute and can then easily query the edge data by that attribute keyword.

Once you’ve decided how to encode the nodes and edges, and whether you have an undirected/directed graph with or without multiedges you are ready to build your network.

Graph Creation

NetworkX graph objects can be created in one of three ways:

  • Graph generators – standard algorithms to create network topologies.
  • Importing data from pre-existing (usually file) sources.
  • Adding edges and nodes explicitly.

Explicit addition and removal of nodes/edges is the easiest to describe. Each graph object supplies methods to manipulate the graph. For example,

>>> import networkx as nx
>>> G=nx.Graph()
>>> G.add_edge(1,2)  # default edge data=1
>>> G.add_edge(2,3,weight=0.9) # specify edge data

Edge attributes can be anything:

>>> import math
>>> G.add_edge('y','x',function=math.cos)
>>> G.add_node(math.cos) # any hashable can be a node

You can add many edges at one time:

>>> elist=[('a','b',5.0),('b','c',3.0),('a','c',1.0),('c','d',7.3)]
>>> G.add_weighted_edges_from(elist)

See the Tutorial for more examples.

Some basic graph operations such as union and intersection are described in the Operators module documentation.

Graph generators such as binomial_graph and powerlaw_graph are provided in the Graph generators subpackage.

For importing network data from formats such as GML, GraphML, edge list text files see the Reading and writing graphs subpackage.

Graph Reporting

Class methods are used for the basic reporting functions neighbors, edges and degree. Reporting of lists is often needed only to iterate through that list so we supply iterator versions of many property reporting methods. For example edges() and nodes() have corresponding methods edges_iter() and nodes_iter(). Using these methods when you can will save memory and often time as well.

The basic graph relationship of an edge can be obtained in two basic ways. One can look for neighbors of a node or one can look for edges incident to a node. We jokingly refer to people who focus on nodes/neighbors as node-centric and people who focus on edges as edge-centric. The designers of NetworkX tend to be node-centric and view edges as a relationship between nodes. You can see this by our avoidance of notation like G[u,v] in favor of G[u][v]. Most data structures for sparse graphs are essentially adjacency lists and so fit this perspective. In the end, of course, it doesn’t really matter which way you examine the graph. G.edges() removes duplicate representations of each edge while G.neighbors(n) or G[n] is slightly faster but doesn’t remove duplicates.

Any properties that are more complicated than edges, neighbors and degree are provided by functions. For example nx.triangles(G,n) gives the number of triangles which include node n as a vertex. These functions are grouped in the code and documentation under the term algorithms.

Algorithms

A number of graph algorithms are provided with NetworkX. These include shortest path, and breadth first search (see traversal), clustering and isomorphism algorithms and others. There are many that we have not developed yet too. If you implement a graph algorithm that might be useful for others please let us know through the NetworkX Google group or the Github Developer Zone.

As an example here is code to use Dijkstra’s algorithm to find the shortest weighted path:

>>> G=nx.Graph()
>>> e=[('a','b',0.3),('b','c',0.9),('a','c',0.5),('c','d',1.2)]
>>> G.add_weighted_edges_from(e)
>>> print(nx.dijkstra_path(G,'a','d'))
['a', 'c', 'd']
Drawing

While NetworkX is not designed as a network layout tool, we provide a simple interface to drawing packages and some simple layout algorithms. We interface to the excellent Graphviz layout tools like dot and neato with the (suggested) pygraphviz package or the pydot interface. Drawing can be done using external programs or the Matplotlib Python package. Interactive GUI interfaces are possible though not provided. The drawing tools are provided in the module drawing.

The basic drawing functions essentially place the nodes on a scatterplot using the positions in a dictionary or computed with a layout function. The edges are then lines between those dots.

>>> G=nx.cubical_graph()
>>> nx.draw(G)   # default spring_layout
>>> nx.draw(G,pos=nx.spectral_layout(G), nodecolor='r',edge_color='b')

See the examples for more ideas.

Data Structure

NetworkX uses a “dictionary of dictionaries of dictionaries” as the basic network data structure. This allows fast lookup with reasonable storage for large sparse networks. The keys are nodes so G[u] returns an adjacency dictionary keyed by neighbor to the edge attribute dictionary. The expression G[u][v] returns the edge attribute dictionary itself. A dictionary of lists would have also been possible, but not allowed fast edge detection nor convenient storage of edge data.

Advantages of dict-of-dicts-of-dicts data structure:

  • Find edges and remove edges with two dictionary look-ups.
  • Prefer to “lists” because of fast lookup with sparse storage.
  • Prefer to “sets” since data can be attached to edge.
  • G[u][v] returns the edge attribute dictionary.
  • n in G tests if node n is in graph G.
  • for n in G: iterates through the graph.
  • for nbr in G[n]: iterates through neighbors.

As an example, here is a representation of an undirected graph with the edges (‘A’,’B’), (‘B’,’C’)

>>> G=nx.Graph()
>>> G.add_edge('A','B')
>>> G.add_edge('B','C')
>>> print(G.adj)
{'A': {'B': {}}, 'C': {'B': {}}, 'B': {'A': {}, 'C': {}}}

The data structure gets morphed slightly for each base graph class. For DiGraph two dict-of-dicts-of-dicts structures are provided, one for successors and one for predecessors. For MultiGraph/MultiDiGraph we use a dict-of-dicts-of-dicts-of-dicts [1] where the third dictionary is keyed by an edge key identifier to the fourth dictionary which contains the edge attributes for that edge between the two nodes.

Graphs use a dictionary of attributes for each edge. We use a dict-of-dicts-of-dicts data structure with the inner dictionary storing “name-value” relationships for that edge.

>>> G=nx.Graph()
>>> G.add_edge(1,2,color='red',weight=0.84,size=300)
>>> print(G[1][2]['size'])
300

Footnotes

[1]“It’s dictionaries all the way down.”

Graph types

NetworkX provides data structures and methods for storing graphs.

All NetworkX graph classes allow (hashable) Python objects as nodes. and any Python object can be assigned as an edge attribute.

The choice of graph class depends on the structure of the graph you want to represent.

Which graph class should I use?

Graph Type NetworkX Class
Undirected Simple Graph
Directed Simple DiGraph
With Self-loops Graph, DiGraph
With Parallel edges MultiGraph, MultiDiGraph

Basic graph types

Graph – Undirected graphs with self loops
Overview
Graph(data=None, **attr)[source]

Base class for undirected graphs.

A Graph stores nodes and edges with optional data, or attributes.

Graphs hold undirected edges. Self loops are allowed but multiple (parallel) edges are not.

Nodes can be arbitrary (hashable) Python objects with optional key/value attributes.

Edges are represented as links between nodes with optional key/value attributes.

Parameters:
  • data (input graph) – Data to initialize graph. If data=None (default) an empty graph is created. The data can be an edge list, or any NetworkX graph object. If the corresponding optional Python packages are installed the data can also be a NumPy matrix or 2d ndarray, a SciPy sparse matrix, or a PyGraphviz graph.
  • attr (keyword arguments, optional (default= no attributes)) – Attributes to add to graph as key=value pairs.

Examples

Create an empty graph structure (a “null graph”) with no nodes and no edges.

>>> G = nx.Graph()

G can be grown in several ways.

Nodes:

Add one node at a time:

>>> G.add_node(1)

Add the nodes from any container (a list, dict, set or even the lines from a file or the nodes from another graph).

>>> G.add_nodes_from([2,3])
>>> G.add_nodes_from(range(100,110))
>>> H=nx.Graph()
>>> H.add_path([0,1,2,3,4,5,6,7,8,9])
>>> G.add_nodes_from(H)

In addition to strings and integers any hashable Python object (except None) can represent a node, e.g. a customized node object, or even another Graph.

>>> G.add_node(H)

Edges:

G can also be grown by adding edges.

Add one edge,

>>> G.add_edge(1, 2)

a list of edges,

>>> G.add_edges_from([(1,2),(1,3)])

or a collection of edges,

>>> G.add_edges_from(H.edges())

If some edges connect nodes not yet in the graph, the nodes are added automatically. There are no errors when adding nodes or edges that already exist.

Attributes:

Each graph, node, and edge can hold key/value attribute pairs in an associated attribute dictionary (the keys must be hashable). By default these are empty, but can be added or changed using add_edge, add_node or direct manipulation of the attribute dictionaries named graph, node and edge respectively.

>>> G = nx.Graph(day="Friday")
>>> G.graph
{'day': 'Friday'}

Add node attributes using add_node(), add_nodes_from() or G.node

>>> G.add_node(1, time='5pm')
>>> G.add_nodes_from([3], time='2pm')
>>> G.node[1]
{'time': '5pm'}
>>> G.node[1]['room'] = 714
>>> del G.node[1]['room'] # remove attribute
>>> G.nodes(data=True)
[(1, {'time': '5pm'}), (3, {'time': '2pm'})]

Warning: adding a node to G.node does not add it to the graph.

Add edge attributes using add_edge(), add_edges_from(), subscript notation, or G.edge.

>>> G.add_edge(1, 2, weight=4.7 )
>>> G.add_edges_from([(3,4),(4,5)], color='red')
>>> G.add_edges_from([(1,2,{'color':'blue'}), (2,3,{'weight':8})])
>>> G[1][2]['weight'] = 4.7
>>> G.edge[1][2]['weight'] = 4

Shortcuts:

Many common graph features allow python syntax to speed reporting.

>>> 1 in G     # check if node in graph
True
>>> [n for n in G if n<3]   # iterate through nodes
[1, 2]
>>> len(G)  # number of nodes in graph
5

The fastest way to traverse all edges of a graph is via adjacency_iter(), but the edges() method is often more convenient.

>>> for n,nbrsdict in G.adjacency_iter():
...     for nbr,eattr in nbrsdict.items():
...        if 'weight' in eattr:
...            (n,nbr,eattr['weight'])
(1, 2, 4)
(2, 1, 4)
(2, 3, 8)
(3, 2, 8)
>>> G.edges(data='weight')
[(1, 2, 4), (2, 3, 8), (3, 4, None), (4, 5, None)]

Reporting:

Simple graph information is obtained using methods. Iterator versions of many reporting methods exist for efficiency. Methods exist for reporting nodes(), edges(), neighbors() and degree() as well as the number of nodes and edges.

For details on these and other miscellaneous methods, see below.

Subclasses (Advanced):

The Graph class uses a dict-of-dict-of-dict data structure. The outer dict (node_dict) holds adjacency lists keyed by node. The next dict (adjlist) represents the adjacency list and holds edge data keyed by neighbor. The inner dict (edge_attr) represents the edge data and holds edge attribute values keyed by attribute names.

Each of these three dicts can be replaced by a user defined dict-like object. In general, the dict-like features should be maintained but extra features can be added. To replace one of the dicts create a new graph class by changing the class(!) variable holding the factory for that dict-like structure. The variable names are node_dict_factory, adjlist_dict_factory and edge_attr_dict_factory.

node_dict_factory : function, (default: dict)
Factory function to be used to create the outer-most dict in the data structure that holds adjacency lists keyed by node. It should require no arguments and return a dict-like object.
adjlist_dict_factory : function, (default: dict)
Factory function to be used to create the adjacency list dict which holds edge data keyed by neighbor. It should require no arguments and return a dict-like object
edge_attr_dict_factory : function, (default: dict)
Factory function to be used to create the edge attribute dict which holds attrbute values keyed by attribute name. It should require no arguments and return a dict-like object.

Examples

Create a graph object that tracks the order nodes are added.

>>> from collections import OrderedDict
>>> class OrderedNodeGraph(nx.Graph):
...     node_dict_factory=OrderedDict
>>> G=OrderedNodeGraph()
>>> G.add_nodes_from( (2,1) )
>>> G.nodes()
[2, 1]
>>> G.add_edges_from( ((2,2), (2,1), (1,1)) )
>>> G.edges()
[(2, 1), (2, 2), (1, 1)]

Create a graph object that tracks the order nodes are added and for each node track the order that neighbors are added.

>>> class OrderedGraph(nx.Graph):
...    node_dict_factory = OrderedDict
...    adjlist_dict_factory = OrderedDict
>>> G = OrderedGraph()
>>> G.add_nodes_from( (2,1) )
>>> G.nodes()
[2, 1]
>>> G.add_edges_from( ((2,2), (2,1), (1,1)) )
>>> G.edges()
[(2, 2), (2, 1), (1, 1)]

Create a low memory graph class that effectively disallows edge attributes by using a single attribute dict for all edges. This reduces the memory used, but you lose edge attributes.

>>> class ThinGraph(nx.Graph):
...     all_edge_dict = {'weight': 1}
...     def single_edge_dict(self):
...         return self.all_edge_dict
...     edge_attr_dict_factory = single_edge_dict
>>> G = ThinGraph()
>>> G.add_edge(2,1)
>>> G.edges(data= True)
[(1, 2, {'weight': 1})]
>>> G.add_edge(2,2)
>>> G[2][1] is G[2][2]
True
Adding and removing nodes and edges
Graph.__init__([data]) Initialize a graph with edges, name, graph attributes.
Graph.add_node(n[, attr_dict]) Add a single node n and update node attributes.
Graph.add_nodes_from(nodes, **attr) Add multiple nodes.
Graph.remove_node(n) Remove node n.
Graph.remove_nodes_from(nodes) Remove multiple nodes.
Graph.add_edge(u, v[, attr_dict]) Add an edge between u and v.
Graph.add_edges_from(ebunch[, attr_dict]) Add all the edges in ebunch.
Graph.add_weighted_edges_from(ebunch[, weight]) Add all the edges in ebunch as weighted edges with specified weights.
Graph.remove_edge(u, v) Remove the edge between u and v.
Graph.remove_edges_from(ebunch) Remove all edges specified in ebunch.
Graph.add_star(nodes, **attr) Add a star.
Graph.add_path(nodes, **attr) Add a path.
Graph.add_cycle(nodes, **attr) Add a cycle.
Graph.clear() Remove all nodes and edges from the graph.
Iterating over nodes and edges
Graph.nodes([data]) Return a list of the nodes in the graph.
Graph.nodes_iter([data]) Return an iterator over the nodes.
Graph.__iter__() Iterate over the nodes.
Graph.edges([nbunch, data, default]) Return a list of edges.
Graph.edges_iter([nbunch, data, default]) Return an iterator over the edges.
Graph.get_edge_data(u, v[, default]) Return the attribute dictionary associated with edge (u,v).
Graph.neighbors(n) Return a list of the nodes connected to the node n.
Graph.neighbors_iter(n) Return an iterator over all neighbors of node n.
Graph.__getitem__(n) Return a dict of neighbors of node n.
Graph.adjacency_list() Return an adjacency list representation of the graph.
Graph.adjacency_iter() Return an iterator of (node, adjacency dict) tuples for all nodes.
Graph.nbunch_iter([nbunch]) Return an iterator of nodes contained in nbunch that are also in the graph.
Information about graph structure
Graph.has_node(n) Return True if the graph contains the node n.
Graph.__contains__(n) Return True if n is a node, False otherwise.
Graph.has_edge(u, v) Return True if the edge (u,v) is in the graph.
Graph.order() Return the number of nodes in the graph.
Graph.number_of_nodes() Return the number of nodes in the graph.
Graph.__len__() Return the number of nodes.
Graph.degree([nbunch, weight]) Return the degree of a node or nodes.
Graph.degree_iter([nbunch, weight]) Return an iterator for (node, degree).
Graph.size([weight]) Return the number of edges.
Graph.number_of_edges([u, v]) Return the number of edges between two nodes.
Graph.nodes_with_selfloops() Return a list of nodes with self loops.
Graph.selfloop_edges([data, default]) Return a list of selfloop edges.
Graph.number_of_selfloops() Return the number of selfloop edges.
Making copies and subgraphs
Graph.copy() Return a copy of the graph.
Graph.to_undirected() Return an undirected copy of the graph.
Graph.to_directed() Return a directed representation of the graph.
Graph.subgraph(nbunch) Return the subgraph induced on nodes in nbunch.
DiGraph - Directed graphs with self loops
Overview
DiGraph(data=None, **attr)[source]

Base class for directed graphs.

A DiGraph stores nodes and edges with optional data, or attributes.

DiGraphs hold directed edges. Self loops are allowed but multiple (parallel) edges are not.

Nodes can be arbitrary (hashable) Python objects with optional key/value attributes.

Edges are represented as links between nodes with optional key/value attributes.

Parameters:
  • data (input graph) – Data to initialize graph. If data=None (default) an empty graph is created. The data can be an edge list, or any NetworkX graph object. If the corresponding optional Python packages are installed the data can also be a NumPy matrix or 2d ndarray, a SciPy sparse matrix, or a PyGraphviz graph.
  • attr (keyword arguments, optional (default= no attributes)) – Attributes to add to graph as key=value pairs.

Examples

Create an empty graph structure (a “null graph”) with no nodes and no edges.

>>> G = nx.DiGraph()

G can be grown in several ways.

Nodes:

Add one node at a time:

>>> G.add_node(1)

Add the nodes from any container (a list, dict, set or even the lines from a file or the nodes from another graph).

>>> G.add_nodes_from([2,3])
>>> G.add_nodes_from(range(100,110))
>>> H=nx.Graph()
>>> H.add_path([0,1,2,3,4,5,6,7,8,9])
>>> G.add_nodes_from(H)

In addition to strings and integers any hashable Python object (except None) can represent a node, e.g. a customized node object, or even another Graph.

>>> G.add_node(H)

Edges:

G can also be grown by adding edges.

Add one edge,

>>> G.add_edge(1, 2)

a list of edges,

>>> G.add_edges_from([(1,2),(1,3)])

or a collection of edges,

>>> G.add_edges_from(H.edges())

If some edges connect nodes not yet in the graph, the nodes are added automatically. There are no errors when adding nodes or edges that already exist.

Attributes:

Each graph, node, and edge can hold key/value attribute pairs in an associated attribute dictionary (the keys must be hashable). By default these are empty, but can be added or changed using add_edge, add_node or direct manipulation of the attribute dictionaries named graph, node and edge respectively.

>>> G = nx.DiGraph(day="Friday")
>>> G.graph
{'day': 'Friday'}

Add node attributes using add_node(), add_nodes_from() or G.node

>>> G.add_node(1, time='5pm')
>>> G.add_nodes_from([3], time='2pm')
>>> G.node[1]
{'time': '5pm'}
>>> G.node[1]['room'] = 714
>>> del G.node[1]['room'] # remove attribute
>>> G.nodes(data=True)
[(1, {'time': '5pm'}), (3, {'time': '2pm'})]

Warning: adding a node to G.node does not add it to the graph.

Add edge attributes using add_edge(), add_edges_from(), subscript notation, or G.edge.

>>> G.add_edge(1, 2, weight=4.7 )
>>> G.add_edges_from([(3,4),(4,5)], color='red')
>>> G.add_edges_from([(1,2,{'color':'blue'}), (2,3,{'weight':8})])
>>> G[1][2]['weight'] = 4.7
>>> G.edge[1][2]['weight'] = 4

Shortcuts:

Many common graph features allow python syntax to speed reporting.

>>> 1 in G     # check if node in graph
True
>>> [n for n in G if n<3]   # iterate through nodes
[1, 2]
>>> len(G)  # number of nodes in graph
5

The fastest way to traverse all edges of a graph is via adjacency_iter(), but the edges() method is often more convenient.

>>> for n,nbrsdict in G.adjacency_iter():
...     for nbr,eattr in nbrsdict.items():
...        if 'weight' in eattr:
...            (n,nbr,eattr['weight'])
(1, 2, 4)
(2, 3, 8)
>>> G.edges(data='weight')
[(1, 2, 4), (2, 3, 8), (3, 4, None), (4, 5, None)]

Reporting:

Simple graph information is obtained using methods. Iterator versions of many reporting methods exist for efficiency. Methods exist for reporting nodes(), edges(), neighbors() and degree() as well as the number of nodes and edges.

For details on these and other miscellaneous methods, see below.

Subclasses (Advanced):

The Graph class uses a dict-of-dict-of-dict data structure. The outer dict (node_dict) holds adjacency lists keyed by node. The next dict (adjlist) represents the adjacency list and holds edge data keyed by neighbor. The inner dict (edge_attr) represents the edge data and holds edge attribute values keyed by attribute names.

Each of these three dicts can be replaced by a user defined dict-like object. In general, the dict-like features should be maintained but extra features can be added. To replace one of the dicts create a new graph class by changing the class(!) variable holding the factory for that dict-like structure. The variable names are node_dict_factory, adjlist_dict_factory and edge_attr_dict_factory.

node_dict_factory : function, optional (default: dict)
Factory function to be used to create the outer-most dict in the data structure that holds adjacency lists keyed by node. It should require no arguments and return a dict-like object.
adjlist_dict_factory : function, optional (default: dict)
Factory function to be used to create the adjacency list dict which holds edge data keyed by neighbor. It should require no arguments and return a dict-like object
edge_attr_dict_factory : function, optional (default: dict)
Factory function to be used to create the edge attribute dict which holds attrbute values keyed by attribute name. It should require no arguments and return a dict-like object.

Examples

Create a graph object that tracks the order nodes are added.

>>> from collections import OrderedDict
>>> class OrderedNodeGraph(nx.Graph):
...     node_dict_factory=OrderedDict
>>> G=OrderedNodeGraph()
>>> G.add_nodes_from( (2,1) )
>>> G.nodes()
[2, 1]
>>> G.add_edges_from( ((2,2), (2,1), (1,1)) )
>>> G.edges()
[(2, 1), (2, 2), (1, 1)]

Create a graph object that tracks the order nodes are added and for each node track the order that neighbors are added.

>>> class OrderedGraph(nx.Graph):
...    node_dict_factory = OrderedDict
...    adjlist_dict_factory = OrderedDict
>>> G = OrderedGraph()
>>> G.add_nodes_from( (2,1) )
>>> G.nodes()
[2, 1]
>>> G.add_edges_from( ((2,2), (2,1), (1,1)) )
>>> G.edges()
[(2, 2), (2, 1), (1, 1)]

Create a low memory graph class that effectively disallows edge attributes by using a single attribute dict for all edges. This reduces the memory used, but you lose edge attributes.

>>> class ThinGraph(nx.Graph):
...     all_edge_dict = {'weight': 1}
...     def single_edge_dict(self):
...         return self.all_edge_dict
...     edge_attr_dict_factory = single_edge_dict
>>> G = ThinGraph()
>>> G.add_edge(2,1)
>>> G.edges(data= True)
[(1, 2, {'weight': 1})]
>>> G.add_edge(2,2)
>>> G[2][1] is G[2][2]
True
Adding and removing nodes and edges
DiGraph.__init__([data]) Initialize a graph with edges, name, graph attributes.
DiGraph.add_node(n[, attr_dict]) Add a single node n and update node attributes.
DiGraph.add_nodes_from(nodes, **attr) Add multiple nodes.
DiGraph.remove_node(n) Remove node n.
DiGraph.remove_nodes_from(nbunch) Remove multiple nodes.
DiGraph.add_edge(u, v[, attr_dict]) Add an edge between u and v.
DiGraph.add_edges_from(ebunch[, attr_dict]) Add all the edges in ebunch.
DiGraph.add_weighted_edges_from(ebunch[, weight]) Add all the edges in ebunch as weighted edges with specified weights.
DiGraph.remove_edge(u, v) Remove the edge between u and v.
DiGraph.remove_edges_from(ebunch) Remove all edges specified in ebunch.
DiGraph.add_star(nodes, **attr) Add a star.
DiGraph.add_path(nodes, **attr) Add a path.
DiGraph.add_cycle(nodes, **attr) Add a cycle.
DiGraph.clear() Remove all nodes and edges from the graph.
Iterating over nodes and edges
DiGraph.nodes([data]) Return a list of the nodes in the graph.
DiGraph.nodes_iter([data]) Return an iterator over the nodes.
DiGraph.__iter__() Iterate over the nodes.
DiGraph.edges([nbunch, data, default]) Return a list of edges.
DiGraph.edges_iter([nbunch, data, default]) Return an iterator over the edges.
DiGraph.out_edges([nbunch, data, default]) Return a list of edges.
DiGraph.out_edges_iter([nbunch, data, default]) Return an iterator over the edges.
DiGraph.in_edges([nbunch, data]) Return a list of the incoming edges.
DiGraph.in_edges_iter([nbunch, data]) Return an iterator over the incoming edges.
DiGraph.get_edge_data(u, v[, default]) Return the attribute dictionary associated with edge (u,v).
DiGraph.neighbors(n) Return a list of successor nodes of n.
DiGraph.neighbors_iter(n) Return an iterator over successor nodes of n.
DiGraph.__getitem__(n) Return a dict of neighbors of node n.
DiGraph.successors(n) Return a list of successor nodes of n.
DiGraph.successors_iter(n) Return an iterator over successor nodes of n.
DiGraph.predecessors(n) Return a list of predecessor nodes of n.
DiGraph.predecessors_iter(n) Return an iterator over predecessor nodes of n.
DiGraph.adjacency_list() Return an adjacency list representation of the graph.
DiGraph.adjacency_iter() Return an iterator of (node, adjacency dict) tuples for all nodes.
DiGraph.nbunch_iter([nbunch]) Return an iterator of nodes contained in nbunch that are also in the graph.
Information about graph structure
DiGraph.has_node(n) Return True if the graph contains the node n.
DiGraph.__contains__(n) Return True if n is a node, False otherwise.
DiGraph.has_edge(u, v) Return True if the edge (u,v) is in the graph.
DiGraph.order() Return the number of nodes in the graph.
DiGraph.number_of_nodes() Return the number of nodes in the graph.
DiGraph.__len__() Return the number of nodes.
DiGraph.degree([nbunch, weight]) Return the degree of a node or nodes.
DiGraph.degree_iter([nbunch, weight]) Return an iterator for (node, degree).
DiGraph.in_degree([nbunch, weight]) Return the in-degree of a node or nodes.
DiGraph.in_degree_iter([nbunch, weight]) Return an iterator for (node, in-degree).
DiGraph.out_degree([nbunch, weight]) Return the out-degree of a node or nodes.
DiGraph.out_degree_iter([nbunch, weight]) Return an iterator for (node, out-degree).
DiGraph.size([weight]) Return the number of edges.
DiGraph.number_of_edges([u, v]) Return the number of edges between two nodes.
DiGraph.nodes_with_selfloops() Return a list of nodes with self loops.
DiGraph.selfloop_edges([data, default]) Return a list of selfloop edges.
DiGraph.number_of_selfloops() Return the number of selfloop edges.
Making copies and subgraphs
DiGraph.copy() Return a copy of the graph.
DiGraph.to_undirected([reciprocal]) Return an undirected representation of the digraph.
DiGraph.to_directed() Return a directed copy of the graph.
DiGraph.subgraph(nbunch) Return the subgraph induced on nodes in nbunch.
DiGraph.reverse([copy]) Return the reverse of the graph.
MultiGraph - Undirected graphs with self loops and parallel edges
Overview
MultiGraph(data=None, **attr)[source]

An undirected graph class that can store multiedges.

Multiedges are multiple edges between two nodes. Each edge can hold optional data or attributes.

A MultiGraph holds undirected edges. Self loops are allowed.

Nodes can be arbitrary (hashable) Python objects with optional key/value attributes.

Edges are represented as links between nodes with optional key/value attributes.

Parameters:
  • data (input graph) – Data to initialize graph. If data=None (default) an empty graph is created. The data can be an edge list, or any NetworkX graph object. If the corresponding optional Python packages are installed the data can also be a NumPy matrix or 2d ndarray, a SciPy sparse matrix, or a PyGraphviz graph.
  • attr (keyword arguments, optional (default= no attributes)) – Attributes to add to graph as key=value pairs.

Examples

Create an empty graph structure (a “null graph”) with no nodes and no edges.

>>> G = nx.MultiGraph()

G can be grown in several ways.

Nodes:

Add one node at a time:

>>> G.add_node(1)

Add the nodes from any container (a list, dict, set or even the lines from a file or the nodes from another graph).

>>> G.add_nodes_from([2,3])
>>> G.add_nodes_from(range(100,110))
>>> H=nx.Graph()
>>> H.add_path([0,1,2,3,4,5,6,7,8,9])
>>> G.add_nodes_from(H)

In addition to strings and integers any hashable Python object (except None) can represent a node, e.g. a customized node object, or even another Graph.

>>> G.add_node(H)

Edges:

G can also be grown by adding edges.

Add one edge,

>>> G.add_edge(1, 2)

a list of edges,

>>> G.add_edges_from([(1,2),(1,3)])

or a collection of edges,

>>> G.add_edges_from(H.edges())

If some edges connect nodes not yet in the graph, the nodes are added automatically. If an edge already exists, an additional edge is created and stored using a key to identify the edge. By default the key is the lowest unused integer.

>>> G.add_edges_from([(4,5,dict(route=282)), (4,5,dict(route=37))])
>>> G[4]
{3: {0: {}}, 5: {0: {}, 1: {'route': 282}, 2: {'route': 37}}}

Attributes:

Each graph, node, and edge can hold key/value attribute pairs in an associated attribute dictionary (the keys must be hashable). By default these are empty, but can be added or changed using add_edge, add_node or direct manipulation of the attribute dictionaries named graph, node and edge respectively.

>>> G = nx.MultiGraph(day="Friday")
>>> G.graph
{'day': 'Friday'}

Add node attributes using add_node(), add_nodes_from() or G.node

>>> G.add_node(1, time='5pm')
>>> G.add_nodes_from([3], time='2pm')
>>> G.node[1]
{'time': '5pm'}
>>> G.node[1]['room'] = 714
>>> del G.node[1]['room'] # remove attribute
>>> G.nodes(data=True)
[(1, {'time': '5pm'}), (3, {'time': '2pm'})]

Warning: adding a node to G.node does not add it to the graph.

Add edge attributes using add_edge(), add_edges_from(), subscript notation, or G.edge.

>>> G.add_edge(1, 2, weight=4.7 )
>>> G.add_edges_from([(3,4),(4,5)], color='red')
>>> G.add_edges_from([(1,2,{'color':'blue'}), (2,3,{'weight':8})])
>>> G[1][2][0]['weight'] = 4.7
>>> G.edge[1][2][0]['weight'] = 4

Shortcuts:

Many common graph features allow python syntax to speed reporting.

>>> 1 in G     # check if node in graph
True
>>> [n for n in G if n<3]   # iterate through nodes
[1, 2]
>>> len(G)  # number of nodes in graph
5
>>> G[1] # adjacency dict keyed by neighbor to edge attributes
...            # Note: you should not change this dict manually!
{2: {0: {'weight': 4}, 1: {'color': 'blue'}}}

The fastest way to traverse all edges of a graph is via adjacency_iter(), but the edges() method is often more convenient.

>>> for n,nbrsdict in G.adjacency_iter():
...     for nbr,keydict in nbrsdict.items():
...        for key,eattr in keydict.items():
...            if 'weight' in eattr:
...                (n,nbr,key,eattr['weight'])
(1, 2, 0, 4)
(2, 1, 0, 4)
(2, 3, 0, 8)
(3, 2, 0, 8)
>>> G.edges(data='weight', keys=True)
[(1, 2, 0, 4), (1, 2, 1, None), (2, 3, 0, 8), (3, 4, 0, None), (4, 5, 0, None)]

Reporting:

Simple graph information is obtained using methods. Iterator versions of many reporting methods exist for efficiency. Methods exist for reporting nodes(), edges(), neighbors() and degree() as well as the number of nodes and edges.

For details on these and other miscellaneous methods, see below.

Subclasses (Advanced):

The MultiGraph class uses a dict-of-dict-of-dict-of-dict data structure. The outer dict (node_dict) holds adjacency lists keyed by node. The next dict (adjlist) represents the adjacency list and holds edge_key dicts keyed by neighbor. The edge_key dict holds each edge_attr dict keyed by edge key. The inner dict (edge_attr) represents the edge data and holds edge attribute values keyed by attribute names.

Each of these four dicts in the dict-of-dict-of-dict-of-dict structure can be replaced by a user defined dict-like object. In general, the dict-like features should be maintained but extra features can be added. To replace one of the dicts create a new graph class by changing the class(!) variable holding the factory for that dict-like structure. The variable names are node_dict_factory, adjlist_dict_factory, edge_key_dict_factory and edge_attr_dict_factory.

node_dict_factory : function, (default: dict)
Factory function to be used to create the outer-most dict in the data structure that holds adjacency lists keyed by node. It should require no arguments and return a dict-like object.
adjlist_dict_factory : function, (default: dict)
Factory function to be used to create the adjacency list dict which holds multiedge key dicts keyed by neighbor. It should require no arguments and return a dict-like object.
edge_key_dict_factory : function, (default: dict)
Factory function to be used to create the edge key dict which holds edge data keyed by edge key. It should require no arguments and return a dict-like object.
edge_attr_dict_factory : function, (default: dict)
Factory function to be used to create the edge attribute dict which holds attrbute values keyed by attribute name. It should require no arguments and return a dict-like object.

Examples

Create a multigraph object that tracks the order nodes are added.

>>> from collections import OrderedDict
>>> class OrderedGraph(nx.MultiGraph):
...    node_dict_factory = OrderedDict
>>> G = OrderedGraph()
>>> G.add_nodes_from( (2,1) )
>>> G.nodes()
[2, 1]
>>> G.add_edges_from( ((2,2), (2,1), (2,1), (1,1)) )
>>> G.edges()
[(2, 1), (2, 1), (2, 2), (1, 1)]

Create a multgraph object that tracks the order nodes are added and for each node track the order that neighbors are added and for each neighbor tracks the order that multiedges are added.

>>> class OrderedGraph(nx.MultiGraph):
...    node_dict_factory = OrderedDict
...    adjlist_dict_factory = OrderedDict
...    edge_key_dict_factory = OrderedDict
>>> G = OrderedGraph()
>>> G.add_nodes_from( (2,1) )
>>> G.nodes()
[2, 1]
>>> G.add_edges_from( ((2,2), (2,1,2,{'weight':0.1}), (2,1,1,{'weight':0.2}), (1,1)) )
>>> G.edges(keys=True)
[(2, 2, 0), (2, 1, 2), (2, 1, 1), (1, 1, 0)]
Adding and removing nodes and edges
MultiGraph.__init__([data])
MultiGraph.add_node(n[, attr_dict]) Add a single node n and update node attributes.
MultiGraph.add_nodes_from(nodes, **attr) Add multiple nodes.
MultiGraph.remove_node(n) Remove node n.
MultiGraph.remove_nodes_from(nodes) Remove multiple nodes.
MultiGraph.add_edge(u, v[, key, attr_dict]) Add an edge between u and v.
MultiGraph.add_edges_from(ebunch[, attr_dict]) Add all the edges in ebunch.
MultiGraph.add_weighted_edges_from(ebunch[, ...]) Add all the edges in ebunch as weighted edges with specified weights.
MultiGraph.remove_edge(u, v[, key]) Remove an edge between u and v.
MultiGraph.remove_edges_from(ebunch) Remove all edges specified in ebunch.
MultiGraph.add_star(nodes, **attr) Add a star.
MultiGraph.add_path(nodes, **attr) Add a path.
MultiGraph.add_cycle(nodes, **attr) Add a cycle.
MultiGraph.clear() Remove all nodes and edges from the graph.
Iterating over nodes and edges
MultiGraph.nodes([data]) Return a list of the nodes in the graph.
MultiGraph.nodes_iter([data]) Return an iterator over the nodes.
MultiGraph.__iter__() Iterate over the nodes.
MultiGraph.edges([nbunch, data, keys, default]) Return a list of edges.
MultiGraph.edges_iter([nbunch, data, keys, ...]) Return an iterator over the edges.
MultiGraph.get_edge_data(u, v[, key, default]) Return the attribute dictionary associated with edge (u,v).
MultiGraph.neighbors(n) Return a list of the nodes connected to the node n.
MultiGraph.neighbors_iter(n) Return an iterator over all neighbors of node n.
MultiGraph.__getitem__(n) Return a dict of neighbors of node n.
MultiGraph.adjacency_list() Return an adjacency list representation of the graph.
MultiGraph.adjacency_iter() Return an iterator of (node, adjacency dict) tuples for all nodes.
MultiGraph.nbunch_iter([nbunch]) Return an iterator of nodes contained in nbunch that are also in the graph.
Information about graph structure
MultiGraph.has_node(n) Return True if the graph contains the node n.
MultiGraph.__contains__(n) Return True if n is a node, False otherwise.
MultiGraph.has_edge(u, v[, key]) Return True if the graph has an edge between nodes u and v.
MultiGraph.order() Return the number of nodes in the graph.
MultiGraph.number_of_nodes() Return the number of nodes in the graph.
MultiGraph.__len__() Return the number of nodes.
MultiGraph.degree([nbunch, weight]) Return the degree of a node or nodes.
MultiGraph.degree_iter([nbunch, weight]) Return an iterator for (node, degree).
MultiGraph.size([weight]) Return the number of edges.
MultiGraph.number_of_edges([u, v]) Return the number of edges between two nodes.
MultiGraph.nodes_with_selfloops() Return a list of nodes with self loops.
MultiGraph.selfloop_edges([data, keys, default]) Return a list of selfloop edges.
MultiGraph.number_of_selfloops() Return the number of selfloop edges.
Making copies and subgraphs
MultiGraph.copy() Return a copy of the graph.
MultiGraph.to_undirected() Return an undirected copy of the graph.
MultiGraph.to_directed() Return a directed representation of the graph.
MultiGraph.subgraph(nbunch) Return the subgraph induced on nodes in nbunch.
MultiDiGraph - Directed graphs with self loops and parallel edges
Overview
MultiDiGraph(data=None, **attr)[source]

A directed graph class that can store multiedges.

Multiedges are multiple edges between two nodes. Each edge can hold optional data or attributes.

A MultiDiGraph holds directed edges. Self loops are allowed.

Nodes can be arbitrary (hashable) Python objects with optional key/value attributes.

Edges are represented as links between nodes with optional key/value attributes.

Parameters:
  • data (input graph) – Data to initialize graph. If data=None (default) an empty graph is created. The data can be an edge list, or any NetworkX graph object. If the corresponding optional Python packages are installed the data can also be a NumPy matrix or 2d ndarray, a SciPy sparse matrix, or a PyGraphviz graph.
  • attr (keyword arguments, optional (default= no attributes)) – Attributes to add to graph as key=value pairs.

Examples

Create an empty graph structure (a “null graph”) with no nodes and no edges.

>>> G = nx.MultiDiGraph()

G can be grown in several ways.

Nodes:

Add one node at a time:

>>> G.add_node(1)

Add the nodes from any container (a list, dict, set or even the lines from a file or the nodes from another graph).

>>> G.add_nodes_from([2,3])
>>> G.add_nodes_from(range(100,110))
>>> H=nx.Graph()
>>> H.add_path([0,1,2,3,4,5,6,7,8,9])
>>> G.add_nodes_from(H)

In addition to strings and integers any hashable Python object (except None) can represent a node, e.g. a customized node object, or even another Graph.

>>> G.add_node(H)

Edges:

G can also be grown by adding edges.

Add one edge,

>>> G.add_edge(1, 2)

a list of edges,

>>> G.add_edges_from([(1,2),(1,3)])

or a collection of edges,

>>> G.add_edges_from(H.edges())

If some edges connect nodes not yet in the graph, the nodes are added automatically. If an edge already exists, an additional edge is created and stored using a key to identify the edge. By default the key is the lowest unused integer.

>>> G.add_edges_from([(4,5,dict(route=282)), (4,5,dict(route=37))])
>>> G[4]
{5: {0: {}, 1: {'route': 282}, 2: {'route': 37}}}

Attributes:

Each graph, node, and edge can hold key/value attribute pairs in an associated attribute dictionary (the keys must be hashable). By default these are empty, but can be added or changed using add_edge, add_node or direct manipulation of the attribute dictionaries named graph, node and edge respectively.

>>> G = nx.MultiDiGraph(day="Friday")
>>> G.graph
{'day': 'Friday'}

Add node attributes using add_node(), add_nodes_from() or G.node

>>> G.add_node(1, time='5pm')
>>> G.add_nodes_from([3], time='2pm')
>>> G.node[1]
{'time': '5pm'}
>>> G.node[1]['room'] = 714
>>> del G.node[1]['room'] # remove attribute
>>> G.nodes(data=True)
[(1, {'time': '5pm'}), (3, {'time': '2pm'})]

Warning: adding a node to G.node does not add it to the graph.

Add edge attributes using add_edge(), add_edges_from(), subscript notation, or G.edge.

>>> G.add_edge(1, 2, weight=4.7 )
>>> G.add_edges_from([(3,4),(4,5)], color='red')
>>> G.add_edges_from([(1,2,{'color':'blue'}), (2,3,{'weight':8})])
>>> G[1][2][0]['weight'] = 4.7
>>> G.edge[1][2][0]['weight'] = 4

Shortcuts:

Many common graph features allow python syntax to speed reporting.

>>> 1 in G     # check if node in graph
True
>>> [n for n in G if n<3]   # iterate through nodes
[1, 2]
>>> len(G)  # number of nodes in graph
5
>>> G[1] # adjacency dict keyed by neighbor to edge attributes
...            # Note: you should not change this dict manually!
{2: {0: {'weight': 4}, 1: {'color': 'blue'}}}

The fastest way to traverse all edges of a graph is via adjacency_iter(), but the edges() method is often more convenient.

>>> for n,nbrsdict in G.adjacency_iter():
...     for nbr,keydict in nbrsdict.items():
...        for key,eattr in keydict.items():
...            if 'weight' in eattr:
...                (n,nbr,eattr['weight'])
(1, 2, 4)
(2, 3, 8)
>>> G.edges(data='weight')
[(1, 2, 4), (1, 2, None), (2, 3, 8), (3, 4, None), (4, 5, None)]

Reporting:

Simple graph information is obtained using methods. Iterator versions of many reporting methods exist for efficiency. Methods exist for reporting nodes(), edges(), neighbors() and degree() as well as the number of nodes and edges.

For details on these and other miscellaneous methods, see below.

Subclasses (Advanced):

The MultiDiGraph class uses a dict-of-dict-of-dict-of-dict structure. The outer dict (node_dict) holds adjacency lists keyed by node. The next dict (adjlist) represents the adjacency list and holds edge_key dicts keyed by neighbor. The edge_key dict holds each edge_attr dict keyed by edge key. The inner dict (edge_attr) represents the edge data and holds edge attribute values keyed by attribute names.

Each of these four dicts in the dict-of-dict-of-dict-of-dict structure can be replaced by a user defined dict-like object. In general, the dict-like features should be maintained but extra features can be added. To replace one of the dicts create a new graph class by changing the class(!) variable holding the factory for that dict-like structure. The variable names are node_dict_factory, adjlist_dict_factory, edge_key_dict_factory and edge_attr_dict_factory.

node_dict_factory : function, (default: dict)
Factory function to be used to create the outer-most dict in the data structure that holds adjacency lists keyed by node. It should require no arguments and return a dict-like object.
adjlist_dict_factory : function, (default: dict)
Factory function to be used to create the adjacency list dict which holds multiedge key dicts keyed by neighbor. It should require no arguments and return a dict-like object.
edge_key_dict_factory : function, (default: dict)
Factory function to be used to create the edge key dict which holds edge data keyed by edge key. It should require no arguments and return a dict-like object.
edge_attr_dict_factory : function, (default: dict)
Factory function to be used to create the edge attribute dict which holds attrbute values keyed by attribute name. It should require no arguments and return a dict-like object.

Examples

Create a multigraph object that tracks the order nodes are added.

>>> from collections import OrderedDict
>>> class OrderedGraph(nx.MultiDiGraph):
...    node_dict_factory = OrderedDict
>>> G = OrderedGraph()
>>> G.add_nodes_from( (2,1) )
>>> G.nodes()
[2, 1]
>>> G.add_edges_from( ((2,2), (2,1), (2,1), (1,1)) )
>>> G.edges()
[(2, 1), (2, 1), (2, 2), (1, 1)]

Create a multdigraph object that tracks the order nodes are added and for each node track the order that neighbors are added and for each neighbor tracks the order that multiedges are added.

>>> class OrderedGraph(nx.MultiDiGraph):
...    node_dict_factory = OrderedDict
...    adjlist_dict_factory = OrderedDict
...    edge_key_dict_factory = OrderedDict
>>> G = OrderedGraph()
>>> G.add_nodes_from( (2,1) )
>>> G.nodes()
[2, 1]
>>> G.add_edges_from( ((2,2), (2,1,2,{'weight':0.1}), (2,1,1,{'weight':0.2}), (1,1)) )
>>> G.edges(keys=True)
[(2, 2, 0), (2, 1, 2), (2, 1, 1), (1, 1, 0)]
Adding and Removing Nodes and Edges
MultiDiGraph.__init__([data])
MultiDiGraph.add_node(n[, attr_dict]) Add a single node n and update node attributes.
MultiDiGraph.add_nodes_from(nodes, **attr) Add multiple nodes.
MultiDiGraph.remove_node(n) Remove node n.
MultiDiGraph.remove_nodes_from(nbunch) Remove multiple nodes.
MultiDiGraph.add_edge(u, v[, key, attr_dict]) Add an edge between u and v.
MultiDiGraph.add_edges_from(ebunch[, attr_dict]) Add all the edges in ebunch.
MultiDiGraph.add_weighted_edges_from(ebunch) Add all the edges in ebunch as weighted edges with specified weights.
MultiDiGraph.remove_edge(u, v[, key]) Remove an edge between u and v.
MultiDiGraph.remove_edges_from(ebunch) Remove all edges specified in ebunch.
MultiDiGraph.add_star(nodes, **attr) Add a star.
MultiDiGraph.add_path(nodes, **attr) Add a path.
MultiDiGraph.add_cycle(nodes, **attr) Add a cycle.
MultiDiGraph.clear() Remove all nodes and edges from the graph.
Iterating over nodes and edges
MultiDiGraph.nodes([data]) Return a list of the nodes in the graph.
MultiDiGraph.nodes_iter([data]) Return an iterator over the nodes.
MultiDiGraph.__iter__() Iterate over the nodes.
MultiDiGraph.edges([nbunch, data, keys, default]) Return a list of edges.
MultiDiGraph.edges_iter([nbunch, data, ...]) Return an iterator over the edges.
MultiDiGraph.out_edges([nbunch, keys, data]) Return a list of the outgoing edges.
MultiDiGraph.out_edges_iter([nbunch, data, ...]) Return an iterator over the edges.
MultiDiGraph.in_edges([nbunch, keys, data]) Return a list of the incoming edges.
MultiDiGraph.in_edges_iter([nbunch, data, keys]) Return an iterator over the incoming edges.
MultiDiGraph.get_edge_data(u, v[, key, default]) Return the attribute dictionary associated with edge (u,v).
MultiDiGraph.neighbors(n) Return a list of successor nodes of n.
MultiDiGraph.neighbors_iter(n) Return an iterator over successor nodes of n.
MultiDiGraph.__getitem__(n) Return a dict of neighbors of node n.
MultiDiGraph.successors(n) Return a list of successor nodes of n.
MultiDiGraph.successors_iter(n) Return an iterator over successor nodes of n.
MultiDiGraph.predecessors(n) Return a list of predecessor nodes of n.
MultiDiGraph.predecessors_iter(n) Return an iterator over predecessor nodes of n.
MultiDiGraph.adjacency_list() Return an adjacency list representation of the graph.
MultiDiGraph.adjacency_iter() Return an iterator of (node, adjacency dict) tuples for all nodes.
MultiDiGraph.nbunch_iter([nbunch]) Return an iterator of nodes contained in nbunch that are also in the graph.
Information about graph structure
MultiDiGraph.has_node(n) Return True if the graph contains the node n.
MultiDiGraph.__contains__(n) Return True if n is a node, False otherwise.
MultiDiGraph.has_edge(u, v[, key]) Return True if the graph has an edge between nodes u and v.
MultiDiGraph.order() Return the number of nodes in the graph.
MultiDiGraph.number_of_nodes() Return the number of nodes in the graph.
MultiDiGraph.__len__() Return the number of nodes.
MultiDiGraph.degree([nbunch, weight]) Return the degree of a node or nodes.
MultiDiGraph.degree_iter([nbunch, weight]) Return an iterator for (node, degree).
MultiDiGraph.in_degree([nbunch, weight]) Return the in-degree of a node or nodes.
MultiDiGraph.in_degree_iter([nbunch, weight]) Return an iterator for (node, in-degree).
MultiDiGraph.out_degree([nbunch, weight]) Return the out-degree of a node or nodes.
MultiDiGraph.out_degree_iter([nbunch, weight]) Return an iterator for (node, out-degree).
MultiDiGraph.size([weight]) Return the number of edges.
MultiDiGraph.number_of_edges([u, v]) Return the number of edges between two nodes.
MultiDiGraph.nodes_with_selfloops() Return a list of nodes with self loops.
MultiDiGraph.selfloop_edges([data, keys, ...]) Return a list of selfloop edges.
MultiDiGraph.number_of_selfloops() Return the number of selfloop edges.
Making copies and subgraphs
MultiDiGraph.copy() Return a copy of the graph.
MultiDiGraph.to_undirected([reciprocal]) Return an undirected representation of the digraph.
MultiDiGraph.to_directed() Return a directed copy of the graph.
MultiDiGraph.subgraph(nbunch) Return the subgraph induced on nodes in nbunch.
MultiDiGraph.reverse([copy]) Return the reverse of the graph.

Algorithms

Approximation

Connectivity

Fast approximation for node connectivity

all_pairs_node_connectivity(G[, nbunch, cutoff]) Compute node connectivity between all pairs of nodes.
local_node_connectivity(G, source, target[, ...]) Compute node connectivity between source and target.
node_connectivity(G[, s, t]) Returns an approximation for node connectivity for a graph or digraph G.
K-components

Fast approximation for k-component structure

k_components(G[, min_density]) Returns the approximate k-component structure of a graph G.
Clique

Cliques.

max_clique(G) Find the Maximum Clique
clique_removal(G) Repeatedly remove cliques from the graph.
Clustering
average_clustering(G[, trials]) Estimates the average clustering coefficient of G.
Dominating Set

Functions for finding node and edge dominating sets.

A `dominating set`_[1] for an undirected graph *G with vertex set V and edge set E is a subset D of V such that every vertex not in D is adjacent to at least one member of D. An `edge dominating set`_[2] is a subset *F of E such that every edge not in F is incident to an endpoint of at least one edge in F.

[1]dominating set: https://en.wikipedia.org/wiki/Dominating_set
[2]edge dominating set: https://en.wikipedia.org/wiki/Edge_dominating_set
min_weighted_dominating_set(G[, weight]) Returns a dominating set that approximates the minimum weight node dominating set.
min_edge_dominating_set(G) Return minimum cardinality edge dominating set.
Independent Set

Independent Set

Independent set or stable set is a set of vertices in a graph, no two of which are adjacent. That is, it is a set I of vertices such that for every two vertices in I, there is no edge connecting the two. Equivalently, each edge in the graph has at most one endpoint in I. The size of an independent set is the number of vertices it contains.

A maximum independent set is a largest independent set for a given graph G and its size is denoted α(G). The problem of finding such a set is called the maximum independent set problem and is an NP-hard optimization problem. As such, it is unlikely that there exists an efficient algorithm for finding a maximum independent set of a graph.

http://en.wikipedia.org/wiki/Independent_set_(graph_theory)

Independent set algorithm is based on the following paper:

O(|V|/(log|V|)^2) apx of maximum clique/independent set.

Boppana, R., & Halldórsson, M. M. (1992). Approximating maximum independent sets by excluding subgraphs. BIT Numerical Mathematics, 32(2), 180–196. Springer. doi:10.1007/BF01994876

maximum_independent_set(G) Return an approximate maximum independent set.
Matching
Graph Matching

Given a graph G = (V,E), a matching M in G is a set of pairwise non-adjacent edges; that is, no two edges share a common vertex.

http://en.wikipedia.org/wiki/Matching_(graph_theory)

min_maximal_matching(G) Returns the minimum maximal matching of G.
Ramsey

Ramsey numbers.

ramsey_R2(G) Approximately computes the Ramsey number R(2;s,t) for graph.
Vertex Cover
Vertex Cover

Given an undirected graph G = (V, E) and a function w assigning nonnegative weights to its vertices, find a minimum weight subset of V such that each edge in E is incident to at least one vertex in the subset.

http://en.wikipedia.org/wiki/Vertex_cover

min_weighted_vertex_cover(G[, weight]) 2-OPT Local Ratio for Minimum Weighted Vertex Cover

Assortativity

Assortativity
degree_assortativity_coefficient(G[, x, y, ...]) Compute degree assortativity of graph.
attribute_assortativity_coefficient(G, attribute) Compute assortativity for node attributes.
numeric_assortativity_coefficient(G, attribute) Compute assortativity for numerical node attributes.
degree_pearson_correlation_coefficient(G[, ...]) Compute degree assortativity of graph.
Average neighbor degree
average_neighbor_degree(G[, source, target, ...]) Returns the average degree of the neighborhood of each node.
Average degree connectivity
average_degree_connectivity(G[, source, ...]) Compute the average degree connectivity of graph.
k_nearest_neighbors(G[, source, target, ...]) Compute the average degree connectivity of graph.
Mixing
attribute_mixing_matrix(G, attribute[, ...]) Return mixing matrix for attribute.
degree_mixing_matrix(G[, x, y, weight, ...]) Return mixing matrix for attribute.
degree_mixing_dict(G[, x, y, weight, nodes, ...]) Return dictionary representation of mixing matrix for degree.
attribute_mixing_dict(G, attribute[, nodes, ...]) Return dictionary representation of mixing matrix for attribute.

Bipartite

This module provides functions and operations for bipartite graphs. Bipartite graphs B = (U, V, E) have two node sets U,V and edges in E that only connect nodes from opposite sets. It is common in the literature to use an spatial analogy referring to the two node sets as top and bottom nodes.

The bipartite algorithms are not imported into the networkx namespace at the top level so the easiest way to use them is with:

>>> import networkx as nx
>>> from networkx.algorithms import bipartite

NetworkX does not have a custom bipartite graph class but the Graph() or DiGraph() classes can be used to represent bipartite graphs. However, you have to keep track of which set each node belongs to, and make sure that there is no edge between nodes of the same set. The convention used in NetworkX is to use a node attribute named “bipartite” with values 0 or 1 to identify the sets each node belongs to.

For example:

>>> B = nx.Graph()
>>> B.add_nodes_from([1,2,3,4], bipartite=0) # Add the node attribute "bipartite"
>>> B.add_nodes_from(['a','b','c'], bipartite=1)
>>> B.add_edges_from([(1,'a'), (1,'b'), (2,'b'), (2,'c'), (3,'c'), (4,'a')])

Many algorithms of the bipartite module of NetworkX require, as an argument, a container with all the nodes that belong to one set, in addition to the bipartite graph B. If B is connected, you can find the node sets using a two-coloring algorithm:

>>> nx.is_connected(B)
True
>>> bottom_nodes, top_nodes = bipartite.sets(B)

list(top_nodes) [1, 2, 3, 4] list(bottom_nodes) [‘a’, ‘c’, ‘b’]

However, if the input graph is not connected, there are more than one possible colorations. Thus, the following result is correct:

>>> B.remove_edge(2,'c')
>>> nx.is_connected(B)
False
>>> bottom_nodes, top_nodes = bipartite.sets(B)

list(top_nodes) [1, 2, 4, ‘c’] list(bottom_nodes) [‘a’, 3, ‘b’]

Using the “bipartite” node attribute, you can easily get the two node sets:

>>> top_nodes = set(n for n,d in B.nodes(data=True) if d['bipartite']==0)
>>> bottom_nodes = set(B) - top_nodes

list(top_nodes) [1, 2, 3, 4] list(bottom_nodes) [‘a’, ‘c’, ‘b’]

So you can easily use the bipartite algorithms that require, as an argument, a container with all nodes that belong to one node set:

>>> print(round(bipartite.density(B, bottom_nodes),2))
0.42
>>> G = bipartite.projected_graph(B, top_nodes)
>>> G.edges()
[(1, 2), (1, 4)]

All bipartite graph generators in NetworkX build bipartite graphs with the “bipartite” node attribute. Thus, you can use the same approach:

>>> RB = bipartite.random_graph(5, 7, 0.2)
>>> RB_top = set(n for n,d in RB.nodes(data=True) if d['bipartite']==0)
>>> RB_bottom = set(RB) - RB_top
>>> list(RB_top)
[0, 1, 2, 3, 4]
>>> list(RB_bottom)
[5, 6, 7, 8, 9, 10, 11]

For other bipartite graph generators see the bipartite section of Graph generators.

Basic functions
Bipartite Graph Algorithms
is_bipartite(G) Returns True if graph G is bipartite, False if not.
is_bipartite_node_set(G, nodes) Returns True if nodes and G/nodes are a bipartition of G.
sets(G) Returns bipartite node sets of graph G.
color(G) Returns a two-coloring of the graph.
density(B, nodes) Return density of bipartite graph B.
degrees(B, nodes[, weight]) Return the degrees of the two node sets in the bipartite graph B.
Matching

Provides functions for computing a maximum cardinality matching in a bipartite graph.

If you don’t care about the particular implementation of the maximum matching algorithm, simply use the maximum_matching(). If you do care, you can import one of the named maximum matching algorithms directly.

For example, to find a maximum matching in the complete bipartite graph with two vertices on the left and three vertices on the right:

>>> import networkx as nx
>>> G = nx.complete_bipartite_graph(2, 3)
>>> left, right = nx.bipartite.sets(G)
>>> list(left)
[0, 1]
>>> list(right)
[2, 3, 4]
>>> nx.bipartite.maximum_matching(G)
{0: 2, 1: 3, 2: 0, 3: 1}

The dictionary returned by maximum_matching() includes a mapping for vertices in both the left and right vertex sets.

eppstein_matching(G) Returns the maximum cardinality matching of the bipartite graph G.
hopcroft_karp_matching(G) Returns the maximum cardinality matching of the bipartite graph G.
to_vertex_cover(G, matching) Returns the minimum vertex cover corresponding to the given maximum matching of the bipartite graph G.
Matrix
Biadjacency matrices
biadjacency_matrix(G, row_order[, ...]) Return the biadjacency matrix of the bipartite graph G.
from_biadjacency_matrix(A[, create_using, ...]) Creates a new bipartite graph from a biadjacency matrix given as a SciPy sparse matrix.
Projections

One-mode (unipartite) projections of bipartite graphs.

projected_graph(B, nodes[, multigraph]) Returns the projection of B onto one of its node sets.
weighted_projected_graph(B, nodes[, ratio]) Returns a weighted projection of B onto one of its node sets.
collaboration_weighted_projected_graph(B, nodes) Newman’s weighted projection of B onto one of its node sets.
overlap_weighted_projected_graph(B, nodes[, ...]) Overlap weighted projection of B onto one of its node sets.
generic_weighted_projected_graph(B, nodes[, ...]) Weighted projection of B with a user-specified weight function.
Spectral

Spectral bipartivity measure.

spectral_bipartivity(G[, nodes, weight]) Returns the spectral bipartivity.
Clustering
clustering(G[, nodes, mode]) Compute a bipartite clustering coefficient for nodes.
average_clustering(G[, nodes, mode]) Compute the average bipartite clustering coefficient.
latapy_clustering(G[, nodes, mode]) Compute a bipartite clustering coefficient for nodes.
robins_alexander_clustering(G) Compute the bipartite clustering of G.
Redundancy

Node redundancy for bipartite graphs.

node_redundancy(G[, nodes]) Computes the node redundancy coefficients for the nodes in the bipartite graph G.
Centrality
closeness_centrality(G, nodes[, normalized]) Compute the closeness centrality for nodes in a bipartite network.
degree_centrality(G, nodes) Compute the degree centrality for nodes in a bipartite network.
betweenness_centrality(G, nodes) Compute betweenness centrality for nodes in a bipartite network.
Generators

Generators and functions for bipartite graphs.

complete_bipartite_graph(n1, n2[, create_using]) Return the complete bipartite graph K_{n_1,n_2}.
configuration_model(aseq, bseq[, ...]) Return a random bipartite graph from two given degree sequences.
havel_hakimi_graph(aseq, bseq[, create_using]) Return a bipartite graph from two given degree sequences using a Havel-Hakimi style construction.
reverse_havel_hakimi_graph(aseq, bseq[, ...]) Return a bipartite graph from two given degree sequences using a Havel-Hakimi style construction.
alternating_havel_hakimi_graph(aseq, bseq[, ...]) Return a bipartite graph from two given degree sequences using an alternating Havel-Hakimi style construction.
preferential_attachment_graph(aseq, p[, ...]) Create a bipartite graph with a preferential attachment model from a given single degree sequence.
random_graph(n, m, p[, seed, directed]) Return a bipartite random graph.
gnmk_random_graph(n, m, k[, seed, directed]) Return a random bipartite graph G_{n,m,k}.

Blockmodeling

Functions for creating network blockmodels from node partitions.

Created by Drew Conway <drew.conway@nyu.edu> Copyright (c) 2010. All rights reserved.

blockmodel(G, partitions[, multigraph]) Returns a reduced graph constructed using the generalized block modeling technique.

Boundary

Routines to find the boundary of a set of nodes.

Edge boundaries are edges that have only one end in the set of nodes.

Node boundaries are nodes outside the set of nodes that have an edge to a node in the set.

edge_boundary(G, nbunch1[, nbunch2]) Return the edge boundary.
node_boundary(G, nbunch1[, nbunch2]) Return the node boundary.

Centrality

Degree
degree_centrality(G) Compute the degree centrality for nodes.
in_degree_centrality(G) Compute the in-degree centrality for nodes.
out_degree_centrality(G) Compute the out-degree centrality for nodes.
Closeness
closeness_centrality(G[, u, distance, ...]) Compute closeness centrality for nodes.
Betweenness
betweenness_centrality(G[, k, normalized, ...]) Compute the shortest-path betweenness centrality for nodes.
edge_betweenness_centrality(G[, k, ...]) Compute betweenness centrality for edges.
Current Flow Closeness
current_flow_closeness_centrality(G[, ...]) Compute current-flow closeness centrality for nodes.
Current-Flow Betweenness
current_flow_betweenness_centrality(G[, ...]) Compute current-flow betweenness centrality for nodes.
edge_current_flow_betweenness_centrality(G) Compute current-flow betweenness centrality for edges.
approximate_current_flow_betweenness_centrality(G) Compute the approximate current-flow betweenness centrality for nodes.
Eigenvector
eigenvector_centrality(G[, max_iter, tol, ...]) Compute the eigenvector centrality for the graph G.
eigenvector_centrality_numpy(G[, weight]) Compute the eigenvector centrality for the graph G.
katz_centrality(G[, alpha, beta, max_iter, ...]) Compute the Katz centrality for the nodes of the graph G.
katz_centrality_numpy(G[, alpha, beta, ...]) Compute the Katz centrality for the graph G.
Communicability
communicability(G) Return communicability between all pairs of nodes in G.
communicability_exp(G) Return communicability between all pairs of nodes in G.
communicability_centrality(G) Return communicability centrality for each node in G.
communicability_centrality_exp(G) Return the communicability centrality for each node of G
communicability_betweenness_centrality(G[, ...]) Return communicability betweenness for all pairs of nodes in G.
estrada_index(G) Return the Estrada index of a the graph G.
Load
load_centrality(G[, v, cutoff, normalized, ...]) Compute load centrality for nodes.
edge_load(G[, nodes, cutoff]) Compute edge load.
Dispersion
dispersion(G[, u, v, normalized, alpha, b, c]) Calculate dispersion between u and v in G.

Chordal

Algorithms for chordal graphs.

A graph is chordal if every cycle of length at least 4 has a chord (an edge joining two nodes not adjacent in the cycle). http://en.wikipedia.org/wiki/Chordal_graph

is_chordal(G) Checks whether G is a chordal graph.
chordal_graph_cliques(G) Returns the set of maximal cliques of a chordal graph.
chordal_graph_treewidth(G) Returns the treewidth of the chordal graph G.
find_induced_nodes(G, s, t[, treewidth_bound]) Returns the set of induced nodes in the path from s to t.

Clique

Cliques

Find and manipulate cliques of graphs.

Note that finding the largest clique of a graph has been shown to be an NP-complete problem; the algorithms here could take a long time to run.

http://en.wikipedia.org/wiki/Clique_problem

enumerate_all_cliques(G) Returns all cliques in an undirected graph.
find_cliques(G) Search for all maximal cliques in a graph.
make_max_clique_graph(G[, create_using, name]) Create the maximal clique graph of a graph.
make_clique_bipartite(G[, fpos, ...]) Create a bipartite clique graph from a graph G.
graph_clique_number(G[, cliques]) Return the clique number (size of the largest clique) for G.
graph_number_of_cliques(G[, cliques]) Returns the number of maximal cliques in G.
node_clique_number(G[, nodes, cliques]) Returns the size of the largest maximal clique containing each given node.
number_of_cliques(G[, nodes, cliques]) Returns the number of maximal cliques for each node.
cliques_containing_node(G[, nodes, cliques]) Returns a list of cliques containing the given node.

Clustering

Algorithms to characterize the number of triangles in a graph.

triangles(G[, nodes]) Compute the number of triangles.
transitivity(G) Compute graph transitivity, the fraction of all possible triangles present in G.
clustering(G[, nodes, weight]) Compute the clustering coefficient for nodes.
average_clustering(G[, nodes, weight, ...]) Compute the average clustering coefficient for the graph G.
square_clustering(G[, nodes]) Compute the squares clustering coefficient for nodes.

Coloring

greedy_color(G[, strategy, interchange]) Color a graph using various strategies of greedy graph coloring.

Communities

K-Clique
k_clique_communities(G, k[, cliques]) Find k-clique communities in graph using the percolation method.

Components

Connectivity

Connected components.

is_connected(G) Return True if the graph is connected, false otherwise.
number_connected_components(G) Return the number of connected components.
connected_components(G) Generate connected components.
connected_component_subgraphs(G[, copy]) Generate connected components as subgraphs.
node_connected_component(G, n) Return the nodes in the component of graph containing node n.
Strong connectivity

Strongly connected components.

is_strongly_connected(G) Test directed graph for strong connectivity.
number_strongly_connected_components(G) Return number of strongly connected components in graph.
strongly_connected_components(G) Generate nodes in strongly connected components of graph.
strongly_connected_component_subgraphs(G[, copy]) Generate strongly connected components as subgraphs.
strongly_connected_components_recursive(G) Generate nodes in strongly connected components of graph.
kosaraju_strongly_connected_components(G[, ...]) Generate nodes in strongly connected components of graph.
condensation(G[, scc]) Returns the condensation of G.
Weak connectivity

Weakly connected components.

is_weakly_connected(G) Test directed graph for weak connectivity.
number_weakly_connected_components(G) Return the number of weakly connected components in G.
weakly_connected_components(G) Generate weakly connected components of G.
weakly_connected_component_subgraphs(G[, copy]) Generate weakly connected components as subgraphs.
Attracting components

Attracting components.

is_attracting_component(G) Returns True if G consists of a single attracting component.
number_attracting_components(G) Returns the number of attracting components in G.
attracting_components(G) Generates a list of attracting components in G.
attracting_component_subgraphs(G[, copy]) Generates a list of attracting component subgraphs from G.
Biconnected components

Biconnected components and articulation points.

is_biconnected(G) Return True if the graph is biconnected, False otherwise.
biconnected_components(G) Return a generator of sets of nodes, one set for each biconnected
biconnected_component_edges(G) Return a generator of lists of edges, one list for each biconnected component of the input graph.
biconnected_component_subgraphs(G[, copy]) Return a generator of graphs, one graph for each biconnected component of the input graph.
articulation_points(G) Return a generator of articulation points, or cut vertices, of a graph.
Semiconnectedness

Semiconnectedness.

is_semiconnected(G) Return True if the graph is semiconnected, False otherwise.

Connectivity

Connectivity and cut algorithms

K-node-components

Moody and White algorithm for k-components

k_components(G[, flow_func]) Returns the k-component structure of a graph G.
K-node-cutsets

Kanevsky all minimum node k cutsets algorithm.

all_node_cuts(G[, k, flow_func]) Returns all minimum k cutsets of an undirected graph G.
Flow-based Connectivity

Flow based connectivity algorithms

average_node_connectivity(G[, flow_func]) Returns the average connectivity of a graph G.
all_pairs_node_connectivity(G[, nbunch, ...]) Compute node connectivity between all pairs of nodes of G.
edge_connectivity(G[, s, t, flow_func]) Returns the edge connectivity of the graph or digraph G.
local_edge_connectivity(G, u, v[, ...]) Returns local edge connectivity for nodes s and t in G.
local_node_connectivity(G, s, t[, ...]) Computes local node connectivity for nodes s and t.
node_connectivity(G[, s, t, flow_func]) Returns node connectivity for a graph or digraph G.
Flow-based Minimum Cuts

Flow based cut algorithms

minimum_edge_cut(G[, s, t, flow_func]) Returns a set of edges of minimum cardinality that disconnects G.
minimum_node_cut(G[, s, t, flow_func]) Returns a set of nodes of minimum cardinality that disconnects G.
minimum_st_edge_cut(G, s, t[, flow_func, ...]) Returns the edges of the cut-set of a minimum (s, t)-cut.
minimum_st_node_cut(G, s, t[, flow_func, ...]) Returns a set of nodes of minimum cardinality that disconnect source from target in G.
Stoer-Wagner minimum cut

Stoer-Wagner minimum cut algorithm.

stoer_wagner(G[, weight, heap]) Returns the weighted minimum edge cut using the Stoer-Wagner algorithm.
Utils for flow-based connectivity

Utilities for connectivity package

build_auxiliary_edge_connectivity(G) Auxiliary digraph for computing flow based edge connectivity
build_auxiliary_node_connectivity(G) Creates a directed graph D from an undirected graph G to compute flow based node connectivity.

Cores

Find the k-cores of a graph.

The k-core is found by recursively pruning nodes with degrees less than k.

See the following reference for details:

An O(m) Algorithm for Cores Decomposition of Networks Vladimir Batagelj and Matjaz Zaversnik, 2003. http://arxiv.org/abs/cs.DS/0310049

core_number(G) Return the core number for each vertex.
k_core(G[, k, core_number]) Return the k-core of G.
k_shell(G[, k, core_number]) Return the k-shell of G.
k_crust(G[, k, core_number]) Return the k-crust of G.
k_corona(G, k[, core_number]) Return the k-corona of G.

Cycles

Cycle finding algorithms
cycle_basis(G[, root]) Returns a list of cycles which form a basis for cycles of G.
simple_cycles(G) Find simple cycles (elementary circuits) of a directed graph.
find_cycle(G[, source, orientation]) Returns the edges of a cycle found via a directed, depth-first traversal.

Directed Acyclic Graphs

ancestors(G, source) Return all nodes having a path to source in G.
descendants(G, source) Return all nodes reachable from source in G.
topological_sort(G[, nbunch, reverse]) Return a list of nodes in topological sort order.
topological_sort_recursive(G[, nbunch, reverse]) Return a list of nodes in topological sort order.
is_directed_acyclic_graph(G) Return True if the graph G is a directed acyclic graph (DAG) or False if not.
is_aperiodic(G) Return True if G is aperiodic.
transitive_closure(G) Returns transitive closure of a directed graph
antichains(G) Generates antichains from a DAG.
dag_longest_path(G) Returns the longest path in a DAG
dag_longest_path_length(G) Returns the longest path length in a DAG

Distance Measures

Graph diameter, radius, eccentricity and other properties.

center(G[, e]) Return the center of the graph G.
diameter(G[, e]) Return the diameter of the graph G.
eccentricity(G[, v, sp]) Return the eccentricity of nodes in G.
periphery(G[, e]) Return the periphery of the graph G.
radius(G[, e]) Return the radius of the graph G.

Distance-Regular Graphs

Distance-regular graphs
is_distance_regular(G) Returns True if the graph is distance regular, False otherwise.
intersection_array(G) Returns the intersection array of a distance-regular graph.
global_parameters(b, c) Return global parameters for a given intersection array.

Dominance

Dominance algorithms.

immediate_dominators(G, start) Returns the immediate dominators of all nodes of a directed graph.
dominance_frontiers(G, start) Returns the dominance frontiers of all nodes of a directed graph.

Dominating Sets

dominating_set(G[, start_with]) Finds a dominating set for the graph G.
is_dominating_set(G, nbunch) Checks if nodes in nbunch are a dominating set for G.

Eulerian

Eulerian circuits and graphs.

is_eulerian(G) Return True if G is an Eulerian graph, False otherwise.
eulerian_circuit(G[, source]) Return the edges of an Eulerian circuit in G.

Flows

Maximum Flow
maximum_flow(G, s, t[, capacity, flow_func]) Find a maximum single-commodity flow.
maximum_flow_value(G, s, t[, capacity, ...]) Find the value of maximum single-commodity flow.
minimum_cut(G, s, t[, capacity, flow_func]) Compute the value and the node partition of a minimum (s, t)-cut.
minimum_cut_value(G, s, t[, capacity, flow_func]) Compute the value of a minimum (s, t)-cut.
Edmonds-Karp
edmonds_karp(G, s, t[, capacity, residual, ...]) Find a maximum single-commodity flow using the Edmonds-Karp algorithm.
Shortest Augmenting Path
shortest_augmenting_path(G, s, t[, ...]) Find a maximum single-commodity flow using the shortest augmenting path algorithm.
Preflow-Push
preflow_push(G, s, t[, capacity, residual, ...]) Find a maximum single-commodity flow using the highest-label preflow-push algorithm.
Utils
build_residual_network(G, capacity) Build a residual network and initialize a zero flow.
Network Simplex
network_simplex(G[, demand, capacity, weight]) Find a minimum cost flow satisfying all demands in digraph G.
min_cost_flow_cost(G[, demand, capacity, weight]) Find the cost of a minimum cost flow satisfying all demands in digraph G.
min_cost_flow(G[, demand, capacity, weight]) Return a minimum cost flow satisfying all demands in digraph G.
cost_of_flow(G, flowDict[, weight]) Compute the cost of the flow given by flowDict on graph G.
max_flow_min_cost(G, s, t[, capacity, weight]) Return a maximum (s, t)-flow of minimum cost.
Capacity Scaling Minimum Cost Flow
capacity_scaling(G[, demand, capacity, ...]) Find a minimum cost flow satisfying all demands in digraph G.

Graphical degree sequence

Test sequences for graphiness.

is_graphical(sequence[, method]) Returns True if sequence is a valid degree sequence.
is_digraphical(in_sequence, out_sequence) Returns True if some directed graph can realize the in- and out-degree sequences.
is_multigraphical(sequence) Returns True if some multigraph can realize the sequence.
is_pseudographical(sequence) Returns True if some pseudograph can realize the sequence.
is_valid_degree_sequence_havel_hakimi(...) Returns True if deg_sequence can be realized by a simple graph.
is_valid_degree_sequence_erdos_gallai(...) Returns True if deg_sequence can be realized by a simple graph.

Hierarchy

Flow Hierarchy.

flow_hierarchy(G[, weight]) Returns the flow hierarchy of a directed network.

Hybrid

Provides functions for finding and testing for locally (k, l)-connected graphs.

kl_connected_subgraph(G, k, l[, low_memory, ...]) Returns the maximum locally (k, l)-connected subgraph of G.
is_kl_connected(G, k, l[, low_memory]) Returns True if and only if G is locally (k, l)-connected.

Isolates

Functions for identifying isolate (degree zero) nodes.

is_isolate(G, n) Determine of node n is an isolate (degree zero).
isolates(G) Return list of isolates in the graph.

Isomorphism

is_isomorphic(G1, G2[, node_match, edge_match]) Returns True if the graphs G1 and G2 are isomorphic and False otherwise.
could_be_isomorphic(G1, G2) Returns False if graphs are definitely not isomorphic.
fast_could_be_isomorphic(G1, G2) Returns False if graphs are definitely not isomorphic.
faster_could_be_isomorphic(G1, G2) Returns False if graphs are definitely not isomorphic.
Advanced Interface to VF2 Algorithm
VF2 Algorithm
VF2 Algorithm

An implementation of VF2 algorithm for graph ismorphism testing.

The simplest interface to use this module is to call networkx.is_isomorphic().

Introduction

The GraphMatcher and DiGraphMatcher are responsible for matching graphs or directed graphs in a predetermined manner. This usually means a check for an isomorphism, though other checks are also possible. For example, a subgraph of one graph can be checked for isomorphism to a second graph.

Matching is done via syntactic feasibility. It is also possible to check for semantic feasibility. Feasibility, then, is defined as the logical AND of the two functions.

To include a semantic check, the (Di)GraphMatcher class should be subclassed, and the semantic_feasibility() function should be redefined. By default, the semantic feasibility function always returns True. The effect of this is that semantics are not considered in the matching of G1 and G2.

Examples

Suppose G1 and G2 are isomorphic graphs. Verification is as follows:

>>> from networkx.algorithms import isomorphism
>>> G1 = nx.path_graph(4)
>>> G2 = nx.path_graph(4)
>>> GM = isomorphism.GraphMatcher(G1,G2)
>>> GM.is_isomorphic()
True

GM.mapping stores the isomorphism mapping from G1 to G2.

>>> GM.mapping
{0: 0, 1: 1, 2: 2, 3: 3}

Suppose G1 and G2 are isomorphic directed graphs graphs. Verification is as follows:

>>> G1 = nx.path_graph(4, create_using=nx.DiGraph())
>>> G2 = nx.path_graph(4, create_using=nx.DiGraph())
>>> DiGM = isomorphism.DiGraphMatcher(G1,G2)
>>> DiGM.is_isomorphic()
True

DiGM.mapping stores the isomorphism mapping from G1 to G2.

>>> DiGM.mapping
{0: 0, 1: 1, 2: 2, 3: 3}
Subgraph Isomorphism

Graph theory literature can be ambiguious about the meaning of the above statement, and we seek to clarify it now.

In the VF2 literature, a mapping M is said to be a graph-subgraph isomorphism iff M is an isomorphism between G2 and a subgraph of G1. Thus, to say that G1 and G2 are graph-subgraph isomorphic is to say that a subgraph of G1 is isomorphic to G2.

Other literature uses the phrase ‘subgraph isomorphic’ as in ‘G1 does not have a subgraph isomorphic to G2’. Another use is as an in adverb for isomorphic. Thus, to say that G1 and G2 are subgraph isomorphic is to say that a subgraph of G1 is isomorphic to G2.

Finally, the term ‘subgraph’ can have multiple meanings. In this context, ‘subgraph’ always means a ‘node-induced subgraph’. Edge-induced subgraph isomorphisms are not directly supported, but one should be able to perform the check by making use of nx.line_graph(). For subgraphs which are not induced, the term ‘monomorphism’ is preferred over ‘isomorphism’. Currently, it is not possible to check for monomorphisms.

Let G=(N,E) be a graph with a set of nodes N and set of edges E.

If G’=(N’,E’) is a subgraph, then:
N’ is a subset of N E’ is a subset of E
If G’=(N’,E’) is a node-induced subgraph, then:
N’ is a subset of N E’ is the subset of edges in E relating nodes in N’
If G’=(N’,E’) is an edge-induced subgrpah, then:
N’ is the subset of nodes in N related by edges in E’ E’ is a subset of E

References

[1] Luigi P. Cordella, Pasquale Foggia, Carlo Sansone, Mario Vento,
“A (Sub)Graph Isomorphism Algorithm for Matching Large Graphs”, IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. 26, no. 10, pp. 1367-1372, Oct., 2004. http://ieeexplore.ieee.org/iel5/34/29305/01323804.pdf
[2] L. P. Cordella, P. Foggia, C. Sansone, M. Vento, “An Improved
Algorithm for Matching Large Graphs”, 3rd IAPR-TC15 Workshop on Graph-based Representations in Pattern Recognition, Cuen, pp. 149-159, 2001. http://amalfi.dis.unina.it/graph/db/papers/vf-algorithm.pdf

See also

syntactic_feasibliity, semantic_feasibility

Notes

Modified to handle undirected graphs. Modified to handle multiple edges.

In general, this problem is NP-Complete.

Graph Matcher
GraphMatcher.__init__(G1, G2[, node_match, ...]) Initialize graph matcher.
GraphMatcher.initialize() Reinitializes the state of the algorithm.
GraphMatcher.is_isomorphic() Returns True if G1 and G2 are isomorphic graphs.
GraphMatcher.subgraph_is_isomorphic() Returns True if a subgraph of G1 is isomorphic to G2.
GraphMatcher.isomorphisms_iter() Generator over isomorphisms between G1 and G2.
GraphMatcher.subgraph_isomorphisms_iter() Generator over isomorphisms between a subgraph of G1 and G2.
GraphMatcher.candidate_pairs_iter() Iterator over candidate pairs of nodes in G1 and G2.
GraphMatcher.match() Extends the isomorphism mapping.
GraphMatcher.semantic_feasibility(G1_node, ...) Returns True if mapping G1_node to G2_node is semantically feasible.
GraphMatcher.syntactic_feasibility(G1_node, ...) Returns True if adding (G1_node, G2_node) is syntactically feasible.
DiGraph Matcher
DiGraphMatcher.__init__(G1, G2[, ...]) Initialize graph matcher.
DiGraphMatcher.initialize() Reinitializes the state of the algorithm.
DiGraphMatcher.is_isomorphic() Returns True if G1 and G2 are isomorphic graphs.
DiGraphMatcher.subgraph_is_isomorphic() Returns True if a subgraph of G1 is isomorphic to G2.
DiGraphMatcher.isomorphisms_iter() Generator over isomorphisms between G1 and G2.
DiGraphMatcher.subgraph_isomorphisms_iter() Generator over isomorphisms between a subgraph of G1 and G2.
DiGraphMatcher.candidate_pairs_iter() Iterator over candidate pairs of nodes in G1 and G2.
DiGraphMatcher.match() Extends the isomorphism mapping.
DiGraphMatcher.semantic_feasibility(G1_node, ...) Returns True if mapping G1_node to G2_node is semantically feasible.
DiGraphMatcher.syntactic_feasibility(...) Returns True if adding (G1_node, G2_node) is syntactically feasible.
Match helpers
categorical_node_match(attr, default) Returns a comparison function for a categorical node attribute.
categorical_edge_match(attr, default) Returns a comparison function for a categorical edge attribute.
categorical_multiedge_match(attr, default) Returns a comparison function for a categorical edge attribute.
numerical_node_match(attr, default[, rtol, atol]) Returns a comparison function for a numerical node attribute.
numerical_edge_match(attr, default[, rtol, atol]) Returns a comparison function for a numerical edge attribute.
numerical_multiedge_match(attr, default[, ...]) Returns a comparison function for a numerical edge attribute.
generic_node_match(attr, default, op) Returns a comparison function for a generic attribute.
generic_edge_match(attr, default, op) Returns a comparison function for a generic attribute.
generic_multiedge_match(attr, default, op) Returns a comparison function for a generic attribute.

Matching

Matching
maximal_matching(G) Find a maximal cardinality matching in the graph.
max_weight_matching(G[, maxcardinality]) Compute a maximum-weighted matching of G.

Minors

Provides functions for computing minors of a graph.

contracted_edge(G, edge[, self_loops]) Returns the graph that results from contracting the specified edge.
contracted_nodes(G, u, v[, self_loops]) Returns the graph that results from contracting u and v.
identified_nodes(G, u, v[, self_loops]) Returns the graph that results from contracting u and v.
quotient_graph(G, node_relation[, ...]) Returns the quotient graph of G under the specified equivalence relation on nodes.

Maximal independent set

Algorithm to find a maximal (not maximum) independent set.

maximal_independent_set(G[, nodes]) Return a random maximal independent set guaranteed to contain a given set of nodes.

Minimum Spanning Tree

Computes minimum spanning tree of a weighted graph.

minimum_spanning_tree(G[, weight]) Return a minimum spanning tree or forest of an undirected weighted graph.
minimum_spanning_edges(G[, weight, data]) Generate edges in a minimum spanning forest of an undirected weighted graph.

Operators

Unary operations on graphs

complement(G[, name]) Return the graph complement of G.
reverse(G[, copy]) Return the reverse directed graph of G.

Operations on graphs including union, intersection, difference.

compose(G, H[, name]) Return a new graph of G composed with H.
union(G, H[, rename, name]) Return the union of graphs G and H.
disjoint_union(G, H) Return the disjoint union of graphs G and H.
intersection(G, H) Return a new graph that contains only the edges that exist in both G and H.
difference(G, H) Return a new graph that contains the edges that exist in G but not in H.
symmetric_difference(G, H) Return new graph with edges that exist in either G or H but not both.

Operations on many graphs.

compose_all(graphs[, name]) Return the composition of all graphs.
union_all(graphs[, rename, name]) Return the union of all graphs.
disjoint_union_all(graphs) Return the disjoint union of all graphs.
intersection_all(graphs) Return a new graph that contains only the edges that exist in all graphs.

Graph products.

cartesian_product(G, H) Return the Cartesian product of G and H.
lexicographic_product(G, H) Return the lexicographic product of G and H.
strong_product(G, H) Return the strong product of G and H.
tensor_product(G, H) Return the tensor product of G and H.
power(G, k) Returns the specified power of a graph.

Rich Club

rich_club_coefficient(G[, normalized, Q]) Return the rich-club coefficient of the graph G.

Shortest Paths

Compute the shortest paths and path lengths between nodes in the graph.

These algorithms work with undirected and directed graphs.

shortest_path(G[, source, target, weight]) Compute shortest paths in the graph.
all_shortest_paths(G, source, target[, weight]) Compute all shortest paths in the graph.
shortest_path_length(G[, source, target, weight]) Compute shortest path lengths in the graph.
average_shortest_path_length(G[, weight]) Return the average shortest path length.
has_path(G, source, target) Return True if G has a path from source to target, False otherwise.
Advanced Interface

Shortest path algorithms for unweighted graphs.

single_source_shortest_path(G, source[, cutoff]) Compute shortest path between source and all other nodes reachable from source.
single_source_shortest_path_length(G, source) Compute the shortest path lengths from source to all reachable nodes.
all_pairs_shortest_path(G[, cutoff]) Compute shortest paths between all nodes.
all_pairs_shortest_path_length(G[, cutoff]) Computes the shortest path lengths between all nodes in G.
predecessor(G, source[, target, cutoff, ...]) Returns dictionary of predecessors for the path from source to all nodes in G.

Shortest path algorithms for weighed graphs.

dijkstra_path(G, source, target[, weight]) Returns the shortest path from source to target in a weighted graph G.
dijkstra_path_length(G, source, target[, weight]) Returns the shortest path length from source to target in a weighted graph.
single_source_dijkstra_path(G, source[, ...]) Compute shortest path between source and all other reachable nodes for a weighted graph.
single_source_dijkstra_path_length(G, source) Compute the shortest path length between source and all other reachable nodes for a weighted graph.
all_pairs_dijkstra_path(G[, cutoff, weight]) Compute shortest paths between all nodes in a weighted graph.
all_pairs_dijkstra_path_length(G[, cutoff, ...]) Compute shortest path lengths between all nodes in a weighted graph.
single_source_dijkstra(G, source[, target, ...]) Compute shortest paths and lengths in a weighted graph G.
bidirectional_dijkstra(G, source, target[, ...]) Dijkstra’s algorithm for shortest paths using bidirectional search.
dijkstra_predecessor_and_distance(G, source) Compute shortest path length and predecessors on shortest paths in weighted graphs.
bellman_ford(G, source[, weight]) Compute shortest path lengths and predecessors on shortest paths in weighted graphs.
negative_edge_cycle(G[, weight]) Return True if there exists a negative edge cycle anywhere in G.
johnson(G[, weight]) Compute shortest paths between all nodes in a weighted graph using Johnson’s algorithm.
Dense Graphs

Floyd-Warshall algorithm for shortest paths.

floyd_warshall(G[, weight]) Find all-pairs shortest path lengths using Floyd’s algorithm.
floyd_warshall_predecessor_and_distance(G[, ...]) Find all-pairs shortest path lengths using Floyd’s algorithm.
floyd_warshall_numpy(G[, nodelist, weight]) Find all-pairs shortest path lengths using Floyd’s algorithm.
A* Algorithm

Shortest paths and path lengths using A* (“A star”) algorithm.

astar_path(G, source, target[, heuristic, ...]) Return a list of nodes in a shortest path between source and target using the A* (“A-star”) algorithm.
astar_path_length(G, source, target[, ...]) Return the length of the shortest path between source and target using the A* (“A-star”) algorithm.

Simple Paths

all_simple_paths(G, source, target[, cutoff]) Generate all simple paths in the graph G from source to target.
shortest_simple_paths(G, source, target[, ...]) Generate all simple paths in the graph G from source to target, starting from shortest ones.

Swap

Swap edges in a graph.

double_edge_swap(G[, nswap, max_tries]) Swap two edges in the graph while keeping the node degrees fixed.
connected_double_edge_swap(G[, nswap, ...]) Attempts the specified number of double-edge swaps in the graph G.

Traversal

Depth First Search on Edges
Depth First Search on Edges

Algorithms for a depth-first traversal of edges in a graph.

edge_dfs(G[, source, orientation]) A directed, depth-first traversal of edges in G, beginning at source.

Tree

Recognition
Recognition Tests

A forest is an acyclic, undirected graph, and a tree is a connected forest. Depending on the subfield, there are various conventions for generalizing these definitions to directed graphs.

In one convention, directed variants of forest and tree are defined in an identical manner, except that the direction of the edges is ignored. In effect, each directed edge is treated as a single undirected edge. Then, additional restrictions are imposed to define branchings and arborescences.

In another convention, directed variants of forest and tree correspond to the previous convention’s branchings and arborescences, respectively. Then two new terms, polyforest and polytree, are defined to correspond to the other convention’s forest and tree.

Summarizing:

+-----------------------------+
| Convention A | Convention B |
+=============================+
| forest       | polyforest   |
| tree         | polytree     |
| branching    | forest       |
| arborescence | tree         |
+-----------------------------+

Each convention has its reasons. The first convention emphasizes definitional similarity in that directed forests and trees are only concerned with acyclicity and do not have an in-degree constraint, just as their undirected counterparts do not. The second convention emphasizes functional similarity in the sense that the directed analog of a spanning tree is a spanning arborescence. That is, take any spanning tree and choose one node as the root. Then every edge is assigned a direction such there is a directed path from the root to every other node. The result is a spanning arborescence.

NetworkX follows convention “A”. Explicitly, these are:

undirected forest
An undirected graph with no undirected cycles.
undirected tree
A connected, undirected forest.
directed forest
A directed graph with no undirected cycles. Equivalently, the underlying graph structure (which ignores edge orientations) is an undirected forest. In convention B, this is known as a polyforest.
directed tree
A weakly connected, directed forest. Equivalently, the underlying graph structure (which ignores edge orientations) is an undirected tree. In convention B, this is known as a polytree.
branching
A directed forest with each node having, at most, one parent. So the maximum in-degree is equal to 1. In convention B, this is known as a forest.
arborescence
A directed tree with each node having, at most, one parent. So the maximum in-degree is equal to 1. In convention B, this is known as a tree.

For trees and arborescences, the adjective “spanning” may be added to designate that the graph, when considered as a forest/branching, consists of a single tree/arborescence that includes all nodes in the graph. It is true, by definition, that every tree/arborescence is spanning with respect to the nodes that define the tree/arborescence and so, it might seem redundant to introduce the notion of “spanning”. However, the nodes may represent a subset of nodes from a larger graph, and it is in this context that the term “spanning” becomes a useful notion.

is_tree(G) Returns True if G is a tree.
is_forest(G) Returns True if G is a forest.
is_arborescence(G) Returns True if G is an arborescence.
is_branching(G) Returns True if G is a branching.
Branchings and Spanning Arborescences

Algorithms for finding optimum branchings and spanning arborescences.

This implementation is based on:

J. Edmonds, Optimum branchings, J. Res. Natl. Bur. Standards 71B (1967), 233–240. URL: http://archive.org/details/jresv71Bn4p233
branching_weight(G[, attr, default]) Returns the total weight of a branching.
greedy_branching(G[, attr, default, kind]) Returns a branching obtained through a greedy algorithm.
maximum_branching(G[, attr, default]) Returns a maximum branching from G.
minimum_branching(G[, attr, default]) Returns a minimum branching from G.
maximum_spanning_arborescence(G[, attr, default]) Returns a maximum spanning arborescence from G.
minimum_spanning_arborescence(G[, attr, default]) Returns a minimum spanning arborescence from G.
Edmonds(G[, seed]) Edmonds algorithm for finding optimal branchings and spanning arborescences.

Triads

Functions for analyzing triads of a graph.

triadic_census(G) Determines the triadic census of a directed graph.

Vitality

Vitality measures.

closeness_vitality(G[, weight]) Compute closeness vitality for nodes.

Functions

Functional interface to graph methods and assorted utilities.

Graph

degree(G[, nbunch, weight]) Return degree of single node or of nbunch of nodes.
degree_histogram(G) Return a list of the frequency of each degree value.
density(G) Return the density of a graph.
info(G[, n]) Print short summary of information for the graph G or the node n.
create_empty_copy(G[, with_nodes]) Return a copy of the graph G with all of the edges removed.
is_directed(G) Return True if graph is directed.

Nodes

nodes(G) Return a copy of the graph nodes in a list.
number_of_nodes(G) Return the number of nodes in the graph.
nodes_iter(G) Return an iterator over the graph nodes.
all_neighbors(graph, node) Returns all of the neighbors of a node in the graph.
non_neighbors(graph, node) Returns the non-neighbors of the node in the graph.
common_neighbors(G, u, v) Return the common neighbors of two nodes in a graph.

Edges

edges(G[, nbunch]) Return list of edges incident to nodes in nbunch.
number_of_edges(G) Return the number of edges in the graph.
edges_iter(G[, nbunch]) Return iterator over edges incident to nodes in nbunch.
non_edges(graph) Returns the non-existent edges in the graph.

Attributes

set_node_attributes(G, name, values) Set node attributes from dictionary of nodes and values
get_node_attributes(G, name) Get node attributes from graph
set_edge_attributes(G, name, values) Set edge attributes from dictionary of edge tuples and values.
get_edge_attributes(G, name) Get edge attributes from graph

Freezing graph structure

freeze(G) Modify graph to prevent further change by adding or removing nodes or edges.
is_frozen(G) Return True if graph is frozen.

Graph generators

Atlas

Generators for the small graph atlas.

See “An Atlas of Graphs” by Ronald C. Read and Robin J. Wilson, Oxford University Press, 1998.

Because of its size, this module is not imported by default.

graph_atlas_g() Return the list [G0,G1,...,G1252] of graphs as named in the Graph Atlas.

Classic

Generators for some classic graphs.

The typical graph generator is called as follows:

>>> G=nx.complete_graph(100)

returning the complete graph on n nodes labeled 0,..,99 as a simple graph. Except for empty_graph, all the generators in this module return a Graph class (i.e. a simple, undirected graph).

balanced_tree(r, h[, create_using]) Return the perfectly balanced r-tree of height h.
barbell_graph(m1, m2[, create_using]) Return the Barbell Graph: two complete graphs connected by a path.
complete_graph(n[, create_using]) Return the complete graph K_n with n nodes.
complete_multipartite_graph(*block_sizes) Returns the complete multipartite graph with the specified block sizes.
circular_ladder_graph(n[, create_using]) Return the circular ladder graph CL_n of length n.
cycle_graph(n[, create_using]) Return the cycle graph C_n over n nodes.
dorogovtsev_goltsev_mendes_graph(n[, ...]) Return the hierarchically constructed Dorogovtsev-Goltsev-Mendes graph.
empty_graph([n, create_using]) Return the empty graph with n nodes and zero edges.
grid_2d_graph(m, n[, periodic, create_using]) Return the 2d grid graph of mxn nodes, each connected to its nearest neighbors.
grid_graph(dim[, periodic]) Return the n-dimensional grid graph.
hypercube_graph(n) Return the n-dimensional hypercube.
ladder_graph(n[, create_using]) Return the Ladder graph of length n.
lollipop_graph(m, n[, create_using]) Return the Lollipop Graph; K_m connected to P_n.
null_graph([create_using]) Return the Null graph with no nodes or edges.
path_graph(n[, create_using]) Return the Path graph P_n of n nodes linearly connected by n-1 edges.
star_graph(n[, create_using]) Return the Star graph with n+1 nodes: one center node, connected to n outer nodes.
trivial_graph([create_using]) Return the Trivial graph with one node (with integer label 0) and no edges.
wheel_graph(n[, create_using]) Return the wheel graph: a single hub node connected to each node of the (n-1)-node cycle graph.

Expanders

Provides explicit constructions of expander graphs.

margulis_gabber_galil_graph(n[, create_using]) Return the Margulis-Gabber-Galil undirected MultiGraph on n^2 nodes.
chordal_cycle_graph(p[, create_using]) Return the chordal cycle graph on p nodes.

Small

Various small and named graphs, together with some compact generators.

make_small_graph(graph_description[, ...]) Return the small graph described by graph_description.
LCF_graph(n, shift_list, repeats[, create_using]) Return the cubic graph specified in LCF notation.
bull_graph([create_using]) Return the Bull graph.
chvatal_graph([create_using]) Return the Chvátal graph.
cubical_graph([create_using]) Return the 3-regular Platonic Cubical graph.
desargues_graph([create_using]) Return the Desargues graph.
diamond_graph([create_using]) Return the Diamond graph.
dodecahedral_graph([create_using]) Return the Platonic Dodecahedral graph.
frucht_graph([create_using]) Return the Frucht Graph.
heawood_graph([create_using]) Return the Heawood graph, a (3,6) cage.
house_graph([create_using]) Return the House graph (square with triangle on top).
house_x_graph([create_using]) Return the House graph with a cross inside the house square.
icosahedral_graph([create_using]) Return the Platonic Icosahedral graph.
krackhardt_kite_graph([create_using]) Return the Krackhardt Kite Social Network.
moebius_kantor_graph([create_using]) Return the Moebius-Kantor graph.
octahedral_graph([create_using]) Return the Platonic Octahedral graph.
pappus_graph() Return the Pappus graph.
petersen_graph([create_using]) Return the Petersen graph.
sedgewick_maze_graph([create_using]) Return a small maze with a cycle.
tetrahedral_graph([create_using]) Return the 3-regular Platonic Tetrahedral graph.
truncated_cube_graph([create_using]) Return the skeleton of the truncated cube.
truncated_tetrahedron_graph([create_using]) Return the skeleton of the truncated Platonic tetrahedron.
tutte_graph([create_using]) Return the Tutte graph.

Random Graphs

Generators for random graphs.

fast_gnp_random_graph(n, p[, seed, directed]) Returns a G_{n,p} random graph, also known as an Erdős-Rényi graph or a binomial graph.
gnp_random_graph(n, p[, seed, directed]) Returns a G_{n,p} random graph, also known as an Erdős-Rényi graph or a binomial graph.
dense_gnm_random_graph(n, m[, seed]) Returns a G_{n,m} random graph.
gnm_random_graph(n, m[, seed, directed]) Returns a G_{n,m} random graph.
erdos_renyi_graph(n, p[, seed, directed]) Returns a G_{n,p} random graph, also known as an Erdős-Rényi graph or a binomial graph.
binomial_graph(n, p[, seed, directed]) Returns a G_{n,p} random graph, also known as an Erdős-Rényi graph or a binomial graph.
newman_watts_strogatz_graph(n, k, p[, seed]) Return a Newman–Watts–Strogatz small-world graph.
watts_strogatz_graph(n, k, p[, seed]) Return a Watts–Strogatz small-world graph.
connected_watts_strogatz_graph(n, k, p[, ...]) Returns a connected Watts–Strogatz small-world graph.
random_regular_graph(d, n[, seed]) Returns a random d-regular graph on n nodes.
barabasi_albert_graph(n, m[, seed]) Returns a random graph according to the Barabási–Albert preferential attachment model.
powerlaw_cluster_graph(n, m, p[, seed]) Holme and Kim algorithm for growing graphs with powerlaw degree distribution and approximate average clustering.
duplication_divergence_graph(n, p[, seed]) Returns an undirected graph using the duplication-divergence model.
random_lobster(n, p1, p2[, seed]) Returns a random lobster graph.
random_shell_graph(constructor[, seed]) Returns a random shell graph for the constructor given.
random_powerlaw_tree(n[, gamma, seed, tries]) Returns a tree with a power law degree distribution.
random_powerlaw_tree_sequence(n[, gamma, ...]) Returns a degree sequence for a tree with a power law distribution.

Degree Sequence

Generate graphs with a given degree sequence or expected degree sequence.

configuration_model(deg_sequence[, ...]) Return a random graph with the given degree sequence.
directed_configuration_model(...[, ...]) Return a directed_random graph with the given degree sequences.
expected_degree_graph(w[, seed, selfloops]) Return a random graph with given expected degrees.
havel_hakimi_graph(deg_sequence[, create_using]) Return a simple graph with given degree sequence constructed using the Havel-Hakimi algorithm.
directed_havel_hakimi_graph(in_deg_sequence, ...) Return a directed graph with the given degree sequences.
degree_sequence_tree(deg_sequence[, ...]) Make a tree for the given degree sequence.
random_degree_sequence_graph(sequence[, ...]) Return a simple random graph with the given degree sequence.

Random Clustered

Generate graphs with given degree and triangle sequence.

random_clustered_graph(joint_degree_sequence) Generate a random graph with the given joint independent edge degree and triangle degree sequence.

Directed

Generators for some directed graphs, including growing network (GN) graphs and scale-free graphs.

gn_graph(n[, kernel, create_using, seed]) Return the growing network (GN) digraph with n nodes.
gnr_graph(n, p[, create_using, seed]) Return the growing network with redirection (GNR) digraph with n nodes and redirection probability p.
gnc_graph(n[, create_using, seed]) Return the growing network with copying (GNC) digraph with n nodes.
scale_free_graph(n[, alpha, beta, gamma, ...]) Returns a scale-free directed graph.

Geometric

Generators for geometric graphs.

random_geometric_graph(n, radius[, dim, pos]) Returns a random geometric graph in the unit cube.
geographical_threshold_graph(n, theta[, ...]) Returns a geographical threshold graph.
waxman_graph(n[, alpha, beta, L, domain]) Return a Waxman random graph.
navigable_small_world_graph(n[, p, q, r, ...]) Return a navigable small-world graph.

Line Graph

Functions for generating line graphs.

line_graph(G[, create_using]) Returns the line graph of the graph or digraph G.

Ego Graph

Ego graph.

ego_graph(G, n[, radius, center, ...]) Returns induced subgraph of neighbors centered at node n within a given radius.

Stochastic

Functions for generating stochastic graphs from a given weighted directed graph.

stochastic_graph(G[, copy, weight]) Returns a right-stochastic representation of the directed graph G.

Intersection

Generators for random intersection graphs.

uniform_random_intersection_graph(n, m, p[, ...]) Return a uniform random intersection graph.
k_random_intersection_graph(n, m, k) Return a intersection graph with randomly chosen attribute sets for each node that are of equal size (k).
general_random_intersection_graph(n, m, p) Return a random intersection graph with independent probabilities for connections between node and attribute sets.

Social Networks

Famous social networks.

karate_club_graph() Return Zachary’s Karate Club graph.
davis_southern_women_graph() Return Davis Southern women social network.
florentine_families_graph() Return Florentine families graph.

Community

Generators for classes of graphs used in studying social networks.

caveman_graph(l, k) Returns a caveman graph of l cliques of size k.
connected_caveman_graph(l, k) Returns a connected caveman graph of l cliques of size k.
relaxed_caveman_graph(l, k, p[, seed]) Return a relaxed caveman graph.
random_partition_graph(sizes, p_in, p_out[, ...]) Return the random partition graph with a partition of sizes.
planted_partition_graph(l, k, p_in, p_out[, ...]) Return the planted l-partition graph.
gaussian_random_partition_graph(n, s, v, ...) Generate a Gaussian random partition graph.

Non Isomorphic Trees

Implementation of the Wright, Richmond, Odlyzko and McKay (WROM) algorithm for the enumeration of all non-isomorphic free trees of a given order. Rooted trees are represented by level sequences, i.e., lists in which the i-th element specifies the distance of vertex i to the root.

nonisomorphic_trees(order[, create]) Returns a list of nonisomporphic trees
number_of_nonisomorphic_trees(order) Returns the number of nonisomorphic trees

Linear algebra

Graph Matrix

Adjacency matrix and incidence matrix of graphs.

adjacency_matrix(G[, nodelist, weight]) Return adjacency matrix of G.
incidence_matrix(G[, nodelist, edgelist, ...]) Return incidence matrix of G.

Laplacian Matrix

Laplacian matrix of graphs.

laplacian_matrix(G[, nodelist, weight]) Return the Laplacian matrix of G.
normalized_laplacian_matrix(G[, nodelist, ...]) Return the normalized Laplacian matrix of G.
directed_laplacian_matrix(G[, nodelist, ...]) Return the directed Laplacian matrix of G.

Spectrum

Eigenvalue spectrum of graphs.

laplacian_spectrum(G[, weight]) Return eigenvalues of the Laplacian of G
adjacency_spectrum(G[, weight]) Return eigenvalues of the adjacency matrix of G.

Algebraic Connectivity

Algebraic connectivity and Fiedler vectors of undirected graphs.

algebraic_connectivity(G[, weight, ...]) Return the algebraic connectivity of an undirected graph.
fiedler_vector(G[, weight, normalized, tol, ...]) Return the Fiedler vector of a connected undirected graph.
spectral_ordering(G[, weight, normalized, ...]) Compute the spectral_ordering of a graph.

Attribute Matrices

Functions for constructing matrix-like objects from graph attributes.

attr_matrix(G[, edge_attr, node_attr, ...]) Returns a NumPy matrix using attributes from G.
attr_sparse_matrix(G[, edge_attr, ...]) Returns a SciPy sparse matrix using attributes from G.

Converting to and from other data formats

To NetworkX Graph

Functions to convert NetworkX graphs to and from other formats.

The preferred way of converting data to a NetworkX graph is through the graph constuctor. The constructor calls the to_networkx_graph() function which attempts to guess the input type and convert it automatically.

Examples

Create a graph with a single edge from a dictionary of dictionaries

>>> d={0: {1: 1}} # dict-of-dicts single edge (0,1)
>>> G=nx.Graph(d)

See also

nx_pygraphviz, nx_pydot

to_networkx_graph(data[, create_using, ...]) Make a NetworkX graph from a known data structure.

Dictionaries

to_dict_of_dicts(G[, nodelist, edge_data]) Return adjacency representation of graph as a dictionary of dictionaries.
from_dict_of_dicts(d[, create_using, ...]) Return a graph from a dictionary of dictionaries.

Lists

to_dict_of_lists(G[, nodelist]) Return adjacency representation of graph as a dictionary of lists.
from_dict_of_lists(d[, create_using]) Return a graph from a dictionary of lists.
to_edgelist(G[, nodelist]) Return a list of edges in the graph.
from_edgelist(edgelist[, create_using]) Return a graph from a list of edges.

Numpy

Functions to convert NetworkX graphs to and from numpy/scipy matrices.

The preferred way of converting data to a NetworkX graph is through the graph constuctor. The constructor calls the to_networkx_graph() function which attempts to guess the input type and convert it automatically.

Examples

Create a 10 node random graph from a numpy matrix

>>> import numpy
>>> a = numpy.reshape(numpy.random.random_integers(0,1,size=100),(10,10))
>>> D = nx.DiGraph(a)

or equivalently

>>> D = nx.to_networkx_graph(a,create_using=nx.DiGraph())

See also

nx_pygraphviz, nx_pydot

to_numpy_matrix(G[, nodelist, dtype, order, ...]) Return the graph adjacency matrix as a NumPy matrix.
to_numpy_recarray(G[, nodelist, dtype, order]) Return the graph adjacency matrix as a NumPy recarray.
from_numpy_matrix(A[, parallel_edges, ...]) Return a graph from numpy matrix.

Scipy

to_scipy_sparse_matrix(G[, nodelist, dtype, ...]) Return the graph adjacency matrix as a SciPy sparse matrix.
from_scipy_sparse_matrix(A[, ...]) Creates a new graph from an adjacency matrix given as a SciPy sparse matrix.

Pandas

to_pandas_dataframe(G[, nodelist, ...]) Return the graph adjacency matrix as a Pandas DataFrame.
from_pandas_dataframe(df, source, target[, ...]) Return a graph from Pandas DataFrame.

Relabeling nodes

Relabeling

convert_node_labels_to_integers(G[, ...]) Return a copy of the graph G with the nodes relabeled using consecutive integers.
relabel_nodes(G, mapping[, copy]) Relabel the nodes of the graph G.

Reading and writing graphs

Adjacency List

Adjacency List

Read and write NetworkX graphs as adjacency lists.

Adjacency list format is useful for graphs without data associated with nodes or edges and for nodes that can be meaningfully represented as strings.

Format

The adjacency list format consists of lines with node labels. The first label in a line is the source node. Further labels in the line are considered target nodes and are added to the graph along with an edge between the source node and target node.

The graph with edges a-b, a-c, d-e can be represented as the following adjacency list (anything following the # in a line is a comment):

a b c # source target target
d e
read_adjlist(path[, comments, delimiter, ...]) Read graph in adjacency list format from path.
write_adjlist(G, path[, comments, ...]) Write graph G in single-line adjacency-list format to path.
parse_adjlist(lines[, comments, delimiter, ...]) Parse lines of a graph adjacency list representation.
generate_adjlist(G[, delimiter]) Generate a single line of the graph G in adjacency list format.

Multiline Adjacency List

Multi-line Adjacency List

Read and write NetworkX graphs as multi-line adjacency lists.

The multi-line adjacency list format is useful for graphs with nodes that can be meaningfully represented as strings. With this format simple edge data can be stored but node or graph data is not.

Format

The first label in a line is the source node label followed by the node degree d. The next d lines are target node labels and optional edge data. That pattern repeats for all nodes in the graph.

The graph with edges a-b, a-c, d-e can be represented as the following adjacency list (anything following the # in a line is a comment):

# example.multiline-adjlist
a 2
b
c
d 1
e
read_multiline_adjlist(path[, comments, ...]) Read graph in multi-line adjacency list format from path.
write_multiline_adjlist(G, path[, ...]) Write the graph G in multiline adjacency list format to path
parse_multiline_adjlist(lines[, comments, ...]) Parse lines of a multiline adjacency list representation of a graph.
generate_multiline_adjlist(G[, delimiter]) Generate a single line of the graph G in multiline adjacency list format.

Edge List

Edge Lists

Read and write NetworkX graphs as edge lists.

The multi-line adjacency list format is useful for graphs with nodes that can be meaningfully represented as strings. With the edgelist format simple edge data can be stored but node or graph data is not. There is no way of representing isolated nodes unless the node has a self-loop edge.

Format

You can read or write three formats of edge lists with these functions.

Node pairs with no data:

1 2

Python dictionary as data:

1 2 {'weight':7, 'color':'green'}

Arbitrary data:

1 2 7 green
read_edgelist(path[, comments, delimiter, ...]) Read a graph from a list of edges.
write_edgelist(G, path[, comments, ...]) Write graph as a list of edges.
read_weighted_edgelist(path[, comments, ...]) Read a graph as list of edges with numeric weights.
write_weighted_edgelist(G, path[, comments, ...]) Write graph G as a list of edges with numeric weights.
generate_edgelist(G[, delimiter, data]) Generate a single line of the graph G in edge list format.
parse_edgelist(lines[, comments, delimiter, ...]) Parse lines of an edge list representation of a graph.

GEXF

GEXF

Read and write graphs in GEXF format.

GEXF (Graph Exchange XML Format) is a language for describing complex network structures, their associated data and dynamics.

This implementation does not support mixed graphs (directed and undirected edges together).

Format

GEXF is an XML format. See http://gexf.net/format/schema.html for the specification and http://gexf.net/format/basic.html for examples.

read_gexf(path[, node_type, relabel, version]) Read graph in GEXF format from path.
write_gexf(G, path[, encoding, prettyprint, ...]) Write G in GEXF format to path.
relabel_gexf_graph(G) Relabel graph using “label” node keyword for node label.

GML

Read graphs in GML format.

“GML, the G>raph Modelling Language, is our proposal for a portable file format for graphs. GML’s key features are portability, simple syntax, extensibility and flexibility. A GML file consists of a hierarchical key-value lists. Graphs can be annotated with arbitrary data structures. The idea for a common file format was born at the GD‘95; this proposal is the outcome of many discussions. GML is the standard file format in the Graphlet graph editor system. It has been overtaken and adapted by several other systems for drawing graphs.”

See http://www.infosun.fim.uni-passau.de/Graphlet/GML/gml-tr.html

read_gml(path[, label, destringizer]) Read graph in GML format from path.
write_gml(G, path[, stringizer]) Write a graph G in GML format to the file or file handle path.
parse_gml(lines[, label, destringizer]) Parse GML graph from a string or iterable.
generate_gml(G[, stringizer]) Generate a single entry of the graph G in GML format.
literal_destringizer(rep) Convert a Python literal to the value it represents.
literal_stringizer(value) Convert a value to a Python literal in GML representation.

Pickle

Pickled Graphs

Read and write NetworkX graphs as Python pickles.

“The pickle module implements a fundamental, but powerful algorithm for serializing and de-serializing a Python object structure. “Pickling” is the process whereby a Python object hierarchy is converted into a byte stream, and “unpickling” is the inverse operation, whereby a byte stream is converted back into an object hierarchy.”

Note that NetworkX graphs can contain any hashable Python object as node (not just integers and strings). For arbitrary data types it may be difficult to represent the data as text. In that case using Python pickles to store the graph data can be used.

read_gpickle(path) Read graph object in Python pickle format.
write_gpickle(G, path[, protocol]) Write graph in Python pickle format.

GraphML

GraphML

Read and write graphs in GraphML format.

This implementation does not support mixed graphs (directed and unidirected edges together), hyperedges, nested graphs, or ports.

“GraphML is a comprehensive and easy-to-use file format for graphs. It consists of a language core to describe the structural properties of a graph and a flexible extension mechanism to add application-specific data. Its main features include support of

  • directed, undirected, and mixed graphs,
  • hypergraphs,
  • hierarchical graphs,
  • graphical representations,
  • references to external data,
  • application-specific attribute data, and
  • light-weight parsers.

Unlike many other file formats for graphs, GraphML does not use a custom syntax. Instead, it is based on XML and hence ideally suited as a common denominator for all kinds of services generating, archiving, or processing graphs.”

http://graphml.graphdrawing.org/

Format

GraphML is an XML format. See http://graphml.graphdrawing.org/specification.html for the specification and http://graphml.graphdrawing.org/primer/graphml-primer.html for examples.

read_graphml(path[, node_type]) Read graph in GraphML format from path.
write_graphml(G, path[, encoding, prettyprint]) Write G in GraphML XML format to path

JSON

JSON data

Generate and parse JSON serializable data for NetworkX graphs.

These formats are suitable for use with the d3.js examples http://d3js.org/

The three formats that you can generate with NetworkX are:

node_link_data(G[, attrs]) Return data in node-link format that is suitable for JSON serialization and use in Javascript documents.
node_link_graph(data[, directed, ...]) Return graph from node-link data format.
adjacency_data(G[, attrs]) Return data in adjacency format that is suitable for JSON serialization and use in Javascript documents.
adjacency_graph(data[, directed, ...]) Return graph from adjacency data format.
tree_data(G, root[, attrs]) Return data in tree format that is suitable for JSON serialization and use in Javascript documents.
tree_graph(data[, attrs]) Return graph from tree data format.

LEDA

Read graphs in LEDA format.

LEDA is a C++ class library for efficient data types and algorithms.

read_leda(path[, encoding]) Read graph in LEDA format from path.
parse_leda(lines) Read graph in LEDA format from string or iterable.

YAML

YAML

Read and write NetworkX graphs in YAML format.

“YAML is a data serialization format designed for human readability and interaction with scripting languages.” See http://www.yaml.org for documentation.

read_yaml(path) Read graph in YAML format from path.
write_yaml(G, path[, encoding]) Write graph G in YAML format to path.

SparseGraph6

Graph6

Graph6

Read and write graphs in graph6 format.

Format

“graph6 and sparse6 are formats for storing undirected graphs in a compact manner, using only printable ASCII characters. Files in these formats have text type and contain one line per graph.”

See http://cs.anu.edu.au/~bdm/data/formats.txt for details.

parse_graph6(string) Read a simple undirected graph in graph6 format from string.
read_graph6(path) Read simple undirected graphs in graph6 format from path.
generate_graph6(G[, nodes, header]) Generate graph6 format string from a simple undirected graph.
write_graph6(G, path[, nodes, header]) Write a simple undirected graph to path in graph6 format.
Sparse6

Sparse6

Read and write graphs in sparse6 format.

Format

“graph6 and sparse6 are formats for storing undirected graphs in a compact manner, using only printable ASCII characters. Files in these formats have text type and contain one line per graph.”

See http://cs.anu.edu.au/~bdm/data/formats.txt for details.

parse_sparse6(string) Read an undirected graph in sparse6 format from string.
read_sparse6(path) Read an undirected graph in sparse6 format from path.
generate_sparse6(G[, nodes, header]) Generate sparse6 format string from an undirected graph.
write_sparse6(G, path[, nodes, header]) Write graph G to given path in sparse6 format.

Pajek

Pajek

Read graphs in Pajek format.

This implementation handles directed and undirected graphs including those with self loops and parallel edges.

read_pajek(path[, encoding]) Read graph in Pajek format from path.
write_pajek(G, path[, encoding]) Write graph in Pajek format to path.
parse_pajek(lines) Parse Pajek format graph from string or iterable.

GIS Shapefile

Shapefile

Generates a networkx.DiGraph from point and line shapefiles.

“The Esri Shapefile or simply a shapefile is a popular geospatial vector data format for geographic information systems software. It is developed and regulated by Esri as a (mostly) open specification for data interoperability among Esri and other software products.” See http://en.wikipedia.org/wiki/Shapefile for additional information.

read_shp(path[, simplify]) Generates a networkx.DiGraph from shapefiles.
write_shp(G, outdir) Writes a networkx.DiGraph to two shapefiles, edges and nodes.

Drawing

NetworkX provides basic functionality for visualizing graphs, but its main goal is to enable graph analysis rather than perform graph visualization. In the future, graph visualization functionality may be removed from NetworkX or only available as an add-on package.

Proper graph visualization is hard, and we highly recommend that people visualize their graphs with tools dedicated to that task. Notable examples of dedicated and fully-featured graph visualization tools are Cytoscape, Gephi, Graphviz and, for LaTeX typesetting, PGF/TikZ. To use these and other such tools, you should export your NetworkX graph into a format that can be read by those tools. For example, Cytoscape can read the GraphML format, and so, networkx.write_graphml(G) might be an appropriate choice.

Matplotlib

Matplotlib

Draw networks with matplotlib.

See also

matplotlib
http://matplotlib.org/
pygraphviz
http://pygraphviz.github.io/
draw(G[, pos, ax, hold]) Draw the graph G with Matplotlib.
draw_networkx(G[, pos, arrows, with_labels]) Draw the graph G using Matplotlib.
draw_networkx_nodes(G, pos[, nodelist, ...]) Draw the nodes of the graph G.
draw_networkx_edges(G, pos[, edgelist, ...]) Draw the edges of the graph G.
draw_networkx_labels(G, pos[, labels, ...]) Draw node labels on the graph G.
draw_networkx_edge_labels(G, pos[, ...]) Draw edge labels.
draw_circular(G, **kwargs) Draw the graph G with a circular layout.
draw_random(G, **kwargs) Draw the graph G with a random layout.
draw_spectral(G, **kwargs) Draw the graph G with a spectral layout.
draw_spring(G, **kwargs) Draw the graph G with a spring layout.
draw_shell(G, **kwargs) Draw networkx graph with shell layout.
draw_graphviz(G[, prog]) Draw networkx graph with graphviz layout.

Graphviz AGraph (dot)

Graphviz AGraph

Interface to pygraphviz AGraph class.

Examples

>>> G=nx.complete_graph(5)
>>> A=nx.to_agraph(G)
>>> H=nx.from_agraph(A)

See also

Pygraphviz
http://pygraphviz.github.io/
from_agraph(A[, create_using]) Return a NetworkX Graph or DiGraph from a PyGraphviz graph.
to_agraph(N) Return a pygraphviz graph from a NetworkX graph N.
write_dot(G, path) Write NetworkX graph G to Graphviz dot format on path.
read_dot(path) Return a NetworkX graph from a dot file on path.
graphviz_layout(G[, prog, root, args]) Create node positions for G using Graphviz.
pygraphviz_layout(G[, prog, root, args]) Create node positions for G using Graphviz.

Graphviz with pydot

Pydot

Import and export NetworkX graphs in Graphviz dot format using pydot.

Either this module or nx_pygraphviz can be used to interface with graphviz.

from_pydot(P) Return a NetworkX graph from a Pydot graph.
to_pydot(N[, strict]) Return a pydot graph from a NetworkX graph N.
write_dot(G, path) Write NetworkX graph G to Graphviz dot format on path.
read_dot(path) Return a NetworkX MultiGraph or MultiDiGraph from a dot file on path.
graphviz_layout(G[, prog, root]) Create node positions using Pydot and Graphviz.
pydot_layout(G[, prog, root]) Create node positions using Pydot and Graphviz.

Graph Layout

Layout

Node positioning algorithms for graph drawing.

circular_layout(G[, dim, scale, center]) Position nodes on a circle.
random_layout(G[, dim, center]) Position nodes uniformly at random in the unit square.
shell_layout(G[, nlist, dim, scale, center]) Position nodes in concentric circles.
spring_layout(G[, dim, k, pos, fixed, ...]) Position nodes using Fruchterman-Reingold force-directed algorithm.
spectral_layout(G[, dim, weight, scale, center]) Position nodes using the eigenvectors of the graph Laplacian.

Exceptions

Exceptions

Base exceptions and errors for NetworkX.

class NetworkXException[source]

Base class for exceptions in NetworkX.

class NetworkXError[source]

Exception for a serious error in NetworkX

class NetworkXPointlessConcept[source]

Harary, F. and Read, R. “Is the Null Graph a Pointless Concept?” In Graphs and Combinatorics Conference, George Washington University. New York: Springer-Verlag, 1973.

class NetworkXAlgorithmError[source]

Exception for unexpected termination of algorithms.

class NetworkXUnfeasible[source]

Exception raised by algorithms trying to solve a problem instance that has no feasible solution.

class NetworkXNoPath[source]

Exception for algorithms that should return a path when running on graphs where such a path does not exist.

class NetworkXUnbounded[source]

Exception raised by algorithms trying to solve a maximization or a minimization problem instance that is unbounded.

Utilities

Helper Functions

Miscellaneous Helpers for NetworkX.

These are not imported into the base networkx namespace but can be accessed, for example, as

>>> import networkx
>>> networkx.utils.is_string_like('spam')
True
is_string_like(obj) Check if obj is string.
flatten(obj[, result]) Return flattened version of (possibly nested) iterable object.
iterable(obj) Return True if obj is iterable with a well-defined len().
is_list_of_ints(intlist) Return True if list is a list of ints.
make_str(x) Return the string representation of t.
generate_unique_node() Generate a unique node label.
default_opener(filename) Opens filename using system’s default program.

Data Structures and Algorithms

Union-find data structure.

UnionFind.union(*objects) Find the sets containing the objects and merge them all.

Random Sequence Generators

Utilities for generating random numbers, random sequences, and random selections.

create_degree_sequence(n[, sfunction, max_tries])
pareto_sequence(n[, exponent]) Return sample sequence of length n from a Pareto distribution.
powerlaw_sequence(n[, exponent]) Return sample sequence of length n from a power law distribution.
uniform_sequence(n) Return sample sequence of length n from a uniform distribution.
cumulative_distribution(distribution) Return normalized cumulative distribution from discrete distribution.
discrete_sequence(n[, distribution, ...]) Return sample sequence of length n from a given discrete distribution or discrete cumulative distribution.
zipf_sequence(n[, alpha, xmin]) Return a sample sequence of length n from a Zipf distribution with exponent parameter alpha and minimum value xmin.
zipf_rv(alpha[, xmin, seed]) Return a random value chosen from the Zipf distribution.
random_weighted_sample(mapping, k) Return k items without replacement from a weighted sample.
weighted_choice(mapping) Return a single element from a weighted sample.

Decorators

open_file(path_arg[, mode]) Decorator to ensure clean opening and closing of files.

Cuthill-Mckee Ordering

Cuthill-McKee ordering of graph nodes to produce sparse matrices

cuthill_mckee_ordering(G[, heuristic]) Generate an ordering (permutation) of the graph nodes to make a sparse matrix.
reverse_cuthill_mckee_ordering(G[, heuristic]) Generate an ordering (permutation) of the graph nodes to make a sparse matrix.

Context Managers

reversed(*args, **kwds) A context manager for temporarily reversing a directed graph in place.

License

NetworkX is distributed with the BSD license.

Copyright (C) 2004-2012, NetworkX Developers
Aric Hagberg <hagberg@lanl.gov>
Dan Schult <dschult@colgate.edu>
Pieter Swart <swart@lanl.gov>
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

  * Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.

  * Redistributions in binary form must reproduce the above
    copyright notice, this list of conditions and the following
    disclaimer in the documentation and/or other materials provided
    with the distribution.

  * Neither the name of the NetworkX Developers nor the names of its
    contributors may be used to endorse or promote products derived
    from this software without specific prior written permission.


THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Citing

To cite NetworkX please use the following publication:

Aric A. Hagberg, Daniel A. Schult and Pieter J. Swart, “Exploring network structure, dynamics, and function using NetworkX”, in Proceedings of the 7th Python in Science Conference (SciPy2008), Gäel Varoquaux, Travis Vaught, and Jarrod Millman (Eds), (Pasadena, CA USA), pp. 11–15, Aug 2008

PDF BibTeX

Credits

NetworkX was originally written by Aric Hagberg, Dan Schult, and Pieter Swart, and has been developed with the help of many others. Thanks to everyone who has improved NetworkX by contributing code, bug reports (and fixes), documentation, and input on design, features, and the future of NetworkX.

Contributions

This section aims to provide a list of people and projects that have contributed to networkx. It is intended to be an inclusive list, and anyone who has contributed and wishes to make that contribution known is welcome to add an entry into this file. Generally, no name should be added to this list without the approval of the person associated with that name.

Creating a comprehensive list of contributors can be difficult, and the list within this file is almost certainly incomplete. Contributors include testers, bug reporters, contributors who wish to remain anonymous, funding sources, academic advisors, end users, and even build/integration systems (such as TravisCI, coveralls, and readthedocs).

Do you want to make your contribution known? If you have commit access, edit this file and add your name. If you do not have commit access, feel free to open an issue, submit a pull request, or get in contact with one of the official team members.

A supplementary (but still incomplete) list of contributors is given by the list of names that have commits in networkx‘s git repository. This can be obtained via:

git log --raw | grep "^Author: " | sort | uniq

A historical, partial listing of contributors and their contributions to some of the earlier versions of NetworkX can be found here.

Original Authors
Aric Hagberg
Dan Schult
Pieter Swart

Contributors

Optionally, add your desired name and include a few relevant links. The order is partially historical, and now, mostly arbitrary.

  • Aric Hagberg, GitHub: hagberg
  • Dan Schult, GitHub: dschult
  • Pieter Swart
  • Katy Bold
  • Hernan Rozenfeld
  • Brendt Wohlberg
  • Jim Bagrow
  • Holly Johnsen
  • Arnar Flatberg
  • Chris Myers
  • Joel Miller
  • Keith Briggs
  • Ignacio Rozada
  • Phillipp Pagel
  • Sverre Sundsdal
  • Ross M. Richardson
  • Eben Kenah
  • Sasha Gutfriend
  • Udi Weinsberg
  • Matteo Dell’Amico
  • Andrew Conway
  • Raf Guns
  • Salim Fadhley
  • Matteo Dell’Amico
  • Fabrice Desclaux
  • Arpad Horvath
  • Minh Van Nguyen
  • Willem Ligtenberg
  • Loïc Séguin-C.
  • Paul McGuire
  • Jesus Cerquides
  • Ben Edwards
  • Jon Olav Vik
  • Hugh Brown
  • Ben Reilly
  • Leo Lopes
  • Jordi Torrents, GitHub: jtorrents
  • Dheeraj M R
  • Franck Kalala
  • Simon Knight
  • Conrad Lee
  • Sérgio Nery Simões
  • Robert King
  • Nick Mancuso
  • Brian Cloteaux
  • Alejandro Weinstein
  • Dustin Smith
  • Mathieu Larose
  • Vincent Gauthier
  • Sérgio Nery Simões
  • chebee7i, GitHub: chebee7i
  • Jeffrey Finkelstein
  • Jean-Gabriel Young, Github: jg-you
  • Andrey Paramonov, http://aparamon.msk.ru
  • Mridul Seth, GitHub: MridulS
  • Thodoris Sotiropoulos, GitHub: theosotr
  • Konstantinos Karakatsanis, GitHub: k-karakatsanis
  • Ryan Nelson, GitHub: rnelsonchem

Support

networkx and those who have contributed to networkx have received support throughout the years from a variety of sources. We list them below. If you have provided support to networkx and a support acknowledgment does not appear below, please help us remedy the situation, and similarly, please let us know if you’d like something modified or corrected.

Research Groups

networkx acknowledges support from the following:

Funding

networkx acknowledges support from the following:

  • Google Summer of Code via Python Software Foundation
  • U.S. Army Research Office grant W911NF-12-1-0288
  • DARPA Physical Intelligence Subcontract No. 9060-000709
  • NSF Grant No. PHY-0748828
  • John Templeton Foundation through a grant to the Santa Fe Institute to study complexity
  • U.S. Army Research Laboratory and the U.S. Army Research Office under contract number W911NF-13-1-0340

Glossary

dictionary
A Python dictionary maps keys to values. Also known as “hashes”, or “associative arrays”. See http://docs.python.org/tutorial/datastructures.html#dictionaries
ebunch
An iteratable container of edge tuples like a list, iterator, or file.
edge
Edges are either two-tuples of nodes (u,v) or three tuples of nodes with an edge attribute dictionary (u,v,dict).
edge attribute
Edges can have arbitrary Python objects assigned as attributes by using keyword/value pairs when adding an edge assigning to the G.edge[u][v] attribute dictionary for the specified edge u-v.
hashable

An object is hashable if it has a hash value which never changes during its lifetime (it needs a __hash__() method), and can be compared to other objects (it needs an __eq__() or __cmp__() method). Hashable objects which compare equal must have the same hash value.

Hashability makes an object usable as a dictionary key and a set member, because these data structures use the hash value internally.

All of Python’s immutable built-in objects are hashable, while no mutable containers (such as lists or dictionaries) are. Objects which are instances of user-defined classes are hashable by default; they all compare unequal, and their hash value is their id().

Definition from http://docs.python.org/glossary.html

nbunch
An nbunch is any iterable container of nodes that is not itself a node in the graph. It can be an iterable or an iterator, e.g. a list, set, graph, file, etc..
node
A node can be any hashable Python object except None.
node attribute
Nodes can have arbitrary Python objects assigned as attributes by using keyword/value pairs when adding a node or assigning to the G.node[n] attribute dictionary for the specified node n.

Reference

Release:1.10
Date:October 31, 2015

Testing

Requirements for testing

NetworkX uses the Python nose testing package. If you don’t already have that package installed, follow the directions here http://somethingaboutorange.com/mrl/projects/nose

Testing a source distribution

You can test the complete package from the unpacked source directory with:

python setup_egg.py nosetests

Testing an installed package

If you have a file-based (not a Python egg) installation you can test the installed package with

>>> import networkx
>>> networkx.test()

or:

python -c "import networkx; networkx.test()"

Testing for developers

You can test any or all of NetworkX by using the “nosetests” test runner.

First make sure the NetworkX version you want to test is in your PYTHONPATH (either installed or pointing to your unpacked source directory).

Then you can run individual test files with:

nosetests path/to/file

or all tests found in dir and an directories contained in dir:

nosetests path/to/dir

By default nosetests doesn’t test docutils style tests in Python modules but you can turn that on with:

nosetests --with-doctest

For doctests in stand-alone files NetworkX uses the extension txt so you can add:

nosetests --with-doctest --doctest-extension=txt

to also execute those tests.

These options are on by default if you run nosetests from the root of the NetworkX distribution since they are specified in the setup.cfg file found there.

Developer Guide

Working with networkx source code

Contents:

Introduction

These pages describe a git and github workflow for the networkx project.

There are several different workflows here, for different ways of working with networkx.

This is not a comprehensive git reference, it’s just a workflow for our own project. It’s tailored to the github hosting service. You may well find better or quicker ways of getting stuff done with git, but these should get you started.

For general resources for learning git, see git resources.

Install git

Overview
Debian / Ubuntu sudo apt-get install git
Fedora sudo yum install git-core
Windows Download and install msysGit
OS X Use the git-osx-installer
In detail

See the git page for the most recent information.

Have a look at the github install help pages available from github help

There are good instructions here: http://book.git-scm.com/2_installing_git.html

Following the latest source

These are the instructions if you just want to follow the latest networkx source, but you don’t need to do any development for now.

The steps are:

Get the local copy of the code

From the command line:

git clone git://github.com/networkx/networkx.git

You now have a copy of the code tree in the new networkx directory.

Updating the code

From time to time you may want to pull down the latest code. It is necessary to add the networkx repository as a remote to your configuration file. We call it upstream.

git remote set-url upstream https://github.com/networkx/networkx.git

Now git knows where to fetch updates from.

cd networkx git fetch upstream

The tree in networkx will now have the latest changes from the initial repository, unless you have made local changes in the meantime. In this case, you have to merge.

git merge upstream/master

It is also possible to update your local fork directly from GitHub:

  1. Open your fork on GitHub.
  2. Click on ‘Pull Requests’.
  3. Click on ‘New Pull Request’. By default, GitHub will compare the original with your fork. If you didn’t make any changes, there is nothing to compare.
  4. Click on ‘Switching the base’ or click ‘Edit’ and switch the base manually. Now GitHub will compare your fork with the original, and you should see all the latest changes.
  5. Click on ‘Click to create a pull request for this comparison’ and name your pull request.
  6. Click on Send pull request.
  7. Scroll down and click ‘Merge pull request’ and finally ‘Confirm merge’. You will be able to merge it automatically unless you did not change you local repo.

Making a patch

You’ve discovered a bug or something else you want to change in networkx .. — excellent!

You’ve worked out a way to fix it — even better!

You want to tell us about it — best of all!

The easiest way is to make a patch or set of patches. Here we explain how. Making a patch is the simplest and quickest, but if you’re going to be doing anything more than simple quick things, please consider following the Git for development model instead.

Making patches
Overview
# tell git who you are
git config --global user.email you@yourdomain.example.com
git config --global user.name "Your Name Comes Here"
# get the repository if you don't have it
git clone git://github.com/networkx/networkx.git
# make a branch for your patching
cd networkx
git branch the-fix-im-thinking-of
git checkout the-fix-im-thinking-of
# hack, hack, hack
# Tell git about any new files you've made
git add somewhere/tests/test_my_bug.py
# commit work in progress as you go
git commit -am 'BF - added tests for Funny bug'
# hack hack, hack
git commit -am 'BF - added fix for Funny bug'
# make the patch files
git format-patch -M -C master

Then, send the generated patch files to the networkx mailing list — where we will thank you warmly.

In detail
  1. Tell git who you are so it can label the commits you’ve made:

    git config --global user.email you@yourdomain.example.com
    git config --global user.name "Your Name Comes Here"
    
  2. If you don’t already have one, clone a copy of the networkx repository:

    git clone git://github.com/networkx/networkx.git
    cd networkx
    
  3. Make a ‘feature branch’. This will be where you work on your bug fix. It’s nice and safe and leaves you with access to an unmodified copy of the code in the main branch:

    git branch the-fix-im-thinking-of
    git checkout the-fix-im-thinking-of
    
  4. Do some edits, and commit them as you go:

    # hack, hack, hack
    # Tell git about any new files you've made
    git add somewhere/tests/test_my_bug.py
    # commit work in progress as you go
    git commit -am 'BF - added tests for Funny bug'
    # hack hack, hack
    git commit -am 'BF - added fix for Funny bug'
    

    Note the -am options to commit. The m flag just signals that you’re going to type a message on the command line. The a flag — you can just take on faith — or see why the -a flag?.

  5. When you have finished, check you have committed all your changes:

    git status
    
  6. Finally, make your commits into patches. You want all the commits since you branched from the master branch:

    git format-patch -M -C master
    

    You will now have several files named for the commits:

    0001-BF-added-tests-for-Funny-bug.patch
    0002-BF-added-fix-for-Funny-bug.patch
    

    Send these files to the networkx mailing list.

When you are done, to switch back to the main copy of the code, just return to the master branch:

git checkout master
Moving from patching to development

If you find you have done some patches, and you have one or more feature branches, you will probably want to switch to development mode. You can do this with the repository you have.

Fork the networkx repository on github — Making your own copy (fork) of networkx. Then:

# checkout and refresh master branch from main repo
git checkout master
git pull origin master
# rename pointer to main repository to 'upstream'
git remote rename origin upstream
# point your repo to default read / write to your fork on github
git remote add origin git@github.com:your-user-name/networkx.git
# push up any branches you've made and want to keep
git push origin the-fix-im-thinking-of

Then you can, if you want, follow the Development workflow.

Git for development

Contents:

Making your own copy (fork) of networkx

You need to do this only once. The instructions here are very similar to the instructions at https://help.github.com/articles/fork-a-repo/ — please see that page for more detail. We’re repeating some of it here just to give the specifics for the networkx project, and to suggest some default names.

Set up and configure a github account

If you don’t have a github account, go to the github page, and make one.

You then need to configure your account to allow write access — see the Generating SSH keys help on github help.

Create your own forked copy of networkx
  1. Log into your github account.

  2. Go to the networkx github home at networkx github.

  3. Click on the fork button:

    _images/forking_button.png

    Now, after a short pause and some ‘Hardcore forking action’, you should find yourself at the home page for your own forked copy of networkx.

Set up your fork

First you follow the instructions for Making your own copy (fork) of networkx.

Overview
git clone git@github.com:your-user-name/networkx.git
cd networkx
git remote add upstream git://github.com/networkx/networkx.git
In detail
Clone your fork
  1. Clone your fork to the local computer with git clone git@github.com:your-user-name/networkx.git

  2. Investigate. Change directory to your new repo: cd networkx. Then git branch -a to show you all branches. You’ll get something like:

    * master
    remotes/origin/master
    

    This tells you that you are currently on the master branch, and that you also have a remote connection to origin/master. What remote repository is remote/origin? Try git remote -v to see the URLs for the remote. They will point to your github fork.

    Now you want to connect to the upstream networkx github repository, so you can merge in changes from trunk.

Linking your repository to the upstream repo
cd networkx
git remote add upstream git://github.com/networkx/networkx.git

upstream here is just the arbitrary name we’re using to refer to the main networkx repository at networkx github.

Note that we’ve used git:// for the URL rather than git@. The git:// URL is read only. This means we that we can’t accidentally (or deliberately) write to the upstream repo, and we are only going to use it to merge into our own code.

Just for your own satisfaction, show yourself that you now have a new ‘remote’, with git remote -v show, giving you something like:

upstream     git://github.com/networkx/networkx.git (fetch)
upstream     git://github.com/networkx/networkx.git (push)
origin       git@github.com:your-user-name/networkx.git (fetch)
origin       git@github.com:your-user-name/networkx.git (push)
Configure git
Overview

Your personal git configurations are saved in the .gitconfig file in your home directory.

Here is an example .gitconfig file:

[user]
        name = Your Name
        email = you@yourdomain.example.com

[alias]
        ci = commit -a
        co = checkout
        st = status
        stat = status
        br = branch
        wdiff = diff --color-words

[core]
        editor = vim

[merge]
        summary = true

You can edit this file directly or you can use the git config --global command:

git config --global user.name "Your Name"
git config --global user.email you@yourdomain.example.com
git config --global alias.ci "commit -a"
git config --global alias.co checkout
git config --global alias.st "status -a"
git config --global alias.stat "status -a"
git config --global alias.br branch
git config --global alias.wdiff "diff --color-words"
git config --global core.editor vim
git config --global merge.summary true

To set up on another computer, you can copy your ~/.gitconfig file, or run the commands above.

In detail
user.name and user.email

It is good practice to tell git who you are, for labeling any changes you make to the code. The simplest way to do this is from the command line:

git config --global user.name "Your Name"
git config --global user.email you@yourdomain.example.com

This will write the settings into your git configuration file, which should now contain a user section with your name and email:

[user]
      name = Your Name
      email = you@yourdomain.example.com

Of course you’ll need to replace Your Name and you@yourdomain.example.com with your actual name and email address.

Aliases

You might well benefit from some aliases to common commands.

For example, you might well want to be able to shorten git checkout to git co. Or you may want to alias git diff --color-words (which gives a nicely formatted output of the diff) to git wdiff

The following git config --global commands:

git config --global alias.ci "commit -a"
git config --global alias.co checkout
git config --global alias.st "status -a"
git config --global alias.stat "status -a"
git config --global alias.br branch
git config --global alias.wdiff "diff --color-words"

will create an alias section in your .gitconfig file with contents like this:

[alias]
        ci = commit -a
        co = checkout
        st = status -a
        stat = status -a
        br = branch
        wdiff = diff --color-words
Editor

You may also want to make sure that your editor of choice is used

git config --global core.editor vim
Merging

To enforce summaries when doing merges (~/.gitconfig file again):

[merge]
   log = true

Or from the command line:

git config --global merge.log true
Fancy log output

This is a very nice alias to get a fancy log output; it should go in the alias section of your .gitconfig file:

lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)[%an]%Creset' --abbrev-commit --date=relative

You use the alias with:

git lg

and it gives graph / text output something like this (but with color!):

* 6d8e1ee - (HEAD, origin/my-fancy-feature, my-fancy-feature) NF - a fancy file (45 minutes ago) [Matthew Brett]
*   d304a73 - (origin/placeholder, placeholder) Merge pull request #48 from hhuuggoo/master (2 weeks ago) [Jonathan Terhorst]
|\
| * 4aff2a8 - fixed bug 35, and added a test in test_bugfixes (2 weeks ago) [Hugo]
|/
* a7ff2e5 - Added notes on discussion/proposal made during Data Array Summit. (2 weeks ago) [Corran Webster]
* 68f6752 - Initial implimentation of AxisIndexer - uses 'index_by' which needs to be changed to a call on an Axes object - this is all very sketchy right now. (2 weeks ago) [Corr
*   376adbd - Merge pull request #46 from terhorst/master (2 weeks ago) [Jonathan Terhorst]
|\
| * b605216 - updated joshu example to current api (3 weeks ago) [Jonathan Terhorst]
| * 2e991e8 - add testing for outer ufunc (3 weeks ago) [Jonathan Terhorst]
| * 7beda5a - prevent axis from throwing an exception if testing equality with non-axis object (3 weeks ago) [Jonathan Terhorst]
| * 65af65e - convert unit testing code to assertions (3 weeks ago) [Jonathan Terhorst]
| *   956fbab - Merge remote-tracking branch 'upstream/master' (3 weeks ago) [Jonathan Terhorst]
| |\
| |/

Thanks to Yury V. Zaytsev for posting it.

Development workflow

You already have your own forked copy of the networkx repository, by following Making your own copy (fork) of networkx. You have Set up your fork. You have configured git by following Configure git. Now you are ready for some real work.

Workflow summary

In what follows we’ll refer to the upstream networkx master branch, as “trunk”.

  • Don’t use your master branch for anything. Consider deleting it.
  • When you are starting a new set of changes, fetch any changes from trunk, and start a new feature branch from that.
  • Make a new branch for each separable set of changes — “one task, one branch” (ipython git workflow).
  • Name your branch for the purpose of the changes - e.g. bugfix-for-issue-14 or refactor-database-code.
  • If you can possibly avoid it, avoid merging trunk or any other branches into your feature branch while you are working.
  • If you do find yourself merging from trunk, consider Rebasing on trunk
  • Ask on the networkx mailing list if you get stuck.
  • Ask for code review!

This way of working helps to keep work well organized, with readable history. This in turn makes it easier for project maintainers (that might be you) to see what you’ve done, and why you did it.

See ipython git workflow for some explanation.

Consider deleting your master branch

It may sound strange, but deleting your own master branch can help reduce confusion about which branch you are on. See deleting master on github for details.

Update the mirror of trunk

First make sure you have done Linking your repository to the upstream repo.

From time to time you should fetch the upstream (trunk) changes from github:

git fetch upstream

This will pull down any commits you don’t have, and set the remote branches to point to the right commit. For example, ‘trunk’ is the branch referred to by (remote/branchname) upstream/master - and if there have been commits since you last checked, upstream/master will change after you do the fetch.

Make a new feature branch

When you are ready to make some changes to the code, you should start a new branch. Branches that are for a collection of related edits are often called ‘feature branches’.

Making an new branch for each set of related changes will make it easier for someone reviewing your branch to see what you are doing.

Choose an informative name for the branch to remind yourself and the rest of us what the changes in the branch are for. For example add-ability-to-fly, or buxfix-for-issue-42.

# Update the mirror of trunk
git fetch upstream
# Make new feature branch starting at current trunk
git branch my-new-feature upstream/master
git checkout my-new-feature

Generally, you will want to keep your feature branches on your public github fork of networkx. To do this, you git push this new branch up to your github repo. Generally (if you followed the instructions in these pages, and by default), git will have a link to your github repo, called origin. You push up to your own repo on github with:

git push origin my-new-feature

In git >= 1.7 you can ensure that the link is correctly set by using the --set-upstream option:

git push --set-upstream origin my-new-feature

From now on git will know that my-new-feature is related to the my-new-feature branch in the github repo.

The editing workflow
Overview
# hack hack
git add my_new_file
git commit -am 'NF - some message'
git push
In more detail
  1. Make some changes

  2. See which files have changed with git status (see git status). You’ll see a listing like this one:

    # On branch ny-new-feature
    # Changed but not updated:
    #   (use "git add <file>..." to update what will be committed)
    #   (use "git checkout -- <file>..." to discard changes in working directory)
    #
    #  modified:   README
    #
    # Untracked files:
    #   (use "git add <file>..." to include in what will be committed)
    #
    #  INSTALL
    no changes added to commit (use "git add" and/or "git commit -a")
    
  3. Check what the actual changes are with git diff (git diff).

  4. Add any new files to version control git add new_file_name (see git add).

  5. To commit all modified files into the local copy of your repo,, do git commit -am 'A commit message'. Note the -am options to commit. The m flag just signals that you’re going to type a message on the command line. The a flag — you can just take on faith — or see why the -a flag? — and the helpful use-case description in the tangled working copy problem. The git commit manual page might also be useful.

  6. To push the changes up to your forked repo on github, do a git push (see git push).

Ask for your changes to be reviewed or merged

When you are ready to ask for someone to review your code and consider a merge:

  1. Go to the URL of your forked repo, say http://github.com/your-user-name/networkx.

  2. Use the ‘Switch Branches’ dropdown menu near the top left of the page to select the branch with your changes:

    _images/branch_dropdown.png
  3. Click on the ‘Pull request’ button:

    _images/pull_button.png

    Enter a title for the set of changes, and some explanation of what you’ve done. Say if there is anything you’d like particular attention for - like a complicated change or some code you are not happy with.

    If you don’t think your request is ready to be merged, just say so in your pull request message. This is still a good way of getting some preliminary code review.

Some other things you might want to do
Delete a branch on github
git checkout master
# delete branch locally
git branch -D my-unwanted-branch
# delete branch on github
git push origin :my-unwanted-branch

(Note the colon : before test-branch. See also: http://github.com/guides/remove-a-remote-branch

Several people sharing a single repository

If you want to work on some stuff with other people, where you are all committing into the same repository, or even the same branch, then just share it via github.

First fork networkx into your account, as from Making your own copy (fork) of networkx.

Then, go to your forked repository github page, say http://github.com/your-user-name/networkx

Click on the ‘Admin’ button, and add anyone else to the repo as a collaborator:

_images/pull_button.png

Now all those people can do:

git clone git@githhub.com:your-user-name/networkx.git

Remember that links starting with git@ use the ssh protocol and are read-write; links starting with git:// are read-only.

Your collaborators can then commit directly into that repo with the usual:

git commit -am 'ENH - much better code'
git push origin master # pushes directly into your repo
Explore your repository

To see a graphical representation of the repository branches and commits:

gitk --all

To see a linear list of commits for this branch:

git log

You can also look at the network graph visualizer for your github repo.

Finally the Fancy log output lg alias will give you a reasonable text-based graph of the repository.

Rebasing on trunk

Let’s say you thought of some work you’d like to do. You Update the mirror of trunk and Make a new feature branch called cool-feature. At this stage trunk is at some commit, let’s call it E. Now you make some new commits on your cool-feature branch, let’s call them A, B, C. Maybe your changes take a while, or you come back to them after a while. In the meantime, trunk has progressed from commit E to commit (say) G:

      A---B---C cool-feature
     /
D---E---F---G trunk

At this stage you consider merging trunk into your feature branch, and you remember that this here page sternly advises you not to do that, because the history will get messy. Most of the time you can just ask for a review, and not worry that trunk has got a little ahead. But sometimes, the changes in trunk might affect your changes, and you need to harmonize them. In this situation you may prefer to do a rebase.

rebase takes your changes (A, B, C) and replays them as if they had been made to the current state of trunk. In other words, in this case, it takes the changes represented by A, B, C and replays them on top of G. After the rebase, your history will look like this:

              A'--B'--C' cool-feature
             /
D---E---F---G trunk

See rebase without tears for more detail.

To do a rebase on trunk:

# Update the mirror of trunk
git fetch upstream
# go to the feature branch
git checkout cool-feature
# make a backup in case you mess up
git branch tmp cool-feature
# rebase cool-feature onto trunk
git rebase --onto upstream/master upstream/master cool-feature

In this situation, where you are already on branch cool-feature, the last command can be written more succinctly as:

git rebase upstream/master

When all looks good you can delete your backup branch:

git branch -D tmp

If it doesn’t look good you may need to have a look at Recovering from mess-ups.

If you have made changes to files that have also changed in trunk, this may generate merge conflicts that you need to resolve - see the git rebase man page for some instructions at the end of the “Description” section. There is some related help on merging in the git user manual - see resolving a merge.

Recovering from mess-ups

Sometimes, you mess up merges or rebases. Luckily, in git it is relatively straightforward to recover from such mistakes.

If you mess up during a rebase:

git rebase --abort

If you notice you messed up after the rebase:

# reset branch back to the saved point
git reset --hard tmp

If you forgot to make a backup branch:

# look at the reflog of the branch
git reflog show cool-feature

8630830 cool-feature@{0}: commit: BUG: io: close file handles immediately
278dd2a cool-feature@{1}: rebase finished: refs/heads/my-feature-branch onto 11ee694744f2552d
26aa21a cool-feature@{2}: commit: BUG: lib: make seek_gzip_factory not leak gzip obj
...

# reset the branch to where it was before the botched rebase
git reset --hard cool-feature@{2}
Rewriting commit history

Note

Do this only for your own feature branches.

There’s an embarassing typo in a commit you made? Or perhaps the you made several false starts you would like the posterity not to see.

This can be done via interactive rebasing.

Suppose that the commit history looks like this:

git log --oneline
eadc391 Fix some remaining bugs
a815645 Modify it so that it works
2dec1ac Fix a few bugs + disable
13d7934 First implementation
6ad92e5 * masked is now an instance of a new object, MaskedConstant
29001ed Add pre-nep for a copule of structured_array_extensions.
...

and 6ad92e5 is the last commit in the cool-feature branch. Suppose we want to make the following changes:

  • Rewrite the commit message for 13d7934 to something more sensible.
  • Combine the commits 2dec1ac, a815645, eadc391 into a single one.

We do as follows:

# make a backup of the current state
git branch tmp HEAD
# interactive rebase
git rebase -i 6ad92e5

This will open an editor with the following text in it:

pick 13d7934 First implementation
pick 2dec1ac Fix a few bugs + disable
pick a815645 Modify it so that it works
pick eadc391 Fix some remaining bugs

# Rebase 6ad92e5..eadc391 onto 6ad92e5
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

To achieve what we want, we will make the following changes to it:

r 13d7934 First implementation
pick 2dec1ac Fix a few bugs + disable
f a815645 Modify it so that it works
f eadc391 Fix some remaining bugs

This means that (i) we want to edit the commit message for 13d7934, and (ii) collapse the last three commits into one. Now we save and quit the editor.

Git will then immediately bring up an editor for editing the commit message. After revising it, we get the output:

[detached HEAD 721fc64] FOO: First implementation
 2 files changed, 199 insertions(+), 66 deletions(-)
[detached HEAD 0f22701] Fix a few bugs + disable
 1 files changed, 79 insertions(+), 61 deletions(-)
Successfully rebased and updated refs/heads/my-feature-branch.

and the history looks now like this:

0f22701 Fix a few bugs + disable
721fc64 ENH: Sophisticated feature
6ad92e5 * masked is now an instance of a new object, MaskedConstant

If it went wrong, recovery is again possible as explained above.

Maintainer workflow

This page is for maintainers — those of us who merge our own or other peoples’ changes into the upstream repository.

Being as how you’re a maintainer, you are completely on top of the basic stuff in Development workflow.

The instructions in Linking your repository to the upstream repo add a remote that has read-only access to the upstream repo. Being a maintainer, you’ve got read-write access.

It’s good to have your upstream remote have a scary name, to remind you that it’s a read-write remote:

git remote add upstream-rw git@github.com:networkx/networkx.git
git fetch upstream-rw
Integrating changes

Let’s say you have some changes that need to go into trunk (upstream-rw/master).

The changes are in some branch that you are currently on. For example, you are looking at someone’s changes like this:

git remote add someone git://github.com/someone/networkx.git
git fetch someone
git branch cool-feature --track someone/cool-feature
git checkout cool-feature

So now you are on the branch with the changes to be incorporated upstream. The rest of this section assumes you are on this branch.

A few commits

If there are only a few commits, consider rebasing to upstream:

# Fetch upstream changes
git fetch upstream-rw
# rebase
git rebase upstream-rw/master

Remember that, if you do a rebase, and push that, you’ll have to close any github pull requests manually, because github will not be able to detect the changes have already been merged.

A long series of commits

If there are a longer series of related commits, consider a merge instead:

git fetch upstream-rw
git merge --no-ff upstream-rw/master

The merge will be detected by github, and should close any related pull requests automatically.

Note the --no-ff above. This forces git to make a merge commit, rather than doing a fast-forward, so that these set of commits branch off trunk then rejoin the main history with a merge, rather than appearing to have been made directly on top of trunk.

Check the history

Now, in either case, you should check that the history is sensible and you have the right commits:

git log --oneline --graph
git log -p upstream-rw/master..

The first line above just shows the history in a compact way, with a text representation of the history graph. The second line shows the log of commits excluding those that can be reached from trunk (upstream-rw/master), and including those that can be reached from current HEAD (implied with the .. at the end). So, it shows the commits unique to this branch compared to trunk. The -p option shows the diff for these commits in patch form.

Push to trunk
git push upstream-rw my-new-feature:master

This pushes the my-new-feature branch in this repository to the master branch in the upstream-rw repository.

git resources

Tutorials and summaries

github help is Git’s own help and tutorial site. github more help lists more resources for learning Git and GitHub, including YouTube channels. The list is constantly updated. In case you are used to subversion , you can directly consult the git svn crash course.

To make full use of Git, you need to understand the concept behind Git.

The following pages might help you:

Other than that, many devlopers list their personal tips and tricks. Among others there are Fernando Perez, Nick Quaranto and Linus Torvalds.

Manual pages online

You can get these on your own machine with (e.g) git help push or (same thing) git push --help, but, for convenience, here are the online manual pages for some common commands:

History

Original Creators:

Aric Hagberg, hagberg@lanl.gov
Pieter Swart, swart@lanl.gov
Dan Schult, dschult@colgate.edu

API changes

Version 1.10 notes and API changes

This page includes more detailed release information and API changes from NetworkX 1.9 to NetworkX 1.10.

Please send comments and questions to the networkx-discuss mailing list: <http://groups.google.com/group/networkx-discuss>.

API changes
  • [#1501] connected_components, weakly_connected_components, and strongly_connected_components return now a generator of sets of nodes. Previously the generator was of lists of nodes. This PR also refactored the connected_components and weakly_connected_components implementations making them faster, especially for large graphs.
  • [#1547] The func_iter functions in Di/Multi/Graphs classes are slated for removal in NetworkX 2.0 release. func will behave like func_iter and return an iterator instead of list. These functions are deprecated in NetworkX 1.10 release.
New functionalities
  • [#823] A enumerate_all_cliques function is added in the clique package (networkx.algorithms.clique) for enumerating all cliques (including nonmaximal ones) of undirected graphs.
  • [#1105] A coloring package (networkx.algorithms.coloring) is created for graph coloring algorithms. Initially, a greedy_color function is provided for coloring graphs using various greedy heuristics.
  • [#1193] A new generator edge_dfs, added to networkx.algorithms.traversal, implements a depth-first traversal of the edges in a graph. This complements functionality provided by a depth-first traversal of the nodes in a graph. For multigraphs, it allows the user to know precisely which edges were followed in a traversal. All NetworkX graph types are supported. A traversal can also reverse edge orientations or ignore them.
  • [#1194] A find_cycle function is added to the networkx.algorithms.cycles package to find a cycle in a graph. Edge orientations can be optionally reversed or ignored.
  • [#1210] Add a random generator for the duplication-divergence model.
  • [#1241] A new networkx.algorithms.dominance package is added for dominance/dominator algorithms on directed graphs. It contains a immediate_dominators function for computing immediate dominators/dominator trees and a dominance_frontiers function for computing dominance frontiers.
  • [#1269] The GML reader/parser and writer/generator are rewritten to remove the dependence on pyparsing and enable handling of arbitrary graph data.
  • [#1280] The network simplex method in the networkx.algorithms.flow package is rewritten to improve its performance and support multi- and disconnected networks. For some cases, the new implementation is two or three orders of magnitude faster than the old implementation.
  • [#1286] Added the Margulis–Gabber–Galil graph to networkx.generators.
  • [#1306] Added the chordal p-cycle graph, a mildly explicit algebraic construction of a family of 3-regular expander graphs. Also, moves both the existing expander graph generator function (for the Margulis-Gabber-Galil expander) and the new chordal cycle graph function to a new module, networkx.generators.expanders.
  • [#1314] Allow overwriting of base class dict with dict-like: OrderedGraph, ThinGraph, LogGraph, etc.
  • [#1321] Added to_pandas_dataframe and from_pandas_dataframe.
  • [#1322] Added the Hopcroft–Karp algorithm for finding a maximum cardinality matching in bipartite graphs.
  • [#1336] Expanded data keyword in G.edges and added default keyword.
  • [#1338] Added support for finding optimum branchings and arborescences.
  • [#1340] Added a from_pandas_dataframe function that accepts Pandas DataFrames and returns a new graph object. At a minimum, the DataFrame must have two columns, which define the nodes that make up an edge. However, the function can also process an arbitrary number of additional columns as edge attributes, such as ‘weight’.
  • [#1354] Expanded layout functions to add flexibility for drawing subsets of nodes with distinct layouts and for centering each layout around given coordinates.
  • [#1356] Added ordered variants of default graph class.
  • [#1360] Added harmonic centrality to network.algorithms.centrality.
  • [#1390] The generators.bipartite have been moved to algorithms.bipartite.generators. The functions are not imported in the main namespace, so to use it, the bipartite package has to be imported.
  • [#1391] Added Kanevsky’s algorithm for finding all minimum-size separating node sets in an undirected graph. It is implemented as a generator of node cut sets.
  • [#1399] Added power function for simple graphs
  • [#1405] Added fast approximation for node connectivity based on White and Newman’s approximation algorithm for finding node independent paths between two nodes.
  • [#1413] Added transitive closure and antichains function for directed acyclic graphs in algorithms.dag. The antichains function was contributed by Peter Jipsen and Franco Saliola and originally developed for the SAGE project.
  • [#1425] Added generator function for the complete multipartite graph.
  • [#1427] Added nonisomorphic trees generator.
  • [#1436] Added a generator function for circulant graphs to the networkx.generators.classic module.
  • [#1437] Added function for computing quotient graphs; also created a new module, networkx.algorithms.minors.
  • [#1438] Added longest_path and longest_path_length for DAG.
  • [#1439] Added node and edge contraction functions to networkx.algorithms.minors.
  • [#1445] Added a new modularity matrix module to networkx.linalg, and associated spectrum functions to the networkx.linalg.spectrum module.
  • [#1447] Added function to generate all simple paths starting with the shortest ones based on Yen’s algorithm for finding k shortest paths at algorithms.simple_paths.
  • [#1455] Added the directed modularity matrix to the networkx.linalg.modularity_matrix module.
  • [#1474] Adds triadic_census function; also creates a new module, networkx.algorithms.triads.
  • [#1476] Adds functions for testing if a graph has weighted or negatively weighted edges. Also adds a function for testing if a graph is empty. These are is_weighted, is_negatively_weighted, and is_empty.
  • [#1481] Added Johnson’s algorithm; one more algorithm for shortest paths. It solves all pairs shortest path problem. This is johnson at algorithms.shortest_paths
  • [#1414] Added Moody and White algorithm for identifying k_components in a graph, which is based on Kanevsky’s algorithm for finding all minimum-size node cut-sets (implemented in all_node_cuts #1391).
  • [#1415] Added fast approximation for k_components to the networkx.approximation package. This is based on White and Newman approximation algorithm for finding node independent paths between two nodes (see #1405).
Removed functionalities
  • [#1236] The legacy ford_fulkerson maximum flow function is removed. Use edmonds_karp instead.
Miscellaneous changes
  • [#1192] Support for Python 2.6 is dropped.

Version 1.9 notes and API changes

This page reflects API changes from NetworkX 1.8 to NetworkX 1.9.

Please send comments and questions to the networkx-discuss mailing list: <http://groups.google.com/group/networkx-discuss>.

Flow package

The flow package (networkx.algorithms.flow) is completely rewritten with backward incompatible changes. It introduces a new interface to flow algorithms. Existing code that uses the flow package will not work unmodified with NetworkX 1.9.

Main changes
  1. We added two new maximum flow algorithms (preflow_push and shortest_augmenting_path) and rewrote the Edmonds–Karp algorithm in flow_fulkerson which is now in edmonds_karp. @ysitu contributed implementations of all new maximum flow algorithms. The legacy Edmonds–Karp algorithm implementation in ford_fulkerson is still available but will be removed in the next release.
  2. All maximum flow algorithm implementations (including the legacy ford_fulkerson) output now a residual network (i.e., a DiGraph) after computing the maximum flow. See maximum_flow documentation for the details on the conventions that NetworkX uses for defining a residual network.
  3. We removed the old max_flow and min_cut functions. The main entry points to flow algorithms are now the functions maximum_flow, maximum_flow_value, minimum_cut and minimum_cut_value, which have new parameters that control maximum flow computation: flow_func for specifying the algorithm that will do the actual computation (it accepts a function as argument that implements a maximum flow algorithm), cutoff for suggesting a maximum flow value at which the algorithm stops, value_only for stopping the computation as soon as we have the value of the flow, and residual that accepts as argument a residual network to be reused in repeated maximum flow computation.
  4. All flow algorithms are required to accept arguments for these parameters but may selectively ignored the inapplicable ones. For instance, preflow_push algorithm can stop after the preflow phase without computing a maximum flow if we only need the flow value, but both edmonds_karp and shortest_augmenting_path always compute a maximum flow to obtain the flow value.
  5. The new function minimum_cut returns the cut value and a node partition that defines the minimum cut. The function minimum_cut_value returns only the value of the cut, which is what the removed min_cut function used to return before 1.9.
  6. The functions that implement flow algorithms (i.e., preflow_push, edmonds_karp, shortest_augmenting_path and ford_fulkerson) are not imported to the base NetworkX namespace. You have to explicitly import them from the flow package:
>>> from networkx.algorithms.flow import (ford_fulkerson, preflow_push,
...        edmonds_karp, shortest_augmenting_path)
  1. We also added a capacity-scaling minimum cost flow algorithm: capacity_scaling. It supports MultiDiGraph and disconnected networks.
Examples

Below are some small examples illustrating how to obtain the same output than in NetworkX 1.8.1 using the new interface to flow algorithms introduced in 1.9:

>>> import networkx as nx
>>> G = nx.icosahedral_graph()
>>> nx.set_edge_attributes(G, 'capacity', 1)

With NetworkX 1.8:

>>> flow_value = nx.max_flow(G, 0, 6)
>>> cut_value = nx.min_cut(G, 0, 6)
>>> flow_value == cut_value
True
>>> flow_value, flow_dict = nx.ford_fulkerson(G, 0, 6)

With NetworkX 1.9:

>>> from networkx.algorithms.flow import (ford_fulkerson, preflow_push,
...        edmonds_karp, shortest_augmenting_path)
>>> flow_value = nx.maximum_flow_value(G, 0, 6)
>>> cut_value = nx.minimum_cut_value(G, 0, 6)
>>> flow_value == cut_value
True
>>> # Legacy: this returns the exact same output than ford_fulkerson in 1.8.1
>>> flow_value, flow_dict = nx.maximum_flow(G, 0, 6, flow_func=ford_fulkerson)
>>> # We strongly recommend to use the new algorithms:
>>> flow_value, flow_dict = nx.maximum_flow(G, 0, 6)
>>> # If no flow_func is passed as argument, the default flow_func
>>> # (preflow-push) is used. Therefore this is the same than:
>>> flow_value, flow_dict = nx.maximum_flow(G, 0, 6, flow_func=preflow_push)
>>> # You can also use alternative maximum flow algorithms:
>>> flow_value, flow_dict = nx.maximum_flow(G, 0, 6, flow_func=shortest_augmenting_path)
>>> flow_value, flow_dict = nx.maximum_flow(G, 0, 6, flow_func=edmonds_karp)
Connectivity package

The flow-based connecitivity and cut algorithms from the connectivity package (networkx.algorithms.connectivity) are adapted to take advantage of the new interface to flow algorithms. As a result, flow-based connectivity algorithms are up to 10x faster than in NetworkX 1.8 for some problems, such as sparse networks with highly skewed degree distributions. A few backwards incompatible changes were introduced.

  • The functions for local connectivity and cuts accept now arguments for the new parameters defined for the flow interface: flow_func for defining the algorithm that will perform the underlying maximum flow computations, residual that accepts as argument a residual network to be reused in repeated maximum flow computations, and cutoff for defining a maximum flow value at which the underlying maximum flow algorithm stops. The big speed improvement with respect to 1.8 comes mainly from the reuse of the residual network and the use of cutoff.
  • We removed the flow-based local connectivity and cut functions from the base namespace. Now they have to be explicitly imported from the connectivity package. The main entry point to flow-based connectivity and cut functions are the functions edge_connectivity, node_connectivity, minimum_edge_cut, and minimum_node_cut. All these functions accept a couple of nodes as optional arguments for computing local connectivity and cuts.
  • We improved the auxiliary network for connectivity functions: The node mapping dict needed for node connectivity and minimum node cuts is now a graph attribute of the auxiliary network. Thus we removed the mapping parameter from the local versions of connectivity and cut functions. We also changed the parameter name for the auxuliary digraph from aux_digraph to auxiliary.
  • We changed the name of the function all_pairs_node_connectiviy_matrix to all_pairs_node_connectivity. This function now returns a dictionary instead of a NumPy 2D array. We added a new parameter nbunch for computing node connectivity only among pairs of nodes in nbunch.
  • A stoer_wagner function is added to the connectivity package for computing the weighted minimum cuts of undirected graphs using the Stoer–Wagner algorithm. This algorithm is not based on maximum flows. Several heap implementations are also added in the utility package (networkx.utils) for use in this function. BinaryHeap is recommeded over PairingHeap for Python implementations without optimized attribute accesses (e.g., CPython) despite a slower asymptotic running time. For Python implementations with optimized attribute accesses (e.g., PyPy), PairingHeap provides better performance.
Other new functionalities
  • A disperson function is added in the centrality package (networkx.algorithms.centrality) for computing the dispersion of graphs.
  • A community package (networkx.generators.community) is added for generating community graphs.
  • An is_semiconnected function is added in the connectivity package (networkx.algorithms.connectivity) for recognizing semiconnected graphs.
  • The eulerian_circuit function in the Euler package (networkx.algorithm.euler) is changed to use a linear-time algorithm.
  • A non_edges function in added in the function package (networkx.functions) for enumerating nonexistent edges between existing nodes of graphs.
  • The linear algebra package (networkx.linalg) is changed to use SciPy sparse matrices.
  • Functions algebraic_connectivity, fiedler_vector and spectral_ordering are added in the linear algebra package (networkx.linalg) for computing the algebraic connectivity, Fiedler vectors and spectral orderings of undirected graphs.
  • A link prediction package (networkx.algorithms.link_prediction) is added to provide link prediction-related functionalities.
  • Write Support for the graph6 and sparse6 formats is added in the read/write package (networx.readwrite).
  • A goldberg_radzik function is added in the shortest path package (networkx.algorithms.shortest_paths) for computing shortest paths using the Goldberg–Radzik algorithm.
  • A tree package (networkx.tree) is added to provide tree recognition functionalities.
  • A context manager reversed is added in the utility package (networkx.utils) for temporary in-place reversal of graphs.
Miscellaneous changes
  • The functions in the components package (networkx.algorithms.components) such as connected_components, connected_components_subgraph now return generators instead of lists. To recover the earlier behavior, use list(connected_components(G)).
  • JSON helpers in the JSON graph package (networkx.readwrite.json_graph) are removed. Use functions from the standard library (e.g., json.dumps) instead.
  • Support for Python 3.1 is dropped. Basic support is added for Jython 2.7 and IronPython 2.7, although they remain not officially supported.
  • Numerous reported issues are fixed.

Version 1.8 notes and API changes

This page reflects API changes from networkx-1.7 to networkx-1.8.

Please send comments and questions to the networkx-discuss mailing list: http://groups.google.com/group/networkx-discuss .

  • Laplacian functions now all return matrices. To get a numpy array from a matrix use L = nx.laplacian_matrix(G).A
  • is_directed_acyclic_graph() now returns false on undirected graphs (instead of raising exception)
  • cycles returned from simple_cycles() do not include repeated last node

Version 1.7 notes and API changes

This page reflects API changes from networkx-1.6 to networkx-1.7.

Please send comments and questions to the networkx-discuss mailing list: http://groups.google.com/group/networkx-discuss .

Other
  • Untested bipartite_random_regular_graph() removed.

Version 1.6 notes and API changes

This page reflects API changes from networkx-1.5 to networkx-1.6.

Please send comments and questions to the networkx-discuss mailing list: http://groups.google.com/group/networkx-discuss .

Graph Classes

The degree* methods in the graph classes (Graph, DiGraph, MultiGraph, MultiDiGraph) now take an optional weight= keyword that allows computing weighted degree with arbitrary (numerical) edge attributes. Setting weight=None is equivalent to the previous weighted=False.

Weighted graph algorithms

Many ‘weighted’ graph algorithms now take optional parameter to specifiy which edge attribute should be used for the weight (default=’weight’) (:ticket:`573`)

In some cases the parameter name was changed from weighted, to weight. Here is how to specify which edge attribute will be used in the algorithms:

  • Use weight=None to consider all weights equally (unweighted case)
  • Use weight=’weight’ to use the ‘weight’ edge atribute
  • Use weight=’other’ to use the ‘other’ edge attribute

Algorithms affected are:

to_scipy_sparse_matrix, clustering, average_clustering, bipartite.degree, spectral_layout, neighbor_degree, is_isomorphic, betweenness_centrality, betweenness_centrality_subset, vitality, load_centrality, mincost, shortest_path, shortest_path_length, average_shortest_path_length

Isomorphisms

Node and edge attributes are now more easily incorporated into isomorphism checks via the ‘node_match’ and ‘edge_match’ parameters. As part of this change, the following classes were removed:

WeightedGraphMatcher
WeightedDiGraphMatcher
WeightedMultiGraphMatcher
WeightedMultiDiGraphMatcher

The function signature for ‘is_isomorphic’ is now simply:

is_isomorphic(g1, g2, node_match=None, edge_match=None)

See its docstring for more details. To aid in the creation of ‘node_match’ and ‘edge_match’ functions, users are encouraged to work with:

categorical_node_match
categorical_edge_match
categroical_multiedge_match
numerical_node_match
numerical_edge_match
numerical_multiedge_match
generic_node_match
generic_edge_match
generic_multiedge_match

These functions construct functions which can be passed to ‘is_isomorphic’. Finally, note that the above functions are not imported into the top-level namespace and should be accessed from ‘networkx.algorithms.isomorphism’. A useful import statement that will be repeated throughout documentation is:

import networkx.algorithms.isomorphism as iso
Other
  • attracting_components

    A list of lists is returned instead of a list of tuples.

  • condensation

    The condensation algorithm now takes a second argument (scc) and returns a graph with nodes labeled as integers instead of node tuples.

  • degree connectivity

    average_in_degree_connectivity and average_out_degree_connectivity have have been replaced with

    average_degree_connectivity(G, source=’in’, target=’in’)

    and

    average_degree_connectivity(G, source=’out’, target=’out’)

  • neighbor degree

    average_neighbor_in_degree and average_neighbor_out_degreey have have been replaced with

    average_neighbor_degree(G, source=’in’, target=’in’)

    and

    average_neighbor_degree(G, source=’out’, target=’out’)

Version 1.5 notes and API changes

This page reflects API changes from networkx-1.4 to networkx-1.5.

Please send comments and questions to the networkx-discuss mailing list: http://groups.google.com/group/networkx-discuss .

Weighted graph algorithms

Many ‘weighted’ graph algorithms now take optional parameter to specifiy which edge attribute should be used for the weight (default=’weight’) (:ticket:`509`)

In some cases the parameter name was changed from weighted_edges, or weighted, to weight. Here is how to specify which edge attribute will be used in the algorithms:

  • Use weight=None to consider all weights equally (unweighted case)
  • Use weight=True or weight=’weight’ to use the ‘weight’ edge atribute
  • Use weight=’other’ to use the ‘other’ edge attribute

Algorithms affected are:

betweenness_centrality, closeness_centrality, edge_bewteeness_centrality, betweeness_centrality_subset, edge_betweenness_centrality_subset, betweenness_centrality_source, load, closness_vitality, weiner_index, spectral_bipartivity current_flow_betweenness_centrality, edge_current_flow_betweenness_centrality, current_flow_betweenness_centrality_subset, edge_current_flow_betweenness_centrality_subset, laplacian, normalized_laplacian, adj_matrix, adjacency_spectrum, shortest_path, shortest_path_length, average_shortest_path_length, single_source_dijkstra_path_basic, astar_path, astar_path_length

Random geometric graph

The random geometric graph generator has been simplified. It no longer supports the create_using, repel, or verbose parameters. An optional pos keyword was added to allow specification of node positions.

Version 1.4 notes and API changes

We have made some API changes, detailed below, to add clarity. This page reflects changes from networkx-1.3 to networkx-1.4. For changes from earlier versions to networkx-1.0 see Version 1.0 API changes.

Please send comments and questions to the networkx-discuss mailing list: http://groups.google.com/group/networkx-discuss .

Algorithms changed
Shortest path
astar_path(), astar_path_length(), shortest_path(), shortest_path_length(),
bidirectional_shortest_path(), dijkstra_path(), dijkstra_path_length(),
bidirectional_dijkstra()
These algorithms now raise an exception when a source and a target are specified and no path exist between these two nodes. The exception is a NetworkXNoPath exception.

Version 1.0 notes and API changes

We have made some significant API changes, detailed below, to add functionality and clarity. This page reflects changes from networkx-0.99 to networkx-1.0. For changes from earlier versions to networkx-0.99 see Version 0.99 API changes.

Version 1.0 requires Python 2.4 or greater.

Please send comments and questions to the networkx-discuss mailing list: http://groups.google.com/group/networkx-discuss .

Version numbering

In the future we will use a more standard release numbering system with major.minor[build] labels where major and minor are numbers and [build] is a label such as “dev1379” to indicate a development version or “rc1” to indicate a release candidate.

We plan on sticking closer to a time-based release schedule with smaller incremental changes released on a roughly quarterly basis. The graph classes API will remain fixed, unless we determine there are serious bugs or other defects in the existing classes, until networkx-2.0 is released at some time in the future.

Changes in base classes

The most significant changes in are in the graph classes. All of the graph classes now allow optional graph, node, and edge attributes. Those attributes are stored internally in the graph classes as dictionaries and can be accessed simply like Python dictionaries in most cases.

Graph attributes

Each graph keeps a dictionary of key=value attributes in the member G.graph. These attributes can be accessed directly using G.graph or added at instantiation using keyword arguments.

>>> G=nx.Graph(region='Africa')
>>> G.graph['color']='green'
>>> G.graph
{'color': 'green', 'region': 'Africa'}
Node attributes

Each node has a corresponding dictionary of attributes. Adding attributes to nodes is optional.

Add node attributes using add_node(), add_nodes_from() or G.node

>>> G.add_node(1, time='5pm')
>>> G.add_nodes_from([3], time='2pm')
>>> G.node[1]
{'time': '5pm'}
>>> G.node[1]['room'] = 714
>>> G.nodes(data=True)
[(1, {'room': 714, 'time': '5pm'}), (3, {'time': '2pm'})]
Edge attributes

Each edge has a corresponding dictionary of attributes. The default edge data is now an empty dictionary of attributes and adding attributes to edges is optional.

A common use case is to add a weight attribute to an edge:

>>> G.add_edge(1,2,weight=3.14159)

Add edge attributes using add_edge(), add_edges_from(), subscript notation, or G.edge.

>>> G.add_edge(1, 2, weight=4.7 )
>>> G.add_edges_from([(3,4),(4,5)], color='red')
>>> G.add_edges_from([(1,2,{'color':'blue'}), (2,3,{'weight':8})])
>>> G[1][2]['weight'] = 4.7
>>> G.edge[1][2]['weight'] = 4
Methods changed
Graph(), DiGraph(), MultiGraph(), MultiDiGraph()

Now takes optional keyword=value attributes on initialization.

>>> G=nx.Graph(year='2009',city='New York')
add_node()

Now takes optional keyword=value attributes or a dictionary of attributes.

>>> G.add_node(1,room=714)
add_nodes_from()

Now takes optional keyword=value attributes or a dictionary of attributes applied to all affected nodes.

>>> G.add_nodes_from([1,2],time='2pm')  # all nodes have same attribute
add_edge()

Now takes optional keyword=value attributes or a dictionary of attributes.

>>> G.add_edge(1, 2, weight=4.7 )
add_edges_from()

Now takes optional keyword=value attributes or a dictionary of attributes applied to all affected edges.

>>> G.add_edges_from([(3,4),(4,5)], color='red')
>>> G.add_edges_from([(1,2,{'color':'blue'}), (2,3,{'weight':8})])
nodes() and nodes_iter()

New keyword data=True|False keyword determines whether to return two-tuples (n,dict) (True) with node attribution dictionary

>>> G=nx.Graph([(1,2),(3,4)])
>>> G.nodes(data=True)
[(1, {}), (2, {}), (3, {}), (4, {})]
copy()

Now returns a deep copy of the graph (copies all underlying data and attributes for nodes and edges). Use the class initializer to make a shallow copy:

>>> G=nx.Graph()
>>> G_shallow=nx.Graph(G) # shallow copy
>>> G_deep=G.copy() # deep copy
to_directed(), to_undirected()

Now returns a deep copy of the graph (copies all underlying data and attributes for nodes and edges). Use the class initializer to make a shallow copy:

>>> G=nx.Graph()
>>> D_shallow=nx.DiGraph(G) # shallow copy
>>> D_deep=G.to_directed() # deep copy
subgraph()

With copy=True now returns a deep copy of the graph (copies all underlying data and attributes for nodes and edges).

>>> G=nx.Graph()
>>> # note: copy keyword deprecated in networkx>1.0
>>> # H=G.subgraph([],copy=True) # deep copy of all data
add_cycle(), add_path(), add_star()

Now take optional keyword=value attributes or a dictionary of attributes which are applied to all edges affected by the method.

>>> G=nx.Graph()
>>> G.add_path([0,1,2,3],width=3.2)
Methods removed
delete_node()
The preferred name is now remove_node().
delete_nodes_from()
No longer raises an exception on an attempt to delete a node not in the graph. The preferred name is now remove_nodes_from().
delete_edge()
Now raises an exception on an attempt to delete an edge not in the graph. The preferred name is now remove_edge().
delete_edges_from()
The preferred name is now remove_edges_from().

has_neighbor():

Use has_edge()
get_edge()

Renamed to get_edge_data(). Returns the edge attribute dictionary.

The fastest way to get edge data for edge (u,v) is to use G[u][v] instead of G.get_edge_data(u,v)

Members removed
directed, multigraph, weighted
Use methods G.is_directed() and G.is_multigraph(). All graphs are weighted graphs now if they have numeric values in the ‘weight’ edge attribute.
Methods added
add_weighted edges_from()
Convenience method to add weighted edges to graph using a list of 3-tuples (u,v,weight).
get_edge_data()

Renamed from get_edge().

The fastest way to get edge data for edge (u,v) is to use G[u][v] instead of G.get_edge_data(u,v)

is_directed()
replaces member G.directed
is_multigraph()
replaces member G.multigraph
Classes Removed
LabeledGraph, LabeledDiGraph
These classes have been folded into the regular classes.
UbiGraph
Removed as the ubigraph platform is no longer being supported.
Additional functions/generators

ego_graph, stochastic_graph, PageRank algorithm, HITS algorithm, GraphML writer, freeze, is_frozen, A* algorithm, directed scale-free generator, random clustered graph.

Converting your existing code to networkx-1.0
Weighted edges

Edge information is now stored in an attribution dictionary so all edge data must be given a key to identify it.

There is currently only one standard/reserved key, ‘weight’, which is used by algorithms and functions that use weighted edges. The associated value should be numeric. All other keys are available for users to assign as needed.

>>> G=nx.Graph()
>>> G.add_edge(1,2,weight=3.1415) # add the edge 1-2 with a weight
>>> G[1][2]['weight']=2.3 # set the weight to 2.3

Similarly, for direct access the edge data, use the key of the edge data to retrieve it.

>>> w = G[1][2]['weight']

All NetworkX algorithms that require/use weighted edges now use the ‘weight’ edge attribute. If you have existing algorithms that assumed the edge data was numeric, you should replace G[u][v] and G.get_edge(u,v) with G[u][v][‘weight’].

An idiom for getting a weight for graphs with or without an assigned weight key is

>>> w= G[1][2].get('weight',1)  # set w to 1 if there is no 'weight' key

Version 0.99 API changes

The version networkx-0.99 is the penultimate release before networkx-1.0. We have bumped the version from 0.37 to 0.99 to indicate (in our unusual version number scheme) that this is a major change to NetworkX.

We have made some significant changes, detailed below, to NetworkX to improve performance, functionality, and clarity.

Version 0.99 requires Python 2.4 or greater.

Please send comments and questions to the networkx-discuss mailing list. http://groups.google.com/group/networkx-discuss

Changes in base classes

The most significant changes are in the graph classes. We have redesigned the Graph() and DiGraph() classes to optionally allow edge data. This change allows Graph and DiGraph to naturally represent weighted graphs and to hold arbitrary information on edges.

  • Both Graph and DiGraph take an optional argument weighted=True|False. When weighted=True the graph is assumed to have numeric edge data (with default 1). The Graph and DiGraph classes in earlier versions used the Python None as data (which is still allowed as edge data).
  • The Graph and DiGraph classes now allow self loops.
  • The XGraph and XDiGraph classes are removed and replaced with MultiGraph and MultiDiGraph. MultiGraph and MultiDiGraph optionally allow parallel (multiple) edges between two nodes.

The mapping from old to new classes is as follows:

- Graph -> Graph (self loops allowed now, default edge data is 1)
- DiGraph -> DiGraph (self loops allowed now, default edge data is 1)
- XGraph(multiedges=False) -> Graph
- XGraph(multiedges=True) -> MultiGraph
- XDiGraph(multiedges=False) -> DiGraph
- XDiGraph(multiedges=True) -> MultiDiGraph
Methods changed
edges()
New keyword data=True|False keyword determines whether to return two-tuples (u,v) (False) or three-tuples (u,v,d) (True)
delete_node()
The preferred name is now remove_node().
delete_nodes_from()
No longer raises an exception on an attempt to delete a node not in the graph. The preferred name is now remove_nodes_from().
delete_edge()
Now raises an exception on an attempt to delete an edge not in the graph. The preferred name is now remove_edge().
delete_edges_from()
The preferred name is now remove_edges_from().
add_edge()

The add_edge() method no longer accepts an edge tuple (u,v) directly. The tuple must be unpacked into individual nodes.

>>> import networkx as nx
>>> u='a'
>>> v='b'
>>> e=(u,v)
>>> G=nx.Graph()

Old

>>> # G.add_edge((u,v))  # or G.add_edge(e)

New

>>> G.add_edge(*e) # or G.add_edge(*(u,v))

The * operator unpacks the edge tuple in the argument list.

Add edge now has a data keyword parameter for setting the default (data=1) edge data.

>>> # G.add_edge('a','b','foo')  # add edge with string "foo" as data
>>> # G.add_edge(1,2,5.0)  # add edge with float 5 as data
add_edges_from()

Now can take list or iterator of either 2-tuples (u,v), 3-tuples (u,v,data) or a mix of both.

Now has data keyword parameter (default 1) for setting the edge data for any edge in the edge list that is a 2-tuple.

has_edge()

The has_edge() method no longer accepts an edge tuple (u,v) directly. The tuple must be unpacked into individual nodes.

Old:

>>> # G.has_edge((u,v))  # or has_edge(e)

New:

>>> G.has_edge(*e) # or has_edge(*(u,v))
True

The * operator unpacks the edge tuple in the argument list.

get_edge()

Now has the keyword argument “default” to specify what value to return if no edge is found. If not specified an exception is raised if no edge is found.

The fastest way to get edge data for edge (u,v) is to use G[u][v] instead of G.get_edge(u,v)

degree_iter()
The degree_iter method now returns an iterator over pairs of (node, degree). This was the previous behavior of degree_iter(with_labels=true) Also there is a new keyword weighted=False|True for weighted degree.
subgraph()

The argument inplace=False|True has been replaced with copy=True|False.

Subgraph no longer takes create_using keyword. To change the graph type either make a copy of the graph first and then change type or change type and make a subgraph. E.g.

>>> G=nx.path_graph(5)
>>> H=nx.DiGraph(G.subgraph([0,1])) # digraph of copy of induced subgraph
__getitem__()

Getting node neighbors from the graph with G[v] now returns a dictionary.

>>> G=nx.path_graph(5)
>>> # G[0]
#  {1: 1}

To get a list of neighbors you can either use the keys of that dictionary or use

>>> G.neighbors(0)
[1]

This change allows algorithms to use the underlying dict-of-dict representation through G[v] for substantial performance gains. Warning: The returned dictionary should not be modified as it may corrupt the graph data structure. Make a copy G[v].copy() if you wish to modify the dict.

Methods removed
info()

now a function

>>> G=nx.Graph(name='test me')
>>> nx.info(G)
Name:                  test me
Type:                  Graph
Number of nodes:       0
Number of edges:       0
node_boundary()
now a function
edge_boundary()
now a function
is_directed()

use the directed attribute

>>> G=nx.DiGraph()
>>> # G.directed
#  True
G.out_edges()
use G.edges()
G.in_edges()

use

>>> G=nx.DiGraph()
>>> R=G.reverse()
>>> R.edges()
[]

or

>>> [(v,u) for (u,v) in G.edges()]
[]
Methods added
adjacency_list()

Returns a list-of-lists adjacency list representation of the graph.

adjacency_iter()

Returns an iterator of (node, adjacency_dict[node]) over all nodes in the graph. Intended for fast access to the internal data structure for use in internal algorithms.

Other possible incompatibilities with existing code
Imports

Some of the code modules were moved into subdirectories.

Import statements such as:

import networkx.centrality
from networkx.centrality import *

may no longer work (including that example).

Use either

>>> import networkx # e.g. centrality functions available as networkx.fcn()

or

>>> from networkx import * # e.g. centrality functions available as fcn()
Self-loops

For Graph and DiGraph self loops are now allowed. This might affect code or algorithms that add self loops which were intended to be ignored.

Use the methods

  • nodes_with_selfloops()
  • selfloop_edges()
  • number_of_selfloops()

to discover any self loops.

Copy

Copies of NetworkX graphs including using the copy() method now return complete copies of the graph. This means that all connection information is copied–subsequent changes in the copy do not change the old graph. But node keys and edge data in the original and copy graphs are pointers to the same data.

prepare_nbunch

Used internally - now called nbunch_iter and returns an iterator.

Converting your old code to Version 0.99

Mostly you can just run the code and python will raise an exception for features that changed. Common places for changes are

  • Converting XGraph() to either Graph or MultiGraph
  • Converting XGraph.edges() to Graph.edges(data=True)
  • Switching some rarely used methods to attributes (e.g. directed) or to functions (e.g. node_boundary)
  • If you relied on the old default edge data being None, you will have to account for it now being 1.

You may also want to look through your code for places which could improve speed or readability. The iterators are helpful with large graphs and getting edge data via G[u][v] is quite fast. You may also want to change G.neighbors(n) to G[n] which returns the dict keyed by neighbor nodes to the edge data. It is faster for many purposes but does not work well when you are changing the graph.

Release Log

NetworkX 2.0

Release date: TBD

Support for Python 2.6 is dropped in this release.

NetworkX 1.9.1

Release date: 13 September 2014

Bugfix release for minor installation and documentation issues.

https://github.com/networkx/networkx/milestones/networkx-1.9.1

NetworkX 1.9

Release date: 21 June 2014

Support for Python 3.1 is dropped in this release.

Highlights
  • Completely rewritten maximum flow and flow-based connectivity algorithms with backwards incompatible interfaces
  • Community graph generators
  • Stoer–Wagner minimum cut algorithm
  • Linear-time Eulerian circuit algorithm
  • Linear algebra package changed to use SciPy sparse matrices
  • Algebraic connectivity, Fiedler vector, spectral ordering algorithms
  • Link prediction algorithms
  • Goldberg–Radzik shortest path algorithm
  • Semiconnected graph and tree recognition algorithms

NetworkX 1.8.1

Release date: 4 August 2013

Bugfix release for missing files in source packaging.

NetworkX 1.8

Release date: 28 July 2013

Highlights
  • Faster (linear-time) graphicality tests and Havel-Hakimi graph generators
  • Directed Laplacian matrix generator
  • Katz centrality algorithm
  • Functions to generate all simple paths
  • Improved shapefile reader
  • More flexible weighted projection of bipartite graphs
  • Faster topological sort, decendents and ancestors of DAGs
  • Scaling parameter for force-directed layout
Bug fixes
  • Error with average weighted connectivity for digraphs, correct normalized laplacian with self-loops, load betweenness for single node graphs, isolated nodes missing from dfs/bfs trees, normalize HITS using l1, handle density of graphs with self loops
  • Cleaner handling of current figure status with Matplotlib, Pajek files now don’t write troublesome header line, default alpha value for GEXF files, read curved edges from yEd GraphML

For full details of the issues closed for this release (added features and bug fixes) see: https://github.com/networkx/networkx/issues?milestone=1&page=1&state=closed

NetworkX 1.7

Release date: 4 July 2012

Highlights
  • New functions for k-clique community finding, flow hierarchy, union, disjoint union, compose, and intersection operators that work on lists of graphs, and creating the biadjacency matrix of a bipartite graph.
  • New approximation algorithms for dominating set, edge dominating set, independent set, max clique, and min-weighted vertex cover.
  • Many bug fixes and other improvements.

For full details of the tickets closed for this release (added features and bug fixes) see: https://networkx.lanl.gov/trac/query?status=closed&group=milestone&milestone=networkx-1.7

NetworkX 1.6

Release date: 20 November 2011

Highlights

New functions for finding articulation points, generating random bipartite graphs, constructing adjacency matrix representations, forming graph products, computing assortativity coefficients, measuring subgraph centrality and communicability, finding k-clique communities, and writing JSON format output.

New examples for drawing with D3 Javascript library, and ordering matrices with the Cuthill-McKee algorithm.

More memory efficient implementation of current-flow betweenness and new approximation algorithms for current-flow betweenness and shortest-path betweenness.

Simplified handling of “weight” attributes for algorithms that use weights/costs/values. See Version 1.6 notes and API changes.

Updated all code to work with the PyPy Python implementation http://pypy.org which produces faster performance on many algorithms.

For full details of the tickets closed for this release (added features and bug fixes) see: https://networkx.lanl.gov/trac/query?status=closed&group=milestone&milestone=networkx-1.6

NetworkX 1.5

Release date: 4 June 2011

For full details of the tickets closed for this release see: https://networkx.lanl.gov/trac/query?status=closed&group=milestone&milestone=networkx-1.5

Highlights
New features
Bug fixes

NetworkX 1.3

Release date: 28 August 2010

See: https://networkx.lanl.gov/trac/timeline

New features

NetworkX 1.2

Release date: 28 July 2010

See: https://networkx.lanl.gov/trac/timeline

New features

NetworkX 1.1

Release date: 21 April 2010

See: https://networkx.lanl.gov/trac/timeline

New features
API changes
Returning dictionaries

Several of the algorithms and the degree() method now return dictionaries keyed by node instead of lists. In some cases there was a with_labels keyword which is no longer necessary. For example,

>>> G=nx.Graph()
>>> G.add_edge('a','b')
>>> G.degree() # returns dictionary of degree keyed by node
{'a': 1, 'b': 1}

Asking for the degree of a single node still returns a single number

>>> G.degree('a')
1

The following now return dictionaries by default (instead of lists) and the with_labels keyword has been removed:

The following now return dictionaries by default (instead of lists)

  • pagerank()
  • hits()
Adding nodes

add_nodes_from now accepts (node,attrdict) two-tuples

>>> G=nx.Graph()
>>> G.add_nodes_from([(1,{'color':'red'})])
Bug fixes
  • Support graph attributes with union, intersection, and other graph operations
  • Improve subgraph speed (and related algorithms such as connected_components_subgraphs())
  • Handle multigraphs in more operators (e.g. union)
  • Handle double-quoted labels with pydot
  • Normalize betweenness_centrality for undirected graphs correctly
  • Normalize eigenvector_centrality by l2 norm
  • read_gml() now returns multigraphs

NetworkX 1.0.1

Release date: 11 Jan 2010

See: https://networkx.lanl.gov/trac/timeline

Bug fix release for missing setup.py in manifest.

NetworkX 1.0

Release date: 8 Jan 2010

See: https://networkx.lanl.gov/trac/timeline

New features

This release has significant changes to parts of the graph API to allow graph, node, and edge attributes. See http://networkx.lanl.gov//reference/api_changes.html

  • Update Graph, DiGraph, and MultiGraph classes to allow attributes.
  • Default edge data is now an empty dictionary (was the integer 1)
  • Difference and intersection operators
  • Average shortest path
  • A* (A-Star) algorithm
  • PageRank, HITS, and eigenvector centrality
  • Read Pajek files
  • Line graphs
  • Minimum spanning tree (Kruskal’s algorithm)
  • Dense and sparse Fruchterman-Reingold layout
  • Random clustered graph generator
  • Directed scale-free graph generator
  • Faster random regular graph generator
  • Improved edge color and label drawing with Matplotlib
  • and much more, see https://networkx.lanl.gov/trac/query?status=closed&group=milestone&milestone=networkx-1.0
Examples
  • Update to work with networkx-1.0 API
  • Graph subclass example

NetworkX 0.99

Release date: 18 November 2008

See: https://networkx.lanl.gov/trac/timeline

New features

This release has significant changes to parts of the graph API. See http://networkx.lanl.gov//reference/api_changes.html

  • Update Graph and DiGraph classes to use weighted graphs as default Change in API for performance and code simplicity.
  • New MultiGraph and MultiDiGraph classes (replace XGraph and XDiGraph)
  • Update to use Sphinx documentation system http://networkx.lanl.gov/
  • Developer site at https://networkx.lanl.gov/trac/
  • Experimental LabeledGraph and LabeledDiGraph
  • Moved package and file layout to subdirectories.
Bug fixes
  • handle root= option to draw_graphviz correctly
Examples
  • Update to work with networkx-0.99 API
  • Drawing examples now use matplotlib.pyplot interface
  • Improved drawings in many examples
  • New examples - see http://networkx.lanl.gov/examples/

NetworkX 0.37

Release date: 17 August 2008

See: https://networkx.lanl.gov/trac/timeline

NetworkX now requires Python 2.4 or later for full functionality.

New features
  • Edge coloring and node line widths with Matplotlib drawings
  • Update pydot functions to work with pydot-1.0.2
  • Maximum-weight matching algorithm
  • Ubigraph interface for 3D OpenGL layout and drawing
  • Pajek graph file format reader and writer
  • p2g graph file format reader and writer
  • Secondary sort in topological sort
Bug fixes
  • Better edge data handling with GML writer
  • Edge betweenness fix for XGraph with default data of None
  • Handle Matplotlib version strings (allow “pre”)
  • Interface to PyGraphviz (to_agraph()) now handles parallel edges
  • Fix bug in copy from XGraph to XGraph with multiedges
  • Use SciPy sparse lil matrix format instead of coo format
  • Clear up ambiguous cases for Barabasi-Albert model
  • Better care of color maps with Matplotlib when drawing colored nodes and edges
  • Fix error handling in layout.py
Examples
  • Ubigraph examples showing 3D drawing

NetworkX 0.36

Release date: 13 January 2008

See: https://networkx.lanl.gov/trac/timeline

New features
  • GML format graph reader, tests, and example (football.py)
  • edge_betweenness() and load_betweenness()
Bug fixes
  • remove obsolete parts of pygraphviz interface
  • improve handling of Matplotlib version strings
  • write_dot() now writes parallel edges and self loops
  • is_bipartite() and bipartite_color() fixes
  • configuration model speedup using random.shuffle()
  • convert with specified nodelist now works correctly
  • vf2 isomorphism checker updates

NetworkX 0.35.1

Release date: 27 July 2007

See: https://networkx.lanl.gov/trac/timeline

Small update to fix import readwrite problem and maintain Python2.3 compatibility.

NetworkX 0.35

Release date: 22 July 2007

See: https://networkx.lanl.gov/trac/timeline

New features
  • algorithms for strongly connected components.
  • Brandes betweenness centrality algorithm (weighted and unweighted versions)
  • closeness centrality for weighted graphs
  • dfs_preorder, dfs_postorder, dfs_tree, dfs_successor, dfs_predecessor
  • readers for GraphML, LEDA, sparse6, and graph6 formats.
  • allow arguments in graphviz_layout to be passed directly to graphviz
Bug fixes
  • more detailed installation instructions
  • replaced dfs_preorder,dfs_postorder (see search.py)
  • allow initial node positions in spectral_layout
  • report no error on attempting to draw empty graph
  • report errors correctly when using tuples as nodes #114
  • handle conversions from incomplete dict-of-dict data

NetworkX 0.34

Release date: 12 April 2007

See: https://networkx.lanl.gov/trac/timeline

New features
  • benchmarks for graph classes
  • Brandes betweenness centrality algorithm
  • Dijkstra predecessor and distance algorithm
  • xslt to convert DIA graphs to NetworkX
  • number_of_edges(u,v) counts edges between nodes u and v
  • run tests with python setup_egg.py test (needs setuptools) else use python -c “import networkx; networkx.test()”
  • is_isomorphic() that uses vf2 algorithm
Bug fixes
  • speedups of neighbors()
  • simplified Dijkstra’s algorithm code
  • better exception handling for shortest paths
  • get_edge(u,v) returns None (instead of exception) if no edge u-v
  • floyd_warshall_array fixes for negative weights
  • bad G467, docs, and unittest fixes for graph atlas
  • don’t put nans in numpy or scipy sparse adjacency matrix
  • handle get_edge() exception (return None if no edge)
  • remove extra kwds arguments in many places
  • no multi counting edges in conversion to dict of lists for multigraphs
  • allow passing tuple to get_edge()
  • bad parameter order in node/edge betweenness
  • edge betweenness doesn’t fail with XGraph
  • don’t throw exceptions for nodes not in graph (silently ignore instead) in edges_* and degree_*

NetworkX 0.33

Release date: 27 November 2006

See: https://networkx.lanl.gov/trac/timeline

New features
  • draw edges with specified colormap

  • more efficient version of Floyd’s algorithm for all pairs shortest path

  • use numpy only, Numeric is deprecated

  • include tests in source package (networkx/tests)

  • include documentation in source package (doc)

  • tests can now be run with
    >>> import networkx
    >>> networkx.test()
    
Bug fixes
  • read_gpickle now works correctly with Windows
  • refactored large modules into smaller code files
  • degree(nbunch) now returns degrees in same order as nbunch
  • degree() now works for multiedges=True
  • update node_boundary and edge_boundary for efficiency
  • edited documentation for graph classes, now mostly in info.py
Examples
  • Draw edges with colormap

NetworkX 0.32

Release date: 29 September 2006

See: https://networkx.lanl.gov/trac/timeline

New features
  • Update to work with numpy-1.0x
  • Make egg usage optional: use python setup_egg.py bdist_egg to build egg
  • Generators and functions for bipartite graphs
  • Experimental classes for trees and forests
  • Support for new pygraphviz update (in nx_agraph.py) , see http://networkx.lanl.gov/pygraphviz/ for pygraphviz details
Bug fixes
  • Handle special cases correctly in triangles function
  • Typos in documentation
  • Handle special cases in shortest_path and shortest_path_length, allow cutoff parameter for maximum depth to search
  • Update examples: erdos_renyi.py, miles.py, roget,py, eigenvalues.py
Examples
  • Expected degree sequence
  • New pygraphviz interface

NetworkX 0.31

Release date: 20 July 2006

See: https://networkx.lanl.gov/trac/timeline

New features
  • arbitrary node relabeling (use relabel_nodes)
  • conversion of NetworkX graphs to/from Python dict/list types, numpy matrix or array types, and scipy_sparse_matrix types
  • generator for random graphs with given expected degree sequence
Bug fixes
  • Allow drawing graphs with no edges using pylab
  • Use faster heapq in dijkstra
  • Don’t complain if X windows is not available
Examples
  • update drawing examples

NetworkX 0.30

Release date: 23 June 2006

See: https://networkx.lanl.gov/trac/timeline

New features
  • update to work with Python 2.5
  • bidirectional version of shortest_path and Dijkstra
  • single_source_shortest_path and all_pairs_shortest_path
  • s-metric and experimental code to generate maximal s-metric graph
  • double_edge_swap and connected_double_edge_swap
  • Floyd’s algorithm for all pairs shortest path
  • read and write unicode graph data to text files
  • read and write YAML format text files, http://yaml.org
Bug fixes
  • speed improvements (faster version of subgraph, is_connected)
  • added cumulative distribution and modified discrete distribution utilities
  • report error if DiGraphs are sent to connected_components routines
  • removed with_labels keywords for many functions where it was causing confusion
  • function name changes in shortest_path routines
  • saner internal handling of nbunch (node bunches), raise an exception if an nbunch isn’t a node or iterable
  • better keyword handling in io.py allows reading multiple graphs
  • don’t mix Numeric and numpy arrays in graph layouts and drawing
  • avoid automatically rescaling matplotlib axes when redrawing graph layout
Examples
  • unicode node labels

NetworkX 0.29

Release date: 28 April 2006

See: https://networkx.lanl.gov/trac/timeline

New features
  • Algorithms for betweenness, eigenvalues, eigenvectors, and spectral projection for threshold graphs
  • Use numpy when available
  • dense_gnm_random_graph generator
  • Generators for some directed graphs: GN, GNR, and GNC by Krapivsky and Redner
  • Grid graph generators now label by index tuples. Helper functions for manipulating labels.
  • relabel_nodes_with_function
Bug fixes
  • Betweenness centrality now correctly uses Brandes definition and has normalization option outside main loop
  • Empty graph now labeled as empty_graph(n)
  • shortest_path_length used python2.4 generator feature
  • degree_sequence_tree off by one error caused nonconsecutive labeling
  • periodic_grid_2d_graph removed in favor of grid_2d_graph with periodic=True

NetworkX 0.28

Release date: 13 March 2006

See: https://networkx.lanl.gov/trac/timeline

New features
  • Option to construct Laplacian with rows and columns in specified order
  • Option in convert_node_labels_to_integers to use sorted order
  • predecessor(G,n) function that returns dictionary of nodes with predecessors from breadth-first search of G starting at node n. https://networkx.lanl.gov/trac/ticket/26
Examples
Bug fixes
  • Adjusted names for random graphs.
    • erdos_renyi_graph=binomial_graph=gnp_graph: n nodes with edge probability p
    • gnm_graph: n nodes and m edges
    • fast_gnp_random_graph: gnp for sparse graphs (small p)
  • Documentation contains correct spelling of Barabási, Bollobás, Erdős, and Rényi in UTF-8 encoding

  • Increased speed of connected_components and related functions by using faster BFS algorithm in networkx.paths https://networkx.lanl.gov/trac/ticket/27

  • XGraph and XDiGraph with multiedges=True produced error on delete_edge

  • Cleaned up docstring errors

  • Normalize names of some graphs to produce strings that represent calling sequence

NetworkX 0.27

Release date: 5 February 2006

See: https://networkx.lanl.gov/trac/timeline

New features
  • sparse_binomial_graph: faster graph generator for sparse random graphs
  • read/write routines in io.py now handle XGraph() type and gzip and bzip2 files
  • optional mapping of type for read/write routine to allow on-the-fly conversion of node and edge datatype on read
  • Substantial changes related to digraphs and definitions of neighbors() and edges(). For digraphs edges=out_edges. Neighbors now returns a list of neighboring nodes with possible duplicates for graphs with parallel edges See https://networkx.lanl.gov/trac/ticket/24
  • Addition of out_edges, in_edges and corresponding out_neighbors and in_neighbors for digraphs. For digraphs edges=out_edges.
Examples
  • Minard’s data for Napoleon’s Russian campaign
Bug fixes
  • XGraph(multiedges=True) returns a copy of the list of edges for get_edge()

NetworkX 0.26

Release date: 6 January 2006

New features
  • Simpler interface to drawing with pylab
  • G.info(node=None) function returns short information about graph or node
  • adj_matrix now takes optional nodelist to force ordering of rows/columns in matrix
  • optional pygraphviz and pydot interface to graphviz is now callable as “graphviz” with pygraphviz preferred. Use draw_graphviz(G).
Examples
  • Several new examples showing how draw to graphs with various properties of nodes, edges, and labels
Bug fixes
  • Default data type for all graphs is now None (was the integer 1)
  • add_nodes_from now won’t delete edges if nodes added already exist
  • Added missing names to generated graphs
  • Indexes for nodes in graphs start at zero by default (was 1)

NetworkX 0.25

Release date: 5 December 2005

New features
Examples
  • Email example shows how to use XDiGraph with Python objects as edge data
Documentation
  • Reformat menu, minor changes to Readme, better stylesheet
Bug fixes
  • use create_using= instead of result= keywords for graph types in all cases
  • missing weights for degree 0 and 1 nodes in clustering
  • configuration model now uses XGraph, returns graph with identical degree sequence as input sequence
  • fixed Dijkstra priority queue
  • fixed non-recursive toposort and is_directed_acyclic graph

NetworkX 0.24

Release date: 20 August 2005

Bug fixes
  • Update of Dijkstra algorithm code
  • dfs_successor now calls proper search method
  • Changed to list comprehension in DiGraph.reverse() for python2.3 compatibility
  • Barabasi-Albert graph generator fixed
  • Attempt to add self loop should add node even if parallel edges not allowed

NetworkX 0.23

Release date: 14 July 2005

The NetworkX web locations have changed:

http://networkx.lanl.gov/ - main documentation site http://networkx.lanl.gov/svn/ - subversion source code repository https://networkx.lanl.gov/trac/ - bug tracking and info

Important Change

The naming conventions in NetworkX have changed. The package name “NX” is now “networkx”.

The suggested ways to import the NetworkX package are

  • import networkx
  • import networkx as NX
  • from networkx import *
New features
  • DiGraph reverse

  • Graph generators
    • watts_strogatz_graph now does rewiring method
    • old watts_strogatz_graph->newman_watts_strogatz_graph
Examples
Documentation
Bug fixes
  • Fixed logic in io.py for reading DiGraphs.
  • Path based centrality measures (betweenness, closeness) modified so they work on graphs that are not connected and produce the same result as if each connected component were considered separately.

NetworkX 0.22

Release date: 17 June 2005

New features
  • Topological sort, testing for directed acyclic graphs (DAGs)

  • Dijkstra’s algorithm for shortest paths in weighted graphs

  • Multidimensional layout with dim=n for drawing

  • 3d rendering demonstration with vtk

  • Graph generators
    • random_powerlaw_tree
    • dorogovtsev_goltsev_mendes_graph
Examples
  • Kevin Bacon movie actor graph: Examples/kevin_bacon.py
  • Compute eigenvalues of graph Laplacian: Examples/eigenvalues.py
  • Atlas of small graphs: Examples/atlas.py
Documentation
  • Rewrite of setup scripts to install documentation and tests in documentation directory specified
Bug fixes
  • Handle calls to edges() with non-node, non-iterable items.
  • truncated_tetrahedral_graph was just plain wrong
  • Speedup of betweenness_centrality code
  • bfs_path_length now returns correct lengths
  • Catch error if target of search not in connected component of source
  • Code cleanup to label internal functions with _name
  • Changed import statement lines to always use “import NX” to protect name-spaces
  • Other minor bug-fixes and testing added

Bibliography

[BA02]R. Albert and A.-L. Barabási, “Statistical mechanics of complex networks”, Reviews of Modern Physics, 74, pp. 47-97, 2002. :arxiv:`cond-mat/0106096`
[Bollobas01]B. Bollobás, “Random Graphs”, Second Edition, Cambridge University Press, 2001.
[BE05]U. Brandes and T. Erlebach, “Network Analysis: Methodological Foundations”, Lecture Notes in Computer Science, Volume 3418, Springer-Verlag, 2005.
[CL1996]G. Chartrand and L. Lesniak, “Graphs and Digraphs”, Chapman and Hall/CRC, 1996.
[choudum1986]S.A. Choudum. “A simple proof of the Erdős-Gallai theorem on graph sequences.” Bulletin of the Australian Mathematical Society, 33, pp 67-70, 1986. :doi:`10.1017/S0004972700002872`
[Diestel97]R. Diestel, “Graph Theory”, Springer-Verlag, 1997. :url:`http://diestel-graph-theory.com/index.html`
[DM03]S.N. Dorogovtsev and J.F.F. Mendes, “Evolution of Networks”, Oxford University Press, 2003.
[EppsteinPads]David Eppstein. PADS, A library of Python Algorithms and Data Structures. :url:`http://www.ics.uci.edu/~eppstein/PADS`
[EG1960]Erdős and Gallai, Mat. Lapok 11 264, 1960.
[hakimi1962]Hakimi, S. “On the Realizability of a Set of Integers as Degrees of the Vertices of a Graph.” SIAM J. Appl. Math. 10, 496-506, 1962.
[havel1955]Havel, V. “A Remark on the Existence of Finite Graphs” Casopis Pest. Mat. 80, 477-480, 1955.
[Langtangen04]H.P. Langtangen, “Python Scripting for Computational Science.”, Springer Verlag Series in Computational Science and Engineering, 2004.
[Martelli03]A. Martelli, “Python in a Nutshell”, O’Reilly Media Inc, 2003.
[Newman03]M.E.J. Newman, “The Structure and Function of Complex Networks”, SIAM Review, 45, pp. 167-256, 2003. :url:`http://epubs.siam.org/doi/abs/10.1137/S003614450342480`
[Sedgewick02]R. Sedgewick, “Algorithms in C: Parts 1-4: Fundamentals, Data Structure, Sorting, Searching”, Addison Wesley Professional, 3rd ed., 2002.
[Sedgewick01]R. Sedgewick, “Algorithms in C, Part 5: Graph Algorithms”, Addison Wesley Professional, 3rd ed., 2001.
[West01]D. B. West, “Introduction to Graph Theory”, Prentice Hall, 2nd ed., 2001.
[vanRossum98]Guido van Rossum. Python Patterns - Implementing Graphs, 1998. :url:`http://www.python.org/doc/essays/graphs`
Read the Docs v: networkx-1.10
Versions
latest
stable
networkx-1.10
Downloads
pdf
htmlzip
epub
On Read the Docs
Project Home
Builds

Free document hosting provided by Read the Docs.
PK_Gf?wE*E*"networkx-networkx-1.10/objects.inv# Sphinx inventory version 2 # Project: NetworkX # Version: 1.10 # The remainder of this file is compressed using zlib. x]MqϯPHC8yޥؕ8q9q "! W$3AhsN7n م V_Po2r+R]<;rhv>d[!*deʮR~zHT#yH-;SɀPK_м դtJ35h=~[U|(B *HŪ)b5W SW#߶SߤBˉ%??`SOq?@(k'x|maJ3H5|5o.(CX:nXY-8 Z~G"0Ħe38|;΀93%Z Kk IWr Cqh9tI6효3:0-2cA s@yMi#;z;MV i}e{z E*mJNZAR璘bRUAXl_**W ɀ:WK[Yţm79TR*衒TgYuVNws۔$\Jw^ע)nПbAcK΂9*9r pWџ^}rr!'R=@_QUr|("* Q%pXڵEk9]r&`P_ݟ%*j,Jl[ghry 䴦8}Mۼ xF׫AݳQ5tnJ8vwEBM?4O‘Dhxۧ-Qz(9W]P3`*)WU+W N@ )0'>XØMwؓg2aKr@8l స#(`8X( ۃX!p8B#|#=`!oc8X „ABG%@ٹvP:S2Tg +3l5{}($z:0eELVn8" ie-!Z8"b˘"+av(>Y.Bzm8 n-B:XG!17&Kxآ :g{AD ΛX?M5f#~f\ ?Lo IN %H<#{j!1AMJ`%D|!XTf"dM6 bO`}x_/F'"_=Wk< b}B8Gg?Np=_VYG+PV˸p 9Bm_$_ױmPgJ*vjx0';ԓ夿Ty{ mw/>y#~ihb=lUc;Rxʑ[aS8|f SGIdD "o?#:ScyQi};'T.=~MOΌ2UCxScM#Ĝ>ʻtgY(.?2d^gAMJZI叢~IxW3!˛<^ЅPO~Oo' wtBP\g"Uޝ0zb{ST .$˒/Oh>z$t\T.Ձ;gJ>ȅHYM6wNM Gy[(ǭ>"g_jMY [RوOk競XKn_Ε T|j;;~.uxTA:%%ⅼBL2{-X=O:=M"|Se!iK^F N$B=PZV CH.%<㐋EkTz: v60x+bUSh{ Ѕ|4]c!-R5^HI?ަ{g᳎yvM@>y W]K{`],EIh:(p^&:G" {t;ztߞ]=+կjЖڏZh\t{C4Ew)/q !?]㾈h2F{0^xiwFOh\Xp3S~;[6<-?y9|įx /Z'*lVyAgm=0R\2^mV ~-]HݷO-6wpƲ+6+8@63/BuشkP1AjoZq碸Ҭ?n5&U.o`еxWBqǎ67QޥNH#u4iҕΚ~aq\r;@yWg=WG Q 'qR5b䦹̵Ntܩ؊M+շ+džXKhUy3;jKv_'nF;9.L~ѓhɍWDo",'nGL6LeK[:LD,4iD>_k?)fzdVcx0HGB3aeARm|i6V3ً'ǑPtJN1~3bb}}o XGF;؊״-^?Ty?  %:AYӽ5Rh^gޝtd:z_N {'#yII-^WEKl~jN'h~G^2Yw+ҜѩaYe~)O[v[x[lϹ B= Mߢz0pK\'h\+2xn k'ӹmZuj]/VNOK7`gx#KEԶ}X!3x>'*+,Ya 5K=_3^\!F%}r ~8]RbWF-j4A*PϭT0'"JB4L1jz-K_ͲXռ0RG[z_%gh'ߎzFz"0aU8D `cc?zD )d.X{d'ZO h \q ePenM^Co]Q94Ѷ>ɼ1ev#ABV(UELgsVle}S|5n`6"T5o@D}~i|8~ݸwDcF;j]uEt'#E04 e?} p)l _UMU.+m6*{ޖb;JHIԺ+5\ޱs_P%l H+})]ڵDo)XDԣsf" YC1 Ep3_<18iO><txureS]L*+Ԓx" 8Lm1Hv [ ]+`{5r ]J=yn)++ڤ]698Դ45",# Ky(`l$H]PPv%& `uVR2w GӲ+iX3RFΔKWN9ld3ѭՍsEC΅E<=TC:0(cWnw3!ERl߹aȚxC+˙(=TlAZuj"wJx~M4D>x(DaEs,Q|bi^؂xwS_{^fh =Ȗ{Q}oPK^7cϗ-a=g-γ93$87ff_5+B͉!͆@sa"Շ> w [SGkwZ~k/#Ndi|g&/gR~2MtZ{]&ҫ丁ޝVۧV)ED^V֯6M# &vOg[:ӸO0T 3VbR^1۪sgXLFzTN OƕU!VurJ͵ZesڭE\*Kr,t)ytQlO)6-J;sjNnᴫ.MYowF3HJrf ͝\"xSjlRW^&kDFoH63K1 lJˎTEiG$j ފim믞"=( 9UʯɣHZ=Ft}mٗl|Rv66D\a3*Vt[\]yMt)>6ES .E,U)zdp)ᵚ6Yķ n:-:~b}1)y,2aZP/y@g&9U Je)*^*8`I23vJ/ =`:52n 3g*O#>ywXA}-s ow0e,kM)iW7WWݓ}Z{mK!{uR66t|QB[jwpg=e%[]d\䟠 E^8oNBcM]4Ω<460f8i&B$臚Eu FErп&Ys \k DF7 ; 䢴C7؛#0t Tۯ^up-}Լ{Q]a<؎d97VJMHH}w6$׶ɿڎY2 ͜ǵfF|Zr%ȴVk|7iݭ=liMѦBO42wn#-[BM9f&|j+VںoK~XklSnpY!)vjAdzڞͲtSZY{G=T/ֿw_ԾAZ͢V}ע8V+,eI[Z|qlY&ҿHcadQ-lW{tP XkM+I6@(/F_!q̬󓔁Jt^#Y&7|Lysʺ'rj[i*E$(Ie;z:Qm[vLŲGs`/q"dgS-TM#z2z(NiLFx ֛yW=快qpS*_K̓wW]sȃ5\9lP,X%$?P*g6Rł@3_cal"qM >v6;FuCzo5>RykCjIDǣ'tŋ껗v#jkW/h/j}(G ڗ 5hijJYU#KkIV_-SX417T]w{VXˆU5|&ö-klEI+)1zeGh7|uPnzoA<vyYoPԞ.⎯kT9: H[Fa*_؉Y^up_hgH-'SS#\UzcPdUU8sp ū ٰ*΂١$VÌ3JN E3N ŊD'*H{Ajs|jZ=W;sDkvj,ۿyڒN]!vˌGLphd"TPt8uz fK6#"df܁M 7 TS"%rFjrpC#[ޯXEE]@cզ{@S"Dr "6L2ו 6+ȝ7k]ae%L$MFDȥˉ+"uZR(kPkPK=)hFviLF!eU9K##e=o'0Q|7&/3n1R|1?o,gmߏG/*-.Rh˕a&hVGFT&ݨ6 (\ n@L|a,< Y>;눽W~۪YW$6XAQ?-@6VU9ǺJ3tTKLj UǗ >18InW":aaaq(ɭrz$pĚ*B~iġ'5nz$p)IY6XܥJdR?Yrs-8tմHHv%xLk\*m `U% UJE<{I2~wP4ވV!' 'WRHVYg EFBO찏u/0oG-Jtf4ͨ?7\jS8ݧإa۲Һ7hX tSPEU#x}QaQlXTK4=R,jH9{|d|>vಛe~0.*n&mP=褻My̶0X͜\F,E sEj B VWTrnQ;əM!ѤL]JѤMZ(nq v >.˻փ(iNԣ(j/ȩm刺zpɤBA\UtpU= sܣ]oV FV=Aplϳ - 8slGd6K?)j7_dG?5|~yXwY{Ts/X#wɒ[Fz\[RF: #N27jQCZu4o8Rm1vZ )UGi88u )3xo4cuǂ: n#q&eC>4c SsU{)V'4Ѐ捠/iyɬU A Nr\0NJx{l2':giH!))/ }~ ިUCQ{QlS"e06|)e 5dk!8](&(s:&x8~\GE'5j#A2NY^Yc;G\QTU@⥫Y#9p.s7eu#]Yy[eQ,jJr%Z_Yyra?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="
",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h; if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML="
a",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/\s*$/g,rb={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:k.htmlSerialize?[0,"",""]:[1,"X
","
"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?""!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("