From 7da1f0a9088dbaa541d4a9e9722ab87880f9e43c Mon Sep 17 00:00:00 2001 From: Tiago de Paula Peixoto Date: Fri, 15 May 2009 18:50:04 +0200 Subject: [PATCH] Ongoing documentation improvement This modified several docstrings and introduces a quick-start guide. --- doc/.static/graph-icon.ico | Bin 0 -> 1022 bytes doc/.templates/layout.html | 5 + doc/Makefile | 8 + doc/centrality.rst | 2 + doc/clustering.rst | 1 + doc/community.rst | 3 + doc/conf.py | 24 +- doc/correlations.rst | 3 + doc/draw.rst | 3 + doc/generation.rst | 3 + doc/graph_tool.rst | 9 + doc/misc.rst | 3 + doc/price.py | 92 +++++ doc/quickstart.rst | 336 +++++++++++++++++- doc/run_action.rst | 3 + doc/stats.rst | 3 + doc/util.rst | 3 + src/graph_tool/__init__.py | 5 +- src/graph_tool/centrality/__init__.py | 233 +++++++------ src/graph_tool/clustering/__init__.py | 46 +-- src/graph_tool/community/__init__.py | 8 + src/graph_tool/core.py | 11 +- src/graph_tool/correlations/__init__.py | 445 +++++++++++++++++++++++- src/graph_tool/draw/__init__.py | 13 +- src/graph_tool/generation/__init__.py | 5 + src/graph_tool/misc/__init__.py | 5 + src/graph_tool/run_action/__init__.py | 5 +- src/graph_tool/run_action/inline.py | 38 +- src/graph_tool/stats/__init__.py | 244 ++++++++++++- src/graph_tool/util/__init__.py | 6 + 30 files changed, 1398 insertions(+), 167 deletions(-) create mode 100644 doc/.static/graph-icon.ico create mode 100644 doc/.templates/layout.html create mode 100644 doc/Makefile create mode 100644 doc/centrality.rst create mode 100644 doc/community.rst create mode 100644 doc/correlations.rst create mode 100644 doc/draw.rst create mode 100644 doc/generation.rst create mode 100644 doc/misc.rst create mode 100755 doc/price.py create mode 100644 doc/run_action.rst create mode 100644 doc/stats.rst create mode 100644 doc/util.rst diff --git a/doc/.static/graph-icon.ico b/doc/.static/graph-icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..939efadf05dc407be4521481deac8ff369c36323 GIT binary patch literal 1022 zcma)*%PT~26vscqAjUHx?}>zsB(fRrM;23*g_TFLQADvqUgNd1#w=K{WFuLqnZ!R} zVLi>tpWspW{@hX5od#$6+c@+|95%58E@^?UG`P@zRlMSRR3t z2IbC0nM0%MzRDhe%u3i8hlzSPjlk^(%pWN4cC2x@ds~+FEDFJUxPF7JDTm1EmcZ09 zT)e_z2z=^r%@9;3IfXG_lcGzQI(8sqAIfuLxwhEdeoK|pDbyp(JIlqiSQYv>IUtkQac|bj4;xkH`{stCCX{@dG literal 0 HcmV?d00001 diff --git a/doc/.templates/layout.html b/doc/.templates/layout.html new file mode 100644 index 00000000..03eb665c --- /dev/null +++ b/doc/.templates/layout.html @@ -0,0 +1,5 @@ +{% extends "!layout.html" %} +{% block rootrellink %} +
  • logoProject Homepage »
  • + {{ super() }} +{% endblock %} diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 00000000..e7464414 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,8 @@ +all: + sphinx-build -E -b html . build + +test: + OMP_NUM_THREADS=1 sphinx-build -b doctest . build + +push: + rsync -rEvpLz build/* root@forked.de:/var/www/graph-tool-doc/ diff --git a/doc/centrality.rst b/doc/centrality.rst new file mode 100644 index 00000000..fd9003fa --- /dev/null +++ b/doc/centrality.rst @@ -0,0 +1,2 @@ +.. automodule:: graph_tool.centrality + :members: diff --git a/doc/clustering.rst b/doc/clustering.rst index 30ec2eb3..87b83044 100644 --- a/doc/clustering.rst +++ b/doc/clustering.rst @@ -1,2 +1,3 @@ .. automodule:: graph_tool.clustering :members: + :undoc-members: diff --git a/doc/community.rst b/doc/community.rst new file mode 100644 index 00000000..ad78a446 --- /dev/null +++ b/doc/community.rst @@ -0,0 +1,3 @@ +.. automodule:: graph_tool.community + :members: + :undoc-members: diff --git a/doc/conf.py b/doc/conf.py index f3769e3e..1082e018 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -16,7 +16,7 @@ import sys, os # If your extensions are in another directory, add it here. If the directory # is relative to the documentation root, use os.path.abspath to make it # absolute, like shown here. -#sys.path.append(os.path.abspath('.')) +sys.path.append(os.path.abspath('.')) # General configuration # --------------------- @@ -43,7 +43,7 @@ master_doc = 'index' # General information about the project. project = u'graph-tool' -copyright = u'2008, Tiago de Paula Peixoto' +copyright = u'2009, Tiago de Paula Peixoto ' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -52,7 +52,7 @@ copyright = u'2008, Tiago de Paula Peixoto' # The short X.Y version. version = '2.0' # The full version, including alpha/beta/rc tags. -release = '2.0' +release = '2.0beta1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -88,6 +88,13 @@ exclude_trees = ['.build'] # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' +# doctest + +doctest_global_setup = \ +""" +import graph_tool.all as gt +from numpy import array +""" # Options for HTML output # ----------------------- @@ -111,7 +118,7 @@ html_style = 'default.css' # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +html_favicon = "graph-icon.ico" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, @@ -143,12 +150,12 @@ html_static_path = ['.static'] #html_split_index = False # If true, the reST sources are included in the HTML build as _sources/. -#html_copy_source = True +html_copy_source = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +html_use_opensearch = 'http://projects.forked.de/graph-tool/doc/' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = '' @@ -192,4 +199,7 @@ latex_documents = [ # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'http://docs.python.org/dev': None} +intersphinx_mapping = {'http://docs.python.org': None, + 'http://docs.scipy.org/doc/numpy': None, + 'http://docs.scipy.org/doc/scipy/reference': None, + 'http://matplotlib.sourceforge.net' : None} diff --git a/doc/correlations.rst b/doc/correlations.rst new file mode 100644 index 00000000..e6000c15 --- /dev/null +++ b/doc/correlations.rst @@ -0,0 +1,3 @@ +.. automodule:: graph_tool.correlations + :members: + :undoc-members: diff --git a/doc/draw.rst b/doc/draw.rst new file mode 100644 index 00000000..45cc41e1 --- /dev/null +++ b/doc/draw.rst @@ -0,0 +1,3 @@ +.. automodule:: graph_tool.draw + :members: + :undoc-members: diff --git a/doc/generation.rst b/doc/generation.rst new file mode 100644 index 00000000..af7a1a0f --- /dev/null +++ b/doc/generation.rst @@ -0,0 +1,3 @@ +.. automodule:: graph_tool.generation + :members: + :undoc-members: diff --git a/doc/graph_tool.rst b/doc/graph_tool.rst index c45f3c8b..f2a8751a 100644 --- a/doc/graph_tool.rst +++ b/doc/graph_tool.rst @@ -6,4 +6,13 @@ Available subpackages .. toctree:: + centrality clustering + community + correlations + draw + generation + misc + run_action + stats + util \ No newline at end of file diff --git a/doc/misc.rst b/doc/misc.rst new file mode 100644 index 00000000..2255965b --- /dev/null +++ b/doc/misc.rst @@ -0,0 +1,3 @@ +.. automodule:: graph_tool.misc + :members: + :undoc-members: diff --git a/doc/price.py b/doc/price.py new file mode 100755 index 00000000..d7053a52 --- /dev/null +++ b/doc/price.py @@ -0,0 +1,92 @@ +#! /usr/bin/env python + +# We probably will need some things from several places +import sys, os +from pylab import * # for plotting +from numpy.random import * # for random sampling +seed(42) + +# We need to import the graph_tool module itself +from graph_tool.all import * + +# let's construct a Price network (the one that existed before Barabasi). It is +# a directed network, with preferential attachment. The algorithm below is a +# very naive, and a bit slow, but quite simple. + +# We start with an empty, directed graph +g = Graph() + +# We want also to keep the age information for each vertex and edge. For that +# let's create some property maps +v_age = g.new_vertex_property("int") +e_age = g.new_edge_property("int") + +# The final size of the network +N = 100000 + +# We have to start with one vertex +v = g.add_vertex() +v_age[v] = 0 + +# we will keep a list of the vertices. The number of times a vertex is in this +# list will give the probability of it being selected. +vlist = [v] + +# let's now add the new edges and vertices +for i in xrange(1, N): + # create our new vertex + v = g.add_vertex() + v_age[v] = i + + # we need to sample a new vertex to be the target, based on its in-degree + + # 1. For that, we simply randomly sample it from vlist. + i = randint(0, len(vlist)) + target = vlist[i] + + # add edge + e = g.add_edge(v, target) + e_age[e] = i + + # put v and target in the list + vlist.append(target) + vlist.append(v) + +# now we have a graph! +# let's calculate its in-degree distribution and plot it to a file + +in_hist = vertex_hist(g, "in") + +clf() +errorbar(in_hist[1], in_hist[0], fmt=".", yerr=sqrt(in_hist[0])) +gca().set_yscale("log") +gca().set_xscale("log") +xlabel("$k_{in}$") +ylabel("$P(k_{in})$") +savefig("deg-hist.png") + +# let's do a random walk on the graph and print the age of the vertices we find, +# just for fun. + +v = g.vertex(randint(0, g.num_vertices())) +for i in xrange(0, 100): + print "vertex:", v, "in-degree:", v.in_degree(), "out-degree:",\ + v.out_degree(), "age:", v_age[v] + + if v.out_degree() == 0: + print "Nowhere else to go... We found the main hub!" + break + + n_list = [] + for w in v.out_neighbours(): + n_list.append(w) + v = n_list[randint(0, len(n_list))] + +# let's save our graph for posterity We want to save the age properties as +# well... To do this, they must become "internal" properties, as such: + +g.vertex_properties["age"] = v_age +g.edge_properties["age"] = e_age + +# now we can save it +g.save("price.xml.gz") + diff --git a/doc/quickstart.rst b/doc/quickstart.rst index 1cc85ddf..ceae6c6a 100644 --- a/doc/quickstart.rst +++ b/doc/quickstart.rst @@ -1,10 +1,338 @@ Quick start using `graph-tool` ============================== -Testy test test +The :mod:`graph_tool` module provides a :class:`~graph_tool.Graph` class and +several algorithms that operate on it. The internals of this class, and of most +algorithms, are written in C++ for performance. -.. math:: +The module must be of course imported before it can be used. The package is +subdivided into several sub-modules. To import everything from all of them, one +can do: - (a + b)^2 = a^2 + 2ab + b^2 +.. doctest:: + + >>> from graph_tool.all import * + +In the following, it will always be assumed that the previous line was run. + +Creating and manipulating graphs +-------------------------------- + +An empty graph can be created by instantiating a :class:`~graph_tool.Graph` +class: + +.. doctest:: + + >>> g = Graph() + +By default, newly created graphs are always directed. To construct undirected +graphs, one must pass the ``directed`` parameter: + +.. doctest:: + + >>> ug = Graph(directed=False) + +A graph can always be switched on-the-fly from directed to undirected (and vice +versa), with the :meth:`~graph_tool.Graph.set_directed` method. The "directedness" of the +graph can be queried with the :meth:`~graph_tool.Graph.is_directed` method, + +.. doctest:: + + >>> ug = Graph() + >>> ug.set_directed(False) + >>> assert(ug.is_directed() == False) + +A graph can also be created from another graph, in which case the entire graph +(and its internal property maps, see :ref:`sec_property_maps`) is copied: + +.. doctest:: + + >>> g1 = Graph() + >>> # ... populate g1 ... + >>> g2 = Graph(g1) # g1 and g2 are copies + +Once a graph is created, it can be populated with vertices and edges. A vertex +can be added with the :meth:`~graph_tool.Graph.add_vertex` method, + +.. doctest:: + + >>> v = g.add_vertex() + +which returns an instance of a :class:`~graph_tool.Vertex` class, also called a +*vertex descriptor*. The :meth:`~graph_tool.Graph.add_vertex` method also +accepts an optional parameter which specifies the number of vertices to +create. If this value is greater than 1, it returns a list of vertices: + +.. doctest:: + + >>> vlist = g.add_vertex(10) + >>> print len(vlist) + 10 + +Each vertex has an unique index, which is numbered from 0 to N-1, where N is the +number of vertices. This index can be obtained by using the +:attr:`~graph_tool.Graph.vertex_index` attribute of the graph (which is a +*property map*, see :ref:`sec_property_maps`), or by converting the vertex +descriptor to an int. + +.. doctest:: + + >>> v = g.add_vertex() + >>> print g.vertex_index[v], int(v) + 11 11 + +There is no need to keep the vertex descriptor lying around to access them at a +later point: One can obtain the descriptor of a vertex with a given index using +the :meth:`~graph_tool.Graph.vertex` method, + +.. doctest:: + + >>> print g.vertex(8) + 8 + +Another option is to iterate through the vertices, as described in section +:ref:`sec_iteration`. + +Once we have some vertices in the graph, we can create some edges between them +with the :meth:`~graph_tool.Graph.add_edge` method, which returns an edge +descriptor (an instance of the :class:`~graph_tool.Edge` class). + +.. doctest:: + + >>> v1 = g.add_vertex() + >>> v2 = g.add_vertex() + >>> e = g.add_edge(v1, v2) + +Edges also have an unique index, which is given by the :attr:`~graph_tool.Graph.edge_index` +property: + +.. doctest:: + + >>> print g.edge_index[e] + 0 + +Unlike the vertices, edge indexes are not guaranteed to be continuous in any +range, but they are always unique. + +Both vertex and edge descriptors have methods which query associate information, +such as :meth:`~graph_tool.Vertex.in_degree`, +:meth:`~graph_tool.Vertex.out_degree`, :meth:`~graph_tool.Edge.source` and +:meth:`~graph_tool.Edge.target`: + +.. doctest:: + + >>> v1 = g.add_vertex() + >>> v2 = g.add_vertex() + >>> e = g.add_edge(v1, v2) + >>> print v1.out_degree(), v2.in_degree() + 1 1 + >>> assert(e.source() == v1 and e.target() == v2) + +Edges and vertices can also be removed at any time with the +:meth:`~graph_tool.Graph.remove_vertex` and :meth:`~graph_tool.Graph.remove_edge` methods, + +.. doctest:: + + >>> e = g.add_edge(g.vertex(0), g.vertex(1)) + >>> g.remove_edge(e) # e no longer exists + >>> g.remove_vertex(g.vertex(1)) # the second vertex is also gone + +.. _sec_iteration: + +Iterating over vertices and edges ++++++++++++++++++++++++++++++++++ + +Algorithms must often iterate through the vertices, edges, out edge, etc. of the +graph. The :class:`~graph_tool.Graph` and :class:`~graph_tool.Edge` classes +provide the necessary iterators for doing so. The iterators always give back +edge or vertex descriptors. + +In order to iterate through the vertices or edges of the graph, the +:meth:`~graph_tool.Graph.vertices` and :meth:`~graph_tool.Graph.edges` methods should be used, as such: + +.. doctest:: + + for v in g.vertices(): + print v + for e in e.vertices(): + print e + +The code above will print the vertices and edges of the graph in the order they +are found. + +The out- and in-edges of a vertex, as well as the out- and in-neighbours can be +iterated through with the :meth:`~graph_tool.Vertex.out_edges`, +:meth:`~graph_tool.Vertex.in_edges`, :meth:`~graph_tool.Vertex.out_neighbours` +and :meth:`~graph_tool.Vertex.in_neighbours` respectively. + +.. doctest:: + + from itertools import izip + for v in g.vertices(): + for e in v.out_edges(): + print e + for e in v.out_neighbours(): + print e + + # the edge and neighbours order always match + for e,w in izip(v.out_edges(), v.out_neighbours()): + assert(e.target() == w) + +.. warning: + + You should never remove vertex or edge descriptors when iterating over them, + since this invalidates the iterators. If you plan to remove vertices or edges + during iteration, you must first store them somewhere (such as in a list) and + remove them only later. Removal during iteration will cause bad things to + happen. + +.. _sec_property_maps: + +Property maps +------------- + +Property maps are a way of associating additional to the vertices, edges or to +the graph itself. There are thus three types of property maps: vertex, edge and +graph. All of them are instances of the same class, +:class:`~graph_tool.PropertyMap`. Each property map has an associated *value +type*, which must be chosen from the predefined set: + +.. tabularcolumns:: |l|l| + +.. table:: + + ======================= ================ + Type name Aliases + ======================= ================ + ``bool`` ``uint8_t`` + ``int32_t`` ``int`` + ``int64_t`` ``long`` + ``double`` ``float`` + ``long double`` + ``string`` + ``vector`` ``vector`` + ``vector`` ``vector`` + ``vector`` ``vector`` + ``vector`` ``vector`` + ``vector`` + ``vector`` + ``python::object`` ``object`` + ======================= ================ + +New property maps can be created for a given graph by calling the +:meth:`~graph_tool.Graph.new_vertex_property`, :meth:`~graph_tool.Graph.new_edge_property`, or +:meth:`~graph_tool.Graph.new_graph_property`, for each map type. The values are then +accessed by vertex or edge descriptors, or the graph itself, as such: + +.. doctest:: + + from itertools import izip + from numpy.random import randint + + g = Graph() + g.add_vertex(100) + # insert some random links + for s,t in izip(randint(0, 100, 100), randint(0, 100, 100)): + g.add_edge(g.vertex(s), g.vertex(t)) + + vprop_double = g.new_vertex_property("double") + vprop_vint = g.new_vertex_property("vector") + + eprop_dict = g.new_edge_property("object") + + gprop_bool = g.new_edge_property("bool") + + vprop_double[g.vertex(10)] = 3.1416 + + vprop_vint[g.vertex(40)] = [1, 3, 42, 54] + + eprop_dict[g.edges().next()] = {"foo":"bar", "gnu":42} + + gprop_bool[g] = True + +Property maps with scalar value types can also be accessed as a numpy +:class:`~numpy.ndarray`, with the :meth:`~graph_tool.PropertyMap.get_array` +method, i.e., + +.. doctest:: + + from numpy.random import random + + # this assigns random values to the properties + vprop_double.get_array()[:] = random(g.num_vertices()) + +Internal property maps +++++++++++++++++++++++ + +Any created property map can be made "internal" to the respective graph. This +means that it will be copied and saved to a file together with the +graph. Properties are internalized by including them in the graph's +dictionary-like attributes :attr:`~graph_tool.Graph.vertex_properties`, +:attr:`~graph_tool.Graph.edge_properties` or +:attr:`~graph_tool.Graph.graph_properties`. When inserted in the graph, the +property maps must have an unique name (between those of the same type): + +.. doctest:: + + >>> eprop = g.new_edge_property("string") + >>> g.edge_properties["some name"] = eprop + >>> g.list_properties() + some name (edge) (type: string) + + +Graph I/O +--------- + +Graphs can be saved and loaded in two formats: `graphml +`_ and `dot +`_. Graphml is the default and +preferred format. The dot format is also supported, but since it contains no +type information, all properties are read later as strings, and must be +converted per hand. Therefore you should always use graphml, except when +interfacing with another software which expects dot format. + +A graph can be saved or loaded to a file with the :attr:`~graph_tool.Graph.save` +and :attr:`~graph_tool.Graph.load` methods, which take either a file name or a +file-like object. A graph can also be loaded from disk with the +:func:`~graph_tool.load_graph` function, as such: + +.. doctest:: + + g = Graph() + # ... fill the graph ... + g.save("my_graph.xml.gz") + g2 = load_graph("my_graph.xml.gz") + # g and g2 should be a copy of each other + +Graph classes can also be pickled with the :mod:`pickle` module. + + +An Example: Building a Price Network +------------------------------------ + +.. literalinclude:: price.py + :linenos: + +.. testcode:: + :hide: + + from price import * + clf() + +.. testoutput:: + + vertex: 36063 in-degree: 0 out-degree: 1 age: 36063 + vertex: 9075 in-degree: 4 out-degree: 1 age: 9075 + vertex: 5967 in-degree: 3 out-degree: 1 age: 5967 + vertex: 1113 in-degree: 7 out-degree: 1 age: 1113 + vertex: 25 in-degree: 84 out-degree: 1 age: 25 + vertex: 10 in-degree: 541 out-degree: 1 age: 10 + vertex: 5 in-degree: 140 out-degree: 1 age: 5 + vertex: 2 in-degree: 459 out-degree: 1 age: 2 + vertex: 1 in-degree: 520 out-degree: 1 age: 1 + vertex: 0 in-degree: 210 out-degree: 0 age: 0 + Nowhere else to go... We found the main hub! + + +.. image:: deg-hist.png - (a - b)^2 = a^2 - 2ab + b^2 diff --git a/doc/run_action.rst b/doc/run_action.rst new file mode 100644 index 00000000..0fec616d --- /dev/null +++ b/doc/run_action.rst @@ -0,0 +1,3 @@ +.. automodule:: graph_tool.run_action + :members: + :undoc-members: diff --git a/doc/stats.rst b/doc/stats.rst new file mode 100644 index 00000000..4ff8418d --- /dev/null +++ b/doc/stats.rst @@ -0,0 +1,3 @@ +.. automodule:: graph_tool.stats + :members: + :undoc-members: diff --git a/doc/util.rst b/doc/util.rst new file mode 100644 index 00000000..096d123b --- /dev/null +++ b/doc/util.rst @@ -0,0 +1,3 @@ +.. automodule:: graph_tool.util + :members: + :undoc-members: diff --git a/src/graph_tool/__init__.py b/src/graph_tool/__init__.py index 969db775..249aa4d4 100644 --- a/src/graph_tool/__init__.py +++ b/src/graph_tool/__init__.py @@ -66,7 +66,7 @@ misc stats vertex and edge statistics util - assorted untilities + assorted utilities Utilities --------- @@ -77,6 +77,9 @@ show_config __version__ ``graph_tool`` version string +Classes +------- + """ __author__="Tiago de Paula Peixoto " diff --git a/src/graph_tool/centrality/__init__.py b/src/graph_tool/centrality/__init__.py index cc7ba6a5..2f8e5797 100644 --- a/src/graph_tool/centrality/__init__.py +++ b/src/graph_tool/centrality/__init__.py @@ -17,8 +17,8 @@ # along with this program. If not, see . """ -Centrality -========== +``graph_tool.centrality`` - Centrality measures +----------------------------------------------- This module includes centrality-related algorithms. """ @@ -55,7 +55,7 @@ def pagerank(g, damping=0.8, prop=None, epslon=1e-6, max_iter=None, Returns ------- - A vertex property map containing the PageRank values. + pagerank : A vertex property map containing the PageRank values. See Also -------- @@ -65,12 +65,13 @@ def pagerank(g, damping=0.8, prop=None, epslon=1e-6, max_iter=None, Notes ----- - The value of PageRank of vertex v :math:`PR(v)` is given interactively by - the relation: + The value of PageRank [pagerank_wikipedia]_ of vertex v :math:`PR(v)` is + given interactively by the relation: + + .. math:: - .. math: PR(v) = \frac{1-d}{N} + d \sum_{w \in \Gamma^{-}(v)} - \frac{PR (w)}{d^{+}(w)} + \frac{PR (w)}{d^{+}(w)} where :math:`\Gamma^{-}(v)` are the in-neighbours of v, :math:`d^{+}(w)` is the out-degree of w, and d is a damping factor. @@ -83,33 +84,34 @@ def pagerank(g, damping=0.8, prop=None, epslon=1e-6, max_iter=None, Examples -------- - >>> from numpy.random import poisson + >>> from numpy.random import poisson, seed + >>> seed(42) >>> g = gt.random_graph(100, lambda: (poisson(3), poisson(3)), seed=42) >>> pr = gt.pagerank(g) >>> print pr.get_array() - [ 1.23631405 1.26200483 1.96751522 0.64733031 0.70919769 0.30955985 - 1.52538634 0.61243582 0.53488703 0.5495016 0.63962998 0.45806361 - 1.67723278 0.26623242 0.32215029 0.53362967 0.32231378 0.33050213 - 0.5356975 0.37390974 0.93677559 0.38228945 0.36843877 0.84068062 - 1.06194997 0.53691497 1.13629299 1.16796209 0.55409311 0.75573135 - 0.58224114 0.40017455 0.35638757 1.16638209 0.74002981 0.47176731 - 0.42552094 1.73280634 0.57785889 1.5858852 0.49093732 0.46508149 - 0.71090896 1.31162119 0.6081533 0.795906 0.66140379 1.45468664 - 0.87347307 0.35982942 0.75867436 0.29503668 0.2 0.42730891 - 0.39734128 0.68474907 0.27070849 1.09135253 0.99528067 0.62147738 - 0.45554969 0.60866561 0.3757151 0.76052526 0.24 1.96136727 - 0.45867667 1.69554306 0.5334554 0.33116212 0.58532863 0.59491545 - 0.45311729 0.64750618 0.46664234 0.77742232 0.59982206 0.4484523 - 0.2 0.67184777 1.4206807 0.31958008 0.45240096 0.9407526 - 0.24 0.94460064 0.97453039 0.60548406 0.44192809 0.35467411 - 0.32231378 0.93392279 1.12016048 1.21238 0.34737551 0.39613672 - 0.95560285 0.623376 0.2 0.59657029] + [ 1.01514315 0.60117439 0.32514372 0.28 0.2 1.54971179 + 0.28 1.0236911 0.33123536 0.4778296 0.62078363 1.25377064 + 0.49213262 1.70011842 0.30671734 0.56424761 0.86810689 1.68765055 + 0.49551575 0.72837655 0.39240949 1.43802363 0.51563806 0.41983927 + 0.37857787 0.45875573 0.97033399 0.38531927 0.54001665 0.89328562 + 0.52122532 0.94064256 1.39911631 0.64663655 1.23521006 0.71722741 + 0.59460778 0.2 0.63239854 1.86292923 0.2 0.31277737 + 0.74650027 0.32415672 0.47975325 1.11611173 0.53433883 0.63352435 + 0.23822967 0.93151021 0.5440643 0.69188579 0.97489471 0.51216733 + 1.31721331 1.32808547 0.39894203 0.50384137 0.75225633 0.28220146 + 1.10818407 0.58685184 1.26437262 0.67929902 0.69678112 1.34428502 + 0.61651094 0.43008378 0.7905129 1.35318411 0.2 0.2 + 1.6584374 0.98009079 0.27200222 0.3413639 0.23822967 0.27963213 + 1.22498499 0.34097559 0.50749002 1.21145838 0.50430676 0.50218939 + 0.74232491 0.5335867 0.27254191 0.36031317 0.65344358 0.96712961 + 0.53252883 0.86479464 0.59958851 0.82703737 0.68722079 0.52036384 + 0.65299724 0.42291513 0.81729152 1.7586996 ] References ---------- .. [pagerank_wikipedia] http://en.wikipedia.org/wiki/Pagerank .. [lawrence_pagerank_1998] P. Lawrence, B. Sergey, M. Rajeev, W. Terry, - "The pagerank citation ranking: Bringing order to the web", Technical + "The pagerank citation ranking: Bringing order to the web", Technical report, Stanford University, 1998 """ @@ -144,8 +146,10 @@ def betweenness(g, vprop=None, eprop=None, weight=None, norm=True): Returns ------- - A tuple containing a vertex property map and an edge property map with the - respective betweenness values. + vertex_betweenness : A vertex property map with the vertex betweenness + values. + edge_betweenness : An edge property map with the edge betweenness + values. See Also -------- @@ -158,7 +162,8 @@ def betweenness(g, vprop=None, eprop=None, weight=None, norm=True): ----- Betweenness centrality of a vertex :math:`C_B(v)` is defined as, - .. math: + .. math:: + C_B(v)= \sum_{s \neq v \neq t \in V \atop s \neq t} \frac{\sigma_{st}(v)}{\sigma_{st}} @@ -168,7 +173,7 @@ def betweenness(g, vprop=None, eprop=None, weight=None, norm=True): through the number of pairs of vertices not including v, which is :math:`(n-1)(n-2)/2`. - The algorithm used here is defined in _[brandes_faster_2001], and has a + The algorithm used here is defined in [brandes_faster_2001]_, and has a complexity of :math:`O(VE)` for unweighted graphs and :math:`O(VE + V(V+E) \log V)` for weighted graphs. The space complexity is :math:`O(VE)`. @@ -176,27 +181,28 @@ def betweenness(g, vprop=None, eprop=None, weight=None, norm=True): Examples -------- - >>> from numpy.random import poisson + >>> from numpy.random import poisson, seed + >>> seed(42) >>> g = gt.random_graph(100, lambda: (poisson(3), poisson(3)), seed=42) >>> vb, eb = gt.betweenness(g) >>> print vb.get_array() - [ 0.04156663 0.04437293 0.05111713 0.04426975 0.05518562 0.01015239 - 0. 0.02696981 0.00849224 0.01177936 0.03467101 0.01958941 - 0.05491377 0.00140963 0.00810379 0.0061649 0.01325843 0. - 0.00388506 0. 0.07004857 0.01540617 0.02101045 0.03078003 - 0.02823591 0.01752393 0. 0.0487721 0.04102476 0.02308081 - 0.00320094 0.01265714 0.0168692 0.06652112 0.02913082 0. - 0.01509914 0.08867136 0.01399966 0.09695112 0.01803752 0. - 0.01628919 0.10413395 0.00860251 0. 0. 0.06342465 - 0.07319201 0.01197855 0.01750122 0.00393044 0. 0.01697703 - 0.01301164 0.04819859 0. 0.0284821 0.03074227 0.02090606 - 0.02107045 0.03068094 0.01983066 0.02918679 0.00164227 0.06705493 - 0.02547069 0.10370115 0.02012076 0.02351567 0.01136589 0.01367043 - 0.01392008 0.00634258 0. 0.0530404 0.02245571 0.01590784 - 0. 0.03704311 0.05519485 0.00966124 0.0130797 0.01528993 - 0.00145159 0.00298564 0.02297654 0.03740528 0.02934682 0.0101206 0. - 0.02320795 0.04883052 0.0322225 0.01573123 0. 0.04031835 - 0.05886674 0. 0.01637893] + [ 0.03536033 0.03251351 0.00813873 0.00496977 0. 0.08339989 + 0.00948258 0.05751528 0.00236377 0.00868464 0.04443961 0.04691023 + 0.01768388 0. 0.01130552 0.01277964 0.04223144 0.05040177 + 0.01202611 0.0012722 0.00828095 0.11598601 0.01864867 0.01412404 + 0.03343004 0.01772387 0.04780278 0.01351748 0.03616999 0.09074218 + 0. 0. 0.03901368 0.02526396 0.07471888 0.00219886 + 0. 0. 0.01062083 0.07973799 0. 0.01410051 + 0.02025676 0. 0.00988767 0.07519014 0. 0.06380861 + 0. 0.01954769 0.04576145 0.04151243 0. 0.04198926 + 0.0462918 0.07353227 0.00606605 0.02597097 0.02566416 0.00196642 + 0.06240786 0.02996611 0.03252566 0.01451141 0.05149852 0. + 0.03582571 0.04600123 0.03776439 0.03326425 0. 0. + 0.11568858 0.01361223 0.00515358 0.007151 0.00241302 0.00271168 + 0.01780978 0.01867583 0.02020758 0.01254292 0.00054971 0.00698211 + 0.02359226 0.0385241 0.00157871 0.00576513 0.04173662 0.03233332 + 0.0208791 0.02286212 0.04366053 0.03701801 0.02142117 0.03099565 + 0.02555676 0.03365458 0.03542124 0.06174975] References ---------- @@ -232,7 +238,8 @@ def central_point_dominance(g, betweenness): Returns ------- - The central point dominance (float). + cp : float + The central point dominance. See Also -------- @@ -241,10 +248,11 @@ def central_point_dominance(g, betweenness): Notes ----- Let :math:`v^*` be the vertex with the largest relative betweenness - centrality; then, the central point dominance _[freeman_set_1977] is defined + centrality; then, the central point dominance [freeman_set_1977]_ is defined as: - .. math: + .. math:: + C'_B = \frac{1}{|V|-1} \sum_{v} C_B(v^*) - C_B(v) where :math:`C_B(v)` is the normalized betweenness centrality of vertex @@ -254,11 +262,12 @@ def central_point_dominance(g, betweenness): Examples -------- - >>> from numpy.random import poisson + >>> from numpy.random import poisson, seed + >>> seed(42) >>> g = gt.random_graph(100, lambda: (poisson(3), poisson(3)), seed=42) >>> vb, eb = gt.betweenness(g) >>> print gt.central_point_dominance(g, vb) - 0.138990020139 + 0.0902382147799 References ---------- @@ -297,7 +306,7 @@ def eigentrust(g, trust_map, vprop=None, norm=False, epslon=1e-6, max_iter=0, Returns ------- - A vertex property map containing the eigentrust values. + eigentrust : A vertex property map containing the eigentrust values. See Also -------- @@ -310,13 +319,15 @@ def eigentrust(g, trust_map, vprop=None, norm=False, epslon=1e-6, max_iter=0, The eigentrust _[kamvar_eigentrust_2003] values :math:`t_i` correspond the following limit - .. math: + .. math:: + \mathbf{t} = \lim_{n\to\infty} \left(C^T\right)^n \mathbf{c} where :math:`c_i = 1/|V|` and the elements of the matrix :math:`C` are the normalized trust values: - .. math: + .. math:: + c_{ij} = \frac{\max(s_{ij},0)}{\sum_{j} \max(s_{ij}, 0)} The algorithm has a topology-dependent complexity. @@ -330,33 +341,33 @@ def eigentrust(g, trust_map, vprop=None, norm=False, epslon=1e-6, max_iter=0, >>> g = gt.random_graph(100, lambda: (poisson(3), poisson(3)), seed=42) >>> trust = g.new_edge_property("double") >>> trust.get_array()[:] = random(g.num_edges())*42 - >>> t = eigentrust(g, trust, norm=True) + >>> t = gt.eigentrust(g, trust, norm=True) >>> print t.get_array() - [ 9.48423789e-04 1.66078086e-02 3.24301008e-02 2.51269077e-02 - 4.58889062e-03 6.32886469e-03 3.95308763e-03 4.87246882e-03 - 5.53852192e-03 9.37363084e-03 1.17843106e-02 2.65124314e-03 - 4.47045232e-03 2.51950468e-03 1.59255295e-02 6.03159113e-03 - 6.72140367e-03 1.71280616e-03 1.24012407e-02 1.14231095e-02 - 9.85151282e-03 5.56192871e-03 6.74797491e-03 2.63245538e-03 - 9.21152238e-03 8.16728082e-03 3.98587427e-03 1.70045178e-02 - 8.37146815e-03 1.29174460e-02 3.19556744e-03 2.67554442e-03 - 1.24085488e-02 1.17337267e-02 3.13424443e-03 1.66366342e-02 - 1.25374784e-02 2.65548170e-02 2.17676368e-02 1.73783204e-02 - 9.20641085e-03 2.11744591e-02 6.25110430e-03 2.05212010e-03 - 1.43759959e-02 1.63283789e-02 3.17898495e-03 8.86981181e-03 - 4.94416312e-03 1.24896279e-03 1.07967554e-03 3.54578850e-04 - 3.86590892e-04 4.21633271e-02 2.52101241e-03 2.32337004e-02 - 1.69840276e-02 1.61722366e-02 7.24752207e-03 1.03185292e-02 - 2.04849646e-02 1.94466303e-02 2.01785230e-03 9.31938244e-05 - 1.67364460e-02 9.37317475e-03 2.06112300e-03 3.78202160e-03 - 9.33152939e-03 5.00810967e-03 6.95505313e-03 2.49521643e-03 - 4.53346948e-02 3.74770290e-03 6.78252167e-03 2.55396413e-02 - 0.00000000e+00 6.66150362e-03 0.00000000e+00 8.30734676e-03 - 9.81158582e-03 1.36569726e-03 1.27503978e-02 1.07028771e-02 - 7.91984678e-03 1.81615021e-02 8.05566933e-03 6.71131661e-03 - 2.69021984e-02 3.20556792e-03 3.44845723e-03 2.28971468e-04 - 1.76318611e-02 1.25007850e-02 1.06310753e-02 1.33265004e-02 - 1.10624438e-02 0.00000000e+00 2.00750355e-02 5.37349566e-03] + [ 1.86170852e-02 3.54163528e-03 6.09712602e-04 0.00000000e+00 + 0.00000000e+00 3.49545179e-02 0.00000000e+00 2.59814288e-02 + 8.41396546e-04 4.78599541e-03 1.01228999e-02 1.43178181e-02 + 2.24766294e-03 1.80046830e-02 3.55639433e-03 4.24974765e-03 + 1.11631004e-02 3.12332820e-02 6.70174456e-03 1.09689726e-02 + 5.42202976e-03 2.51547994e-02 6.87197775e-03 3.90316493e-03 + 2.81858126e-03 6.26514036e-03 1.12322993e-02 4.35905749e-03 + 1.86938930e-02 1.93055029e-02 3.25522183e-03 9.48081499e-03 + 1.84882500e-02 8.17367673e-03 4.02113149e-02 1.07092572e-02 + 1.02184616e-02 0.00000000e+00 4.21126174e-03 3.97005433e-02 + 0.00000000e+00 6.23025347e-04 1.92797472e-02 5.22705075e-04 + 4.07751175e-03 2.11704089e-02 7.49484415e-03 8.10935540e-03 + 9.47352873e-05 1.74518912e-02 1.18865927e-02 8.49808309e-03 + 8.07449129e-03 6.04464513e-03 1.31497182e-02 1.61277706e-02 + 3.45965628e-03 9.28003800e-03 5.81189874e-03 2.67273946e-03 + 1.33359267e-02 3.99664807e-03 1.45641237e-02 2.06551771e-03 + 1.89334085e-02 2.44376969e-02 7.44521415e-03 6.35266998e-03 + 9.90439343e-03 2.61315207e-02 0.00000000e+00 0.00000000e+00 + 4.08351424e-02 1.21805039e-02 3.45041723e-03 1.84601840e-03 + 1.09623699e-03 2.37115682e-03 1.70221593e-02 4.57709422e-03 + 4.21193747e-03 2.26493986e-02 3.92636239e-03 2.42441556e-03 + 7.41276227e-03 7.01899189e-03 3.30982461e-03 4.18470116e-04 + 8.46801514e-03 9.05050341e-03 5.09784610e-03 3.20304076e-02 + 6.71276214e-03 5.26109355e-03 5.29170118e-03 3.46248974e-03 + 1.10436337e-02 2.20158077e-03 1.26859707e-02 2.25728004e-02] References ---------- @@ -414,12 +425,14 @@ def absolute_trust(g, trust_map, source=None, vprop=None, epslon=0.001, Returns ------- - A vertex property map containing the absolute trust vector from the - corresponding vertex to the rest of the network. Each element i of the - vector is the trust value of the vertex with index i, from the given vertex. + absolute_trust : PropertyMap + A vertex property map containing the absolute trust vector from the + corresponding vertex to the rest of the network. Each e lement i of the + vector is the trust value of the vertex with index i, from the given + vertex. - If the parameter "source" is specified, the values of the property map are - scalars, instead of vectors. + If the parameter "source" is specified, the values of the + property map are scalars, instead of vectors. See Also -------- @@ -431,7 +444,8 @@ def absolute_trust(g, trust_map, source=None, vprop=None, epslon=0.001, ----- The absolute trust between vertices i and j is defined as - .. math: + .. math:: + t_{ij} = \frac{1}{\sum_{\{i\to j\}}w_{\{i\to j\}}}\sum_{\{i\to j\}} w_{\{i\to j\}} \prod_{e\in \{i\to j\}}c_e @@ -439,7 +453,8 @@ def absolute_trust(g, trust_map, source=None, vprop=None, epslon=0.001, :math:`c_e` is the direct trust value associated with edge e, and :math:`w_{\{i\to j\}}` is the weight of a given path, which is defined as - .. math: + .. math:: + w_{\{i\to j\}} = \prod_{e\in \{i\to j\}}\{\delta_{t(e),j}(1-c_e) + c_e\}, such that the direct trust of the last edge on the path is not considered. @@ -458,31 +473,21 @@ def absolute_trust(g, trust_map, source=None, vprop=None, epslon=0.001, >>> trust.get_array()[:] = random(g.num_edges()) >>> t = gt.absolute_trust(g, trust) >>> print array(t[g.vertex(10)]) - [ 1.98147630e-01 3.86048721e-01 2.15038631e-01 6.35971261e-01 - 3.70028165e-01 8.24462513e-01 1.87542375e-04 2.40775039e-03 - 6.63467272e-01 1.30124153e-02 0.00000000e+00 2.55161924e-01 - 6.11894792e-01 1.64132684e-01 1.08372073e-01 3.58317237e-01 - 7.05106201e-02 2.48412716e-07 4.28006145e-01 8.59461489e-04 - 0.00000000e+00 0.00000000e+00 7.25301232e-01 1.01773307e-01 - 3.16379391e-01 2.53316731e-01 1.59819436e-08 3.70296181e-01 - 1.57203884e-01 0.00000000e+00 7.87247979e-01 2.18598076e-04 - 5.52859606e-01 1.24994552e-01 4.20286331e-02 4.15065578e-01 - 6.43653877e-01 3.24950468e-01 7.38208378e-01 7.29509079e-08 - 1.93750752e-01 7.65610195e-01 3.36921596e-01 6.57309628e-01 - 9.52773935e-02 8.03124227e-03 1.30578359e-02 6.88776780e-01 - 1.73090783e-04 4.82732890e-01 6.26331031e-12 5.35175859e-01 - 1.47736985e-01 1.11789227e-01 2.73859867e-01 5.64369671e-01 - 4.18831134e-01 1.98422984e-15 3.58564257e-01 1.27871795e-01 - 4.29322288e-01 1.42919207e-05 3.02946673e-01 3.90436999e-01 - 2.89626434e-01 1.34307383e-01 3.11974410e-01 3.70614146e-01 - 5.33011347e-02 3.81536049e-02 1.01675425e-01 1.45882725e-02 - 3.53278685e-02 5.43455032e-03 6.52215036e-01 3.61707159e-01 - 6.08608841e-02 8.96019737e-04 2.60395071e-02 0.00000000e+00 - 1.86921647e-01 2.49218885e-01 8.22384329e-01 6.75209818e-03 - 5.27060698e-01 1.34291381e-02 3.25840921e-13 7.88987646e-02 - 2.20961189e-03 4.97124982e-01 0.00000000e+00 1.00335219e-02 - 5.50608327e-01 1.65947138e-04 0.00000000e+00 1.32775697e-03 - 6.21862966e-01 5.42485152e-01 5.41292375e-08 3.73524878e-01] + [ 0. 0. 0. 0. 0. 0. 0. + 0. 0. 0. 0. 0. 0. 0. + 0. 0. 0. 0. 0. 0. 0. + 0. 0. 0. 0. 0. 0. 0. + 0. 0. 0. 0. 0. 0. + 0.83889809 0. 0. 0. 0. 0.26116067 + 0. 0. 0. 0. 0. 0. 0. + 0. 0. 0. 0.54758746 0. 0. 0. + 0. 0. 0. 0. 0. 0. 0. + 0. 0. 0. 0. 0. 0. 0. + 0. 0.04949872 0. 0. 0. 0. 0. + 0. 0. 0. 0.05011676 0. 0. 0. + 0. 0. 0. 0.43799071 0. 0. 0. + 0. 0. 0.04054452 0. 0. 0. 0. + 0. 0. 0. 0.17447756] """ if seed != 0: diff --git a/src/graph_tool/clustering/__init__.py b/src/graph_tool/clustering/__init__.py index 696f12f1..ce140a6f 100644 --- a/src/graph_tool/clustering/__init__.py +++ b/src/graph_tool/clustering/__init__.py @@ -90,7 +90,7 @@ def local_clustering(g, prop=None, undirected=False): >>> g = gt.random_graph(1000, lambda: (5,5), seed=42) >>> clust = gt.local_clustering(g) >>> print gt.vertex_average(g, clust) - (0.0045633333333333333, 0.00041406305209606802) + (0.005048478260869565, 0.00043544409486305209) References ---------- @@ -149,7 +149,7 @@ def global_clustering(g): -------- >>> g = gt.random_graph(1000, lambda: (5,5), seed=42) >>> print gt.global_clustering(g) - (0.0086380072318200073, 0.00044516087903790925) + (0.0079235400765494558, 0.00041721619682007839) References ---------- @@ -195,8 +195,8 @@ def extended_clustering(g, props=None, max_depth=3, undirected=False): :math:`d` is defined as .. math:: - c^d_i = \frac{\left|\right\{ \{u,v\}; u,v \in N_i | d_{G(V\diagdown - \{i\})}(u,v) = d \left\}\right|}{\binom{\left|N_i\right|}{2}}, + c^d_i = \frac{\left|\right\{ \{u,v\}; u,v \in N_i | d_{G(V\setminus + \{i\})}(u,v) = d \left\}\right|}{{\left|N_i\right| \choose 2}}, where :math:`d_G(u,v)` is the shortest distance from vertex :math:`u` to :math:`v` in graph :math:`G`, and @@ -221,11 +221,11 @@ def extended_clustering(g, props=None, max_depth=3, undirected=False): >>> for i in xrange(0, 5): ... print gt.vertex_average(g, clusts[i]) ... - (0.0045633333333333333, 0.00041406305209606802) - (0.027705, 0.0010493633929938454) - (0.11730666666666667, 0.00201118990760307) - (0.41394666666666663, 0.0030157036105470745) - (0.41717499999999996, 0.0030272310298907366) + (0.005048478260869565, 0.00043544409486305209) + (0.025116811594202898, 0.00096935403523205497) + (0.11178014492753624, 0.0019836458026216146) + (0.40412130434782606, 0.0030616964103718316) + (0.43449992753623184, 0.003195885251613022) References ---------- @@ -303,11 +303,11 @@ def motifs(g, k, p=1.0, motif_list=None, undirected=None, seed=0): Examples -------- >>> g = gt.random_graph(1000, lambda: (5,5), seed=42) - >>> motifs, counts = gt.motifs(g, 4, undirected=True)) + >>> motifs, counts = gt.motifs(g, 4, undirected=True) >>> print len(motifs) - 11 + 14 >>> print counts - [115708, 390659, 612, 696, 2872, 1556, 811, 4, 8, 6, 1] + [114942, 387657, 958, 1089, 2482, 2760, 844, 6, 16, 14, 8, 10, 16, 8] References ---------- @@ -445,7 +445,7 @@ def motif_significance(g, k, n_shuffles=10, p=1.0, motif_list=None, z_i = \frac{N_i - \left} {\sqrt{\left<(N^s_i)^2\right> - \left^2}}, - where :math:`N_i` is the number of times motif $i$ found, and :math:`N^s_i` + where :math:`N_i` is the number of times motif i found, and :math:`N^s_i` is the count of the same motif but on a shuffled network. It measures how many standard deviations is each motif count, in respect to a ensemble of randomly shuffled graphs with the same degree sequence. @@ -456,12 +456,12 @@ def motif_significance(g, k, n_shuffles=10, p=1.0, motif_list=None, Examples -------- - >>> g = gt.random_graph(1000, lambda: (5,5), seed=42) + >>> g = gt.random_graph(100, lambda: (3,3), seed=42) >>> motifs, zscores = gt.motif_significance(g, 3) >>> print len(motifs) - 11 + 10 >>> print zscores - [0.23425857453240315, 0.23849227914686885, 0.46705666396159251, 0.26171196129510765, -0.28131244310816039, -0.29007872608538582, -0.56694670951384085, -0.5, -0.33333333333333337, -0.46852128566581813, -0.5] + [-3.9501340809971031, -3.96459679349275, -5.95765904191577, -0.17407765595569785, 3.580195875015368, 3.5906624935876583, 2.2739701341354892, 1.8999999999999999, 0.0, -0.20000000000000001] """ from itertools import izip from .. misc import random_rewire, isomorphism @@ -490,17 +490,21 @@ def motif_significance(g, k, n_shuffles=10, p=1.0, motif_list=None, counts.append(0) s_counts = [ x/float(n_shuffles) for x in s_counts ] - s_dev = [ sqrt(x[0]/float(n_shuffles) - x[1]**2) \ + s_dev = [ max(sqrt(x[0]/float(n_shuffles) - x[1]**2),1) \ for x in izip(s_dev,s_counts) ] list_hist = zip(s_ms, s_counts, s_dev) # sort according to in-degree sequence - list_hist.sort(lambda x,y: cmp(sorted([v.in_degree() for v in x[0].vertices()]), - sorted([v.in_degree() for v in y[0].vertices()]))) + list_hist.sort(lambda x,y: cmp(sorted([v.in_degree()\ + for v in x[0].vertices()]), + sorted([v.in_degree()\ + for v in y[0].vertices()]))) # sort according to out-degree sequence - list_hist.sort(lambda x,y: cmp(sorted([v.out_degree() for v in x[0].vertices()]), - sorted([v.out_degree() for v in y[0].vertices()]))) + list_hist.sort(lambda x,y: cmp(sorted([v.out_degree()\ + for v in x[0].vertices()]), + sorted([v.out_degree()\ + for v in y[0].vertices()]))) # sort according to ascending number of edges list_hist.sort(lambda x,y: cmp(x[0].num_edges(), y[0].num_edges())) diff --git a/src/graph_tool/community/__init__.py b/src/graph_tool/community/__init__.py index 0bb296a7..f457569c 100644 --- a/src/graph_tool/community/__init__.py +++ b/src/graph_tool/community/__init__.py @@ -16,6 +16,14 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +``graph_tool.community`` - Community structure +---------------------------------------------- + +This module contains algorithms for the computation of community structure on +graphs. +""" + from .. dl_import import dl_import dl_import("import libgraph_tool_community") diff --git a/src/graph_tool/core.py b/src/graph_tool/core.py index d46d4014..df617b4c 100644 --- a/src/graph_tool/core.py +++ b/src/graph_tool/core.py @@ -224,11 +224,11 @@ from libgraph_tool_core import Vertex, Edge, GraphError,\ new_graph_property class Graph(object): - """This class encapsulates either a directed multigraph (default) or an - undirected multigraph, with optional internal edge, vertex or graph - properties. + """This class encapsulates either a directed multigraph (default or if + ``directed=True``) or an undirected multigraph (if ``directed=False``), with + optional internal edge, vertex or graph properties. - It is implemented as a adjacency list, where both vertex and edge lists are + It is implemented as an adjacency list, where both vertex and edge lists are C++ STL vectors. """ @@ -480,7 +480,8 @@ class Graph(object): >>> g.properties[("e", "foo")] = g.new_edge_property("vector") >>> g.vertex_properties["foo"] = g.new_vertex_property("double") >>> g.vertex_properties["bar"] = g.new_vertex_property("python::object") - >>> g.graph_properties["gnat"] = g.new_graph_property("string") + >>> g.graph_properties["gnat"] = g.new_graph_property("string",\ + "hi there!") >>> g.list_properties() gnat (graph) (type: string, val: hi there!) bar (vertex) (type: python::object) diff --git a/src/graph_tool/correlations/__init__.py b/src/graph_tool/correlations/__init__.py index 32418081..8f4e89ac 100644 --- a/src/graph_tool/correlations/__init__.py +++ b/src/graph_tool/correlations/__init__.py @@ -16,6 +16,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +``graph_tool.correlations`` - Correlations +------------------------------------------ +""" + + from .. dl_import import dl_import dl_import("import libgraph_tool_correlations") @@ -26,23 +32,307 @@ __all__ = ["assortativity", "scalar_assortativity", "corr_hist", "combined_corr_hist", "avg_neighbour_corr", "avg_combined_corr"] def assortativity(g, deg): + r""" + Obtain the assortativity coefficient for the given graph. + + Parameters + ---------- + g : Graph + Graph to be used. + deg : string or PropertyMap + degree type ("in", "out" or "total") or vertex property map, which + specifies the vertex types. + + Returns + ------- + assortativity coefficient : tuple of two floats + The assortativity coefficient, and its variance. + + See Also + -------- + assortativity: assortativity coefficient + scalar_assortativity: scalar assortativity coefficient + corr_hist: vertex-vertex correlation histogram + combined_corr_hist: combined single-vertex correlation histogram + avg_neighbour_corr: average nearest-neighbour correlation + avg_combined_corr: average combined single-vertex correlation + + Notes + ----- + The assortativity coefficient [newman_mixing_2003]_ tells in a concise + fashion how vertices of different types are preferentially connected amongst + themselves, and is defined by + + .. math:: + r = \frac{\sum_i e_{ii} - \sum_i a_i b_i}{1-\sum_i a_i b_i} + + where :math:`a_i=\sum_je_{ij}` and :math:`b_j=\sum_ie_{ij}`, and + :math:`e_{ij}` is the fraction of edges from a vertex of type + i to a vertex of type j. + + + The variance is obtained with the `jackknife method`_. + + If enabled during compilation, this algorithm runs in parallel. + + Examples + -------- + >>> from numpy.random import randint, random, seed + >>> seed(42) + >>> def sample_k(max): + ... accept = False + ... while not accept: + ... k = randint(1,max+1) + ... accept = random() < 1.0/k + ... return k + ... + >>> g = gt.random_graph(1000, lambda: sample_k(40), + ... lambda i,k: 1.0/(1+abs(i-k)), directed=False) + >>> gt.assortativity(g, "out") + (0.12276644944292621, 0.0047979660158573361) + + References + ---------- + .. [newman_mixing_2003] M. E. J. Newman, "Mixing patterns in networks", + Phys. Rev. E 67, 026126 (2003) + .. _jackknife method: http://en.wikipedia.org/wiki/Resampling_%28statistics%29#Jackknife + + """ return libgraph_tool_correlations.\ assortativity_coefficient(g._Graph__graph, _degree(g, deg)) def scalar_assortativity(g, deg): + r""" + Obtain the scalar assortativity coefficient for the given graph. + + Parameters + ---------- + g : Graph + Graph to be used. + deg : string or PropertyMap + degree type ("in", "out" or "total") or vertex property map, which + specifies the vertex types. + + Returns + ------- + scalar assortativity coefficient : tuple of two floats + The scalar assortativity coefficient, and its variance. + + See Also + -------- + assortativity: assortativity coefficient + scalar_assortativity: scalar assortativity coefficient + corr_hist: vertex-vertex correlation histogram + combined_corr_hist: combined single-vertex correlation histogram + avg_neighbour_corr: average nearest-neighbour correlation + avg_combined_corr: average combined single-vertex correlation + + Notes + ----- + + The scalar assortativity coefficient [newman_mixing_2003]_ tells in a + concise fashion how vertices of different types are preferentially connected + amongst themselves, and is defined by + + .. math:: + r = \frac{\sum_{xy} xy(e_{xy} - a_x b_y)}{\sigma_a\sigma_b} + + where :math:`a_x=\sum_ye_{xy}` and :math:`b_y=\sum_xe_{xy}`, and + :math:`e_{xy}` is the fraction of edges from a vertex of type + x to a vertex of type y. + + The variance is obtained with the `jackknife method`_. + + If enabled during compilation, this algorithm runs in parallel. + + Examples + -------- + >>> from numpy.random import randint, random, seed + >>> seed(42) + >>> def sample_k(max): + ... accept = False + ... while not accept: + ... k = randint(1,max+1) + ... accept = random() < 1.0/k + ... return k + ... + >>> g = gt.random_graph(1000, lambda: sample_k(40), lambda i,k: abs(i-k), + ... directed=False) + >>> gt.scalar_assortativity(g, "out") + (-0.41978974341801006, 0.010989368662810171) + >>> g = gt.random_graph(1000, lambda: sample_k(40), + ... lambda i,k: 1.0/(1+abs(i-k)), + ... directed=False, seed=42) + >>> gt.scalar_assortativity(g, "out") + (0.58078830725966446, 0.011882587893677807) + + References + ---------- + .. [newman_mixing_2003] M. E. J. Newman, "Mixing patterns in networks", + Phys. Rev. E 67, 026126 (2003) + .. _jackknife method: http://en.wikipedia.org/wiki/Resampling_%28statistics%29#Jackknife + """ return libgraph_tool_correlations.\ scalar_assortativity_coefficient(g._Graph__graph, _degree(g, deg)) -def corr_hist(g, deg1, deg2, bins=[[1],[1]], weight=None, float_count=True): +def corr_hist(g, deg_source, deg_target, bins=[[1], [1]], weight=None, + float_count=True): + r""" + Obtain the correlation histogram for the given graph. + + Parameters + ---------- + g : Graph + Graph to be used. + deg_source : string or PropertyMap + degree type ("in", "out" or "total") or vertex property map for the + source vertex. + deg_target : string or PropertyMap + degree type ("in", "out" or "total") or vertex property map for the + target vertex. + bins : list of lists (optional, default: [[1], [1]]) + A list of bins to be used for the source and target degrees. If any list + has size 1, it is used as the constant width of an automatically + generated bin range. + weight : edge property map (optional, default: None) + Weight (multiplicative factor) to be used on each edge. + float_count : bool (optional, default: True) + If True, the bin counts are converted float variables, which is useful + for normalization, and other processing. It False, the bin counts will + be unsigned integers. + + Returns + ------- + bin_counts : ndarray + Two-dimensional array with the bin counts. + source_bins : ndarray + Source degree bins + target_bins : ndarray + Target degree bins + + + See Also + -------- + assortativity: assortativity coefficient + scalar_assortativity: scalar assortativity coefficient + corr_hist: vertex-vertex correlation histogram + combined_corr_hist: combined single-vertex correlation histogram + avg_neighbour_corr: average nearest-neighbour correlation + avg_combined_corr: average combined single-vertex correlation + + Notes + ----- + The correlation histogram counts, for every vertex with degree (or scalar + property) 'source_deg', the number of out-neighbours with degree (or scalar + property) 'target_deg'. + + If enabled during compilation, this algorithm runs in parallel. + + Examples + -------- + >>> from numpy.random import randint, random, seed + >>> from pylab import * + >>> seed(42) + >>> def sample_k(max): + ... accept = False + ... while not accept: + ... k = randint(1,max+1) + ... accept = random() < 1.0/k + ... return k + ... + >>> g = gt.random_graph(10000, lambda: sample_k(40), + ... lambda i,j: (sin(i/pi)*sin(j/pi)+1)/2, + ... directed=False) + >>> h = gt.corr_hist(g, "out", "out") + >>> clf() + >>> xlabel("source deg") + <...> + >>> ylabel("target deg") + <...> + >>> imshow(h[0], interpolation="nearest") + <...> + >>> savefig("corr.png") + + .. image:: corr.png + """ + ret = libgraph_tool_correlations.\ - vertex_correlation_histogram(g._Graph__graph, _degree(g, deg1), - _degree(g, deg2), _prop("e", g, weight), - bins[0], bins[1]) + vertex_correlation_histogram(g._Graph__graph, _degree(g, deg_source), + _degree(g, deg_target), + _prop("e", g, weight), bins[0], bins[1]) return [array(ret[0], dtype="float64") if float_count else ret[0], [ret[1][0], ret[1][1]]] def combined_corr_hist(g, deg1, deg2, bins=[[1],[1]], float_count=True): + r""" + Obtain the single-vertex combined correlation histogram for the given graph. + + Parameters + ---------- + g : Graph + Graph to be used. + deg1 : string or PropertyMap + first degree type ("in", "out" or "total") or vertex property map. + deg2 : string or PropertyMap + second degree type ("in", "out" or "total") or vertex property map. + bins : list of lists (optional, default: [[1], [1]]) + A list of bins to be used for the first and second degrees. If any list + has size 1, it is used as the constant width of an automatically + generated bin range. + float_count : bool (optional, default: True) + If True, the bin counts are converted float variables, which is useful + for normalization, and other processing. It False, the bin counts will + be unsigned integers. + + Returns + ------- + bin_counts : ndarray + Two-dimensional array with the bin counts. + first_bins : ndarray + First degree bins + second_bins : ndarray + Second degree bins + + Notes + ----- + If enabled during compilation, this algorithm runs in parallel. + + See Also + -------- + assortativity: assortativity coefficient + scalar_assortativity: scalar assortativity coefficient + corr_hist: vertex-vertex correlation histogram + combined_corr_hist: combined single-vertex correlation histogram + avg_neighbour_corr: average nearest-neighbour correlation + avg_combined_corr: average combined single-vertex correlation + + Examples + -------- + >>> from numpy.random import randint, random, seed + >>> from pylab import * + >>> seed(42) + >>> def sample_k(max): + ... accept = False + ... while not accept: + ... i = randint(1,max+1) + ... j = randint(1,max+1) + ... accept = random() < (sin(i/pi)*sin(j/pi)+1)/2 + ... return i,j + ... + >>> g = gt.random_graph(10000, lambda: sample_k(40)) + >>> h = gt.combined_corr_hist(g, "in", "out") + >>> clf() + >>> xlabel("first deg") + <...> + >>> ylabel("second deg") + <...> + >>> imshow(h[0], interpolation="nearest") + <...> + >>> savefig("combined_corr.png") + + .. image:: combined_corr.png + """ ret = libgraph_tool_correlations.\ vertex_combined_correlation_histogram(g._Graph__graph, _degree(g, deg1), @@ -51,14 +341,155 @@ def combined_corr_hist(g, deg1, deg2, bins=[[1],[1]], float_count=True): return [array(ret[0], dtype="float64") if float_count else ret[0], [ret[1][0], ret[1][1]]] -def avg_neighbour_corr(g, deg1, deg2, bins=[1], weight=None): +def avg_neighbour_corr(g, deg_source, deg_target, bins=[1], weight=None): + r""" + Obtain the average neighbour-neighbour correlation for the given graph. + + Parameters + ---------- + g : Graph + Graph to be used. + deg_source : string or PropertyMap + degree type ("in", "out" or "total") or vertex property map for the + source vertex. + deg_target : string or PropertyMap + degree type ("in", "out" or "total") or vertex property map for the + target vertex. + bins : list (optional, default: [1]) + Bins to be used for the source degrees. If the list has size 1, it is + used as the constant width of an automatically generated bin range. + weight : edge property map (optional, default: None) + Weight (multiplicative factor) to be used on each edge. + + Returns + ------- + bin_avg : ndarray + Array with the deg_target average for the get_source bins. + bin_dev : ndarray + Array with the standard deviation of the deg_target average for the + get_source bins. + bins : ndarray + Source degree bins + + + See Also + -------- + assortativity: assortativity coefficient + scalar_assortativity: scalar assortativity coefficient + corr_hist: vertex-vertex correlation histogram + combined_corr_hist: combined single-vertex correlation histogram + avg_neighbour_corr: average nearest-neighbour correlation + avg_combined_corr: average combined single-vertex correlation + + Notes + ----- + The average correlation is the average, for every vertex with degree (or + scalar property) 'source_deg', the of the 'target_deg' degree (or + scalar property) of its neighbours. + + If enabled during compilation, this algorithm runs in parallel. + + Examples + -------- + >>> from numpy.random import randint, random, seed + >>> from pylab import * + >>> seed(42) + >>> def sample_k(max): + ... accept = False + ... while not accept: + ... k = randint(1,max+1) + ... accept = random() < 1.0/k + ... return k + ... + >>> g = gt.random_graph(10000, lambda: sample_k(40), + ... lambda i,j: (sin(i/pi)*sin(j/pi)+1)/2, + ... directed=False) + >>> h = gt.avg_neighbour_corr(g, "out", "out") + >>> clf() + >>> xlabel("source deg") + <...> + >>> ylabel("target deg") + <...> + >>> errorbar(h[2], h[0], yerr=h[1]) + (...) + >>> savefig("avg_corr.png") + + .. image:: avg_corr.png + """ + ret = libgraph_tool_correlations.\ - vertex_avg_correlation(g._Graph__graph, _degree(g, deg1), - _degree(g, deg2), _prop("e", g, weight), + vertex_avg_correlation(g._Graph__graph, _degree(g, deg_source), + _degree(g, deg_source), _prop("e", g, weight), bins) return [ret[0], ret[1], ret[2][0]] def avg_combined_corr(g, deg1, deg2, bins=[1]): + r""" + Obtain the single-vertex combined correlation histogram for the given graph. + + Parameters + ---------- + g : Graph + Graph to be used. + deg1 : string or PropertyMap + first degree type ("in", "out" or "total") or vertex property map. + deg2 : string or PropertyMap + second degree type ("in", "out" or "total") or vertex property map. + bins : list (optional, default: [1]) + A list of bins to be used for the first degrees. If the list + has size 1, it is used as the constant width of an automatically + generated bin range. + + Returns + ------- + bin_avg : ndarray + Array with the deg2 average for the deg1 bins. + bin_dev : ndarray + Array with the standard deviation of the deg2 average for the deg1 bins. + bins : ndarray + The deg1 bins. + + Notes + ----- + If enabled during compilation, this algorithm runs in parallel. + + + See Also + -------- + assortativity: assortativity coefficient + scalar_assortativity: scalar assortativity coefficient + corr_hist: vertex-vertex correlation histogram + combined_corr_hist: combined single-vertex correlation histogram + avg_neighbour_corr: average nearest-neighbour correlation + avg_combined_corr: average combined single-vertex correlation + + Examples + -------- + >>> from numpy.random import randint, random, seed + >>> from pylab import * + >>> seed(42) + >>> def sample_k(max): + ... accept = False + ... while not accept: + ... i = randint(1,max+1) + ... j = randint(1,max+1) + ... accept = random() < (sin(i/pi)*sin(j/pi)+1)/2 + ... return i,j + ... + >>> g = gt.random_graph(10000, lambda: sample_k(40)) + >>> h = gt.avg_combined_corr(g, "in", "out") + >>> clf() + >>> xlabel("first deg") + <...> + >>> ylabel("second deg") + <...> + >>> errorbar(h[2], h[0], yerr=h[1]) + (...) + >>> savefig("combined_avg_corr.png") + + .. image:: combined_avg_corr.png + """ + ret = libgraph_tool_correlations.\ vertex_avg_combined_correlation(g._Graph__graph, _degree(g, deg1), _degree(g, deg2), bins) diff --git a/src/graph_tool/draw/__init__.py b/src/graph_tool/draw/__init__.py index abaa76f6..13454868 100644 --- a/src/graph_tool/draw/__init__.py +++ b/src/graph_tool/draw/__init__.py @@ -16,9 +16,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +``graph_tool.draw`` - Graph Drawing +----------------------------------- +""" + import sys, os, os.path, time, warnings -import matplotlib.cm -import matplotlib.colors from .. core import _degree, _prop, PropertyMap from .. decorators import _limit_args @@ -27,6 +30,12 @@ try: except ImportError: warnings.warn("error importing gv module... graph_draw() will not work.", ImportWarning) +try: + import matplotlib.cm + import matplotlib.colors +except ImportError: + warnings.warn("error importing matplotlib module... " + \ + "graph_draw() will not work.", ImportWarning) def graph_draw(g, pos=None, size=(15,15), pin=False, layout="neato", maxiter=None, ratio="fill", overlap=False, splines=False, diff --git a/src/graph_tool/generation/__init__.py b/src/graph_tool/generation/__init__.py index e1402425..b2aba396 100644 --- a/src/graph_tool/generation/__init__.py +++ b/src/graph_tool/generation/__init__.py @@ -16,6 +16,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +``graph_tool.generation`` - Random Graph Generation +--------------------------------------------------- +""" + from .. dl_import import dl_import dl_import("import libgraph_tool_generation") diff --git a/src/graph_tool/misc/__init__.py b/src/graph_tool/misc/__init__.py index 2b828cd2..91f4e383 100644 --- a/src/graph_tool/misc/__init__.py +++ b/src/graph_tool/misc/__init__.py @@ -16,6 +16,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +``graph_tool.misc`` - Miscellaneous functions +--------------------------------------------- +""" + from .. dl_import import dl_import dl_import("import libgraph_tool_misc") diff --git a/src/graph_tool/run_action/__init__.py b/src/graph_tool/run_action/__init__.py index fee02792..67fc1c29 100644 --- a/src/graph_tool/run_action/__init__.py +++ b/src/graph_tool/run_action/__init__.py @@ -17,8 +17,11 @@ # along with this program. If not, see . """ +``graph_tool.run_action`` - Inline C++ code embedding +----------------------------------------------------- + This module implements support for automatic ad-hoc code embedding into -graph-tool +graph-tool. """ __all__ = ["inline"] diff --git a/src/graph_tool/run_action/inline.py b/src/graph_tool/run_action/inline.py index 116ee939..bb1880b2 100644 --- a/src/graph_tool/run_action/inline.py +++ b/src/graph_tool/run_action/inline.py @@ -67,13 +67,43 @@ def get_graph_type(g): return libgraph_tool_core.get_graph_type(g._Graph__graph) def inline(code, arg_names=[], local_dict=None, - global_dict=None, force=0, compiler="gcc", verbose=0, + global_dict=None, force=False, compiler="gcc", verbose=False, auto_downcast=1, support_code="", libraries=[], library_dirs=[], extra_compile_args=[], runtime_library_dirs=[], extra_objects=[], extra_link_args=[], mask_ret=[], debug=False): """Compile (if necessary) and run the C++ action specified by 'code', - using weave.""" + using weave. The (possibly modified) variables in 'arg_names' are returned. + + Parameters + ---------- + code : string + C++ code to be used + arg_names : list, optional (default: []) + List of variables to be passed to the C++ code + local_dict : dict, optional (default: None) + Dictionary of variables to be used as local scope. If none is specified, + the calling functions' local variables are used. + global_dict : dict, optional (default: None) + Dictionary of variables to be used as global scope. If none is + specified, the calling functions' global variables are used. + force : bool, optional (default: False) + If true, compilation is forced. + compiler : string, optional (default: "gcc") + The name of compiler to use when compiling. On windows, it understands + 'msvc' and 'gcc' as well as all the compiler names understood by + distutils. On Unix, it'll only understand the values understood by + distutils. + + On windows, the compiler defaults to the Microsoft C++ compiler. If + this isn't available, it looks for mingw32 (the gcc compiler). + + On Unix, it'll probably use the same compiler that was used when + compiling Python. Cygwin's behavior should be similar. + + + [...] + """ # each term on the expansion will properly unwrap a tuple pointer value # to a reference with the appropriate name and type @@ -200,9 +230,9 @@ def inline(code, arg_names=[], local_dict=None, # call weave and pass all the updated kw arguments ret_vals = \ - scipy.weave.inline(inline_code, arg_alias, force=force, + scipy.weave.inline(inline_code, arg_alias, force=int(force), local_dict=alias_dict, global_dict=global_dict, - compiler=compiler, verbose=verbose, + compiler=compiler, verbose=int(verbose), auto_downcast=auto_downcast, support_code=support_code, libraries=libraries, diff --git a/src/graph_tool/stats/__init__.py b/src/graph_tool/stats/__init__.py index 0e4d8f55..32d64d89 100644 --- a/src/graph_tool/stats/__init__.py +++ b/src/graph_tool/stats/__init__.py @@ -16,6 +16,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +``graph_tool.stats`` - Graph Statistics +--------------------------------------- +""" + from .. dl_import import dl_import dl_import("import libgraph_tool_stats") @@ -27,30 +32,267 @@ __all__ = ["vertex_hist", "edge_hist", "vertex_average", "edge_average", "label_self_loops", "remove_self_loops", "remove_labeled_edges"] def vertex_hist(g, deg, bins=[1], float_count=True): + """ + Return the vertex histogram of the given degree type or property. + + Parameters + ---------- + g : Graph + Graph to be used. + + deg : string or PropertyMap + Degree or property to be used for the histogram. It can be either "in", + "out" or "total", for in-, out-, or total degree of the vertices. It can + also be a vertex property map. + + bins : list of bins + List of bins to be used for the histogram. The values given represent + the edges of the bins (i,e, lower bounds). If the list contains only one + value, this will be used to automatically create an appropriate bin + range, with a constant lenght given by this value. + + float_count : bool (optional, default: True) + If True, the counts in each histogram bin will be returned as floats. If + False, they will be returned as integers. + + Returns + ------- + counts : ndarray + The bin counts. + + bins : ndarray + The bin edges. + + See Also + -------- + edge_hist: Edge histograms. + vertex_average: Average of vertex properties, degrees. + edge_average: Average of edge properties. + + Notes + ----- + The algorithm runs in :math:`O(|V|)` time. + + If enabled during compilation, this algorithm runs in parallel. + + Examples + -------- + >>> from numpy.random import poisson, seed + >>> seed(42) + >>> g = gt.random_graph(1000, lambda: (poisson(5), poisson(5)), seed=42) + >>> print gt.vertex_hist(g, "out") + [array([ 10., 35., 92., 140., 162., 160., 150., 109., 66., + 37., 26., 10., 2., 1.]), array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], dtype=uint64)] + + """ + ret = libgraph_tool_stats.\ get_vertex_histogram(g._Graph__graph, _degree(g, deg), bins) return [array(ret[0], dtype="float64") if float_count else ret[0], ret[1]] def edge_hist(g, eprop, bins=[1], float_count=True): + """ + Return the edge histogram of the given property. + + Parameters + ---------- + g : Graph + Graph to be used. + + eprop : PropertyMap + Edge property to be used for the histogram. + + bins : list of bins + List of bins to be used for the histogram. The values given represent + the edges of the bins (i,e, lower bounds). If the list contains only one + value, this will be used to automatically create an appropriate bin + range, with a constant lenght given by this value. + + float_count : bool (optional, default: True) + If True, the counts in each histogram bin will be returned as floats. If + False, they will be returned as integers. + + Returns + ------- + counts : ndarray + The bin counts. + + bins : ndarray + The bin edges. + + See Also + -------- + vertex_hist : Vertex histograms. + vertex_average : Average of vertex properties, degrees. + edge_average : Average of edge properties. + + Notes + ----- + The algorithm runs in :math:`O(|E|)` time. + + If enabled during compilation, this algorithm runs in parallel. + + Examples + -------- + >>> from numpy import arange + >>> from numpy.random import random + >>> g = gt.random_graph(1000, lambda: (5, 5), seed=42) + >>> eprop = g.new_edge_property("double") + >>> eprop.get_array()[:] = random(g.num_edges()) + >>> print gt.edge_hist(g, eprop, arange(0, 1, 0.1)) + [array([ 500., 440., 487., 494., 507., 496., 524., 526., 486., 540.]), array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])] + + """ + ret = libgraph_tool_stats.\ get_edge_histogram(g._Graph__graph, _prop("e", g, eprop), bins) return [array(ret[0], dtype="float64") if float_count else ret[0], ret[1]] def vertex_average(g, deg): + """ + Return the average of the given degree or vertex property. + + Parameters + ---------- + g : Graph + Graph to be used. + + deg : string or PropertyMap + Degree or property to be used for the histogram. It can be either "in", + "out" or "total", for in-, out-, or total degree of the vertices. It can + also be a vertex property map. + + Returns + ------- + average : float + The average of the given degree or property. + + std : float + The standard deviation of the average. + + See Also + -------- + vertex_hist : Vertex histograms. + edge_hist : Edge histograms. + edge_average : Average of edge properties. + + Notes + ----- + The algorithm runs in :math:`O(|V|)` time. + + If enabled during compilation, this algorithm runs in parallel. + + Examples + -------- + >>> from numpy.random import poisson, seed + >>> seed(42) + >>> g = gt.random_graph(1000, lambda: (poisson(5), poisson(5)), seed=42) + >>> print gt.vertex_average(g, "in") + (5.0179999999999998, 0.072661379012512559) + """ + ret = libgraph_tool_stats.\ get_vertex_average(g._Graph__graph, _degree(g, deg)) return ret def edge_average(g, eprop): + """ + Return the average of the given degree or vertex property. + + Parameters + ---------- + g : Graph + Graph to be used. + + eprop : PropertyMap + Edge property to be used for the histogram. + + Returns + ------- + average : float + The average of the given property. + + std : float + The standard deviation of the average. + + See Also + -------- + vertex_hist : Vertex histograms. + edge_hist : Edge histograms. + vertex_average : Average of vertex degree, properties. + + Notes + ----- + The algorithm runs in :math:`O(|E|)` time. + + If enabled during compilation, this algorithm runs in parallel. + + Examples + -------- + >>> from numpy import arange + >>> from numpy.random import random + >>> g = gt.random_graph(1000, lambda: (5, 5), seed=42) + >>> eprop = g.new_edge_property("double") + >>> eprop.get_array()[:] = random(g.num_edges()) + >>> print gt.edge_average(g, eprop) + (0.50951471604395204, 0.0040790901147649975) + """ + ret = libgraph_tool_stats.\ get_edge_average(g._Graph__graph, _prop("e", g, eprop)) return ret -def label_components(g, vprop=None): +def label_components(g, vprop=None, directed=None): + """ + Labels the components to which each vertex in the graph belongs. If the + graph is directed, it finds the strongly connected components. + + Parameters + ---------- + g : Graph + Graph to be used. + + vprop : PropertyMap (optional, default: None) + Vertex property to store the component labels. If none is supplied, one + is created. + + directed : bool (optional, default:None) + Treat graph as directed or not, independently of its actual + directionality. + + Returns + ------- + comp : PropertyMap + Vertex property map with component labels. + + Notes + ----- + The components are arbitrarily labeled from 0 to N-1, where N is the total + number of components. + + The algorithm runs in :math:`O(|V| + |E|)` time. + + Examples + -------- + >>> g = gt.random_graph(100, lambda: (1, 1), seed=42) + >>> comp = gt.label_components(g) + >>> print comp.get_array() + [0 1 2 3 4 0 3 3 4 4 2 3 4 0 3 3 3 3 0 3 2 1 3 0 0 2 2 3 3 3 0 1 2 3 2 3 0 + 1 0 5 5 1 4 2 2 1 0 3 3 3 3 3 3 0 0 3 4 2 3 2 5 5 0 2 1 0 3 2 0 3 3 0 4 3 + 2 6 2 2 1 3 1 1 0 3 0 1 3 0 3 0 2 0 2 2 0 6 1 1 0 2] + """ + + if directed != None: + g.stash_filter(directed=True) + g.set_directed(directed) + if vprop == None: vprop = g.new_vertex_property("int32_t") libgraph_tool_stats.\ label_components(g._Graph__graph, _prop("v", g, vprop)) + + if directed != None: + g.pop_filter(directed=True) return vprop def remove_labeled_edges(g, label): diff --git a/src/graph_tool/util/__init__.py b/src/graph_tool/util/__init__.py index ca31d129..048282d0 100644 --- a/src/graph_tool/util/__init__.py +++ b/src/graph_tool/util/__init__.py @@ -16,6 +16,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +""" +``graph_tool.util`` - Graph Utilities +------------------------------------- +""" + + from .. dl_import import dl_import dl_import("import libgraph_tool_util") -- GitLab