Commit 49f2ec3b authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Diverse documentation improvements

This better organizes the documentation of the Graph class and provides
other small fixes.
parent f96eec9e
......@@ -223,10 +223,12 @@ latex_elements = {
# Example configuration for intersphinx: refer to the Python standard library.
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}
intersphinx_mapping = {'python': ('http://docs.python.org', None),
'numpy': ('http://docs.scipy.org/doc/numpy', None),
'scipy': ('http://docs.scipy.org/doc/scipy/reference',
None),
'matplotlib': ('http://matplotlib.sourceforge.net',
None)}
extlinks = {'ticket': ('http://projects.skewed.de/graph-tool/ticket/%s',
'ticket '),
......
.. automodule:: graph_tool
.. autoclass:: Graph
:members:
.. automethod:: copy
.. container:: sec_title
Iterating over vertices and edges
See :ref:`sec_iteration` for more documentation and examples.
.. automethod:: vertices
.. automethod:: edges
.. container:: sec_title
Obtaining vertex and edge descriptors
.. automethod:: vertex
.. automethod:: edge
.. container:: sec_title
Number of vertices and edges
.. automethod:: num_vertices
.. automethod:: num_edges
.. container:: sec_title
Modifying vertices and edges
The following functions allow for addition and removal of
vertices in the graph.
.. automethod:: add_vertex
.. automethod:: remove_vertex
.. automethod:: remove_vertex_if
The following functions allow for addition and removal of
edges in the graph.
.. automethod:: add_edge
.. automethod:: remove_edge
.. automethod:: remove_edge_if
The following functions allow for easy removal of vertices of
edges from the graph.
.. automethod:: clear
.. automethod:: clear_vertex
.. automethod:: clear_edges
.. container:: sec_title
Directedness and reversal of edges
.. note::
These functions do not actually modify the graph, and are fully
reversible. They are also very cheap, and have an :math:`O(1)`
complexity.
.. automethod:: set_directed
.. automethod:: is_directed
.. automethod:: set_reversed
.. automethod:: is_reversed
.. container:: sec_title
Creation of new property maps
.. automethod:: new_property
.. automethod:: new_vertex_property
.. automethod:: new_edge_property
.. automethod:: new_graph_property
New property maps can be created by copying already existing
ones.
.. automethod:: copy_property
.. automethod:: degree_property_map
.. container:: sec_title
Index property maps
.. autoattribute:: vertex_index
.. autoattribute:: edge_index
.. autoattribute:: max_edge_index
.. automethod:: reindex_edges
.. container:: sec_title
Internal property maps
Internal property maps are just like regular property maps, with
the only exception that they are saved and loaded to/from files
together with the graph itself. See :ref:`internal property maps <sec_internal_props>`
for more details.
All dictionaries below are mutable.
.. autoattribute:: properties
.. autoattribute:: vertex_properties
.. autoattribute:: edge_properties
.. autoattribute:: graph_properties
.. automethod:: list_properties
.. container:: sec_title
Filtering of vertices and edges.
See :ref:`sec_graph_filtering` for more details.
.. note::
These functions do not actually modify the graph, and are fully
reversible. They are also very cheap, and have an :math:`O(1)`
complexity.
.. automethod:: set_vertex_filter
.. automethod:: get_vertex_filter
.. automethod:: set_edge_filter
.. automethod:: get_edge_filter
.. warning::
The purge functions below irreversibly remove the filtered
vertices or edges from the graph, and return it to an
unfiltered state. Note that, contrary to the functions above,
these are :math:`O(V)` and :math:`O(E)` operations,
respectively.
.. automethod:: purge_vertices
.. automethod:: purge_edges
.. container:: sec_title
Stashing and popping the filter state
.. automethod:: stash_filter
.. automethod:: pop_filter
.. automethod:: get_filter_state
.. automethod:: set_filter_state
.. container:: sec_title
I/O operations
See :ref:`sec_graph_io` for more details.
.. automethod:: load
.. automethod:: save
.. autoclass:: GraphView
:show-inheritance:
:members:
......
......@@ -58,3 +58,39 @@ table.citation td, table.citation th, table.citation {
border: 0px;
padding: 0.25em 0.7em;
}
.container.sec-title {
font-size: 150%;
font-weight: normal;
margin: 30px 0px 10px 0px;
margin-bottom: 1em;
border-bottom: 1px solid #BBBBBB;
padding: 0;
padding-bottom: 0.2em;
}
div.admonition {
margin-left: 0em;
padding-left: 1em;
width: 80%;
}
div.admonition p.admonition-title + p {
margin-top: 0.5em;
}
dl dl pre {
margin-left: 0;
padding-left: 1em;
}
dl pre {
margin-left: 0;
padding-left: 1em;
}
pre {
margin-left: 0;
padding-left: 1em;
}
......@@ -361,6 +361,8 @@ Property maps with scalar value types can also be accessed as a
# or more conveniently (this is equivalent to the above)
vprop_double.a = random(g.num_vertices())
.. _sec_internal_props:
Internal property maps
^^^^^^^^^^^^^^^^^^^^^^
......@@ -381,6 +383,7 @@ type):
>>> g.list_properties()
some name (edge) (type: string)
.. _sec_graph_io:
Graph I/O
---------
......@@ -468,6 +471,8 @@ use the :func:`~graph_tool.draw.graph_draw` function.
A Price network with :math:`10^5` nodes. The vertex colors represent
the age of the vertex, from older (red) to newer (blue).
.. _sec_graph_filtering:
Graph filtering
---------------
......@@ -562,6 +567,8 @@ operation, which does not really modify the graph.
As mentioned previously, the directedness of the graph can also be changed
"on-the-fly" with the :meth:`~graph_tool.Graph.set_directed` method.
.. _sec_graph_views:
Graph views
^^^^^^^^^^^
......
......@@ -311,11 +311,11 @@ struct export_python_interface
class_<PythonEdge<Graph> >
("Edge", no_init)
.def("source", &PythonEdge<Graph>::GetSource,
"Return the source vertex")
"Return the source vertex.")
.def("target", &PythonEdge<Graph>::GetTarget,
"Return the target vertex")
"Return the target vertex.")
.def("is_valid", &PythonEdge<Graph>::IsValid,
"Return whether the edge is valid")
"Return whether the edge is valid.")
.def(python::self == python::self)
.def(python::self != python::self)
.def("__str__", &PythonEdge<Graph>::GetString)
......@@ -391,15 +391,15 @@ void export_python_interface()
class_<PythonVertex>
("Vertex", no_init)
.def("in_degree", &PythonVertex::GetInDegree,
"Return the in-degree")
"Return the in-degree.")
.def("out_degree", &PythonVertex::GetOutDegree,
"Return the out-degree")
"Return the out-degree.")
.def("out_edges", &PythonVertex::OutEdges,
"Return an iterator over the out-edges")
"Return an iterator over the out-edges.")
.def("in_edges", &PythonVertex::InEdges,
"Return an iterator over the in-edges")
"Return an iterator over the in-edges.")
.def("is_valid", &PythonVertex::IsValid,
"Return whether the vertex is valid")
"Return whether the vertex is valid.")
.def(python::self == python::self)
.def(python::self != python::self)
.def("__str__", &PythonVertex::GetString)
......
......@@ -43,7 +43,7 @@ Summary
This module provides:
1. A Graph object for graph representation and manipulation
1. A :class:`~graph_tool.Graph` class for graph representation and manipulation
2. Property maps for Vertex, Edge or Graph.
3. Fast algorithms implemented in C++.
......@@ -325,7 +325,9 @@ class PropertyArray(numpy.ndarray):
class PropertyMap(object):
"""This class provides a mapping from vertices, edges or whole graphs to arbitrary properties.
The possible property types are listed below.
See :ref:`sec_property_maps` for more details.
The possible property value types are listed below.
.. table::
......@@ -426,7 +428,13 @@ class PropertyMap(object):
def get_array(self):
"""Get a :class:`~graph_tool.PropertyArray` with the property values.
.. WARNING::
.. note::
An array is returned *only if* the value type of the property map is
a scalar. For vector, string or object types, ``None`` is returned
instead.
.. warning::
The returned array does not own the data, which belongs to the
property map. Therefore, if the graph changes, the array may become
......@@ -642,14 +650,13 @@ def group_vector_property(props, value_type=None, vprop=None, pos=None):
g.stash_filter(directed=True, reversed=True)
g.set_directed(True)
g.set_reversed(False)
libcore.group_vector_property(g._Graph__graph,
_prop(k, g, vprop),
libcore.group_vector_property(g._Graph__graph, _prop(k, g, vprop),
_prop(k, g, p),
i if pos == None else pos[i],
k == 'e')
g.pop_filter(directed=True, reversed=True)
else:
vprop[g][i if pos == None else pos[i]] = p[g]
vprop[g][i if pos is None else pos[i]] = p[g]
return vprop
......@@ -852,18 +859,18 @@ class Graph(object):
"add_vertex": True, "del_vertex": True}
def copy(self):
"""Return a deep copy of self. All internal property maps are also
copied."""
"""Return a deep copy of self. All :ref:`internal property maps <sec_internal_props>`
are also copied."""
return Graph(self)
def __repr__(self):
# provide some more useful information
# provide more useful information
d = "directed" if self.is_directed() else "undirected"
fr = ", reversed" if self.is_reversed() and self.is_directed() else ""
f = ""
if self.get_edge_filter()[0] != None:
if self.get_edge_filter()[0] is not None:
f += ", edges filtered by %s" % (str(self.get_edge_filter()))
if self.get_vertex_filter()[0] != None:
if self.get_vertex_filter()[0] is not None:
f += ", vertices filtered by %s" % (str(self.get_vertex_filter()))
n = self.num_vertices()
e = self.num_edges()
......@@ -880,7 +887,13 @@ class Graph(object):
raise RuntimeError("the graph cannot be modified at this point!")
def vertices(self):
"""Return an iterator over the vertices.
"""Return an :meth:`iterator <iterator.__iter__>` over the vertices.
.. note::
The order of the vertices traversed by the iterator **always**
corresponds to the vertex index ordering, as given by the
:attr:`~graph_tool.Graph.vertex_index` property map.
Examples
--------
......@@ -929,7 +942,19 @@ class Graph(object):
return None
def edges(self):
"""Return an iterator over the edges."""
"""Return an :meth:`iterator <iterator.__iter__>` over the edges.
.. note::
The order of the edges traversed by the iterator **does not**
necessesarly correspond to the edge index ordering, as given by the
:attr:`~graph_tool.Graph.edge_index` property map. This will only
happen after :meth:`~graph_tool.Graph.reindex_edges` is called, or in
certain situations such as just after a graph is loaded from a
file. However, further manipulation of the graph may destroy the
ordering.
"""
return libcore.get_edges(weakref.ref(self.__graph))
def add_vertex(self, n=1):
......@@ -1029,8 +1054,8 @@ class Graph(object):
doc=
"""Dictionary of internal properties. Keys must always be a tuple, where the
first element if a string from the set {'v', 'e', 'g'}, representing a
vertex, edge or graph property, and the second element is the name of the
property map.
vertex, edge or graph property, respectively, and the second element is the
name of the property map.
Examples
--------
......@@ -1040,8 +1065,8 @@ class Graph(object):
""")
def __get_specific_properties(self, t):
props = dict([(k[1], v) for k,v in self.__properties.iteritems() \
if k[0] == t ])
props = dict([(k[1], v) for k, v in self.__properties.iteritems() \
if k[0] == t])
return props
# vertex properties
......@@ -1051,7 +1076,7 @@ class Graph(object):
lambda g, k, v: g.__set_property("v", k, v),
lambda g, k: g.__del_property("v", k))
vertex_properties = property(__get_vertex_properties,
doc="Dictionary of vertex properties")
doc="Dictionary of internal vertex properties. The keys are the property names.")
# edge properties
def __get_edge_properties(self):
......@@ -1060,7 +1085,7 @@ class Graph(object):
lambda g, k, v: g.__set_property("e", k, v),
lambda g, k: g.__del_property("e", k))
edge_properties = property(__get_edge_properties,
doc="Dictionary of edge properties")
doc="Dictionary of internal edge properties. The keys are the property names.")
# graph properties
def __get_graph_properties(self):
......@@ -1069,10 +1094,10 @@ class Graph(object):
lambda g, k, v: g.__set_property("g", k, v),
lambda g, k: g.__del_property("g", k))
graph_properties = property(__get_graph_properties,
doc="Dictionary of graph properties")
doc="Dictionary of internal graph properties. The keys are the property names.")
def list_properties(self):
"""List all internal properties.
"""Print a list of all internal properties.
Examples
--------
......@@ -1111,11 +1136,42 @@ class Graph(object):
def _get_vertex_index(self):
return self.__vertex_index
vertex_index = property(_get_vertex_index,
doc="Vertex index map. This map is immutable.")
doc="""Vertex index map.
It maps for each vertex in the graph an unique
integer in the range [0, :meth:`~graph_tool.Graph.num_vertices` - 1].
.. note::
This is a special instance of a :class:`~graph_tool.PropertyMap`
class, which is **immutable**, and cannot be
accessed as an array.""")
def _get_edge_index(self):
return self.__edge_index
edge_index = property(_get_edge_index, doc="Edge index map.")
edge_index = property(_get_edge_index, doc="""Edge index map.
It maps for each edge in the graph an unique
integer.
.. warning::
Differently from :attr:`~graph_tool.Graph.vertex_index`,
this is a **regular** instance of a :class:`~graph_tool.PropertyMap`
class, and is therefore **mutable**!
Additionally, the indexes may not necessarily
lie in the range [0, :meth:`~graph_tool.Graph.num_edges` - 1].
However this will always happen whenever no
edges are deleted from the graph.
The internal consistency expected by most
algorithms and the proper functioning of
property maps assume that the indexes are unique
and constant, which is guaranteed by the
library. Therefore it is recommended **never**
to modify these values, unless you know what you
are doing.""")
def _get_max_edge_index(self):
return self.__graph.GetMaxEdgeIndex()
......@@ -1132,8 +1188,8 @@ class Graph(object):
Calling this function will invalidate all existing edge property
maps, if the index ordering is modified! The property maps will still
be usable, but their contents will still be tied to the old indices,
and thus may be scrambled.
be usable, but their contents will still be tied to the old indexes,
and thus may become scrambled.
"""
self.__graph.ReIndexEdges()
......@@ -1405,11 +1461,23 @@ class Graph(object):
# ======================
def num_vertices(self):
"""Get the number of vertices."""
"""Get the number of vertices.
.. note::
If the vertices are being filtered, this operation is
:math:`O(N)`. Otherwise it is :math:`O(1)`.
"""
return self.__graph.GetNumberOfVertices()
def num_edges(self):
"""Get the number of edges."""
"""Get the number of edges.
.. note::
If the edges are being filtered, this operation is
:math:`O(E)`. Otherwise it is :math:`O(1)`.
"""
return self.__graph.GetNumberOfEdges()
# Pickling support
......@@ -1467,7 +1535,11 @@ from libgraph_tool_core import Vertex, Edge
Vertex.__doc__ = """Vertex descriptor.
This class represents a vertex in a :class:`~graph_tool.Graph`."""
This class represents a vertex in a :class:`~graph_tool.Graph` instance.
:class:`~graph_tool.Vertex` instances are hashable, and are convertible to
integers, corresponding to its index (see :attr:`~graph_tool.Graph.vertex_index`).
"""
def _out_neighbours(self):
......@@ -1510,7 +1582,11 @@ Vertex.__repr__ = _vertex_repr
_edge_doc = """Edge descriptor.
This class represents an edge in a :class:`~graph_tool.Graph`."""
This class represents an edge in a :class:`~graph_tool.Graph`.
:class:`~graph_tool.Edge` instances are hashable, and are convertible to a
tuple, which contains the source and target vertices.
"""
def _edge_iter(self):
......@@ -1578,7 +1654,8 @@ class GraphView(Graph):
This class uses shared data from another :class:`~graph_tool.Graph`
instance, but allows for local filtering of vertices and/or edges, edge
directionality or reversal.
directionality or reversal. See :ref:`sec_graph_views` for more details and
examples.
The existence of a :class:`~graph_tool.GraphView` object does not affect the
original graph, except if the graph view is modified (addition or removal of
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment