igraph Reference Manual
***********************

1 Introduction
**************

This is another library for creating and manipulating graphs.  You can
look at it two ways: first, igraph contains the implementation of quite
a lot graph algorithms. These include classic graph algorithms like
graph isomorphism, graph girth and connectivity and also the new wave
graph algorithms like transitivity, graph motifs and community
structure detection. Skim through the table of contents or the index of
this book to get an impression.

   Second, igraph provides a platform for the developing and/or
implementing graph algorithms. It has a quite efficient data structure
for representing graphs and a number of other data structures like
flexible vectors, stacks, heaps, queues, adjacency lists to accomplish
this. In fact these data structures evolved along the implementation of
the classic and non-classic graph algorithms which make up the major
part of the igraph library. This way they were fine tuned and checked
for correctness several times.

   Our main goal with developing igraph was to create a graph library
which is efficient on large but not extremely large graphs. More
precisely, it is assumed that the graph(s) fit into the physical memory
of the computer. Nowadays this means graphs with several million
vertices and/or edges. Our definition of efficient is that it runs
fast, both in theory and (more importantly) in practice.

   We believe that one of the big strengths of igraph is that it can be
embedded into a higher level language or environment. Two such
embeddings (or interfaces if you look at them the other way) are
currently being developed by us: igraph as a GNU R package and igraph
as a Python extension module. A third embedding, being developed by
another developer is a Ruby extension. Other are likely to come. The
high level languages as R or Python make it possible to do use graph
routines with mush greater comfort, without actually writing a single
line of C code. They have some, usually very small, speed penalty
compared to the C version, but add ease and much flexibility. This
manual however covers only the C library. If you want to use Python or
GNU R, please see the documentation written specifically for these
interfaces and come back here only if you're interested in some detail
which is not covered in those documents.

   We still consider igraph as a child project. It has much room for
development and we are sure that it will improve a lot in the near
future. Any feedback we can get from the users is very important for
us, as most of the time these questions and comments guide us in what
to add and what to improve.

   igraph is open source and distributed under the terms of the GNU GPL.
We strongly believe that all the algorithms used in science, let that
be graph theory or not, should have an efficient open source
implementation allowing use and modification for anyone.

1.1 igraph is free software
===========================

igraph library

   Copyright (C) 2003, 2004, 2005  Gabor Csardi <csardi@rmki.kfki.hu>
MTA RMKI, Konkoly-Thege Miklos st. 29-33, Budapest 1121, Hungary

   This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.

   This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

   You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

1.2 Citing igraph
=================

To cite igraph in publications, please use the following reference:

   Ga'bor Csa'rdi, Tama's Nepusz: The igraph software package for
complex network research. InterJournal Complex Systems, 1695, 2006.

2 Installation
**************

First download the latest version of `igraph' from `igraph' homepage
(http://cneurocvs.rmki.kfki.hu/igraph) or from SourceForge
(http://sourceforge.net/project/showfiles.php?group_id=160289), and
uncompress it to a temporary directory:

     $ wget http://cneurocvs.rmki.kfki.hu/igraph/download/igraph-0.2.tar.gz
     $ tar xzf igraph-0.2.tar.gz
     $ cd igraph-0.2

   To install the complete C library typing

     $ ./configure
     $ make
     $ make install

(the latter as root) should work on most systems. You can try

     $ ./configure --help

to see installations options, and reading the `INSTALL' file.

   Installing the `igraph' R package is very simple, you don't need to
download anything by hand, just give the command

     > install.packages("igraph", lib="~/.R/library")

in R and select a mirror site close to you. The `lib' argument
specifies the directory to which the package will be installed. If not
specified, this will be default system wide R package directory. You
must have write permissions for this directory.

   Also, consult your R documentation.

   Installing the `igraph' Python package is a little bit more
difficult, since chances are that you have to compile it for yourself
(as long as there is no compile farm at the Python Package Index and we
can't compile it ourselves to all platforms). First, check if there is
a compiled version available for your system at igraph's Python Package
Index page (http://www.python.org/pypi/igraph). If there is, just use
that. (Python eggs should be put anywhere in your Python library path,
executable installers should be executed of course). If there isn't,
you'll have to compile it by hand. So, first install a recent C
compiler.

   We usually compile `igraph' with the GNU C compiler
(http://gcc.gnu.org). If you are a Windows user, you can find it as
part of the Cygwin (http://www.cygwin.com) environment or in the
MinGW+MSYS (http://www.mingw.org) project. You can also try Microsoft's
free C compiler suite (or even worse, Visual Studio), but there are
known issues with the compilation of `igraph' in MSVC, and you'll have
to resolve them yourself by tweaking the source code. (Patches are
welcome! :)). If you use Linux, `gcc' is usually included in your
default system, but even if it isn't, there will be a package from
which you can install it. (In Debian and Ubuntu Linux, you'll have to
install the package called `build-essential').  If you have a Mac,
`gcc' is part of the Xcode developer suite, which is usually included
in your OS X install DVD, or can be obtained freely from the Apple
Developer Connection (http://developer.apple.com/tools/downloads/)
website.

   After having obtained a C compiler, you'll have to install an XML
processing library called `libxml2'. Windows users should get it from
this website (http://xmlsoft.org) (there are binary versions, no need
to compile anything), Linux users should be able to find a package
again in their respective distribution (Debian and Ubuntu users:
install the `libxml2' and `libxml2-dev' libraries).  Mac users should
not do anything, since `libxml2' is part of the default system
installation. However, you should check it anyway, launch a terminal
and type the following command:

     $ xml2-config

If you don't receive any error message, you can go on to the next step.

   Now, get the `igraph' source from the Python Package Index
(http://www.python.org/pypi/igraph), extract it to a directory and
start the compilation. On Windows, launch the Cygwin or MinGW
environment and type:

     $ python setup.py build --compiler=cygwin

(Instead of `--compiler=cygwin', `--compiler=mingw32' should also work,
then you have no POSIX emulation available (you don't really need it for
`igraph' yet), but you also won't need `cygwin1.dll'). If the shell
keeps on complaining that it does not find the Python interpreter, use
its full path. For instance, if you have Python installed in
`C:\Devel\Python24', use the following command:

     $ /cygdrive/c/devel/python24/python setup.py build --compiler=cygwin

If the compilation finished without errors, you can install the library:

     $ python setup.py install

(Use the full path again if necessary).

   Linux and Mac users should succeed with the following commands
issued from the `igraph' root directory:

     $ python setup.py build
     $ python setup.py install

Note that you'll need write permissions to the Python library path, so
usually you must have root permissions to issue the second command. If
you want to install it to a different directory, just copy everything
from the `build/lib.*' subdirectory to wherever you want.

3 Tutorial
**********

3.1 Lesson 1. Compiling programs using igraph.
==============================================

The following short example program demonstrates the basic usage of the
`igraph' library.

     #include <igraph.h>

     int main(void)
     {
          igraph_real_t diameter;
          igraph_t graph;
          igraph_erdos_renyi_game(&graph, IGRAPH_ERDOS_RENYI_GNP, 1000, 5.0/1000,
                                  IGRAPH_UNDIRECTED, IGRAPH_NO_LOOPS);
          igraph_diameter(&graph, &diameter, 0, 0, 0, IGRAPH_UNDIRECTED, 1);
          printf("Diameter of a random graph with average degree 5: %f\n",
                  (double) diameter);
          igraph_destroy(&graph);
          return 0;
     }

   This example illustrates a couple of points. First, programs using
the `igraph' library should include the `igraph.h' header file. Second,
`igraph' uses the `igraph_real_t' type for real numbers instead of
`double'. Third, `igraph' graph objects are represented by the
`igraph_t' data type. Fourth, the `igraph_erdos_renyi_game()' creates a
graph and `igraph_destroy()' destroys it, ie. deallocates the memory
associated to it.

   For compiling this program you need a C compiler, if this is called
`gcc' and the previous code is saved in file `igraph_test.c', you will
need a command like this:

     gcc igraph_test.c -I/usr/local/igraph -L/usr/local/lib -ligraph -o igraph_test

   The exact form depends on where `igraph' was installed on your
system. The directory after the `-I' switch is the one containing the
`igraph.h' file, while the one following `-L' should contain the
library file itself, usually a file called `libigraph.so',
`libigraph.a' or `igraph.dll'.  It your system has the `pkg-config'
utility you are likely to get the neccessary compile options by issuing
the command

     pkg-config --libs --cflags igraph

   The executable can be run by simply typing its name like this:

     ./igraph_test

on most systems. If you use dynamic linking and the `igraph' libraries
are not at a standard place, you may need to set the `LD_LIBRARY_PATH'
variable, the syntax depends on the shell use are using. In `bash' it
goes like this:

     export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/user/libs/igraph
     ./igraph_test

Here we assumed that the `igraph' library is installed in
`/home/user/libs/igraph'. Alternatively, you can use the `LD_PRELOAD'
variable to preload the `igraph' library before invoking your program:

     LD_PRELOAD=/home/user/libs/igraph/libigraph.so ./igraph_test

Please note that `LD_PRELOAD' and `LD_LIBRARY_PATH' are usually
available only on Un*x-like systems. On Windows using Cygwin it is
usually enough to set the `PATH' enviroment variable to include the
folder in which the `igraph' library is installed, look for the
`cygigraph-0.dll' or similar file.

3.2 Lesson 2. Creating your first graphs.
=========================================

The functions generating graph objects are called graph generators.
Stochastic (=randomized) graph generators are called `games'.

   `igraph' can handle directed and undirected graphs. Most graph
generators are able to create both types of graphs and most other
functions are usually also capable of handling both. Eg.
`igraph_shortest_paths()' which (surprisingly) calculates shortest
paths from a vertex to another vertices can calculate directed or
undirected paths.

   `igraph' has sophisticated ways for creating graphs. The simplest
graphs are deterministic regular structures like star graphs
(`igraph_star()'), ring graphs (`igraph_ring()'), lattices
(`igraph_lattice()') or trees (`igraph_tree()').

   The following example creates an undirected regular circular lattice,
adds some random edges to it and calculates the average length of
shortest paths between all pairs of vertices in the graph before and
after adding the random edges. (The message is that some random edges
can reduce path lengths a lot.)

     #include <igraph.h>

     int main(void) {
       igraph_real_t avg_path;
       igraph_t graph;
       igraph_vector_t dimvector;
       igraph_vector_t edges;
       int i;

       igraph_vector_init(&dimvector, 2);
       VECTOR(dimvector)[0]=30;
       VECTOR(dimvector)[1]=30;
       igraph_lattice(&graph, &dimvector, 0, IGRAPH_UNDIRECTED, 0, 1);

       srand(100);
       igraph_vector_init(&edges, 20);
       for (i=0; i<igraph_vector_size(&edges); i++) {
         VECTOR(edges)[i] = rand() % (int)igraph_vcount(&graph);
       }

       igraph_average_path_length(&graph, &avg_path, IGRAPH_UNDIRECTED, 1);
       printf("Average path length (lattice):            %f\n", (double) avg_path);

       igraph_add_edges(&graph, &edges, 0);
       igraph_average_path_length(&graph, &avg_path, IGRAPH_UNDIRECTED, 1);
       printf("Average path length (randomized lattice): %f\n", (double) avg_path);

       igraph_vector_destroy(&dimvector);
       igraph_vector_destroy(&edges);
       igraph_destroy(&graph);

       return 0;
     }

   This example illustrates some new points. `igraph' uses
`igraph_vector_t' instead of plain C arrays. `igraph_vector_t' is
superior to regular arrays in almost every sense. Vectors are created
by the `igraph_vector_init()' function and like graphs they should be
destroyed if not needed any more by calling `igraph_vector_destroy()'
on them. A vector can be indexed by the `VECTOR()' function (right now
it is a macro). Vectors can be resized, eg. most `igraph' functions
returning the result in a vector resize it to the size of the result.

   `igraph_lattice()' takes a vector argument specifying the dimensions
of the lattice, in this example we generate a 30x30 two dimensional
lattice. See the documentation of `igraph_lattice()' in the reference
manual for the other arguments.

   The vertices in a graph are identified by an integer number between
0 and N-1, N is the number of vertices in the graph (this can be
obtained by `igraph_vcount()', as in the example).

   The `igraph_add_edges()' function simply takes a graph and a vector
of vertex ids defining the new edges. The first edge is between the
first two vertex ids in the vector, the second edge is between the
second two, etc. This way we add ten random edges to the lattice.

   Note that in the example it is possible to add loop edges, edges
pointing to the same vertex and multiple edges, more than one edge
between the same pair of vertices.  `igraph_t' can of course represent
loops and multiple edges, although some routines expect simple graphs,
ie. graphs without loop and multiple edges, because for example some
structural properties are ill-defined for non-simple graphs. Loop edges
can be removed by calling `igraph_simplify()'.

3.3 Lesson 3. Calculating various properties of graphs.
=======================================================

In our next example we will calculate various centrality measures in a
friendship graph. The friendship graph is from the famous Zachary karate
club study. (Web search on 'Zachary karate' if you want to know more
about this.) Centrality measures quantify how central is the position of
individual vertices in the graph.

     #include <igraph.h>

     int main(void) {
          igraph_t graph;
          igraph_vector_t v;
          igraph_vector_t result;
          igraph_real_t edges[] = { 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8,
                                    0,10, 0,11, 0,12, 0,13, 0,17, 0,19, 0,21, 0,31,
                                    1, 2, 1, 3, 1, 7, 1,13, 1,17, 1,19, 1,21, 1,30,
                                    2, 3, 2, 7, 2,27, 2,28, 2,32, 2, 9, 2, 8, 2,13,
                                    3, 7, 3,12, 3,13, 4, 6, 4,10, 5, 6, 5,10, 5,16,
                                    6,16, 8,30, 8,32, 8,33, 9,33,13,33,14,32,14,33,
                                   15,32,15,33,18,32,18,33,19,33,20,32,20,33,
                                   22,32,22,33,23,25,23,27,23,32,23,33,23,29,
                                   24,25,24,27,24,31,25,31,26,29,26,33,27,33,
                                   28,31,28,33,29,32,29,33,30,32,30,33,31,32,31,33,
                                   32,33
          };

          igraph_vector_view(&v, edges, sizeof(edges)/sizeof(double));
          igraph_create(&graph, &v, 0, IGRAPH_UNDIRECTED);

          igraph_vector_init(&result, 0);

          igraph_degree(&graph, &result, igraph_vss_all(), IGRAPH_ALL,
                        IGRAPH_LOOPS);
          printf("Maximum degree is      %10i, vertex %2i.\n",
                 (int)igraph_vector_max(&result), (int)igraph_vector_which_max(&result));

          igraph_closeness(&graph, &result, igraph_vss_all(), IGRAPH_ALL);
          printf("Maximum closeness is   %10f, vertex %2i.\n",
                  (double)igraph_vector_max(&result), (int)igraph_vector_which_max(&result));

          igraph_betweenness(&graph, &result, igraph_vss_all(),
                                  IGRAPH_UNDIRECTED);
          printf("Maximum betweenness is %10f, vertex %2i.\n",
                  (double)igraph_vector_max(&result), (int)igraph_vector_which_max(&result));

          igraph_vector_destroy(&result);
          igraph_destroy(&graph);

          return 0;
     }

   This example reflects some new features. First of all, it shows a
way to define a graph simply as defining a C array with its edges.
Function `igraph_vector_view()' creates a _view_ of a C array. It does
not copy any data, this also means that you should not call
`igraph_vector_destroy()' on a vector created this way. This vector is
then used to create the undirected graph.

   Then the degree, closeness and betweenness centrality of the vertices
is calculated and the highest values are printed. Note that the vector
(`result') which returns the result from these functions has to be
initialized first, and also that the functions resize it to be able to
hold the result.

   The `igraph_vss_all()' argument tells the functions to calculate the
property for every vertex in the graph, it is shorthand for a _vertex
selector_ (`igraph_vs_t').  Vertex selectors help performing operations
on a subset of vertices, you can read more about them in one of the
following chapters.

4 About igraph graphs, the basic interface
******************************************

4.1 The igraph data model
=========================

The igraph library can handle directed and undirected graphs. The
igraph graphs are multisets of ordered (if directed) or unordered (if
undirected) labeled pairs.  The labels of the pairs plus the number of
vertices always starts with zero and ends with the number of edges
minus one. In addition to that a table of metadata is also attached to
every graph, its most important entries are the number of vertices in
the graph and whether the graph is directed or undirected.

   Like the edges, the igraph vertices are also labeled by number
between zero and the number of vertices minus one.  So, to summarize, a
directed graph can be imagined like this:

       ( vertices: 6,
         directed: yes,
         {
          (0,2),
          (2,2),
          (2,3),
          (3,3),
          (3,4),
          (3,4),
          (4,1)
         }
       )

Here the edges are ordered pairs or vertex ids, and the graph is a
multiset of edges plus some meta-data.

   An undirected graph is like this:

       ( vertices: 6,
         directed: no,
         {
          {0,2},
          {2},
          {2,3},
          {3},
          {3,4},
          {3,4},
          {4,1}
         }
       )

Here an edge is a set of one or two vertex ids, two for most of the
time, except for loop edges. A graph is a multiset of edges plus meta
data, just like in the directed case.

   It is possible to convert a directed graph to an undirected one, see
the `igraph_to_directed()' (see igraph_to_directed --- Convert an undirected graph to a directed one)
and `igraph_to_undirected()'
(see igraph_to_undirected --- Convert a directed graph to an undirected one_)
functions.

   Note that igraph has some limited support for graphs with multiple
edges. The support means that multiple edges can be stored in igraph
graphs, but for most functions (like `igraph_betweenness()' (see
igraph_betweenness --- Betweenness centrality of some vertices_)) it
is not checked that they work well on graphs with multiple edges.  To
eliminate multiple edges from a graph, you can use `igraph_simplify()'
(see igraph_simplify --- Removes loop and/or multiple edges from the graph_).

4.2 The basic interface
=======================

This is the very minimal API in `igraph'. All the other functions use
this minimal set for creating and manipulating the graphs.

   This is a very important principle since it makes possible to
implement other data representations by implementing only this minimal
set.

4.2.1 Graph Constructors and Destructors
----------------------------------------

4.2.1.1 igraph_empty -- Creates an empty graph with some vertices and no edges.
...............................................................................

     int igraph_empty(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed);

   The most basic constructor, all the other constructors should call
this to create a minimal graph object.

   *Arguments:. *

`graph':
     Pointer to a not-yet initialized graph object.

`n':
     The number of vertices in the graph, a non-negative integer number
     is expected.

`directed':
     Whether the graph is directed or not.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVAL': invalid number of vertices.

   Time complexity: O(|V|) for a graph with |V| vertices (and no edges).

4.2.1.2 igraph_empty_attrs -- Creates an empty graph with some vertices, no edges and some graph attributes.
............................................................................................................

     int igraph_empty_attrs(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, void* attr);

   Use this instead of `igraph_empty()' (see igraph_empty --- Creates an empty graph with some vertices and no edges_)
if you wish to add
some graph attributes right after initialization. This function is
currently not very interesting for the ordinary user, just supply 0
here or use `igraph_empty()' (see igraph_empty --- Creates an empty graph with some vertices and no edges_).

   *Arguments:. *

`graph':
     Pointer to a not-yet initialized graph object.

`n':
     The number of vertices in the graph, a non-negative integer number
     is expected.

`directed':
     Whether the graph is directed or not.

`attr':
     The attributes.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVAL': invalid number of vertices.

   Time complexity: O(|V|) for a graph with |V| vertices (and no edges).

4.2.1.3 igraph_copy -- Creates an exact (deep) copy of a graph.
...............................................................

     int igraph_copy(igraph_t *to, const igraph_t *from);

   This function deeply copies a graph object to create an exact
replica of it. The new replica should be destroyed by calling
`igraph_destroy()' (see igraph_destroy --- Frees the memory allocated for a graph object_)
on it when not needed any more.

   You can also create a shallow copy of a graph by simply using the
standard assignment operator, but be careful and do _not_ destroy a
shallow replica. To avoid this mistake creating shallow copies is not
recommended.

   *Arguments:. *

`to':
     Pointer to an uninitialized graph object.

`from':
     Pointer to the graph object to copy.

   *Returns:. *

`'
     Error code.

   Time complexity:  O(|V|+|E|) for a graph with |V| vertices and |E|
edges.

4.2.1.4 igraph_destroy -- Frees the memory allocated for a graph object.
........................................................................

     int igraph_destroy(igraph_t *graph);

   This function should be called for every graph object exactly once.

   This function invalidates all iterators (of course), but the
iterators of are graph should be destroyed before the graph itself
anyway.

   *Arguments:. *

`graph':
     Pointer to the graph to free.

   *Returns:. *

`'
     Error code.

   Time complexity: operating system specific.

4.2.2 Basic Query Operations
----------------------------

4.2.2.1 igraph_vcount -- The number of vertices in a graph
..........................................................

     igraph_integer_t igraph_vcount(const igraph_t *graph);

   *Arguments:. *

`graph':
     The graph.

   *Returns:. *

`'
     Number of vertices.

   Time complexity: O(1)

4.2.2.2 igraph_ecount -- The number of edges in a graph
.......................................................

     igraph_integer_t igraph_ecount(const igraph_t *graph);

   *Arguments:. *

`graph':
     The graph.

   *Returns:. *

`'
     Number of edges.

   Time complexity: O(1)

4.2.2.3 igraph_edge -- Gives the head and tail vertices of an edge.
...................................................................

     int igraph_edge(const igraph_t *graph, igraph_integer_t eid,
     		igraph_integer_t *from, igraph_integer_t *to);

   *Arguments:. *

`graph':
     The graph object.

`eid':
     The edge id.

`from':
     Pointer to an `igraph_integer_t'. The tail of the edge will be
     placed here.

`to':
     Pointer to an `igraph_integer_t'. The head of the edge will be
     placed here.

   *Returns:. *

`'
     Error code. The current implementation always returns with success.

   *See also:. *

`'
     `igraph_get_eid()' (see igraph_get_eid --- Get the edge id from the end points of an edge)
     for the opposite operation.

   Added in version 0.2.

   Time complexity: O(1).

4.2.2.4 igraph_get_eid -- Get the edge id from the end points of an edge
........................................................................

     int igraph_get_eid(const igraph_t *graph, igraph_integer_t *eid,
     		   igraph_integer_t pfrom, igraph_integer_t pto,
     		   igraph_bool_t directed);

   For undirected graphs `from' and `to' are exchangable.

   *Arguments:. *

`graph':
     The graph object.

`eid':
     Pointer to an integer, the edge id will be stored here.

`from':
     The starting point of the edge.

`to':
     The end points of the edge.

`directed':
     Logical constant, whether to search for directed edges in a
     directed graph. Ignored for undirected graphs.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_edge()' (see igraph_edge --- Gives the head and tail vertices of an edge_)
     for the opposite operation.

   Time complexity: O(log (d)), where d is smaller of the out-degree of
from and in-degree of to if `directed' is true. If `directed' is false,
then it is O(log(d)+log(d2)), where d is the same as before and d2 is
the minimum of the out-degree of to and the in-degree of from.  Added
in version 0.2.

4.2.2.5 igraph_neighbors -- Adjacent vertices to a vertex.
..........................................................

     int igraph_neighbors(const igraph_t *graph, igraph_vector_t *neis, igraph_integer_t pnode,
     		     igraph_neimode_t mode);

   *Arguments:. *

`graph':
     The graph to work on.

`neis':
     This vector will contain the result. The vector should be
     initialized before and will be resized. Starting from igraph
     version 0.4 this vector is always sorted, the vertex ids are in
     increasing order.

`pnode':
     The id of the node of which the adjacent vertices are searched.

`mode':
     Defines the way adjacent vertices are searched for directed
     graphs. It can have the following values: `IGRAPH_OUT', vertices
     reachable by an edge from the specified vertex are searched,
     `IGRAPH_IN', vertices from which the specified vertex is reachable
     are searched.  `IGRAPH_ALL', both kind of vertices are searched.
     This parameter is ignored for undirected graphs.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVVID': invalid vertex id.
     `IGRAPH_EINVMODE': invalid mode argument.  `IGRAPH_ENOMEM': not
     enough memory.

   Time complexity: O(d), d is the number of adjacent vertices to the
queried vertex.

4.2.2.6 igraph_adjacent -- Gives the adjacent edges of a vertex.
................................................................

     int igraph_adjacent(const igraph_t *graph, igraph_vector_t *eids,
     		    igraph_integer_t pnode, igraph_neimode_t mode);

   *Arguments:. *

`graph':
     The graph object.

`eids':
     An initialized `vector_t' object. It will be resized to hold the
     result.

`pnode':
     A vertex id.

`mode':
     Specifies what kind of edges to include for directed graphs.
     `IGRAPH_OUT' means only outgoing edges, `IGRAPH_IN' only incoming
     edges, `IGRAPH_ALL' both. This parameter is ignored for undirected
     graphs.

   *Returns:. *

`'
     Error code. `IGRAPH_EINVVID': invalid `pnode' argument,
     `IGRAPH_EINVMODE': invalid `mode' argument.

   Added in version 0.2.

   Time complexity: O(d), the number of adjacent edges to `pnode'.

4.2.2.7 igraph_is_directed -- Is this a directed graph?
.......................................................

     igraph_bool_t igraph_is_directed(const igraph_t *graph);

   *Arguments:. *

`graph':
     The graph.

   *Returns:. *

`'
     Logical value, ` TRUE'  if the graph is directed, ` FALSE'
     otherwise.

   Time complexity: O(1)

4.2.2.8 igraph_degree -- The degree of some vertices in a graph.
................................................................

     int igraph_degree(const igraph_t *graph, igraph_vector_t *res,
     		  const igraph_vs_t vids,
     		  igraph_neimode_t mode, igraph_bool_t loops);

   This function calculates the in-, out- or total degree of the
specified vertices.

   *Arguments:. *

`graph':
     The graph.

`res':
     Vector, this will contain the result. It should be initialized and
     will be resized to be the appropriate size.

`vids':
     Vector, giving the vertex ids of which the degree will be
     calculated.

`mode':
     Defines the type of the degree.  `IGRAPH_OUT', out-degree,
     `IGRAPH_IN', in-degree, `IGRAPH_ALL', total degree (sum of the in-
     and out-degree).  This parameter is ignored for undirected graphs.

`loops':
     Boolean, gives whether the self-loops should be counted.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVVID': invalid vertex id.
     `IGRAPH_EINVMODE': invalid mode argument.

   Time complexity: O(v) if loops is TRUE, and O(v*d) otherwise. v is
the number vertices for which the degree will be calculated, and d is
their (average) degree.

   *See also:. *

`'
     `igraph_strength()' (see igraph_strength --- Strength of the vertices; weighted vertex degree in other words)
     for the version
     that takes into account edge weigths.

4.2.3 Adding and Deleting Vertices and Edges
--------------------------------------------

4.2.3.1 igraph_add_edge -- Adds a single edge to a graph
........................................................

     int igraph_add_edge(igraph_t *graph, igraph_integer_t from, igraph_integer_t to);

   For directed graphs the edge points from `from' to `to'.

   Note that if you want to add many edges to a big graph, then it is
unefficient to add them one by one, it is better to collect them into a
vector and add all of them via a single `igraph_add_edges()' (see
igraph_add_edges --- Adds edges to a graph object_) call.

   *Arguments:. *

`igraph':
     The graph.

`from':
     The id of the first vertex of the edge.

`to':
     The id of the second vertex of the edge.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_add_edges()' (see igraph_add_edges --- Adds edges to a graph object_)
     to add many edges, `igraph_delete_edges()' (see
     igraph_delete_edges --- Removes edges from a graph_) to remove
     edges and `igraph_add_vertices()' (see igraph_add_vertices --- Adds vertices to a graph_)
     to add vertices.

   Time complexity: O(|V|+|E|), the number of edges plus the number of
vertices.

4.2.3.2 igraph_add_edges -- Adds edges to a graph object.
.........................................................

     int igraph_add_edges(igraph_t *graph, const igraph_vector_t *edges,
     		     void *attr);

   The edges are given in a vector, the first two elements define the
first edge (the order is ` from' , ` to'  for directed graphs). The
vector should contain even number of integer numbers between zero and
the number of vertices in the graph minus one (inclusive). If you also
want to add new vertices, call igraph_add_vertices() first.

   *Arguments:. *

`graph':
     The graph to which the edges will be added.

`edges':
     The edges themselves.

`attr':
     The attributes of the new edges, only used by high level
     interfaces currently, you can supply 0 here.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVEVECTOR': invalid (odd) edges vector
     length, `IGRAPH_EINVVID': invalid vertex id in edges vector.

   This function invalidates all iterators.

   Time complexity: O(|V|+|E|) where |V| is the number of vertices and
|E| is the number of edges in the _new,_ extended graph.

4.2.3.3 igraph_add_vertices -- Adds vertices to a graph.
........................................................

     int igraph_add_vertices(igraph_t *graph, igraph_integer_t nv, void *attr);

   This function invalidates all iterators.

   *Arguments:. *

`graph':
     The graph object to extend.

`nv':
     Non-negative integer giving the number of vertices to add.

`attr':
     The attributes of the new vertices, only used by high level
     interfaces, you can supply 0 here.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVAL': invalid number of new vertices.

   Time complexity: O(|V|) where |V| is the number of vertices in the
_new,_ extended graph.

4.2.3.4 igraph_delete_edges -- Removes edges from a graph.
..........................................................

     int igraph_delete_edges(igraph_t *graph, igraph_es_t edges);

   The edges to remove are given as an edge selector.

   This function cannot remove vertices, they will be kept, even if
they lose all their edges.

   This function invalidates all iterators.

   *Arguments:. *

`graph':
     The graph to work on.

`edges':
     The edges to remove.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|) where |V| and |E| are the number of
vertices and edges in the _original_ graph, respectively.

4.2.3.5 igraph_delete_vertices -- Removes vertices (with all their edges) from the graph.
.........................................................................................

     int igraph_delete_vertices(igraph_t *graph, const igraph_vs_t vertices);

   This function changes the ids of the vertices (except in some very
special cases, but these should not be relied on anyway).

   This function invalidates all iterators.

   *Arguments:. *

`graph':
     The graph to work on.

`vertices':
     The ids of the vertices to remove in a vector. The vector may
     contain the same id more than once.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVVID': invalid vertex id.

   Time complexity: O(|V|+|E|), |V| and |E| are the number of vertices
and edges in the original graph.

5 Error Handling
****************

5.1 Error handling basics
=========================

`igraph' functions can run into various problems preventing them from
normal operation: the user might have supplied invalid arguments, eg. a
non-square matrix when a square-matrix was expected, or the program has
run out of memory while some more memory allocation is required, etc.

   By default `igraph' aborts the program when it runs into an error.
While this behavior might be good enough for smaller programs, it is
without doubt avoidable in larger projects. Please read further if your
project requires more sophisticated error handling. You can safely skip
the rest of this chapter otherwise.

5.2 Error handlers
==================

If `igraph' runs into an error - an invalid argument was supplied to a
function, or we've ran out of memory - the control is transferred to
the _ error handler _ function.

   The default error handler is `igraph_error_handler_abort' (see
igraph_error_handler_abort --- Abort program in case of error_) which
prints an error message and aborts the program.

   The `igraph_set_error_handler()' (see igraph_set_error_handler --- Set a new error handler_)
function can be used to set a new error
handler function of type `igraph_error_handler_t' (see
igraph_error_handler_t --- Type of error handler functions_), see the
documentation of this type for details.

   There are two other predefined error handler functions,
`igraph_error_handler_ignore' (see igraph_error_handler_ignore --- Ignore errors_)
and `igraph_error_handler_printignore' (see
igraph_error_handler_printignore --- Print and ignore errors_), these
deallocate the temporarily allocated memory (more about this later) and
return with the error code. The latter also prints an error message. If
you use these error handlers you need to take care about possible
errors yourself by checking the return value of (almost) every non-void
`igraph' function.

   Independently of the error handler installed, all functions in the
library do their best to leave their arguments _semantically_ unchanged
if an error happens. By semantically we mean that the implementation of
an object supplied as an argument might change, but its `meaning' in
most cases does not. The rare occasions when this rule is violated are
documented in this manual.

5.2.1 igraph_error_handler_t -- Type of error handler functions.
----------------------------------------------------------------

     typedef void igraph_error_handler_t (const char * reason, const char * file,
     				     int line, int igraph_errno);

   This is the type of the error handler functions.

   *Arguments:. *

`reason':
     Textual description of the error.

`file':
     The source file in which the error is noticed.

`line':
     The number of the line in the source file which triggered the error

`igraph_errno':
     The `igraph' error code.

5.2.2 igraph_error_handler_abort -- Abort program in case of error.
-------------------------------------------------------------------

     extern igraph_error_handler_t igraph_error_handler_abort;

   The default error handler, prints an error message and aborts the
program.

5.2.3 igraph_error_handler_ignore -- Ignore errors.
---------------------------------------------------

     extern igraph_error_handler_t igraph_error_handler_ignore;

   This error handler frees the temporarily allocated memory and returns
with the error code.

5.2.4 igraph_error_handler_printignore -- Print and ignore errors.
------------------------------------------------------------------

     extern igraph_error_handler_t igraph_error_handler_printignore;

   Frees temporarily allocated memory, prints an error message to the
standard error and returns with the error code.

5.3 Error codes
===============

Every `igraph' function which can fail return a single integer error
code. Some functions are very simple and cannot run into any error,
these may return other types, or `void' as well. The error codes are
defined by the `igraph_error_type_t' (see igraph_error_type_t --- Error code type_)
enumeration.

5.3.1 igraph_error_type_t -- Error code type.
---------------------------------------------

     typedef enum {
       IGRAPH_SUCCESS       = 0,
       IGRAPH_FAILURE       = 1,
       IGRAPH_ENOMEM        = 2,
       IGRAPH_PARSEERROR    = 3,
       IGRAPH_EINVAL        = 4,
       IGRAPH_EXISTS        = 5,
       IGRAPH_EINVEVECTOR   = 6,
       IGRAPH_EINVVID       = 7,
       IGRAPH_NONSQUARE     = 8,
       IGRAPH_EINVMODE      = 9,
       IGRAPH_EFILE         = 10,
       IGRAPH_UNIMPLEMENTED = 12,
       IGRAPH_INTERRUPTED   = 13,
       IGRAPH_DIVERGED      = 14,
       IGRAPH_ARPACK_PROD      = 15,
       IGRAPH_ARPACK_NPOS      = 16,
       IGRAPH_ARPACK_NEVNPOS   = 17,
       IGRAPH_ARPACK_NCVSMALL  = 18,
       IGRAPH_ARPACK_NONPOSI   = 19,
       IGRAPH_ARPACK_WHICHINV  = 20,
       IGRAPH_ARPACK_BMATINV   = 21,
       IGRAPH_ARPACK_WORKLSMALL= 22,
       IGRAPH_ARPACK_TRIDERR   = 23,
       IGRAPH_ARPACK_ZEROSTART = 24,
       IGRAPH_ARPACK_MODEINV   = 25,
       IGRAPH_ARPACK_MODEBMAT  = 26,
       IGRAPH_ARPACK_ISHIFT    = 27,
       IGRAPH_ARPACK_NEVBE     = 28,
       IGRAPH_ARPACK_NOFACT    = 29,
       IGRAPH_ARPACK_FAILED    = 30,
       IGRAPH_ARPACK_HOWMNY    = 31,
       IGRAPH_ARPACK_HOWMNYS   = 32,
       IGRAPH_ARPACK_EVDIFF    = 33,
       IGRAPH_ARPACK_SHUR      = 34,
       IGRAPH_ARPACK_LAPACK    = 35,
       IGRAPH_ARPACK_UNKNOWN   = 36,
       IGRAPH_ENEGLOOP         = 37,
       IGRAPH_EINTERNAL        = 38
     } igraph_error_type_t;

   These are the possible valued returned by `igraph' functions.  Note
that these are interesting only if you defined an error handler with
`igraph_set_error_handler()' (see igraph_set_error_handler --- Set a new error handler_).
Otherwise the program is aborted and the
function causing the error never returns.

   *Values:. *

`IGRAPH_SUCCESS':
     The function successfully completed its task.

`IGRAPH_FAILURE':
     Something went wrong. You'll almost never meet this error as
     normally more specific error codes are used.

`IGRAPH_ENOMEM':
     There wasn't enough memory to allocate on the heap.

`IGRAPH_PARSEERROR':
     A parse error was found in a file.

`IGRAPH_EINVAL':
     A parameter's value is invalid. Eg. negative number was specified
     as the number of vertices.

`IGRAPH_EXISTS':
     A graph/vertex/edge attribute is already installed with the given
     name.

`IGRAPH_EINVEVECTOR':
     Invalid vector of vertex ids. A vertex id is either negative or
     bigger than the number of vertices minus one.

`IGRAPH_EINVVID':
     Invalid vertex id, negative or too big.

`IGRAPH_NONSQUARE':
     A non-square matrix was received while a square matrix was
     expected.

`IGRAPH_EINVMODE':
     Invalid mode parameter.

`IGRAPH_EFILE':
     A file operation failed. Eg. a file doesn't exist, or the user ha
     no rights to open it.

`IGRAPH_UNIMPLEMENTED':
     Attempted to call an unimplemented or disabled (at compile-time)
     function.

`IGRAPH_DIVERGED':
     A numeric algorithm failed to converge.

`IGRAPH_ARPACK_PROD':
     Matrix-vector product failed.

`IGRAPH_ARPACK_NPOS':
     N must be positive.

`IGRAPH_ARPACK_NEVNPOS':
     NEV must be positive.

`IGRAPH_ARPACK_NCVSMALL':
     NCV must be bigger.

`IGRAPH_ARPACK_NONPOSI':
     Maximum number of iterations should be positive.

`IGRAPH_ARPACK_WHICHINV':
     Invalid WHICH parameter.

`IGRAPH_ARPACK_BMATINV':
     Invalid BMAT parameter.

`IGRAPH_ARPACK_WORKLSMALL':
     WORKL is too small.

`IGRAPH_ARPACK_TRIDERR':
     LAPACK error in tridiagonal eigenvalue calculation.

`IGRAPH_ARPACK_ZEROSTART':
     Starting vector is zero.

`IGRAPH_ARPACK_MODEINV':
     MODE is invalid.

`IGRAPH_ARPACK_MODEBMAT':
     MODE and BMAT are not compatible.

`IGRAPH_ARPACK_ISHIFT':
     ISHIFT must be 0 or 1.

`IGRAPH_ARPACK_NEVBE':
     NEV and WHICH='BE' are incompatible.

`IGRAPH_ARPACK_NOFACT':
     Could not build an Arnoldi factorization.

`IGRAPH_ARPACK_FAILED':
     No eigenvalues to sufficient accuracy.

`IGRAPH_ARPACK_HOWMNY':
     HOWMNY is invalid.

`IGRAPH_ARPACK_HOWMNYS':
     HOWMNY='S' is not implemented.

`IGRAPH_ARPACK_EVDIFF':
     Different number of converged Ritz values.

`IGRAPH_ARPACK_SHUR':
     Error from calculation of a real Schur form.

`IGRAPH_ARPACK_LAPACK':
     LAPACK (dtrevc) error for calculating eigenvectors.

`IGRAPH_ARPACK_UNKNOWN':
     Unkown ARPACK error.

`IGRAPH_ENEGLOOP':
     Negative loop detected while calculating shortest paths.

`IGRAPH_EINTERNAL':
     Internal error, likely a bug in igraph.

5.3.2 igraph_strerror -- Textual description of an error.
---------------------------------------------------------

     const char* igraph_strerror(const int igraph_errno);

   This is a simple utility function, it gives a short general textual
description for an `igraph' error code.

   *Arguments:. *

`igraph_errno':
     The `igraph' error code.

   *Returns:. *

`'
     pointer to the textual description of the error code.

5.4 Advanced topics
===================

5.4.1 Writing error handlers
----------------------------

The contents of the rest of this chapter might be useful only for those
who want to create an interface to `igraph' from another language. Most
readers can safely skip to the next chapter.

   You can write and install error handlers simply by defining a
function of type `igraph_error_handler_t' (see igraph_error_handler_t --- Type of error handler functions_)
and calling
`igraph_set_error_handler()' (see igraph_set_error_handler --- Set a new error handler_).
This feature is useful for interface writers, as
`igraph' will have the chance to signal errors the appropriate way, eg.
the R interface defines an error handler which calls the `error()'
function, as required by R, while the Python interface has an error
handler which raises an exception according to the Python way.

   If you want to write an error handler, your error handler should
call `IGRAPH_FINALLY_FREE()' (see IGRAPH_FINALLY_FREE --- Deallocate all registered objects_)
to deallocate all temporary memory to
prevent memory leaks.

5.4.1.1 igraph_set_error_handler -- Set a new error handler.
............................................................

     igraph_error_handler_t*
     igraph_set_error_handler(igraph_error_handler_t* new_handler);

   Installs a new error handler. If called with 0, it installs the
default error handler (which is currently `igraph_error_handler_abort'
(see igraph_error_handler_abort --- Abort program in case of error_)).

   *Arguments:. *

`new_handler':
     The error handler function to install.

   *Returns:. *

`'
     The old error handler function. This should be saved and restored
     if `new_handler' is not needed any more.

5.4.2 Error handling internals
------------------------------

If an error happens, the functions in the library call the
`IGRAPH_ERROR' (see IGRAPH_ERROR --- Trigger an error_) macro with
a textual description of the error and an `igraph' error code. This
macro calls (through the `igraph_error()' (see igraph_error --- Trigger an error_)
function) the installed error handler. Another
useful macro is `IGRAPH_CHECK()' (see IGRAPH_CHECK --- Check the return value of a function call_),
this checks the return value of its
argument which is normally a function call, and calls `IGRAPH_ERROR'
(see IGRAPH_ERROR --- Trigger an error_) if it is not
`IGRAPH_SUCCESS'.

5.4.2.1 IGRAPH_ERROR -- Trigger an error.
.........................................

     #define IGRAPH_ERROR(reason,igraph_errno)

   `igraph' functions usually use this macro when they notice an error.
It calls `igraph_error()' (see igraph_error --- Trigger an error_)
with the proper parameters and if that returns the macro returns the
"calling" function as well, with the error code. If for some
(suspicious) reason you want to call the error handler without
returning from the current function, call `igraph_error()' (see
igraph_error --- Trigger an error_) directly.

   *Arguments:. *

`reason':
     Textual description of the error. This should be something more
     explaning than the text associated with the error code. Eg. if the
     error code is `IGRAPH_EINVAL', its asssociated text (see
     `igraph_strerror()' (see igraph_strerror --- Textual description of an error_))
     is "Invalid value" and this string should explain
     which parameter was invalid and maybe why.

`igraph_errno':
     The `igraph' error code.

5.4.2.2 igraph_error -- Trigger an error.
.........................................

     int igraph_error(const char *reason, const char *file, int line,
     		 int igraph_errno);

   `igraph' functions usually call this fuction (most often via the
`IGRAPH_ERROR' (see IGRAPH_ERROR --- Trigger an error_) macro) if
they notice an error.  It calls the currently installed error handler
function with the supplied arguments.

   *Arguments:. *

`reason':
     Textual description of the error.

`file':
     The source file in which the error was noticed.

`line':
     The number of line in the source file which triggered the error.

`igraph_errno':
     The `igraph' error code.

   *Returns:. *

`'
     the error code (if it returns)

5.4.2.3 IGRAPH_CHECK -- Check the return value of a function call.
..................................................................

     #define IGRAPH_CHECK(a)

   *Arguments:. *

`a':
     An expression, usually a function call.

   Executes the expression and checks its value. If this is not
`IGRAPH_SUCCESS', it calls `IGRAPH_ERROR' (see IGRAPH_ERROR --- Trigger an error_)
with the value as the error code. Here is an
example usage:

      IGRAPH_CHECK(vector_push_back(&v, 100));

   There is only one reason to use this macro when writing `igraph'
functions. If the user installs an error handler which returns to the
auxilary calling code (like `igraph_error_handler_ignore' (see
igraph_error_handler_ignore --- Ignore errors_) and
`igraph_error_handler_printignore' (see
igraph_error_handler_printignore --- Print and ignore errors_)), and
the `igraph' function signalling the error is called from another
`igraph' function then we need to make sure that the error is
propagated back to the auxilary (ie. non-igraph) calling function. This
is achieved by using `IGRAPH_CHECK' on every `igraph' call which can
return an error code.

5.4.3 Deallocating memory
-------------------------

If a function runs into an error (and the program is not aborted) the
error handler should deallocate all temporary memory. This is done by
storing the address and the destroy function of all temporary objects
in a stack. The `IGRAPH_FINALLY' (see IGRAPH_FINALLY --- Register an object for deallocation_)
function declares an object as temporary by
placing its address in the stack. If an `igraph' function returns with
success it calls `IGRAPH_FINALLY_CLEAN()' (see IGRAPH_FINALLY_CLEAN --- Signal clean deallocation of objects_)
with the number of objects
to remove from the stack. If an error happens however, the error
handler should call `IGRAPH_FINALLY_FREE()' (see IGRAPH_FINALLY_FREE --- Deallocate all registered objects_)
to deallocate each object
added to the stack. This means that the temporary objects allocated in
the calling function (and etc.) will be freed as well.

5.4.3.1 IGRAPH_FINALLY -- Register an object for deallocation.
..............................................................

     #define IGRAPH_FINALLY(func,ptr)

   *Arguments:. *

`func':
     The address of the function which is normally called to destroy
     the object.

`ptr':
     Pointer to the object itself.

   This macro places the address of an object, together with the
address of its destructor in a stack. This stack is used if an error
happens to deallocate temporarily allocated objects to prevent memory
leaks.

5.4.3.2 IGRAPH_FINALLY_CLEAN -- Signal clean deallocation of objects.
.....................................................................

     void IGRAPH_FINALLY_CLEAN(int num);

   Removes the specified number of objects from the stack of
temporarily allocated objects. Most often this is called just before
returning from a function.

   *Arguments:. *

`num':
     The number of objects to remove from the bookkeeping stack.

5.4.3.3 IGRAPH_FINALLY_FREE -- Deallocate all registered objects.
.................................................................

     void IGRAPH_FINALLY_FREE(void);

   Calls the destroy function for all objects in the stack of
temporarily allocated objects. This is usually called only from an
error handler. It is _not_ appropriate to use it instead of destroying
each unneeded object of a function, as it destroys the temporary
objects of the caller function (and so on) as well.

5.4.4 Writing igraph functions with proper error handling
---------------------------------------------------------

There are some simple rules to keep in order to have functions behaving
well in erroneous situations. First, check the arguments of the
functions and call `IGRAPH_ERROR' (see IGRAPH_ERROR --- Trigger an error_)
if they are invalid. Second, call `IGRAPH_FINALLY' (see
IGRAPH_FINALLY --- Register an object for deallocation_) on each
dynamically allocated object and call `IGRAPH_FINALLY_CLEAN()' (see
IGRAPH_FINALLY_CLEAN --- Signal clean deallocation of objects_) with
the proper argument before returning. Third, use IGRAPH_CHECK on all
`igraph' function calls which can generate errors.

   The size of the stack used for this bookkeeping is fixed, and small.
If you want to allocate several objects, write a destroy function which
can deallocate all of these. See the `adjlist.c' file in the `igraph'
source for an example.

   For some functions these mechanisms are simply not flexible enough.
These functions should define their own error handlers and restore the
error handler before they return.

5.4.5 Error handling and threads
--------------------------------

It is likely that the `igraph' error handling method is _not_
thread-safe, mainly because of the static global stack which is used to
store the address of the temporarily allocated objects. This issue
might be addressed in a later version of `igraph'.

6 Data structure library: vector, matrix, other data types
**********************************************************

6.1 About template types
========================

Some of the container types listed in this section are defined for many
base types. This is similar to templates in C++ and generics in Ada,
but it is implemented via precompiler macros since the C language
cannot handle it. Here is the list of template types and the all base
types they currently support:

vector
     Vector is currently defined for `igraph_real_t', `long int'
     (long), `char' (char), `igraph_bool_t' (bool). The default is
     `igraph_real_t'.

matrix
     Matrix is currently defined for `igraph_real_t', `long int'
     (long), `char' (char), `igraph_bool_t' (bool). The default is
     `igraph_real_t'.

array3
     Array3 is currently defined for `igraph_real_t', `long int'
     (long), `char' (char), `igraph_bool_t' (bool). The default is
     `igraph_real_t'.

stack
     Stack is currently defined for `igraph_real_t', `long int' (long),
     `char' (char), `igraph_bool_t' (bool). The default is
     `igraph_real_t'.

double-ended queue
     Dqueue is currently defined for `igraph_real_t', `long int'
     (long), `char' (char), `igraph_bool_t' (bool). The default is
     `igraph_real_t'.

heap
     Heap is currently defined for `igraph_real_t', `long int' (long),
     `char' (char).  In addition both maximum and minimum heaps are
     available.  The default is the `igraph_real_t' maximum heap.

   The name of the base element (in parens) is added to the function
names, except for te default type.

   Some examples:

   * `igraph_vector_t' is a vector of `igraph_real_t' elements. Its
     functions are `igraph_vector_init', `igraph_vector_destroy',
     `igraph_vector_sort', etc.

   * `igraph_vector_bool_t' is a vector of `igraph_bool_t' elements,
     initialize it with `igraph_vector_bool_init', destroy it with
     `igraph_vector_bool_destroy', etc.

   * `igraph_heap_t' is a maximum heap with `igraph_real_t' elements.
     The corresponding functions are `igraph_heap_init',
     `igraph_heap_pop', etc.

   * `igraph_heap_min_t' is a minimum heap with `igraph_real_t'
     elements. The corresponding functions are called
     `igraph_heap_min_init', `igraph_heap_min_pop', etc.

   * `igraph_heap_long_t' is a maximum heap with `long int' elements.
     Its function have the `igraph_heap_long_' prefix.

   * `igraph_heap_min_long_t' is a minimum heap containing `long int'
     elements. Its functions have the `igraph_heap_min_long_' prefix.

   Note that the VECTOR (see VECTOR --- Accessing an element of a vector_)
and the MATRIX (see MATRIX --- Accessing an element of a matrix_)
macros can be used on _all_ vector and matrix types.

6.2 Vectors
===========

6.2.1 About igraph_vector_t objects
-----------------------------------

The `igraph_vector_t' data type is a simple and efficient interface to
arrays containing numbers. It is something similar as (but much simpler
than) the `vector' template in the C++ standard library.

   Vectors are used extensively in `igraph', all functions which expect
or return a list of numbers use igraph_vector_t to achieve this.

   The `igraph_vector_t' type usually uses O(n) space to store n
elements. Sometimes it uses more, this is because vectors can shrink,
but even if they shrink, the current implementation does not free a
single bit of memory.

   The elements in an `igraph_vector_t' object are indexed from zero,
we follow the usual C convention here.

   The elements of a vector always occupy a single block of memory, the
starting address of this memory block can be queried with the `VECTOR'
(see VECTOR --- Accessing an element of a vector_) macro. This way,
vector objects can be used with standard mathematical libraries, like
the GNU Scientific Library.

6.2.2 Constructors and Destructors
----------------------------------

`igraph_vector_t' objects have to be initialized before using them,
this is analogous to calling a constructor on them. There are a number
of `igraph_vector_t' constructors, for your convenience.
`igraph_vector_init()' (see igraph_vector_init --- Initializes a vector object [constructor]_)
is the basic constructor, it creates a
vector of the given length, filled with zeros.  `igraph_vector_copy()'
(see igraph_vector_copy --- Initializes a vector from another vector object [constructor]_)
creates a new identical copy of an already
existing and initialized vector. `igraph_vector_init_copy()' (see
igraph_vector_init_copy --- Initializes a vector from an ordinary C array [constructor]_)
creates a vector by copying a regular C array.
`igraph_vector_init_seq()' (see igraph_vector_init_seq --- Initializes a vector with a sequence_)
creates a vector containing a
regular sequence with increment one.

   `igraph_vector_view()' (see igraph_vector_view --- Handle a regular C array as a igraph_vector_t_)
is a special constructor, it
allows you to handle a regular C array as a `vector' without copying
its elements.

   If a `igraph_vector_t' object is not needed any more, it should be
destroyed to free its allocated memory by calling the `igraph_vector_t'
destructor, `igraph_vector_destroy()' (see igraph_vector_destroy --- Destroys a vector object_).

   Note that vectors created by `igraph_vector_view()' (see
igraph_vector_view --- Handle a regular C array as a igraph_vector_t_)
are special, you mustn't call
`igraph_vector_destroy()' (see igraph_vector_destroy --- Destroys a vector object_)
on these.

6.2.2.1 igraph_vector_init -- Initializes a vector object (constructor).
........................................................................

     int igraph_vector_init      (igraph_vector_t* v, int long size);

   Every vector needs to be initialized before it can be used, and
there are a number of initialization functions or otherwise called
constructors.

   Every vector object initialized by this function should be destroyed
(ie. the memory allocated for it should be freed) when it is not needed
anymore, the `igraph_vector_destroy()' (see igraph_vector_destroy --- Destroys a vector object_)
function is responsible for this.

   *Arguments:. *

`v':
     Pointer to a not yet initialized vector object.

`size':
     The size of the vector.

   *Returns:. *

`'
     error code: `IGRAPH_ENOMEM' if there is not enough memory.

   Time complexity: operating system dependent, the amount of `time'
required to allocate O(n) elements, n is the number of elements.

6.2.2.2 igraph_vector_init_copy -- Initializes a vector from an ordinary C array (constructor).
...............................................................................................

     int igraph_vector_init_copy(igraph_vector_t *v,
     				      igraph_real_t *data, long int length);

   *Arguments:. *

`v':
     Pointer to an uninitialized vector object.

`data':
     A regular C array.

`length':
     The length of the C array.

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM' if there is not enough memory.

   Time complexity: operating system specific, usually O(`length').

6.2.2.3 igraph_vector_init_seq -- Initializes a vector with a sequence.
.......................................................................

     int igraph_vector_init_seq(igraph_vector_t *v,
     				     igraph_real_t from, igraph_real_t to);

   The vector will contain the numbers `from', `from'+1, ..., `to'.

   *Arguments:. *

`v':
     Pointer to an uninitialized vector object.

`from':
     The lower limit in the sequence (inclusive).

`to':
     The upper limit in the sequence (inclusive).

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM': out of memory.

   Time complexity: O(n), the number of elements in the vector.

6.2.2.4 igraph_vector_copy -- Initializes a vector from another vector object (constructor).
............................................................................................

     int igraph_vector_copy(igraph_vector_t *to,
     				 const igraph_vector_t *from);

   The contents of the existing vector object will be copied to the new
one.

   *Arguments:. *

`to':
     Pointer to a not yet initialized vector object.

`from':
     The original vector object to copy.

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM' if there is not enough memory.

   Time complexity: operating system dependent, usually O(n), n is the
size of the vector.

6.2.2.5 igraph_vector_destroy -- Destroys a vector object.
..........................................................

     void igraph_vector_destroy   (igraph_vector_t* v);

   All vectors initialized by `igraph_vector_init()' (see
igraph_vector_init --- Initializes a vector object [constructor]_)
should be properly destroyed by this function. A destroyed vector needs
to be reinitialized by `igraph_vector_init()' (see igraph_vector_init --- Initializes a vector object [constructor]_),
`igraph_vector_init_copy()' (see igraph_vector_init_copy --- Initializes a vector from an ordinary C array [constructor]_)
or
another constructor.

   *Arguments:. *

`v':
     Pointer to the (previously initialized) vector object to destroy.

   Time complexity: operating system dependent.

6.2.3 Initializing elements
---------------------------

6.2.3.1 igraph_vector_null -- Sets each element in the vector to zero.
......................................................................

     void igraph_vector_null      (igraph_vector_t* v);

   Note that `igraph_vector_init()' (see igraph_vector_init --- Initializes a vector object [constructor]_)
sets the elements to zero
as well, so it makes no sense to call this function on a just
initialized vector.

   *Arguments:. *

`v':
     The vector object.

   Time complexity: O(n), the size of the vector.

6.2.3.2 igraph_vector_fill -- Fill a vector with a constant element
...................................................................

     void igraph_vector_fill      (igraph_vector_t* v, igraph_real_t e);

   Sets each element of the vector to the supplied constant.

   *Arguments:. *

`vector':
     The vector to work on.

`e':
     The element to fill with.

   Time complexity: O(n), the size of the vector.

6.2.4 Accessing elements
------------------------

The simplest way to access an element of a vector is to use the
`VECTOR' (see VECTOR --- Accessing an element of a vector_) macro.
This macro can be used both for querying and setting `igraph_vector_t'
elements. If you need a function, `igraph_vector_e()' (see
igraph_vector_e --- Access an element of a vector_) queries and
`igraph_vector_set()' (see igraph_vector_set --- Assignment to an element of a vector_)
sets an element of a vector.
`igraph_vector_e_ptr()' (see igraph_vector_e_ptr --- Get the address of an element of a vector)
returns the address of an element.

   `igraph_vector_tail()' (see igraph_vector_tail --- Returns the last element in a vector_)
returns the last element of a non-empty
vector. There is no `igraph_vector_head()' function however, as it is
easy to write ` VECTOR(v)[0]' instead.

6.2.4.1 VECTOR -- Accessing an element of a vector.
...................................................

     #define VECTOR(v)

   Usage:

      VECTOR(v)[0]

to access the first element of the vector, you can also use this in
assignments, like:

      VECTOR(v)[10]=5;

Note that there are no range checks right now.  This functionality
might be redefined later as a real function instead of a ` #define' .

   *Arguments:. *

`v':
     The vector object.

   Time complexity: O(1).

6.2.4.2 igraph_vector_e -- Access an element of a vector.
.........................................................

     igraph_real_t igraph_vector_e         (const igraph_vector_t* v, long int pos);

   *Arguments:. *

`v':
     The `igraph_vector_t' object.

`pos':
     The position of the element, the index of the first element is
     zero.

   *Returns:. *

`'
     The desired element.

   *See also:. *

`'
     `igraph_vector_e_ptr()' (see igraph_vector_e_ptr --- Get the address of an element of a vector)
     and the `VECTOR' (see
     VECTOR --- Accessing an element of a vector_) macro.

   Time complexity: O(1).

6.2.4.3 igraph_vector_e_ptr -- Get the address of an element of a vector
........................................................................

     igraph_real_t* igraph_vector_e_ptr  (const igraph_vector_t* v, long int pos);

   *Arguments:. *

`v':
     The `igraph_vector_t' object.

`pos':
     The position of the element, the position of the first element is
     zero.

   *Returns:. *

`'
     Pointer to the desired element.

   *See also:. *

`'
     `igraph_vector_e()' (see igraph_vector_e --- Access an element of a vector_)
     and the `VECTOR' (see VECTOR --- Accessing an element of a vector_)
     macro.

   Time complexity: O(1).

6.2.4.4 igraph_vector_set -- Assignment to an element of a vector.
..................................................................

     void igraph_vector_set       (igraph_vector_t* v,
     					long int pos, igraph_real_t value);

   *Arguments:. *

`v':
     The `igraph_vector_t' element.

`pos':
     Position of the element to set.

`value':
     New value of the element.

   *See also:. *

`'
     `igraph_vector_e()' (see igraph_vector_e --- Access an element of a vector_).

6.2.4.5 igraph_vector_tail -- Returns the last element in a vector.
...................................................................

     igraph_real_t igraph_vector_tail(const igraph_vector_t *v);

   It is an error to call this function on an empty vector, the result
is undefined.

   *Arguments:. *

`v':
     The vector object.

   *Returns:. *

`'
     The last element.

   Time complexity: O(1).

6.2.5 Vector views
------------------

6.2.5.1 igraph_vector_view -- Handle a regular C array as a igraph_vector_t.
............................................................................

     const igraph_vector_t*igraph_vector_view (const igraph_vector_t *v,
     							const igraph_real_t *data,
     							long int length);

   This is a special `igraph_vector_t' constructor. It allows to handle
a regular C array as a `igraph_vector_t' temporarily.  Be sure that you
_don't_ ever call the destructor (`igraph_vector_destroy()' (see
igraph_vector_destroy --- Destroys a vector object_)) on objects
created by this constructor.

   *Arguments:. *

`v':
     Pointer to an uninitialized `igraph_vector_t' object.

`data':
     Pointer, the C array.

`length':
     The length of the C array.

   *Returns:. *

`'
     Pointer to the vector object, the same as the `v' parameter, for
     convenience.

   Time complexity: O(1)

6.2.6 Copying vectors
---------------------

6.2.6.1 igraph_vector_copy_to -- Copies the contents of a vector to a C array.
..............................................................................

     void igraph_vector_copy_to(const igraph_vector_t *v, igraph_real_t *to);

   The C array should have sufficient length.

   *Arguments:. *

`v':
     The vector object.

`to':
     The C array.

   Time complexity: O(n), n is the size of the vector.

6.2.6.2 igraph_vector_update -- Update a vector from another one.
.................................................................

     int igraph_vector_update(igraph_vector_t *to,
     				   const igraph_vector_t *from);

   After this operation the contents of `to' will be exactly the same
`from'. `to' will be resized if it was originally shorter or longer
than `from'.

   *Arguments:. *

`to':
     The vector to update.

`from':
     The vector to update from.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), the number of elements in `from'.

6.2.6.3 igraph_vector_append -- Append a vector to another one.
...............................................................

     int igraph_vector_append(igraph_vector_t *to,
     				   const igraph_vector_t *from);

   The target vector will be resized (except `from' is empty).

   *Arguments:. *

`to':
     The vector to append to.

`from':
     The vector to append, it is kept unchanged.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), the number of elements in the new vector.

6.2.6.4 igraph_vector_swap -- Swap elements of two vectors.
...........................................................

     int igraph_vector_swap(igraph_vector_t *v1, igraph_vector_t *v2);

   The two vectors must have the same length, otherwise an error
happens.

   *Arguments:. *

`v1':
     The first vector.

`v2':
     The second vector.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), the length of the vectors.

6.2.7 Exchanging elements
-------------------------

6.2.7.1 igraph_vector_swap_elements -- Swap two elements in a vector.
.....................................................................

     int igraph_vector_swap_elements(igraph_vector_t *v,
     					  long int i, long int j);

   Note that currently no range checking if performed.

   *Arguments:. *

`v':
     The input vector.

`i':
     Index of the first element.

`j':
     index of the second element. (Might be the same the first.)

   *Returns:. *

`'
     Error code, currently always `IGRAPH_SUCCESS'.

   Time complexity: O(1).

6.2.7.2 igraph_vector_reverse -- Reverse the elements of a vector.
..................................................................

     int igraph_vector_reverse(igraph_vector_t *v);

   The first element will be last, the last element will be first, etc.

   *Arguments:. *

`v':
     The input vector.

   *Returns:. *

`'
     Error code, currently always `IGRAPH_SUCCESS'.

   Time complexity: O(n), the number of elements.

6.2.8 Vector operations
-----------------------

6.2.8.1 igraph_vector_add_constant -- Add a constant to the vector.
...................................................................

     void igraph_vector_add_constant(igraph_vector_t *v, igraph_real_t plus);

   `plus' is added to every element of `v'. Note that overflow might
happen.

   *Arguments:. *

`v':
     The input vector.

`plus':
     The constant to add.

   Time complexity: O(n), the number of elements.

6.2.8.2 igraph_vector_scale -- Multiply all elements of a vector by a constant
..............................................................................

     void igraph_vector_scale(igraph_vector_t *v, igraph_real_t by);

   *Arguments:. *

`v':
     The vector.

`by':
     The constant.

   *Returns:. *

`'
     Error code. The current implementation always returns with success.

   Added in version 0.2.

   Time complexity: O(n), the number of elements in a vector.

6.2.8.3 igraph_vector_add -- Add two vectors.
.............................................

     int igraph_vector_add(igraph_vector_t *v1,
     				const igraph_vector_t *v2);

   Add the elements of `v2' to `v1', the result is stored in `v1'. The
two vectors must have the same length.

   *Arguments:. *

`v1':
     The first vector, the result will be stored here.

`v2':
     The second vector, its contents will be unchanged.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), the number of elements.

6.2.8.4 igraph_vector_sub -- Subtract a vector from another one.
................................................................

     int igraph_vector_sub(igraph_vector_t *v1,
     				const igraph_vector_t *v2);

   Substract the elements of `v2' from `v1', the result is stored in
`v1'. The two vectors must have the same length.

   *Arguments:. *

`v1':
     The first vector, to subtract from. The result is stored here.

`v2':
     The vector to subtract, it will be unchanged.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), the length of the vectors.

6.2.8.5 igraph_vector_mul -- Multiply two vectors.
..................................................

     int igraph_vector_mul(igraph_vector_t *v1,
     				const igraph_vector_t *v2);

   `v1' will be multiplied by `v2', elementwise. The two vectors must
have the same length.

   *Arguments:. *

`v1':
     The first vector, the result will be stored here.

`v2':
     The second vector, it is left unchanged.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), the number of elements.

6.2.8.6 igraph_vector_div -- Divide a vector by another one.
............................................................

     int igraph_vector_div(igraph_vector_t *v1,
     				const igraph_vector_t *v2);

   `v1' is divided by `v2', elementwise. They must have the same
length. If the base type of the vector can generate divide by zero
errors then please make sure that `v2' contains no zero if you want to
avoid trouble.

   *Arguments:. *

`v1':
     The dividend. The result is also stored here.

`v2':
     The divisor, it is left unchanged.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), the length of the vectors.

6.2.9 Finding minimum and maximum
---------------------------------

6.2.9.1 igraph_vector_min -- Smallest element of a vector.
..........................................................

     igraph_real_t igraph_vector_min(const igraph_vector_t* v);

   The vector must be non-empty.

   *Arguments:. *

`v':
     The input vector.

   *Returns:. *

`'
     The smallest element of `v'.

   Time complexity: O(n), the number of elements.

6.2.9.2 igraph_vector_max -- Gives the maximum element of the vector.
.....................................................................

     igraph_real_t igraph_vector_max(const igraph_vector_t* v);

   If the size of the vector is zero, an arbitrary number is returned.

   *Arguments:. *

`v':
     The vector object.

   *Returns:. *

`'
     The maximum element.

   Time complexity: O(n), n is the size of the vector.

6.2.9.3 igraph_vector_which_min -- Index of the smallest element.
.................................................................

     long int igraph_vector_which_min(const igraph_vector_t* v);

   The vector must be non-empty.  If the smallest element is not
unique, then the index of the first is returned.

   *Arguments:. *

`v':
     The input vector.

   *Returns:. *

`'
     Index of the smallest element.

   Time complexity: O(n), the number of elements.

6.2.9.4 igraph_vector_which_max -- Gives the position of the maximum element of the vector.
...........................................................................................

     long int igraph_vector_which_max(const igraph_vector_t* v);

   If the size of the vector is zero, -1 is returned.

   *Arguments:. *

`v':
     The vector object.

   *Returns:. *

`'
     The position of the first maximum element.

   Time complexity: O(n), n is the size of the vector.

6.2.9.5 igraph_vector_minmax -- Minimum and maximum elements of a vector.
.........................................................................

     int igraph_vector_minmax(const igraph_vector_t *v,
     				   igraph_real_t *min, igraph_real_t *max);

   Handy if you want to have both the smallest and largest element of a
vector. The vector is only traversed once. The vector must by non-empty.

   *Arguments:. *

`v':
     The input vector. It must contain at least one element.

`min':
     Pointer to a base type variable, the minimum is stored here.

`max':
     Pointer to a base type variable, the maximum is stored here.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), the number of elements.

6.2.9.6 igraph_vector_which_minmax -- Index of the minimum and maximum elements
...............................................................................

     int igraph_vector_which_minmax(const igraph_vector_t *v,
     					 long int *which_min, long int *which_max);

   Handy if you need the indices of the smallest and largest elements.
The vector is traversed only once. The vector must to non-empty.

   *Arguments:. *

`v':
     The input vector. It must contain at least one element.

`which_min':
     The index of the minimum element will be stored here.

`which_max':
     The index of the maximum element will be stored here.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), the number of elements.

6.2.10 Vector properties
------------------------

6.2.10.1 igraph_vector_empty -- Decides whether the size of the vector is zero.
...............................................................................

     igraph_bool_t igraph_vector_empty     (const igraph_vector_t* v);

   *Arguments:. *

`v':
     The vector object.

   *Returns:. *

`'
     Non-zero number if the size of the vector is not zero and zero
     otherwise.

   Time complexity: O(1).

6.2.10.2 igraph_vector_size -- Gives the size (=length) of the vector.
......................................................................

     long int igraph_vector_size      (const igraph_vector_t* v);

   *Arguments:. *

`v':
     The vector object

   *Returns:. *

`'
     The size of the vector.

   Time complexity: O(1).

6.2.10.3 igraph_vector_sum -- Calculates the sum of the elements in the vector.
...............................................................................

     igraph_real_t igraph_vector_sum(const igraph_vector_t *v);

   For the empty vector 0.0 is returned.

   *Arguments:. *

`v':
     The vector object.

   *Returns:. *

`'
     The sum of the elements.

   Time complexity: O(n), the size of the vector.

6.2.10.4 igraph_vector_prod -- Calculates the product of the elements in the vector.
....................................................................................

     igraph_real_t igraph_vector_prod(const igraph_vector_t *v);

   For the empty vector one (1) is returned.

   *Arguments:. *

`v':
     The vector object.

   *Returns:. *

`'
     The product of the elements.

   Time complexity: O(n), the size of the vector.

6.2.10.5 igraph_vector_isininterval -- Checks if all elements of a vector are in the given
..........................................................................................

     igraph_bool_t igraph_vector_isininterval(const igraph_vector_t *v,
     						   igraph_real_t low,
     						   igraph_real_t high);

   interval.

   *Arguments:. *

`v':
     The vector object.

`low':
     The lower limit of the interval (inclusive).

`high':
     The higher limit of the interval (inclusive).

   *Returns:. *

`'
     True (positive integer) if all vector elements are in the
     interval, false (zero) otherwise.

   Time complexity: O(n), the number of elements in the vector.

6.2.10.6 igraph_vector_is_equal -- Decides whether two vectors contain exactly the same elements
................................................................................................

     igraph_bool_t igraph_vector_is_equal(const igraph_vector_t *lhs,
     					       const igraph_vector_t *rhs);

   (in the same order).

   *Arguments:. *

`lhs':
     The first vector.

`rhs':
     The second vector.

   *Returns:. *

`'
     Positive integer if the two vectors are equal element by element
     or zero if they are not.

   Time complexity: O(n), the length of the vectors.

6.2.10.7 igraph_vector_maxdifference -- The largest element of m1 - m2
......................................................................

     igraph_real_t igraph_vector_maxdifference(const igraph_vector_t *m1,
     					   const igraph_vector_t *m2);

   The maximum the elementwise performed difference is returned.  Both
vectors must be non-empty, but they not need to have the same length,
the extra elements in the longer vector are ignored.

   *Arguments:. *

`m1':
     The first vector.

`m2':
     The second vector.

   *Returns:. *

`'
     The maximum of the difference of `m1' and `m2'.

   Time complexity: O(n), the number of elements in the shorter vector.

6.2.11 Searching for elements
-----------------------------

6.2.11.1 igraph_vector_contains -- Linear search in a vector.
.............................................................

     igraph_bool_t igraph_vector_contains(const igraph_vector_t *v,
     					       igraph_real_t e);

   Check whether the supplied element is included in the vector, by
linear search.

   *Arguments:. *

`v':
     The input vector.

`e':
     The element to look for.

   *Returns:. *

`'
     `TRUE' if the element is found and `FALSE' otherwise.

   Time complexity: O(n), the length of the vector.

6.2.11.2 igraph_vector_search -- Search from a given position
.............................................................

     igraph_bool_t igraph_vector_search(const igraph_vector_t *v,
     					     long int from, igraph_real_t what,
     					     long int *pos);

   The supplied element `what' is searched in vector `v', starting from
element index `from'. If found then the index of the first instance
(after `from') is stored in `pos'.

   *Arguments:. *

`v':
     The input vector.

`from':
     The index to start searching from. No range checking is performed.

`what':
     The element to find.

`pos':
     If not `NULL' then the index of the found element is stored here.

   *Returns:. *

`'
     Boolean, `TRUE' if the element was found, `FALSE' otherwise.

   Time complexity: O(m), the number of elements to search, the length
of the vector minus the `from' argument.

6.2.11.3 igraph_vector_binsearch -- Finds an element by binary searching a sorted vector.
.........................................................................................

     igraph_bool_t igraph_vector_binsearch(const igraph_vector_t *v,
     						igraph_real_t what, long int *pos);

   It is assumed that the vector is sorted. If the specified element
(`what') is not in the vector, then the position of where it should be
inserted (to keep the vector sorted) is returned.

   *Arguments:. *

`v':
     The `igraph_vector_t' object.

`what':
     The element to search for.

`pos':
     Pointer to a `long' int. This is set to the position of an
     instance of `what' in the vector if it is present. If `v' does not
     contain `what' then `pos' is set to the position to which it
     should be inserted (to keep the the vector sorted of course).

   *Returns:. *

`'
     Positive integer (true) if `what' is found in the vector, zero
     (false) otherwise.

   Time complexity: O(log(n)), n is the number of elements in `v'.

6.2.11.4 igraph_vector_binsearch2 -- Binary search, without returning the index.
................................................................................

     igraph_bool_t igraph_vector_binsearch2(const igraph_vector_t *v,
     						 igraph_real_t what);

   It is assumed that the vector is sorted. If the specified element
(`what') is not in the vector, then the position of where it should be
inserted (to keep the vector sorted) is returned.

   *Arguments:. *

`v':
     The `igraph_vector_t' object.

`what':
     The element to search for.

   *Returns:. *

`'
     Positive integer (true) if `what' is found in the vector, zero
     (false) otherwise.

   Time complexity: O(log(n)), n is the number of elements in `v'.

6.2.12 Resizing operations
--------------------------

6.2.12.1 igraph_vector_clear -- Removes all elements from a vector.
...................................................................

     void igraph_vector_clear     (igraph_vector_t* v);

   This function simply sets the size of the vector to zero, it does
not free any allocated memory. For that you have to call
`igraph_vector_destroy()' (see igraph_vector_destroy --- Destroys a vector object_).

   *Arguments:. *

`v':
     The vector object.

   Time complexity: O(1).

6.2.12.2 igraph_vector_reserve -- Reserves memory for a vector.
...............................................................

     int igraph_vector_reserve   (igraph_vector_t* v, long int size);

   `igraph' vectors are flexible, they can grow and shrink. Growing
however occasionally needs the data in the vector to be copyed.  In
order to avoid you can call this function to reserve space for future
growth of the vector.

   Note that this function does _not_ change the size of the vector.
Let us see a small example to clarify things: if you reserve space for
100 elements and the size of your vector was (and still is) 60, then
you can surely add additional 40 elements to your vector before it will
be copied.

   *Arguments:. *

`v':
     The vector object.

`size':
     The new _allocated_ size of the vector.

   *Returns:. *

`'
     Error code: `IGRPAH_ENOMEM' if there is not enough memory.

   Time complexity: operating system dependent, should be around O(n), n
is the new allocated size of the vector.

6.2.12.3 igraph_vector_resize -- Resize the vector.
...................................................

     int igraph_vector_resize(igraph_vector_t* v, long int newsize);

   Note that this function does not free any memory, just sets the size
of the vector to the given one. It can on the other hand allocate more
memory if the new size is larger than the previous one. In this case
the newly appeared elements in the vector are _not_ set to zero, they
are uninitialized.

   *Arguments:. *

`v':
     The vector object

`newsize':
     The new size of the vector.

   *Returns:. *

`'
     Error code, `IGRAPH_ENOMEM' if there is not enough memory. Note
     that this function _never_ returns an error if the vector is made
     smaller.

   *See also:. *

`'
     `igraph_vector_reserve()' (see igraph_vector_reserve --- Reserves memory for a vector_)
     for allocating memory for future
     extensions of a vector.

   Time complexity: O(1) if the new size is smaller, operating system
dependent if it is larger. In the latter case it is usually around O(n),
n is the new size of the vector.

6.2.12.4 igraph_vector_push_back -- Appends one element to a vector.
....................................................................

     int igraph_vector_push_back (igraph_vector_t* v, igraph_real_t e);

   This function resizes the vector to be one element longer and sets
the very last element in the vector to `e'.

   *Arguments:. *

`v':
     The vector object.

`e':
     The element to append to the vector.

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM': not enough memory.

   Time complexity: operating system dependent. What is important that
a sequence of n subsequent calls to this function has time complexity
O(n), even if there hadn't been any space reserved for the new elements
by `igraph_vector_reserve()' (see igraph_vector_reserve --- Reserves memory for a vector_).
This is implemented by a trick similar to the
C++ `vector' class: each time more memory is allocated for a vector,
the size of the additionally allocated memory is the same as the
vector's current length. (We assume here that the time complexity of
memory allocation is at most linear.)

6.2.12.5 igraph_vector_pop_back -- Removes and returns the last element of a vector.
....................................................................................

     igraph_real_t igraph_vector_pop_back(igraph_vector_t* v);

   It is an error to call this function with an empty vector.

   *Arguments:. *

`v':
     The vector object.

   *Returns:. *

`'
     The removed last element.

   Time complexity: O(1).

6.2.12.6 igraph_vector_insert -- Inserts a single element into a vector.
........................................................................

     int igraph_vector_insert(igraph_vector_t *v, long int pos,
     				   igraph_real_t value);

   Note that this function does not do range checking. Insertion will
shift the elements from the position given to the end of the vector one
position to the right, and the new element will be inserted in the
empty space created at the given position. The size of the vector will
increase by one.

   *Arguments:. *

`v':
     The vector object.

`pos':
     The position where the new element is inserted.

6.2.12.7 igraph_vector_remove -- Removes a single element from a vector.
........................................................................

     void igraph_vector_remove(igraph_vector_t *v, long int elem);

   Note that this function does not do range checking.

   *Arguments:. *

`v':
     The vector object.

`elem':
     The position of the element to remove.

   Time complexity: O(n-elem), n is the number of elements in the
vector.

6.2.12.8 igraph_vector_remove_section -- Deletes a section from a vector.
.........................................................................

     void igraph_vector_remove_section(igraph_vector_t *v,
     					    long int from, long int to);

   Note that this function does not do range checking. The result is
undefined if you supply invalid limits.

   *Arguments:. *

`v':
     The vector object.

`from':
     The position of the first element to remove.

`to':
     The position of the first element _not_ to remove.

   Time complexity: O(n-from), n is the number of elements in the
vector.

6.2.13 Sorting
--------------

6.2.13.1 igraph_vector_sort -- Sorts the elements of the vector into ascending order.
.....................................................................................

     void igraph_vector_sort(igraph_vector_t *v);

   This function uses the built-in sort function of the C library.

   *Arguments:. *

`v':
     Pointer to an initialized vector object.

   Time complexity: should be O(nlogn) for n elements.

6.2.14 Pointer vectors (igraph_vector_ptr_t)
--------------------------------------------

The `igraph_vector_ptr_t' data type is very similar to the
`igraph_vector_t' type, but it stores generic pointers instead of real
numbers.

   This type has the same space complexity as `igraph_vector_t', and
most implemented operations work the same way as for `igraph_vector_t'.

   This type is mostly used to pass to or receive from a set of graphs
to some `igraph' functions, such as `igraph_decompose()' (see
igraph_decompose --- Decompose a graph into connected components_),
which decomposes a graph to connected components.

   The same `VECTOR' (see VECTOR --- Accessing an element of a vector_)
macro used for ordinary vectors can be used for pointer
vectors as well, please note that a typeless generic pointer will be
provided by this macro and you may need to cast it to a specific
pointer before starting to work with it.

6.2.14.1 igraph_vector_ptr_init -- Initialize a pointer vector (constructor).
.............................................................................

     int igraph_vector_ptr_init      (igraph_vector_ptr_t* v, int long size);

   This is the constructor of the pointer vector data type. All pointer
vectors constructed this way should be destroyed via calling
`igraph_vector_ptr_destroy()' (see igraph_vector_ptr_destroy --- Destroys a pointer vector_).

   *Arguments:. *

`v':
     Pointer to an uninitialized `igraph_vector_ptr_t' object, to be
     created.

`size':
     Integer, the size of the pointer vector.

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM' if out of memory

   Time complexity: operating system dependent, the amount of `time'
required to allocate `size' elements.

6.2.14.2 igraph_vector_ptr_copy -- Copy a pointer vector (constructor).
.......................................................................

     int igraph_vector_ptr_copy(igraph_vector_ptr_t *to, const igraph_vector_ptr_t *from);

   This function creates a pointer vector by copying another one. This
is shallow copy, only the pointers in the vector will be copyed.

   *Arguments:. *

`to':
     Pointer to an uninitialized pointer vector object.

`from':
     A pointer vector object.

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM' if out of memory

   Time complexity: O(n) if allocating memory for n elements can be
done in O(n) time.

6.2.14.3 igraph_vector_ptr_destroy -- Destroys a pointer vector.
................................................................

     void igraph_vector_ptr_destroy   (igraph_vector_ptr_t* v);

   The destructor for pointer vectors.

   *Arguments:. *

`v':
     Pointer to the pointer vector to destroy.

   Time complexity: operating system dependend, the `time' required to
deallocate O(n) bytes, n is the number of elements allocated for the
pointer vector (not neccessarily the number of elements in the vector).

6.2.14.4 igraph_vector_ptr_free_all -- Calls free() on all elements of a pointer vector.
........................................................................................

     void igraph_vector_ptr_free_all   (igraph_vector_ptr_t* v);

   *Arguments:. *

`v':
     Pointer to the pointer vector whose elements will be freed.

   Time complexity: operating system dependent, the `time' required to
deallocate O(n) pointers, each pointing to a memory area of arbitrary
size. n is the number of elements in the pointer vector.

6.2.14.5 igraph_vector_ptr_destroy_all -- Calls free() on all elements and destroys the pointer vector.
.......................................................................................................

     void igraph_vector_ptr_destroy_all   (igraph_vector_ptr_t* v);

   *Arguments:. *

`v':
     Pointer to the pointer vector to destroy.

   Time complexity: operating system dependent, the `time' required to
deallocate O(n) pointers, each pointing to a memory area of arbitrary
size, plus the `time' required to deallocate O(n) bytes, n being the
number of elements allocated for the pointer vector (not necessarily
the number of elements in the vector).

6.2.14.6 igraph_vector_ptr_size -- Gives the number of elements in the pointer vector.
......................................................................................

     long int igraph_vector_ptr_size      (const igraph_vector_ptr_t* v);

   *Arguments:. *

`v':
     The pointer vector object.

   *Returns:. *

`'
     The size of the object, ie. the number of pointers stored.

   Time complexity: O(1).

6.2.14.7 igraph_vector_ptr_clear -- Removes all elements from a pointer vector.
...............................................................................

     void igraph_vector_ptr_clear     (igraph_vector_ptr_t* v);

   This function resizes a pointer to vector to zero length. Note that
the pointed objects are _not_ deallocated, you should call free() on
them, or make sure that their allocated memory is freed in some other
way, you'll get memory leaks otherwise.

   Note that the current implementation of this function does _not_
deallocate the memory required for storing the pointers, so making a
pointer vector smaller this way does not give back any memory. This
behavior might change in the future.

   *Arguments:. *

`v':
     The pointer vector to clear.

   Time complexity: O(1).

6.2.14.8 igraph_vector_ptr_push_back -- Appends an elements to the back of a pointer vector.
............................................................................................

     int igraph_vector_ptr_push_back (igraph_vector_ptr_t* v, void* e);

   *Arguments:. *

`v':
     The pointer vector.

`e':
     The new element to include in the pointer vector.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     igraph_vector_push_back() for the corresponding operation of the
     ordinary vector type.

   Time complexity: O(1) or O(n), n is the number of elements in the
vector. The pointer vector implementation ensures that n subsequent
push_back operations need O(n) time to complete.

6.2.14.9 igraph_vector_ptr_e -- Access an element of a pointer vector.
......................................................................

     void* igraph_vector_ptr_e         (const igraph_vector_ptr_t* v, long int pos);

   *Arguments:. *

`v':
     Pointer to a pointer vector.

`pos':
     The index of the pointer to return.

   *Returns:. *

`'
     The pointer at `pos' position.

   Time complexity: O(1).

6.2.14.10 igraph_vector_ptr_set -- Assign to an element of a pointer vector.
............................................................................

     void igraph_vector_ptr_set       (igraph_vector_ptr_t* v, long int pos, void* value);

   *Arguments:. *

`v':
     Pointer to a pointer vector.

`pos':
     The index of the pointer to update.

`value':
     The new pointer to set in the vector.

   Time complexity: O(1).

6.2.14.11 igraph_vector_ptr_resize -- Resizes a pointer vector.
...............................................................

     int igraph_vector_ptr_resize(igraph_vector_ptr_t* v, long int newsize);

   Note that if a vector is made smaller the pointed object are not
deallocated by this function.

   *Arguments:. *

`v':
     A pointer vector.

`newsize':
     The new size of the pointer vector.

   *Returns:. *

`'
     Error code.

   Time complexity: O(1) if the vector if made smaller. Operating
system dependent otherwise, the amount of `time' needed to allocate the
memory for the vector elements.

6.3 Matrices
============

6.3.1 About igraph_matrix_t objects
-----------------------------------

This type is just an interface to `igraph_vector_t'.

   The `igraph_matrix_t' type usually stores n elements in O(n) space,
but not always, see the documentation of the vector type.

6.3.2 Matrix constructors and destructors
-----------------------------------------

6.3.2.1 igraph_matrix_init -- Initializes a matrix.
...................................................

     int igraph_matrix_init(igraph_matrix_t *m, long int nrow, long int ncol);

   Every matrix needs to be initialized before using it, this is done
by calling this function. A matrix has to be destroyed if it is not
needed any more, see `igraph_matrix_destroy()' (see
igraph_matrix_destroy --- Destroys a matrix object_).

   *Arguments:. *

`m':
     Pointer to a not yet initialized matrix object to be initialized.

`nrow':
     The number of rows in the matrix.

`ncol':
     The number of columns in the matrix.

   *Returns:. *

`'
     Error code.

   Time complexity: usually O(n), n is the number of elements in the
matrix.

6.3.2.2 igraph_matrix_copy -- Copies a matrix.
..............................................

     int igraph_matrix_copy(igraph_matrix_t *to, const igraph_matrix_t *from);

   Creates a matrix object by copying another one.

   *Arguments:. *

`to':
     Pointer to an uninitialized matrix object.

`from':
     The initialized matrix object to copy.

   *Returns:. *

`'
     Error code, `IGRAPH_ENOMEM' if there isn't enough memory to
     allocate the new matrix.

   Time complexity: O(n), the number of elements in the matrix.

6.3.2.3 igraph_matrix_destroy -- Destroys a matrix object.
..........................................................

     void igraph_matrix_destroy(igraph_matrix_t *m);

   This function frees all the memory allocated for a matrix object.
The destroyed object needs to be reinitialized before using it again.

   *Arguments:. *

`m':
     The matrix to destroy.

   Time complexity: operating system dependent.

6.3.3 Initializing elements
---------------------------

6.3.3.1 igraph_matrix_null -- Sets all element in a matrix to zero.
...................................................................

     void igraph_matrix_null(igraph_matrix_t *m);

   *Arguments:. *

`m':
     Pointer to an initialized matrix object.

   Time complexity: O(n), n is the number of  elements in the matrix.

6.3.3.2 igraph_matrix_fill -- Fill with an element.
...................................................

     void igraph_matrix_fill(igraph_matrix_t *m, igraph_real_t e);

   Set the matrix to a constant matrix.

   *Arguments:. *

`m':
     The input matrix.

`e':
     The element to set.

   Time complexity: O(mn), the number of elements.

6.3.4 Copying matrices
----------------------

6.3.4.1 igraph_matrix_copy_to -- Copies a matrix to a regular C array.
......................................................................

     void igraph_matrix_copy_to(const igraph_matrix_t *m, igraph_real_t *to);

   The matrix is copied columnwise, as this is the format most programs
and languages use.  The C array should be of sufficient size, there are
(of course) not range checks done.

   *Arguments:. *

`m':
     Pointer to an initialized matrix object.

`to':
     Pointer to a C array, the place to copy the data to.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), n is the number of elements in the matrix.

6.3.4.2 igraph_matrix_update -- Update from another matrix.
...........................................................

     int igraph_matrix_update(igraph_matrix_t *to,
     				   const igraph_matrix_t *from);

   This function replicates `from' in the matrix `to'.  Note that `to'
must be already initialized.

   *Arguments:. *

`to':
     The result matrix.

`from':
     The matrix to replicate, it is left unchanged.

   *Returns:. *

`'
     Error code.

   Time complexity: O(mn), the number of elements.

6.3.4.3 igraph_matrix_swap -- Swap two matrices
...............................................

     int igraph_matrix_swap(igraph_matrix_t *m1, igraph_matrix_t *m2);

   The contents of the two matrices will be swapped. They must be the
same size.

   *Arguments:. *

`m1':
     The first matrix.

`m2':
     The second matrix.

   *Returns:. *

`'
     Error code.

   Time complexity: O(mn), the number of elements in the matrices.

6.3.5 Accessing elements of a matrix
------------------------------------

6.3.5.1 MATRIX -- Accessing an element of a matrix.
...................................................

     #define MATRIX(m,i,j)

   Note that there are no range checks right now.  This functionality
might be redefines as a proper function later.

   *Arguments:. *

`m':
     The matrix object.

`i':
     The index of the row, starting with zero.

`j':
     The index of the column, starting with zero.

   Time complexity: O(1).

6.3.5.2 igraph_matrix_e -- Extract an element
.............................................

     igraph_real_t igraph_matrix_e(const igraph_matrix_t *m,
     			       long int row, long int col);

   Use this if you need a function for some reason and cannot use the
`MATRIX' (see MATRIX --- Accessing an element of a matrix_) macro.
Note that no range checking is performed.

   *Arguments:. *

`m':
     The input matrix.

`row':
     The row index.

`col':
     The column index.

   *Returns:. *

`'
     The element in the given row and column.

   Time complexity: O(1).

6.3.5.3 igraph_matrix_e_ptr -- Pointer to an element
....................................................

     igraph_real_t* igraph_matrix_e_ptr(const igraph_matrix_t *m,
     				    long int row, long int col);

   The function returns a pointer to an element. No range checking is
performed.

   *Arguments:. *

`m':
     The input matrix.

`row':
     The row index.

`col':
     The column index.

   *Returns:. *

`'
     Pointer to the element in the given row and column.

   Time complexity: O(1).

6.3.5.4 igraph_matrix_set -- Set an element.
............................................

     void igraph_matrix_set(igraph_matrix_t* m, long int row, long int col,
     				 igraph_real_t value);

   Set and element of a matrix. No range cheking is performed.

   *Arguments:. *

`m':
     The input matrix.

`row':
     The row index.

`col':
     The column index.

`value':
     The new value of the element.

   Time complexity: O(1).

6.3.6 Operations on rows and columns
------------------------------------

6.3.6.1 igraph_matrix_get_row -- Extract a row
..............................................

     int igraph_matrix_get_row(const igraph_matrix_t *m,
     				    igraph_vector_t *res, long int index);

   Extract a row from a matrix and return it as a vector.

   *Arguments:. *

`m':
     The input matrix.

`res':
     Pointer to an initialized vector, it will be resized if needed.

`index':
     The index of the row to select.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), the number of columns in the matrix.

6.3.6.2 igraph_matrix_get_col -- Select a column
................................................

     int igraph_matrix_get_col(const igraph_matrix_t *m,
     				    igraph_vector_t *res,
     				    long int index);

   Extract a column of a matrix and return it in a vector.

   *Arguments:. *

`m':
     The input matrix.

`res':
     The result will we stored in this vector. It should be initialized
     and will be resized as needed.

`index':
     The index of the solumn to select.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), the number of rows in the matrix.

6.3.6.3 igraph_matrix_set_row -- Set a row from a vector.
.........................................................

     int igraph_matrix_set_row(igraph_matrix_t *m,
     				    const igraph_vector_t *v, long int index);

   Sets the elements of a row, from the given vector. The length of the
vector and the number of columns in the matrix must match, otherwise
and error is triggered.

   *Arguments:. *

`m':
     The input matrix.

`v':
     The vector containing the new elements of the row.

`index':
     Index of the row to set.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), the number of columns in the matrix.

6.3.6.4 igraph_matrix_set_col -- Set a column from a vector.
............................................................

     int igraph_matrix_set_col(igraph_matrix_t *m,
     				    const igraph_vector_t *v, long int index);

   Sets the elements of a column, from the given vector. The length of
the vector and the number of rows in the matrix must match, otherwise
and error is triggered.

   *Arguments:. *

`m':
     The input matrix.

`v':
     The vector containing the new elements of the column.

`index':
     Index of the column to set.

   *Returns:. *

`'
     Error code.

   Time complexity: O(m), the number of rows in the matrix.

6.3.6.5 igraph_matrix_swap_rows -- Swap two rows
................................................

     int igraph_matrix_swap_rows(igraph_matrix_t *m,
     				      long int i, long int j);

   Swap two rows in the matrix.

   *Arguments:. *

`m':
     The input matrix.

`i':
     The index of the first row.

`j':
     The index of the second row.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), the number of columns.

6.3.6.6 igraph_matrix_swap_cols -- Swap two columns
...................................................

     int igraph_matrix_swap_cols(igraph_matrix_t *m,
     				      long int i, long int j);

   Swap two columns in the matrix.

   *Arguments:. *

`m':
     The input matrix.

`i':
     The index of the first column.

`j':
     The index of the second column.

   *Returns:. *

`'
     Error code.

   Time complexity: O(m), the number of rows.

6.3.6.7 igraph_matrix_select_rows -- Select some rows of a matrix
.................................................................

     int igraph_matrix_select_rows(const igraph_matrix_t *m,
     					igraph_matrix_t *res,
     					const igraph_vector_t *rows);

   This function selects some rows of a matrix and returns them in a
new matrix. The result matrix should be initialized before calling the
function.

   *Arguments:. *

`m':
     The input matrix.

`res':
     The result matrix. It should be initialized and will be resized as
     needed.

`rows':
     Vector, it contains the row indices (starting with zero) to
     extract. Note that no range checking is performed.

   *Returns:. *

`'
     Error code.

   Time complexity: O(nm), n is the number of rows, m the number of
columns of the result matrix.

6.3.6.8 igraph_matrix_select_cols -- Select some columns of a matrix
....................................................................

     int igraph_matrix_select_cols(const igraph_matrix_t *m,
     					igraph_matrix_t *res,
     					const igraph_vector_t *cols);

   This function selects some columns of a matrix and returns them in a
new matrix. The result matrix should be initialized before calling the
function.

   *Arguments:. *

`m':
     The input matrix.

`res':
     The result matrix. It should be initialized and will be resized as
     needed.

`cols':
     Vector, it contains the column indices (starting with zero) to
     extract. Note that no range checking is performed.

   *Returns:. *

`'
     Error code.

   Time complexity: O(nm), n is the number of rows, m the number of
columns of the result matrix.

6.3.7 Matrix operations
-----------------------

6.3.7.1 igraph_matrix_add_constant -- Add a constant to every element.
......................................................................

     void igraph_matrix_add_constant(igraph_matrix_t *m, igraph_real_t plus);

   *Arguments:. *

`m':
     The input matrix.

`plud':
     The constant to add.

   Time complexity: O(mn), the number of elements.

6.3.7.2 igraph_matrix_scale -- Multiplies each element of the matrix by a constant.
...................................................................................

     void igraph_matrix_scale(igraph_matrix_t *m, igraph_real_t by);

   *Arguments:. *

`m':
     The matrix.

`by':
     The constant.

   Added in version 0.2.

   Time complexity: O(n), the number of elements in the matrix.

6.3.7.3 igraph_matrix_add -- Add two matrices.
..............................................

     int igraph_matrix_add(igraph_matrix_t *m1,
     				const igraph_matrix_t *m2);

   Add `m2' to `m1', and store the result in `m1'. The size of the
matrices must match.

   *Arguments:. *

`m1':
     The first matrix, the result will be stored here.

`m2':
     The second matrix, it is left unchanged.

   *Returns:. *

`'
     Error code.

   Time complexity: O(mn), the number of elements.

6.3.7.4 igraph_matrix_sub -- Difference of two matrices.
........................................................

     int igraph_matrix_sub(igraph_matrix_t *m1,
     				const igraph_matrix_t *m2);

   Subtract `m2' from `m1' and store the result in `m1'.  The size of
the two matrices must match.

   *Arguments:. *

`m1':
     The first matrix, the result is stored here.

`m2':
     The second matrix, it is left unchanged.

   *Returns:. *

`'
     Error code.

   Time complexity: O(mn), the number of elements.

6.3.7.5 igraph_matrix_mul_elements -- Elementwise multiplication.
.................................................................

     int igraph_matrix_mul_elements(igraph_matrix_t *m1,
     					 const igraph_matrix_t *m2);

   Multiply `m1' by `m2' elementwise and store the result in `m1'.  The
size of the two matrices must match.

   *Arguments:. *

`m1':
     The first matrix, the result is stored here.

`m2':
     The second matrix, it is left unchanged.

   *Returns:. *

`'
     Error code.

   Time complexity: O(mn), the number of elements.

6.3.7.6 igraph_matrix_div_elements -- Elementwise division.
...........................................................

     int igraph_matrix_div_elements(igraph_matrix_t *m1,
     					 const igraph_matrix_t *m2);

   Divide `m1' by `m2' elementwise and store the result in `m1'.  The
size of the two matrices must match.

   *Arguments:. *

`m1':
     The divident. The result is store here.

`m2':
     The divisor. It is left unchanged.

   *Returns:. *

`'
     Error code.

   Time complexity: O(mn), the number of elements.

6.3.7.7 igraph_matrix_sum -- Sum of elements
............................................

     igraph_real_t igraph_matrix_sum(const igraph_matrix_t *m);

   Returns the sum of the elements of a matrix.

   *Arguments:. *

`m':
     The input matrix.

   *Returns:. *

`'
     The sum of the elements.

   Time complexity: O(mn), the number of elements in the matrix.

6.3.7.8 igraph_matrix_prod -- Product of the elements.
......................................................

     igraph_real_t igraph_matrix_prod(const igraph_matrix_t *m);

   Note this function can result an overflow easily, even for not too
big matrices.

   *Arguments:. *

`The':
     input matrix.

   *Returns:. *

`'
     The product of the elements.

   Time complexity: O(mn), the number of elements.

6.3.7.9 igraph_matrix_rowsum -- Rowwise sum
...........................................

     int igraph_matrix_rowsum(const igraph_matrix_t *m,
     				   igraph_vector_t *res);

   Calculate the sum of the elements in each row.

   *Arguments:. *

`m':
     The input matrix.

`res':
     Pointer to an initialized vector, the result is stored here. It
     will be resized if necessary.

   *Returns:. *

`'
     Error code.

   Time complexity: O(mn), the number of elements in the matrix.

6.3.7.10 igraph_matrix_colsum -- Columnwise sum
...............................................

     int igraph_matrix_colsum(const igraph_matrix_t *m,
     				   igraph_vector_t *res);

   Calculate the sum of the elements in each column.

   *Arguments:. *

`m':
     The input matrix.

`res':
     Pointer to an initialized vector, the result is stored here. It
     will be resized if necessary.

   *Returns:. *

`'
     Error code.

   Time complexity: O(mn), the number of elements in the matrix.

6.3.7.11 igraph_matrix_transpose -- Transpose
.............................................

     int igraph_matrix_transpose(igraph_matrix_t *m);

   Calculate the transpose of a matrix. Note that the function
reallocates the memory used for the matrix.

   *Arguments:. *

`m':
     The input (and output) matrix.

   *Returns:. *

`'
     Error code.

   Time complexity: O(mn), the number of elements in the matrix.

6.3.8 Combining matrices
------------------------

6.3.8.1 igraph_matrix_rbind -- Combine two matrices rowwise
...........................................................

     int igraph_matrix_rbind(igraph_matrix_t *to,
     				  const igraph_matrix_t *from);

   This function places the rows of `from' below the rows of `to' and
stores the result in `to'. The number of columns in the two matrices
must match.

   *Arguments:. *

`to':
     The upper matrix, the result is also stored here.

`from':
     The lower matrix. It is left unchanged.

   *Returns:. *

`'
     Error code.

   Time complexity: O(mn), the number of elements in the newly created
matrix.

6.3.8.2 igraph_matrix_cbind -- Combine matrices, columnwise.
............................................................

     int igraph_matrix_cbind(igraph_matrix_t *to,
     				  const igraph_matrix_t *from);

   This function places the columns of `from' on the right of `to', and
stores the result in `to'.

   *Arguments:. *

`to':
     The left matrix, the result is stored here too.

`from':
     The right matrix. It is left unchanged.

   *Returns:. *

`'
     Error code.

   Time complexity: O(mn), the number of elements on the new matrix.

6.3.9 Finding minimum and maximum
---------------------------------

6.3.9.1 igraph_matrix_min -- Minimum element.
.............................................

     igraph_real_t igraph_matrix_min(const igraph_matrix_t *m);

   Returns the smallest element of a non-empty matrix.

   *Arguments:. *

`m':
     The input matrix.

   *Returns:. *

`'
     The smallest element.

   Time complexity: O(mn), the number of elements.

6.3.9.2 igraph_matrix_max -- Returns the maximal element of a matrix.
.....................................................................

     igraph_real_t igraph_matrix_max(const igraph_matrix_t *m);

   *Arguments:. *

`m':
     The matrix object.

   *Returns:. *

`'
     The maximum element. For empty matrix the returned value is
     undefined.

   Added in version 0.2.

   Time complexity: O(n), the number of elements in the matrix.

6.3.9.3 igraph_matrix_which_min -- Indices of the minimum.
..........................................................

     int igraph_matrix_which_min(const igraph_matrix_t *m,
     				      long int *i, long int *j);

   Gives the indices of the (first) smallest element in a non-empty
matrix.

   *Arguments:. *

`m':
     The matrix.

`i':
     Pointer to a `long int'. The row index of the minimum is stored
     here.

`j':
     Pointer to a `long int'. The column index of the minimum is stored
     here.

   *Returns:. *

`'
     Error code.

   Time complexity: O(mn), the number of elements.

6.3.9.4 igraph_matrix_which_max -- Indices of the maximum.
..........................................................

     int igraph_matrix_which_max(const igraph_matrix_t *m,
     				      long int *i, long int *j);

   Gives the indices of the (first) largest element in a non-empty
matrix.

   *Arguments:. *

`m':
     The matrix.

`i':
     Pointer to a `long int'. The row index of the maximum is stored
     here.

`j':
     Pointer to a `long int'. The column index of the maximum is stored
     here.

   *Returns:. *

`'
     Error code.

   Time complexity: O(mn), the number of elements.

6.3.9.5 igraph_matrix_minmax -- Minimum and maximum
...................................................

     int igraph_matrix_minmax(const igraph_matrix_t *m,
     				   igraph_real_t *min, igraph_real_t *max);

   The maximum and minimum elements of a non-empty matrix.

   *Arguments:. *

`m':
     The input matrix.

`min':
     Pointer to a base type. The minimum is stored here.

`max':
     Pointer to a base type. The maximum is stored here.

   *Returns:. *

`'
     Error code.

   Time complexity: O(mn), the number of elements.

6.3.9.6 igraph_matrix_which_minmax -- Indices of the minimum and maximum
........................................................................

     int igraph_matrix_which_minmax(const igraph_matrix_t *m,
     					 long int *imin, long int *jmin,
     					 long int *imax, long int *jmax);

   Find the positions of the smallest and largest elements of a
non-empty matrix.

   *Arguments:. *

`m':
     The input matrix.

`imin':
     Pointer to a `long int', the row index of the minimum is stored
     here.

`jmin':
     Pointer to a `long int', the column index of the minimum is stored
     here.

`imax':
     Pointer to a `long int', the row index of the maximum is stored
     here.

`jmax':
     Pointer to a `long int', the column index of the maximum is stored
     here.

   *Returns:. *

`'
     Error code.

   Time complexity: O(mn), the number of elements.

6.3.10 Matrix properties
------------------------

6.3.10.1 igraph_matrix_empty -- Check for an empty matrix.
..........................................................

     igraph_bool_t igraph_matrix_empty(const igraph_matrix_t *m);

   It is possible to have a matrix with zero rows or zero columns, or
even both. This functions checks for these.

   *Arguments:. *

`m':
     The input matrix.

   *Returns:. *

`'
     Boolean, `TRUE' if the matrix contains zero elements, and `FALSE'
     otherwise.

   Time complexity: O(1).

6.3.10.2 igraph_matrix_isnull -- Check for a null matrix.
.........................................................

     igraph_bool_t igraph_matrix_isnull(const igraph_matrix_t *m);

   Checks whether all elements are zero.

   *Arguments:. *

`m':
     The input matrix.

   *Returns:. *

`'
     Boolean, `TRUE' is `m' contains only zeros and `FALSE' otherwise.

   Time complexity: O(mn), the number of elements.

6.3.10.3 igraph_matrix_size -- The number of elements in a matrix.
..................................................................

     long int igraph_matrix_size(const igraph_matrix_t *m);

   *Arguments:. *

`m':
     Pointer to an initialized matrix object.

   *Returns:. *

`'
     The size of the matrix.

   Time complexity: O(1).

6.3.10.4 igraph_matrix_nrow -- The number of rows in a matrix.
..............................................................

     long int igraph_matrix_nrow(const igraph_matrix_t *m);

   *Arguments:. *

`m':
     Pointer to an initialized matrix object.

   *Returns:. *

`'
     The number of rows in the matrix.

   Time complexity: O(1).

6.3.10.5 igraph_matrix_ncol -- The number of columns in a matrix.
.................................................................

     long int igraph_matrix_ncol(const igraph_matrix_t *m);

   *Arguments:. *

`m':
     Pointer to an initialized matrix object.

   *Returns:. *

`'
     The number of columns in the matrix.

   Time complexity: O(1).

6.3.10.6 igraph_matrix_is_symmetric -- Check for symmetric matrix.
..................................................................

     igraph_bool_t igraph_matrix_is_symmetric(const igraph_matrix_t *m);

   A non-square matrix is not symmetric by definition.

   *Arguments:. *

`m':
     The input matrix.

   *Returns:. *

`'
     Boolean, `TRUE' if the matrix is square and symmetric, `FALSE'
     otherwise.

   Time complexity: O(mn), the number of elements. O(1) for non-square
matrices.

6.3.10.7 igraph_matrix_is_equal -- Are two matrices equal?
..........................................................

     igraph_bool_t igraph_matrix_is_equal(const igraph_matrix_t *m1,
     					      const igraph_matrix_t *m2);

   Decides whether two matrices are equal. Two matrices are equal if
they have the same size and contain exactly the same elements.

   *Arguments:. *

`m1':
     The first matrix.

`m2':
     The second matrix.

   *Returns:. *

`'
     `TRUE' if they are equal, `FALSE' otherwise.

   Time complexity: O(1) if the sizes are different, O(mn) otherwise.

6.3.10.8 igraph_matrix_maxdifference -- Maximum difference
..........................................................

     igraph_real_t igraph_matrix_maxdifference(const igraph_matrix_t *m1,
     					   const igraph_matrix_t *m2);

   Calculate the maximum difference of two matrices. Both matrices must
be non-empty. If their size differs then a warning is given and the
comparision is performed by vectors columnwise from both matrices,
columnwise, the remaining elements in the larger vector are ignored.

   *Arguments:. *

`m1':
     The first matrix.

`m2':
     The second matrix.

   *Returns:. *

`'
     The maximum of `m1' - `m2'.

   Time complexity: O(mn), the elements in the smaller matrix.

6.3.11 Searching for elements
-----------------------------

6.3.11.1 igraph_matrix_contains -- Search for an element.
.........................................................

     igraph_bool_t igraph_matrix_contains(const igraph_matrix_t *m,
     					       igraph_real_t e);

   Search for the given element in the matrix.

   *Arguments:. *

`m':
     The input matrix.

`e':
     The element to search for.

   *Returns:. *

`'
     Boolean, `TRUE' if the matrix contains `e', `FALSE' otherwise.

   Time complexity: O(mn), the number of elements.

6.3.11.2 igraph_matrix_search -- Search from a given position.
..............................................................

     igraph_bool_t igraph_matrix_search(const igraph_matrix_t *m,
     					     long int from, igraph_real_t what,
     					     long int *pos,
     					     long int *row, long int *col);

   Search for an element in a matrix and start the search from the
given position. The search is performed columnwise.

   *Arguments:. *

`m':
     The input matrix.

`from':
     The position to search from, the positions are enumerated
     columnwise.

`what':
     The element to search for.

`pos':
     Pointer to a `long int'. If the element is found, then this is set
     to the position of its first appearance.

`row':
     Pointer to a `long int'. If the element is found, then this is set
     to its row index.

`col':
     Pointer to a `long int'. If the element is found, then this is set
     to its column index.

   *Returns:. *

`'
     Boolean, `TRUE' if the element is found, `FALSE' otherwise.

   Time complexity: O(mn), the number of elements.

6.3.12 Resizing operations
--------------------------

6.3.12.1 igraph_matrix_resize -- Resizes a matrix.
..................................................

     int igraph_matrix_resize(igraph_matrix_t *m, long int nrow, long int ncol);

   This function resizes a matrix by adding more elements to it.  The
matrix contains arbitrary data after resizing it.  Ie. after calling
this function you cannot expect that element (i,j) in the matrix
remains the same as before.

   *Arguments:. *

`m':
     Pointer to an already initialized matrix object.

`nrow':
     The number of rows in the resized matrix.

`ncol':
     The number of columns in the resized matrix.

   *Returns:. *

`'
     Error code.

   Time complexity: O(1) if the matrix gets smaller, usually O(n) if it
gets larger, n is the number of elements in the resized matrix.

6.3.12.2 igraph_matrix_add_rows -- Adds rows to a matrix.
.........................................................

     int igraph_matrix_add_rows(igraph_matrix_t *m, long int n);

   *Arguments:. *

`m':
     The matrix object.

`n':
     The number of rows to add.

   *Returns:. *

`'
     Error code, `IGRAPH_ENOMEM' if there isn't enough memory for the
     operation.

   Time complexity: linear with the number of elements of the new,
resized, matrix.

6.3.12.3 igraph_matrix_add_cols -- Adds columns to a matrix.
............................................................

     int igraph_matrix_add_cols(igraph_matrix_t *m, long int n);

   *Arguments:. *

`m':
     The matrix object.

`n':
     The number of columns to add.

   *Returns:. *

`'
     Error code, `IGRAPH_ENOMEM' if there is not enough memory to
     perform the operation.

   Time complexity: linear with the number of elements of the new,
resized matrix.

6.3.12.4 igraph_matrix_remove_row -- Remove a row
.................................................

     int igraph_matrix_remove_row(igraph_matrix_t *m, long int row);

   A row is removed from the matrix.

   *Arguments:. *

`m':
     The input matrix.

`row':
     The index of the row to remove.

   *Returns:. *

`'
     Error code.

   Time complexity: O(mn), the number of elements in the matrix.

6.3.12.5 igraph_matrix_remove_col -- Removes a column from a matrix.
....................................................................

     int igraph_matrix_remove_col(igraph_matrix_t *m, long int col);

   *Arguments:. *

`m':
     The matrix object.

`col':
     The column to remove.

   *Returns:. *

`'
     Error code, always returns with success.

   Time complexity: linear with the number of elements of the new,
resized matrix.

6.4 Sparse matrices
===================

6.4.1 About igraph_spmatrix_t objects
-------------------------------------

The `igraph_spmatrix_t' type stores a sparse matrix with the assumption
that the number of nonzero elements in the matrix scales linearly with
the row or column count of the matrix (so most of the elements are
zero). Of course it can store an arbitrary real matrix, but if most of
the elements are nonzero, one should use `igraph_matrix_t' instead.

   The elements are stored in column compressed format, so the elements
in the same column are stored adjacent in the computer's memory. The
storage requirement for a sparse matrix is O(n) where n is the number
of nonzero elements. Actually it can be a bit larger, see the
documentation of the vector type for an explanation.

6.4.2 Sparse matrix constructors and destructors.
-------------------------------------------------

6.4.2.1 igraph_spmatrix_init -- Initializes a sparse matrix.
............................................................

     int igraph_spmatrix_init(igraph_spmatrix_t *m, long int nrow, long int ncol);

   Every sparse matrix needs to be initialized before using it, this is
done by calling this function. A matrix has to be destroyed if it is not
needed any more, see `igraph_spmatrix_destroy()' (see
igraph_spmatrix_destroy --- Destroys a sparse matrix object_).

   *Arguments:. *

`m':
     Pointer to a not yet initialized sparse matrix object to be
     initialized.

`nrow':
     The number of rows in the matrix.

`ncol':
     The number of columns in the matrix.

   *Returns:. *

`'
     Error code.

   Time complexity: operating system dependent.

6.4.2.2 igraph_spmatrix_copy -- Copies a sparse matrix.
.......................................................

     int igraph_spmatrix_copy(igraph_spmatrix_t *to, const igraph_spmatrix_t *from);

   Creates a sparse matrix object by copying another one.

   *Arguments:. *

`to':
     Pointer to an uninitialized sparse matrix object.

`from':
     The initialized sparse matrix object to copy.

   *Returns:. *

`'
     Error code, `IGRAPH_ENOMEM' if there isn't enough memory to
     allocate the new sparse matrix.

   Time complexity: O(n), the number of elements in the matrix.

6.4.2.3 igraph_spmatrix_destroy -- Destroys a sparse matrix object.
...................................................................

     void igraph_spmatrix_destroy(igraph_spmatrix_t *m);

   This function frees all the memory allocated for a sparse matrix
object. The destroyed object needs to be reinitialized before using it
again.

   *Arguments:. *

`m':
     The matrix to destroy.

   Time complexity: operating system dependent.

6.4.3 Accessing elements of a sparse matrix
-------------------------------------------

6.4.3.1 igraph_spmatrix_e -- Accessing an element of a sparse matrix.
.....................................................................

     igraph_real_t igraph_spmatrix_e(const igraph_spmatrix_t *m,
                                     long int row, long int col);

   Note that there are no range checks right now.

   *Arguments:. *

`m':
     The matrix object.

`row':
     The index of the row, starting with zero.

`col':
     The index of the column, starting with zero.

   Time complexity: O(log n), where n is the number of nonzero elements
in the requested column.

6.4.3.2 igraph_spmatrix_set -- Setting an element of a sparse matrix.
.....................................................................

     int igraph_spmatrix_set(igraph_spmatrix_t *m, long int row, long int col,
                 igraph_real_t value);

   Note that there are no range checks right now.

   *Arguments:. *

`m':
     The matrix object.

`row':
     The index of the row, starting with zero.

`col':
     The index of the column, starting with zero.

`value':
     The new value.

   Time complexity: O(log n), where n is the number of nonzero elements
in the requested column.

6.4.3.3 igraph_spmatrix_add_e -- Adding a real value to an element of a sparse matrix.
......................................................................................

     int igraph_spmatrix_add_e(igraph_spmatrix_t *m, long int row, long int col,
                 igraph_real_t value);

   Note that there are no range checks right now. This is implemented
to avoid double lookup of a given element in the matrix by using
`igraph_spmatrix_e()' (see igraph_spmatrix_e --- Accessing an element of a sparse matrix_)
and `igraph_spmatrix_set()' (see
igraph_spmatrix_set --- Setting an element of a sparse matrix_)
consecutively.

   *Arguments:. *

`m':
     The matrix object.

`row':
     The index of the row, starting with zero.

`col':
     The index of the column, starting with zero.

`value':
     The value to add.

   Time complexity: O(log n), where n is the number of nonzero elements
in the requested column.

6.4.4 Matrix query operations
-----------------------------

6.4.4.1 igraph_spmatrix_size -- The number of elements in a sparse matrix.
..........................................................................

     long int igraph_spmatrix_size(const igraph_spmatrix_t *m);

   *Arguments:. *

`m':
     Pointer to an initialized sparse matrix object.

   *Returns:. *

`'
     The size of the matrix.

   Time complexity: O(1).

6.4.4.2 igraph_spmatrix_nrow -- The number of rows in a sparse matrix.
......................................................................

     long int igraph_spmatrix_nrow(const igraph_spmatrix_t *m);

   *Arguments:. *

`m':
     Pointer to an initialized sparse matrix object.

   *Returns:. *

`'
     The number of rows in the matrix.

   Time complexity: O(1).

6.4.4.3 igraph_spmatrix_ncol -- The number of columns in a sparse matrix.
.........................................................................

     long int igraph_spmatrix_ncol(const igraph_spmatrix_t *m);

   *Arguments:. *

`m':
     Pointer to an initialized sparse matrix object.

   *Returns:. *

`'
     The number of columns in the sparse matrix.

   Time complexity: O(1).

6.4.4.4 igraph_spmatrix_count_nonzero -- The number of non-zero elements in a sparse matrix.
............................................................................................

     long int igraph_spmatrix_count_nonzero(const igraph_spmatrix_t *m);

   *Arguments:. *

`m':
     Pointer to an initialized sparse matrix object.

   *Returns:. *

`'
     The size of the matrix.

   Time complexity: O(1).

6.4.4.5 igraph_spmatrix_max -- Returns the maximum element of a matrix.
.......................................................................

     igraph_real_t igraph_spmatrix_max(const igraph_spmatrix_t *m,
         igraph_real_t *ridx, igraph_real_t *cidx);

   If the matrix is empty, zero is returned.

   *Arguments:. *

`m':
     the matrix object.

`ridx':
     the row index of the maximum element if not `NULL'.

`cidx':
     the column index of the maximum element if not `NULL'.

   Time complexity: O(n), the number of nonzero elements in the matrix.

6.4.5 Matrix operations
-----------------------

6.4.5.1 igraph_spmatrix_scale -- Multiplies each element of the sparse matrix by a constant.
............................................................................................

     void igraph_spmatrix_scale(igraph_spmatrix_t *m, igraph_real_t by);

   *Arguments:. *

`m':
     The matrix.

`by':
     The constant.

   Time complexity: O(n), the number of elements in the matrix.

6.4.5.2 igraph_spmatrix_add_rows -- Adds rows to a sparse matrix.
.................................................................

     int igraph_spmatrix_add_rows(igraph_spmatrix_t *m, long int n);

   *Arguments:. *

`m':
     The sparse matrix object.

`n':
     The number of rows to add.

   *Returns:. *

`'
     Error code.

   Time complexity: O(1).

6.4.5.3 igraph_spmatrix_add_cols -- Adds columns to a sparse matrix.
....................................................................

     int igraph_spmatrix_add_cols(igraph_spmatrix_t *m, long int n);

   *Arguments:. *

`m':
     The sparse matrix object.

`n':
     The number of columns to add.

   *Returns:. *

`'
     Error code.

   Time complexity: O(1).

6.4.5.4 igraph_spmatrix_resize -- Resizes a sparse matrix.
..........................................................

     int igraph_spmatrix_resize(igraph_spmatrix_t *m, long int nrow, long int ncol);

   This function resizes a sparse matrix by adding more elements to it.
The matrix retains its data even after resizing it, except for the data
which lies outside the new boundaries (if the new size is smaller).

   *Arguments:. *

`m':
     Pointer to an already initialized sparse matrix object.

`nrow':
     The number of rows in the resized matrix.

`ncol':
     The number of columns in the resized matrix.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n).  n is the number of elements in the old
matrix.

6.5 Stacks
==========

6.5.1 igraph_stack_init -- Initializes a stack.
-----------------------------------------------

     int igraph_stack_init       (igraph_stack_t* s, long int size);

   The initialized stack is always empty.

   *Arguments:. *

`s':
     Pointer to an uninitialized stack.

`size':
     The number of elements to allocate memory for.

   *Returns:. *

`'
     Error code.

   Time complexity: O(`size').

6.5.2 igraph_stack_destroy -- Destroys a stack object.
------------------------------------------------------

     void igraph_stack_destroy    (igraph_stack_t* s);

   Deallocate the memory used for a stack.  It is possible to
reinitialize a destroyed stack again by `igraph_stack_init()' (see
igraph_stack_init --- Initializes a stack_).

   *Arguments:. *

`s':
     The stack to destroy.

   Time complexity: O(1).

6.5.3 igraph_stack_reserve -- Reserve memory.
---------------------------------------------

     int igraph_stack_reserve    (igraph_stack_t* s, long int size);

   Reverse memory for future use. The actual size of the stack is
unchanged.

   *Arguments:. *

`s':
     The stack object.

`size':
     The number of elements to reserve memory for. If it is not bigger
     than the current size then nothing happens.

   *Returns:. *

`'
     Error code.

   Time complexity: should be around O(n), the new allocated size of
the stack.

6.5.4 igraph_stack_empty -- Decides whether a stack object is empty.
--------------------------------------------------------------------

     igraph_bool_t igraph_stack_empty      (igraph_stack_t* s);

   *Arguments:. *

`s':
     The stack object.

   *Returns:. *

`'
     Boolean, `TRUE' if the stack is empty, `FALSE' otherwise.

   Time complexity: O(1).

6.5.5 igraph_stack_size -- Returns the number of elements in a stack.
---------------------------------------------------------------------

     long int igraph_stack_size       (igraph_stack_t* s);

   *Arguments:. *

`s':
     The stack object.

   *Returns:. *

`'
     The number of elements in the stack.

   Time complexity: O(1).

6.5.6 igraph_stack_clear -- Removes all elements from a stack.
--------------------------------------------------------------

     void igraph_stack_clear      (igraph_stack_t* s);

   *Arguments:. *

`s':
     The stack object.

   Time complexity: O(1).

6.5.7 igraph_stack_push -- Places an element on the top of a stack.
-------------------------------------------------------------------

     int igraph_stack_push(igraph_stack_t* s, igraph_real_t elem);

   The capacity of the stack is increased, if needed.

   *Arguments:. *

`s':
     The stack object.

`elem':
     The element to push.

   *Returns:. *

`'
     Error code.

   Time complexity: O(1) is no reallocation is needed, O(n) otherwise,
but it is ensured that n push operations are performed in O(n) time.

6.5.8 igraph_stack_pop -- Removes and returns an element from the top of a stack.
---------------------------------------------------------------------------------

     igraph_real_t igraph_stack_pop        (igraph_stack_t* s);

   The stack must contain at least one element, call
`igraph_stack_empty()' (see igraph_stack_empty --- Decides whether a stack object is empty_)
to make sure of this.

   *Arguments:. *

`s':
     The stack object.

   *Returns:. *

`'
     The removed top element.

   Time complexity: O(1).

6.5.9 igraph_stack_top -- Query top element.
--------------------------------------------

     igraph_real_t igraph_stack_top        (const igraph_stack_t* s);

   Returns the top element of the stack, without removing it.  The
stack must be non-empty.

   *Arguments:. *

`s':
     The stack.

   *Returns:. *

`'
     The top element.

   Time complexity: O(1).

6.6 Double-ended queues
=======================

6.6.1 igraph_dqueue_init -- Initialize a double ended queue (deque).
--------------------------------------------------------------------

     int igraph_dqueue_init (igraph_dqueue_t* q, long int size);

   The queue will be always empty.

   *Arguments:. *

`q':
     Pointer to an uninitialized deque.

`size':
     How many elements to allocate memory for.

   *Returns:. *

`'
     Error code.

   Time complexity: O(`size').

6.6.2 igraph_dqueue_destroy -- Destroy a double ended queue.
------------------------------------------------------------

     void igraph_dqueue_destroy (igraph_dqueue_t* q);

   *Arguments:. *

`q':
     The queue to destroy

   Time complexity: O(1).

6.6.3 igraph_dqueue_empty -- Decide whether the queue is empty.
---------------------------------------------------------------

     igraph_bool_t igraph_dqueue_empty (igraph_dqueue_t* q);

   *Arguments:. *

`q':
     The queue.

   *Returns:. *

`'
     Boolean, `TRUE' if `q' contains at least one element, `FALSE'
     otherwise.

   Time complexity: O(1).

6.6.4 igraph_dqueue_full -- Check whether the queue is full.
------------------------------------------------------------

     igraph_bool_t igraph_dqueue_full (igraph_dqueue_t* q);

   If a queue is full the next igraph_dqueue_push() operation will
allocate more memory.

   *Arguments:. *

`q':
     The queue.

   *Returns:. *

`'
     `TRUE' if `q' is full, `FALSE' otherwise.

   Time complecity: O(1).

6.6.5 igraph_dqueue_clear -- Remove all elements from the queue.
----------------------------------------------------------------

     void igraph_dqueue_clear   (igraph_dqueue_t* q);

   *Arguments:. *

`q':
     The queue

   Time complexity: O(1).

6.6.6 igraph_dqueue_size -- Number of elements in the queue.
------------------------------------------------------------

     long int igraph_dqueue_size (igraph_dqueue_t* q);

   *Arguments:. *

`q':
     The queue.

   *Returns:. *

`'
     Integer, the number of elements currently in the queue.

   Time complexity: O(1).

6.6.7 igraph_dqueue_head -- Head of the queue.
----------------------------------------------

     igraph_real_t igraph_dqueue_head (igraph_dqueue_t* q);

   The queue must contain at least one element.

   *Arguments:. *

`q':
     The queue.

   *Returns:. *

`'
     The first element in the queue.

   Time complexity: O(1).

6.6.8 igraph_dqueue_back -- Tail of the queue.
----------------------------------------------

     igraph_real_t igraph_dqueue_back (igraph_dqueue_t* q);

   The queue must contain at least one element.

   *Arguments:. *

`q':
     The queue.

   *Returns:. *

`'
     The last element in the queue.

   Time complexity: O(1).

6.6.9 igraph_dqueue_pop -- Remove the head.
-------------------------------------------

     igraph_real_t igraph_dqueue_pop (igraph_dqueue_t* q);

   Removes and returns the first element in the queue. The queue must
be non-empty.

   *Arguments:. *

`q':
     The input queue.

   *Returns:. *

`'
     The first element in the queue.

   Time complexity: O(1).

6.6.10 igraph_dqueue_pop_back -- Remove the tail
------------------------------------------------

     igraph_real_t igraph_dqueue_pop_back (igraph_dqueue_t* q);

   Removes and returns the last element in the queue. The queue must be
non-empty.

   *Arguments:. *

`q':
     The queue.

   *Returns:. *

`'
     The last element in the queue.

   Time complexity: O(1).

6.6.11 igraph_dqueue_push -- Appends an element.
------------------------------------------------

     int igraph_dqueue_push (igraph_dqueue_t* q, igraph_real_t elem);

   Append an element to the end of the queue.

   *Arguments:. *

`q':
     The queue.

`elem':
     The element to append.

   *Returns:. *

`'
     Error code.

   Time complexity: O(1) if no memory allocation is needed, O(n), the
number of elements in the queue otherwise. But not that by allocating
always twice as much memory as the current size of the queue we ensure
that n push operations can always be done in at most O(n) time.
(Assuming memory allocation is at most linear.)

6.7 Maximum and minimum heaps
=============================

6.7.1 igraph_heap_init -- Initializes an empty heap object.
-----------------------------------------------------------

     int igraph_heap_init(igraph_heap_t* h, long int alloc_size);

   Creates an empty heap, but allocates size for some elements.

   *Arguments:. *

`h':
     Pointer to an uninitialized heap object.

`alloc_size':
     Number of elements to allocate memory for.

   *Returns:. *

`'
     Error code.

   Time complexity: O(`alloc_size'), assuming memory allocation is a
linear operation.

6.7.2 igraph_heap_init_array -- Build a heap from an array.
-----------------------------------------------------------

     int igraph_heap_init_array(igraph_heap_t *h, igraph_real_t* data, long int len);

   Initializes a heap object from an array, the heap is also built of
course (constructor).

   *Arguments:. *

`h':
     Pointer to an uninitialized heap object.

`data':
     Pointer to an array of base data type.

`len':
     The length of the array at `data'.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), the number of elements in the heap.

6.7.3 igraph_heap_destroy -- Destroys an initialized heap object.
-----------------------------------------------------------------

     void igraph_heap_destroy(igraph_heap_t* h);

   *Arguments:. *

`h':
     The heap object.

   Time complexity: O(1).

6.7.4 igraph_heap_empty -- Decides whether a heap object is empty.
------------------------------------------------------------------

     igraph_bool_t igraph_heap_empty(igraph_heap_t* h);

   *Arguments:. *

`h':
     The heap object.

   *Returns:. *

`'
     `TRUE' if the heap is empty, `FALSE' otherwise.

   TIme complexity: O(1).

6.7.5 igraph_heap_push -- Add an element.
-----------------------------------------

     int igraph_heap_push(igraph_heap_t* h, igraph_real_t elem);

   Adds an element to the heap.

   *Arguments:. *

`h':
     The heap object.

`elem':
     The element to add.

   *Returns:. *

`'
     Error code.

   Time complexity: O(log n), n is the number of elements in the heap
if no reallocation is needed, O(n) otherwise. It is ensured that n push
operations are performed in O(n log n) time.

6.7.6 igraph_heap_top -- Top element.
-------------------------------------

     igraph_real_t igraph_heap_top(igraph_heap_t* h);

   For maximum heaps this is the largest, for minimum heaps the
smallest element of the heap.

   *Arguments:. *

`h':
     The heap object.

   *Returns:. *

`'
     The top element.

   Time complexity: O(1).

6.7.7 igraph_heap_delete_top -- Return and removes the top element
------------------------------------------------------------------

     igraph_real_t igraph_heap_delete_top(igraph_heap_t* h);

   Removes and returns the top element of the heap. For maximum heaps
this is the largest, for minimum heaps the smallest element.

   *Arguments:. *

`h':
     The heap object.

   *Returns:. *

`'
     The top element.

   Time complexity: O(log n), n is the number of elements in the heap.

6.7.8 igraph_heap_size -- Number of elements
--------------------------------------------

     long int igraph_heap_size(igraph_heap_t* h);

   Gives the number of elements in a heap.

   *Arguments:. *

`h':
     The heap object.

   *Returns:. *

`'
     The number of elements in the heap.

   Time complexity: O(1).

6.7.9 igraph_heap_reserve -- Allocate more memory
-------------------------------------------------

     int igraph_heap_reserve(igraph_heap_t* h, long int size);

   Allocates memory for future use. The size of the heap is unchanged.
If the heap is larger than the `size' parameter then nothing happens.

   *Arguments:. *

`h':
     The heap object.

`size':
     The number of elements to allocate memory for.

   *Returns:. *

`'
     Error code.

   Time complexity: O(`size') if `size' is larger than the current
number of elements. O(1) otherwise.

6.8 String vectors
==================

The `igraph_strvector_t' type is a vector of strings.  The current
implementation is very simple and not too efficient. It works fine for
not too many strings, e.g. the list of attribute names is returned in a
string vector by `igraph_cattribute_list()' (see
igraph_cattribute_list --- List all attributes). Do not expect great
performace from this type.

6.8.1 igraph_strvector_init -- Initialize
-----------------------------------------

     int igraph_strvector_init(igraph_strvector_t *sv, long int len);

   Reserves memory for the string vector, a string vector must be first
initialized before calling other functions on it.  All elements of the
string vector are set to the empty string.

   *Arguments:. *

`sv':
     Pointer to an initialized string vector.

`len':
     The (initial) length of the string vector.

   *Returns:. *

`'
     Error code.

   Time complexity: O(`len').

6.8.2 igraph_strvector_copy -- Initialization by copying.
---------------------------------------------------------

     int igraph_strvector_copy(igraph_strvector_t *to,
     			  const igraph_strvector_t *from);

   Initializes a string vector by copying another string vector.

   *Arguments:. *

`to':
     Pointer to an uninitialized string vector.

`from':
     The other string vector, to be copied.

   *Returns:. *

`'
     Error code.

   Time complexity: O(l), the total length of the strings in `from'.

6.8.3 igraph_strvector_destroy -- Free allocated memory
-------------------------------------------------------

     void igraph_strvector_destroy(igraph_strvector_t *sv);

   Destroy a string vector. It may be reinitialized with
`igraph_strvector_init()' (see igraph_strvector_init --- Initialize)
later.

   *Arguments:. *

`sv':
     The string vector.

   Time complexity: O(l), the total length of the strings, maybe less
depending on the memory manager.

6.8.4 STR -- Indexing string vectors
------------------------------------

     #define STR(sv,i)

   This is a macro which allows to query the elements of a string
vector in simpler way than `igraph_strvector_get()' (see
igraph_strvector_get --- Indexing). Note this macro cannot be used to
set an element, for that use `igraph_strvector_set()' (see
igraph_strvector_set --- Set an element).

   *Arguments:. *

`sv':
     The string vector

`i':
     The the index of the element.

   *Returns:. *

`'
     The element at position `i'.

   Time complexity: O(1).

6.8.5 igraph_strvector_get -- Indexing
--------------------------------------

     void igraph_strvector_get(const igraph_strvector_t *sv, long int idx,
     			  char **value);

   Query an element of a string vector. See also the `STR' (see STR --- Indexing string vectors)
macro for an easier way.

   *Arguments:. *

`sv':
     The input string vector.

`idx':
     The index of the element to query.

`Pointer':
     to a `char*', the address of the string is stored here.

   Time complexity: O(1).

6.8.6 igraph_strvector_set -- Set an element
--------------------------------------------

     int igraph_strvector_set(igraph_strvector_t *sv, long int idx,
     			 const char *value);

   The provided `value' is copied into the `idx' position in the string
vector.

   *Arguments:. *

`sv':
     The string vector.

`idx':
     The position to set.

`value':
     The new value.

   *Returns:. *

`'
     Error code.

   Time complexity: O(l), the length of the new string. Maybe more,
depending on the memory management, if reallocation is needed.

6.8.7 igraph_strvector_set2 -- Sets an element
----------------------------------------------

     int igraph_strvector_set2(igraph_strvector_t *sv, long int idx,
     			  const char *value, int len);

   This is almost the same as `igraph_strvector_set' (see
igraph_strvector_set --- Set an element), but the new value is not a
zero terminated string, but its length is given.

   *Arguments:. *

`sv':
     The string vector.

`idx':
     The position to set.

`value':
     The new value.

`len':
     The length of the new value.

   *Returns:. *

`'
     Error code.

   Time complexity: O(l), the length of the new string. Maybe more,
depending on the memory management, if reallocation is needed.

6.8.8 igraph_strvector_remove -- Removes a single element from a string vector.
-------------------------------------------------------------------------------

     void igraph_strvector_remove(igraph_strvector_t *v, long int elem);

   The string will be one shorter.

   *Arguments:. *

`The':
     string vector.

`elem':
     The index of the element to remove.

   Time complexity: O(n), the length of the string.

6.8.9 igraph_strvector_append -- Concatenate two string vectors.
----------------------------------------------------------------

     int igraph_strvector_append(igraph_strvector_t *to,
     			    const igraph_strvector_t *from);

   *Arguments:. *

`to':
     The first string vector, the result is stored here.

`from':
     The second string vector, it is kep unchanged.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n+l2), n is the number of strings in the new
string vector, l2 is the total length of strings in the `from' string
vector.

6.8.10 igraph_strvector_clear -- Remove all elements
----------------------------------------------------

     void igraph_strvector_clear(igraph_strvector_t *sv);

   After this operation the string vector will be empty.

   *Arguments:. *

`sv':
     The string vector.

   Time complexity: O(l), the total length of strings, maybe less,
depending on the memory manager.

6.8.11 igraph_strvector_resize -- Resize
----------------------------------------

     int igraph_strvector_resize(igraph_strvector_t* v, long int newsize);

   If the new size is bigger then empty strings are added, if it is
smaller then the unneeded elements are removed.

   *Arguments:. *

`v':
     The string vector.

`newsize':
     The new size.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), the number of strings if the vector is made
bigger, O(l), the total length of the deleted strings if it is made
smaller, maybe less, depending on memory management.

6.8.12 igraph_strvector_size -- Gives the size of a string vector.
------------------------------------------------------------------

     long int igraph_strvector_size(const igraph_strvector_t *sv);

   *Arguments:. *

`sv':
     The string vector.

   *Returns:. *

`'
     The length of the string vector.

   Time complexity: O(1).

6.8.13 igraph_strvector_add -- Adds an element to the back of a string vector.
------------------------------------------------------------------------------

     int igraph_strvector_add(igraph_strvector_t *v, const char *value);

   *Arguments:. *

`v':
     The string vector.

`value':
     The string to add, it will be copied.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n+l), n is the total number of strings, l is the
length of the new string.

6.9 Adjacency lists
===================

Sometimes it is easier to work with a graph which is in adjacency list
format: a list of vectors; each vector contains the neighbor vertices
or adjacent edges of a given vertex. Typically, this representation is
good if we need to iterate over the neigbors of all vertices many
times. E.g. when finding the shortest paths between every pairs of
vertices or calculating closeness centrality for all the vertices.

   The `igraph_adjlist_t' stores the adjacency lists of a graph. After
creation it is independent of the original graph, it can be modified
freely with the usual vector operations, the graph is not affected.
E.g. the adjacency list can be used to rewire the edges of a graph
efficiently. If one used the straightforward `igraph_delete_edges()'
(see igraph_delete_edges --- Removes edges from a graph_) and
`igraph_add_edges()' (see igraph_add_edges --- Adds edges to a graph object_)
combination for this that needs O(|V|+|E|) time for every
single deletion and insertion operation, it is thus very slow if many
edges are rewired. Extracting the graph into an adjacency list, do all
the rewiring operations on the vectors of the adjacency list and then
creating a new graph needs (depending on how exactly the rewiring is
done) typically O(|V|+|E|) time for the whole rewiring process.

   Lazy adjacency lists are a bit different. When creating a lazy
adjacency list, the neighbors of the vertices are not queried, only
some memory is allocated for the vectors. When
`igraph_lazy_adjlist_get()' (see igraph_lazy_adjlist_get --- Query neighbor vertices)
is called for vertex v the first time, the
neighbors of v are queried and stored in a vector of the adjacency
list, so they don't need to be queried again. Lazy adjacency lists are
handy if you have an at least linear operation (because initialization
is generally linear in terms of number of vertices), but you don't know
how many vertices you will visit during the computation.

6.9.1 Adjacent vertices
-----------------------

6.9.1.1 igraph_adjlist_init -- Initialize an adjacency list of vertices
.......................................................................

     int igraph_adjlist_init(const igraph_t *graph, igraph_adjlist_t *al,
     			  igraph_neimode_t mode);

   Create a list of vectors containing the neighbors of all vertices in
a graph. The adjacency list is independent of the graph after creation,
e.g. the graph can be destroyed and modified, the adjacency list
contains the state of the graph at the time of its initialization.

   *Arguments:. *

`graph':
     The input graph.

`al':
     Pointer to an uninitialized `igraph_adjlist_t' object.

`mode':
     Constant specifying whether outgoing (` IGRAPH_OUT' ), incoming (`
     IGRAPH_IN' ), or both (` IGRAPH_ALL' ) types of neighbors to
     include in the adjacency list. It is ignored for undirected
     networks.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), linear in the number of vertices and
edges.

6.9.1.2 igraph_adjlist_init_complementer -- Adjacency lists for the complementer graph
......................................................................................

     int igraph_adjlist_init_complementer(const igraph_t *graph,
     				       igraph_adjlist_t *al,
     				       igraph_neimode_t mode,
     				       igraph_bool_t loops);

   This function creates adjacency lists for the complementer of the
input graph. In the complementer graph all edges are present which are
not present in the original graph. Multiple edges in the input graph
are ignored.

   *Arguments:. *

`graph':
     The input graph.

`al':
     Pointer to a not yet initialized adjacency list.

`mode':
     Constant specifying whether outgoing (` IGRAPH_OUT' ), incoming (`
     IGRAPH_IN' ), or both (` IGRAPH_ALL' ) types of neighbors (in the
     complementer graph) to include in the adjacency list. It is
     ignored for undirected networks.

`loops':
     Whether to consider loop edges.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|^2+|E|), quadratic in the number of vertices.

6.9.1.3 igraph_adjlist_destroy -- Deallocate memory
...................................................

     void igraph_adjlist_destroy(igraph_adjlist_t *al);

   Free all memory allocated for an adjacency list.

   *Arguments:. *

`al':
     The adjacency list to destroy.

   Time complexity: depends on memory management.

6.9.1.4 igraph_adjlist_get -- Query a vector in an adjlist
..........................................................

     #define igraph_adjlist_get(al,no)

   Returns a pointer to an `igraph_vector_t' object from an adjacency
list. The vector can be modified as desired.

   *Arguments:. *

`al':
     The adjacency list object.

`no':
     The vertex of which the vertex of adjacent vertices are returned.

   *Returns:. *

`'
     Pointer to the `igraph_vector_t' object.

   Time complexity: O(1).

6.9.1.5 igraph_adjlist_sort -- Sort each vector in an adjacency list.
.....................................................................

     void igraph_adjlist_sort(igraph_adjlist_t *al);

   Sorts every vector of the adjacency list.

   *Arguments:. *

`al':
     The adjacency list.

   Time complexity: O(n log n), n is the total number of elements in
the adjacency list.

6.9.1.6 igraph_adjlist_simplify -- Simplify
...........................................

     int igraph_adjlist_simplify(igraph_adjlist_t *al);

   Simplify an adjacency list, ie. remove loop and multiple edges.

   *Arguments:. *

`al':
     The adjacency list.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), linear in the number of edges and
vertices.

6.9.2 Adjacent edges
--------------------

6.9.2.1 igraph_adjedgelist_init -- Initialize an adjacency list of edges
........................................................................

     int igraph_adjedgelist_init(const igraph_t *graph,
     			      igraph_adjedgelist_t *ael,
     			      igraph_neimode_t mode);

   Create a list of vectors containing the adjacent edges for all
vertices. The adjacency list is independent of the graph after
creation, subsequent changes of the graph object do not update the
adjacency list, and changes to the adjacency list do no update the
graph.

   *Arguments:. *

`graph':
     The input graph.

`ael':
     Pointer to an uninitialized adjcency list.

`mode':
     Constant specifying whether incoming edges (` IGRAPH_IN' ),
     outgoing edges (` IGRAPH_OUT' ) or both (` IGRAPH_ALL' ) to
     include in the adjacency lists of directed graphs. It is ignored
     for undirected graphs.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), linear in the number of vertices and
edges.

6.9.2.2 igraph_adjedgelist_destroy -- Destroy
.............................................

     void igraph_adjedgelist_destroy(igraph_adjedgelist_t *ael);

   Free all memory allocated for an adjacency list.

   *Arguments:. *

`eal':
     The adjcency list to destroy.

   Time complexity: depends on memory management.

6.9.2.3 igraph_adjedgelist_get -- Query a vector in an adjedgelist
..................................................................

     #define igraph_adjedgelist_get(ael,no)

   Returns a pointer to an `igraph_vector_t' object from an adjacency
list containing edge ids. The vector can be modified, resized, etc. as
desired.

   *Arguments:. *

`graph':
     ael The edge adjacency list.

`no':
     The vertex of which the adjacent edges are returned.

   *Returns:. *

`'
     Pointer to an `igraph_vector_t' object.

   Time complexity: O(1).

6.9.3 Lazy adjacency list for vertices
--------------------------------------

6.9.3.1 igraph_lazy_adjlist_init -- Constructor
...............................................

     int igraph_lazy_adjlist_init(const igraph_t *graph,
     			       igraph_lazy_adjlist_t *al,
     			       igraph_neimode_t mode,
     			       igraph_lazy_adlist_simplify_t simplify);

   Create a lazy adjacency list for vertices. This function only
allocates some memory for storing the vectors of an adjacency list, but
the neighbor vertices are not queried, only at the
`igraph_lazy_adjlist_get()' (see igraph_lazy_adjlist_get --- Query neighbor vertices)
calls.

   *Arguments:. *

`graph':
     The input graph.

`al':
     Pointer to an uninitialized adjacency list object.

`mode':
     Constant, it gives whether incoming edges (` IGRAPH_IN' ),
     outgoing edges (` IGRPAH_OUT' ) or both types of edges (`
     IGRAPH_ALL' ) are considered. It is ignored for undirected graphs.

`simplify':
     Constant, it gives whether to simplify the vectors in the
     adjacency list (` IGRAPH_SIMPLIFY' ) ot not (`
     IGRAPH_DONT_SIMPLIFY' ).

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|), the number of vertices, possibly, but
depends on the underlying memory management too.

6.9.3.2 igraph_lazy_adjlist_destroy -- Deallocate memory
........................................................

     void igraph_lazy_adjlist_destroy(igraph_lazy_adjlist_t *al);

   Free all allocated memory for a lazy adjacency list.

   *Arguments:. *

`al':
     The adjacency list to deallocate.

   Time complexity: depends on the memory management.

6.9.3.3 igraph_lazy_adjlist_get -- Query neighbor vertices
..........................................................

     #define igraph_lazy_adjlist_get(al,no)

   If the function is called for the first time for a vertex then the
result is stored in the adjacency list and no further query operations
are needed when the neighbors of the same vertex are queried again.

   *Arguments:. *

`al':
     The lazy adjacency list.

`no':
     The vertex id to query.

   *Returns:. *

`'
     Pointer to a vector. It is allowed to modify it and modification
     does not affect the original graph.

   Time complexity: O(d), the number of neighbor vertices for the first
time, O(1) for subsequent calls.

6.9.4 Lazy adjacency list for edges
-----------------------------------

6.9.4.1 igraph_lazy_adjedgelist_init -- Constructor
...................................................

     int igraph_lazy_adjedgelist_init(const igraph_t *graph,
     				   igraph_lazy_adjedgelist_t *al,
     				   igraph_neimode_t mode);

   Create a lazy adjacency list for edges. This function only allocates
some memory for storing the vectors of an adjacency list, but the
adjacent edges are not queried, only when
`igraph_lazy_adjedgelist_get()' (see igraph_lazy_adjedgelist_get --- Query adjacent edges)
is called.

   *Arguments:. *

`graph':
     The input graph.

`al':
     Pointer to an uninitialized adjacency list.

`mode':
     Constant, it gives whether incoming edges (` IGRAPH_IN' ),
     outgoing edges (` IGRPAH_OUT' ) or both types of edges (`
     IGRAPH_ALL' ) are considered. It is ignored for undirected graphs.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|), the number of vertices, possibly. But it
also depends on the underlying memory management too.

6.9.4.2 igraph_lazy_adjedgelist_destroy -- Deallocate memory
............................................................

     void igraph_lazy_adjedgelist_destroy(igraph_lazy_adjedgelist_t *al);

   Free all allocated memory for a lazy edge adjacency list.

   *Arguments:. *

`al':
     The adjacency list to deallocate.

   Time complexity: depends on memory management.

6.9.4.3 igraph_lazy_adjedgelist_get -- Query adjacent edges
...........................................................

     #define igraph_lazy_adjedgelist_get(al,no)

   If the function is called for the first time for a vertex, then the
result is stored in the adjacency list and no further query operations
are needed when the adjacent edges of the same vertex are queried again.

   *Arguments:. *

`al':
     The lazy adjacency list object.

`no':
     The vertex id to query.

   *Returns:. *

`'
     Pointer to a vector. It is allowed to modify it and modification
     does not affect the original graph.

   Time complexity: O(d), the number of adjacent edges for the first
time, O(1) for subsequent calls with the same `no' argument.

7 Graph Generators
******************

Graph generators create graphs.

   Almost all functions which create graph objects are documented here.
The exceptions are `igraph_subgraph()' (see igraph_subgraph --- Creates a subgraph with the specified vertices_)
and alike, these
create graphs based on another graph.

7.1 Deterministic Graph Generators
==================================

7.1.1 igraph_create -- Creates a graph with the specified edges.
----------------------------------------------------------------

     int igraph_create(igraph_t *graph, const igraph_vector_t *edges, igraph_integer_t n,
     		  igraph_bool_t directed);

   *Arguments:. *

`graph':
     An uninitialized graph object.

`edges':
     The edges to add, the first two elements are the first edge, etc.

`n':
     The number of vertices in the graph, if smaller or equal to the
     highest vertex id in the `edges' vector it will be increased
     automatically. So it is safe to give 0 here.

`directed':
     Boolean, whether to create a directed graph or not. If yes, then
     the first edge points from the first vertex id in `edges' to the
     second, etc.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVEVECTOR': invalid edges vector (odd number
     of vertices).  `IGRAPH_EINVVID': invalid (negative) vertex id.

   Time complexity: O(|V|+|E|), |V| is the number of vertices, |E| the
number of edges in the graph.

7.1.2 igraph_small -- Shortand to create a short graph, giving the edges as agruments
-------------------------------------------------------------------------------------

     int igraph_small(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed,
     		 ...);

   This function is handy when a relatively small graph needs to be
created.  Instead giving the edges in vector, they are given simply as
arguments and a '-1' needs to be given after the last meaningful edge
argument.

   Note that only graphs which have vertices less than the highest
value of the 'int' type can be created this way. If you give larger
values then the result is undefined.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object, the result will be
     stored here.

`n':
     The number of vertices in the graph, an integer.

`directed':
     Logical constant, gives whether the graph should be directed.

`...':
     The additional arguments giving the edges of the graph. Don't
     forget to supply an additional '-1' after the last (meaningful)
     argument.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges in the graph to create.

7.1.3 igraph_adjacency -- Creates a graph object from an adjacency matrix.
--------------------------------------------------------------------------

     int igraph_adjacency(igraph_t *graph, igraph_matrix_t *adjmatrix,
     		     igraph_adjacency_t mode);

   The order of the vertices in the matrix is preserved, i.e. the vertex
corresponding to the first row/column will be vertex with id 0, the
next row is for vertex 1, etc.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`adjmatrix':
     The adjacency matrix. How it is interpreted depends on the `mode'
     argument.

`mode':
     Constant to specify how the given matrix is interpreted as an
     adjacency matrix. Possible values (A(i,j) is the element in row i
     and column j in the adjacency matrix (`adjmatrix'):

    `IGRAPH_ADJ_DIRECTED'
          the graph will be directed and an element gives the number of
          edges between two vertices.

    `IGRAPH_ADJ_UNDIRECTED'
          this is the same as `IGRAPH_ADJ_MAX', for convenience.

    `IGRAPH_ADJ_MAX'
          undirected graph will be created and the number of edges
          between vertex i and j is max(A(i,j), A(j,i)).

    `IGRAPH_ADJ_MIN'
          undirected graph will be created with min(A(i,j), A(j,i))
          edges between vertex i and j.

    `IGRAPH_ADJ_PLUS '
          undirected graph will be created with A(i,j)+A(j,i) edges
          between vertex i and j.

    `IGRAPH_ADJ_UPPER '
          undirected graph will be created, only the upper right
          triangle (including the diagonal) is used for the number of
          edges.

    `IGRAPH_ADJ_LOWER '
          undirected graph will be created, only the lower left
          triangle (including the diagonal) is used for creating the
          edges.

   *Returns:. *

`'
     Error code, `IGRAPH_NONSQUARE': non-square matrix.

   Time complexity: O(|V||V|), |V| is the number of vertices in the
graph.

7.1.4 igraph_weighted_adjacency -- Creates a graph object from a weighted adjacency matrix.
-------------------------------------------------------------------------------------------

     int igraph_weighted_adjacency(igraph_t *graph, igraph_matrix_t *adjmatrix,
     		     igraph_adjacency_t mode, const char* attr);

   The order of the vertices in the matrix is preserved, i.e. the vertex
corresponding to the first row/column will be vertex with id 0, the
next row is for vertex 1, etc.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`adjmatrix':
     The weighted adjacency matrix. How it is interpreted depends on
     the `mode' argument. The common feature is that edges with zero
     weights are considered nonexistent (however, negative weights are
     permitted).

`mode':
     Constant to specify how the given matrix is interpreted as an
     adjacency matrix. Possible values (A(i,j) is the element in row i
     and column j in the adjacency matrix (`adjmatrix'):

    `IGRAPH_ADJ_DIRECTED'
          the graph will be directed and an element gives the weight of
          the edge between two vertices.

    `IGRAPH_ADJ_UNDIRECTED'
          this is the same as `IGRAPH_ADJ_MAX', for convenience.

    `IGRAPH_ADJ_MAX'
          undirected graph will be created and the weight of the edge
          between vertex i and j is max(A(i,j), A(j,i)).

    `IGRAPH_ADJ_MIN'
          undirected graph will be created with edge weight min(A(i,j),
          A(j,i)) between vertex i and j.

    `IGRAPH_ADJ_PLUS '
          undirected graph will be created with edge weight
          A(i,j)+A(j,i) between vertex i and j.

    `IGRAPH_ADJ_UPPER '
          undirected graph will be created, only the upper right
          triangle (including the diagonal) is used for the edge
          weights.

    `IGRAPH_ADJ_LOWER '
          undirected graph will be created, only the lower left
          triangle (including the diagonal) is used for the edge
          weights.

`attr':
     the name of the attribute that will store the edge weights.  If
     `NULL' , it will use `weight' as the attribute name.

   *Returns:. *

`'
     Error code, `IGRAPH_NONSQUARE': non-square matrix.

   Time complexity: O(|V||V|), |V| is the number of vertices in the
graph.a

7.1.5 igraph_adjlist -- Create a graph from an adjacency list
-------------------------------------------------------------

     int igraph_adjlist(igraph_t *graph, const igraph_adjlist_t *adjlist,
     		   igraph_bool_t directed, igraph_bool_t duplicate);

   An adjacency list is list of vectors, containing the neighbors of
all vertices. For operations that involve many changes of the graph
structure, it is recommended that you convert the graph into and
adjacency list via `igraph_adjlist_init()' (see igraph_adjlist_init --- Initialize an adjacency list of vertices),
perform the
modifications (these are cheap for an adjacency list) and then recreate
the igraph graph via this function.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`adjlist':
     The adjacency list.

`directed':
     Logical, whether or not to create a directed graph.

`duplicate':
     Logical, for undirected graphs this specified whether each edge is
     included twice, in the vectors of both adjacenct vertices. If this
     is false (0), then it is assumed that every edge is included only
     once. This argument is ignored for directed graphs.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_adjlist_init()' (see igraph_adjlist_init --- Initialize an adjacency list of vertices)
     for the opposite operation.

   Time complexity: O(|V|+|E|).

7.1.6 igraph_star -- Creates a star graph, every vertex connects only to the center.
------------------------------------------------------------------------------------

     int igraph_star(igraph_t *graph, igraph_integer_t n, igraph_star_mode_t mode,
     		igraph_integer_t center);

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object, this will be the result.

`n':
     Integer constant, the number of vertices in the graph.

`mode':
     Constant, gives the type of the star graph to create. Possible
     values:

    `IGRAPH_STAR_OUT'
          directed star graph, edges point _from_ the center to the
          other vertices.

    `IGRAPH_STAR_IN'
          directed star graph, edges point _to_ the center from the
          other vertices.

    `IGRAPH_STAR_UNDIRECTED '
          an undirected star graph is created.

`center':
     Id of the vertex which will be the center of the graph.

   *Returns:. *

`'
     Error code:

    `IGRAPH_EINVVID '
          invalid number of vertices.

    `IGRAPH_EINVAL '
          invalid center vertex.

    `IGRAPH_EINVMODE '
          invalid mode argument.

   Time complexity: O(|V|), the number of vertices in the graph.

   *See also:. *

`'
     `igraph_lattice()' (see igraph_lattice --- Creates most kind of lattices_),
     `igraph_ring()' (see igraph_ring --- Creates a ring graph; a one dimensional lattice_),
     `igraph_tree()' (see
     igraph_tree --- Creates a tree in which almost all vertices have the same number of children_)
     for creating other regular
     structures.

7.1.7 igraph_lattice -- Creates most kind of lattices.
------------------------------------------------------

     int igraph_lattice(igraph_t *graph, const igraph_vector_t *dimvector, igraph_integer_t nei,
     		   igraph_bool_t directed, igraph_bool_t mutual, igraph_bool_t circular);

   *Arguments:. *

`graph':
     An uninitialized graph object.

`dimvector':
     Vector giving the sizes of the lattice in each of its dimensions.
     Ie. the dimension of the lattice will be the same as the length of
     this vector.

`nei':
     Integer value giving the distance (number of steps) within which
     two vertices will be connected. Not implemented yet.

`directed':
     Boolean, whether to create a directed graph. The direction of the
     edges is determined by the generation algorithm and is unlikely to
     suit you, so this isn't a very useful option.

`mutual':
     Boolean, if the graph is directed this gives whether to create all
     connections as mutual.

`circular':
     Boolean, defines whether the generated lattice is periodic.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVAL': invalid (negative) dimension vector.

   Time complexity: if `nei' is less than two then it is O(|V|+|E|) (as
far as i remember), |V| and |E| are the number of vertices and edges in
the generated graph. Otherwise it is O(|V|*d^o+|E|), d is the average
degree of the graph, o is the `nei' argument.

7.1.8 igraph_ring -- Creates a ring graph, a one dimensional lattice.
---------------------------------------------------------------------

     int igraph_ring(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, igraph_bool_t mutual,
     		igraph_bool_t circular);

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`n':
     The number of vertices in the ring.

`directed':
     Logical, whether to create a directed ring.

`mutual':
     Logical, whether to create mutual edges in a directed ring. It is
     ignored for undirected graphs.

`circular':
     Logical, if false, the ring will be open (this is not a real
     _ring_ actually).

   *Returns:. *

`'
     Error code: `IGRAPH_EINVAL': invalid number of vertices.

   Time complexity: O(|V|), the number of vertices in the graph.

   *See also:. *

`'
     `igraph_lattice()' (see igraph_lattice --- Creates most kind of lattices_)
     for generating more general lattices.

7.1.9 igraph_tree -- Creates a tree in which almost all vertices have the same number of children.
--------------------------------------------------------------------------------------------------

     int igraph_tree(igraph_t *graph, igraph_integer_t n, igraph_integer_t children,
     		igraph_tree_mode_t type);

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`n':
     Integer, the number of vertices in the graph.

`children':
     Integer, the number of children of a vertex in the tree.

`type':
     Constant, gives whether to create a directed tree, and if this is
     the case, also its orientation. Possible values:

    `IGRAPH_TREE_OUT '
          directed tree, the edges point from the parents to their
          children,

    `IGRAPH_TREE_IN '
          directed tree, the edges point from the children to their
          parents.

    `IGRAPH_TREE_UNDIRECTED'
          undirected tree.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVAL': invalid number of vertices.
     `IGRAPH_INVMODE': invalid mode argument.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges in the graph.

   *See also:. *

`'
     `igraph_lattice()' (see igraph_lattice --- Creates most kind of lattices_),
     `igraph_star()' (see igraph_star --- Creates a star graph; every vertex connects only to the center_)
     for
     creating other regular structures.

7.1.10 igraph_full -- Creates a full graph (directed or undirected, with or without loops).
-------------------------------------------------------------------------------------------

     int igraph_full(igraph_t *graph, igraph_integer_t n, igraph_bool_t directed, igraph_bool_t loops);

   In a full graph every possible edge is present, every vertex is
connected to every other vertex.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`n':
     Integer, the number of vertices in the graph.

`directed':
     Logical, whether to create a directed graph.

`loops':
     Logical, whether to include self-edges (loops).

   *Returns:. *

`'
     Error code: `IGRAPH_EINVAL': invalid number of vertices.

   Time complexity: O(|V|+|E|), |V| is the number of vertices, |E| the
number of edges in the graph. Of course this is the same as
O(|E|)=O(|V||V|) here.

   *See also:. *

`'
     `igraph_lattice()' (see igraph_lattice --- Creates most kind of lattices_),
     `igraph_star()' (see igraph_star --- Creates a star graph; every vertex connects only to the center_),
     `igraph_tree()' (see igraph_tree --- Creates a tree in which almost all vertices have the same number of children_)
     for
     creating other regular structures.

7.1.11 igraph_full_citation -- Creates a full citation graph
------------------------------------------------------------

     int igraph_full_citation(igraph_t *graph, igraph_integer_t n,
     			 igraph_bool_t directed);

   This is a directed graph, where every ` i->j'  edge is present if
and only if ` j<i' .  If the `directed' argument is zero then an
undirected graph is created, and it is just a full graph.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object, the result is stored
     here.

`n':
     The number of vertices.

`directed':
     Whether to created a directed graph. If zero an undirected graph
     is created.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|^2), as we have many edges.

7.1.12 igraph_famous -- Create a famous graph by simply providing its name
--------------------------------------------------------------------------

     int igraph_famous(igraph_t *graph, const char *name);

   The name of the graph can be simply supplied as a string.  Note that
this function creates graphs which don't take any parameters, there are
separate functions for graphs with parameters, eg. `igraph_full()'
(see igraph_full --- Creates a full graph [directed or undirected; with or without loops]_)
for creating a full graph.

   The following graphs are supported:

`Bull'
     The bull graph, 5 vertices, 5 edges, resembles to the head of a
     bull if drawn properly.

`Chvatal '
     This is the smallest triangle-free graph that is both 4-chromatic
     and 4-regular. According to the Grunbaum conjecture there exists
     an m-regular, m-chromatic graph with n vertices for every m>1 and
     n>2. The Chvatal graph is an example for m=4 and n=12. It has 24
     edges.

`Coxeter '
     A non-Hamiltonian cubic symmetric graph with 28 vertices and 42
     edges.

`Cubical'
     The Platonic graph of the cube. A convex regular polyhedron with 8
     vertices and 12 edges.

`Diamond'
     A graph with 4 vertices and 5 edges, resembles to a schematic
     diamond if drawn properly.

`Dodecahedral, Dodecahedron'
     Another Platonic solid with 20 vertices and 30 edges.

`Folkman '
     The semisymmetric graph with minimum number of vertices, 20 and 40
     edges. A semisymmetric graph is regular, edge transitive and not
     vertex transitive.

`Franklin '
     This is a graph whose embedding to the Klein bottle can be colored
     with six colors, it is a counterexample to the neccessity of the
     Heawood conjecture on a Klein bottle. It has 12 vertices and 18
     edges.

`Frucht '
     The Frucht Graph is the smallest cubical graph whose automorphism
     group consists only of the identity element. It has 12 vertices
     and 18 edges.

`Grotzsch '
     The Gro"tzsch graph is a triangle-free graph with 11 vertices, 20
     edges, and chromatic number 4. It is named after German
     mathematician Herbert Gro"tzsch, and its existence demonstrates
     that the assumption of planarity is necessary in Gro"tzsch's
     theorem that every triangle-free planar graph is 3-colorable.

`Heawood '
     The Heawood graph is an undirected graph with 14 vertices and 21
     edges. The graph is cubic, and all cycles in the graph have six or
     more edges. Every smaller cubic graph has shorter cycles, so this
     graph is the 6-cage, the smallest cubic graph of girth 6.

`Herschel '
     The Herschel graph is the smallest nonhamiltonian polyhedral
     graph. It is the unique such graph on 11 nodes, and has 18 edges.

`House'
     The house graph is a 5-vertex, 6-edge graph, the schematic draw of
     a house if drawn properly, basicly a triangle of the top of a
     square.

`HouseX'
     The same as the house graph with an X in the square. 5 vertices
     and 8 edges.

`Icosahedral, Icosahedron '
     A Platonic solid with 12 vertices and 30 edges.

`Krackhardt_Kite'
     A social network with 10 vertices and 18 edges.  Krackhardt, D.
     Assessing the Political Landscape: Structure, Cognition, and Power
     in Organizations.  Admin. Sci. Quart. 35, 342-369, 1990.

`Levi '
     The graph is a 4-arc transitive cubic graph, it has 30 vertices
     and 45 edges.

`McGee '
     The McGee graph is the unique 3-regular 7-cage graph, it has 24
     vertices and 36 edges.

`Meredith '
     The Meredith graph is a quartic graph on 70 nodes and 140 edges
     that is a counterexample to the conjecture that every 4-regular
     4-connected graph is Hamiltonian.

`Noperfectmatching '
     A connected graph with 16 vertices and 27 edges containing no
     perfect matching. A matching in a graph is a set of pairwise
     non-adjacent edges; that is, no two edges share a common vertex. A
     perfect matching is a matching which covers all vertices of the
     graph.

`Nonline '
     A graph whose connected components are the 9 graphs whose presence
     as a vertex-induced subgraph in a graph makes a nonline graph. It
     has 50 vertices and 72 edges.

`Octahedral, Octahedron '
     Platonic solid with 6 vertices and 12 edges.

`Petersen'
     A 3-regular graph with 10 vertices and 15 edges. It is the
     smallest hypohamiltonian graph, ie. it is non-hamiltonian but
     removing any single vertex from it makes it Hamiltonian.

`Robertson '
     The unique (4,5)-cage graph, ie. a 4-regular graph of girth 5. It
     has 19 vertices and 38 edges.

`Smallestcyclicgroup '
     A smallest nontrivial graph whose automorphism group is cyclic. It
     has 9 vertices and 15 edges.

`Tetrahedral, Tetrahedron '
     Platonic solid with 4 vertices and 6 edges.

`Thomassen '
     The smallest hypotraceable graph, on 34 vertices and 52 edges. A
     hypotracable graph does not contain a Hamiltonian path but after
     removing any single vertex from it the remainder always contains a
     Hamiltonian path. A graph containing a Hamiltonian path is called
     tracable.

`Tutte '
     Tait's Hamiltonian graph conjecture states that every 3-connected
     3-regular planar graph is Hamiltonian.  This graph is a
     counterexample. It has 46 vertices and 69 edges.

`Uniquely3colorable '
     Returns a 12-vertex, triangle-free graph with chromatic number 3
     that is uniquely 3-colorable.

`Walther '
     An identity graph with 25 vertices and 31 edges. An identity graph
     has a single graph automorphism, the trivial one.

   *Arguments:. *

`graph':
     Pointer to an unitialized graph object.

`name':
     Character constant, the name of the graph to be created, it is
     case insensitive.

   *Returns:. *

`'
     Error code, IGRAPH_EINVAL if there is no graph with the given name.

   *See also:. *

`'
     Other functions for creating graph structures: `igraph_ring()'
     (see igraph_ring --- Creates a ring graph; a one dimensional lattice_),
     `igraph_tree()' (see igraph_tree --- Creates a tree in which almost all vertices have the same number of children_),
     `igraph_lattice()' (see igraph_lattice --- Creates most kind of lattices_),
     `igraph_full()' (see igraph_full --- Creates a full graph [directed or undirected; with or without loops]_).

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges in the graph.

7.1.13 igraph_lcf -- Create a graph from LCF notation
-----------------------------------------------------

     int igraph_lcf(igraph_t *graph, igraph_integer_t n, ...);

   LCF is short for Lederberg-Coxeter-Frucht, it is a concise notation
for 3-regular Hamiltonian graphs. It consists of three parameters, the
number of vertices in the graph, a list of shifts giving additional
edges to a cycle backbone and another integer giving how many times the
shifts should be performed. See
http://mathworld.wolfram.com/LCFNotation.html
(http://mathworld.wolfram.com/LCFNotation.html) for details.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`n':
     Integer, the number of vertices in the graph.

`...':
     The shifts and the number of repeats for the shifts, plus an
     additional 0 to mark the end of the arguments.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     See `igraph_lcf_vector()' (see igraph_lcf_vector --- Create a graph from LCF notation)
     for a similar function using a vector_t
     instead of the variable length argument list.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges.

7.1.14 igraph_lcf_vector -- Create a graph from LCF notation
------------------------------------------------------------

     int igraph_lcf_vector(igraph_t *graph, igraph_integer_t n,
     		      const igraph_vector_t *shifts,
     		      igraph_integer_t repeats);

   This function is essentially the same as `igraph_lcf()' (see
igraph_lcf --- Create a graph from LCF notation), only the way for
giving the arguments is different. See `igraph_lcf()' (see igraph_lcf --- Create a graph from LCF notation)
for details.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`n':
     Integer constant giving the number of vertices.

`shifts':
     A vector giving the shifts.

`repeats':
     An integer constant giving the number of repeats for the shifts.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_lcf()' (see igraph_lcf --- Create a graph from LCF notation)

   Time complexity: O(|V|+|E|), linear in the number of vertices plus
the number of edges.

7.1.15 igraph_atlas -- Create a small graph from the Graph Atlas.
-----------------------------------------------------------------

     int igraph_atlas(igraph_t *graph, int number);

   The number of the graph is given as a parameter.  The graphs are
listed:

  1. in increasing order of number of nodes;

  2. for a fixed number of nodes, in increasing order of the number of
     edges;

  3. for fixed numbers of nodes and edges, in increasing order of the
     degree sequence, for example 111223 < 112222;

  4. for fixed degree sequence, in increasing number of automorphisms.

   The data was converted from the networkx software package, see
http://networkx.lanl.gov. (http://networkx.lanl.gov.)

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

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`number':
     The number of the graph to generate.

   Added in version 0.2.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges.

7.1.16 igraph_de_bruijn -- Generate a de Bruijn graph.
------------------------------------------------------

     int igraph_de_bruijn(igraph_t *graph, igraph_integer_t m, igraph_integer_t n);

   A de Bruijn graph represents relationships between strings. An
alphabet of `m' letters are used and strings of length `n' are
considered.  A vertex corresponds to every possible string and there is
a directed edge from vertex `v' to vertex `w' if the string of `v' can
be transformed into the string of `w' by removing its first letter and
appending a letter to it.

   Please note that the graph will have `m' to the power `n' vertices
and even more edges, so probably you don't want to supply too big
numbers for `m' and `n'.

   De Bruijn graphs have some interesting properties, please see
another source, eg. Wikipedia for details.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object, the result will be
     stored here.

`m':
     Integer, the number of letters in the alphabet.

`n':
     Integer, the length of the strings.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_kautz()' (see igraph_kautz --- Generate a Kautz graph_).

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges.

7.1.17 igraph_kautz -- Generate a Kautz graph.
----------------------------------------------

     int igraph_kautz(igraph_t *graph, igraph_integer_t m, igraph_integer_t n);

   A Kautz graph is a labeled graph, vertices are labeled by strings of
length `n'+1 above an alphabet with `m'+1 letters, with the restriction
that every two consecutive letters in the string must be different.
There is a directed edge from a vertex `v' to another vertex `w' if it
is possible to transform the string of `v' into the string of `w' by
removing the first letter and appending a letter to it.

   Kautz graphs have some interesting properties, see eg. Wikipedia for
details.

   Vincent Matossian wrote the first version of this function in R,
thanks.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object, the result will be
     stored here.

`m':
     Integer, `m'+1 is the number of letters in the alphabet.

`n':
     Integer, `n'+1 is the length of the strings.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_de_bruijn()' (see igraph_de_bruijn --- Generate a de Bruijn graph_).

   Time complexity: O(|V|* [(m+1)/m]^n +|E|), in practice it is more
like O(|V|+|E|). |V| is the number of vertices, |E| is the number of
edges and `m' and `n' are the corresponding arguments.

7.1.18 igraph_extended_chordal_ring -- Create an extended chordal ring
----------------------------------------------------------------------

     int igraph_extended_chordal_ring(igraph_t *graph, igraph_integer_t nodes,
     				 const igraph_matrix_t *W);

   An extended chordal ring is regular graph, each node has the same
degree. It can be obtained from a simple ring by adding some extra
edges specified by a matrix. Let p denote the number of columns in the
`W' matrix. The extra edges of vertex i are added according to column
(i mod p) in `W'. The number of extra edges is the number of rows in
`W': for each row j an edge i->i+w[ij] is added if i+w[ij] is less than
the number of total nodes.

   See also Kotsis, G: Interconnection Topologies for Parallel
Processing Systems, PARS Mitteilungen 11, 1-6, 1993.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object, the result will be
     stored here. The result is always an undirected graph.

`nodes':
     Integer constant, the number of vertices in the graph. It must be
     at least 3.

`W':
     The matrix specifying the extra edges. The number of columns
     should divide the number of total vertices.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_ring()' (see igraph_ring --- Creates a ring graph; a one dimensional lattice_).

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges.

7.1.19 igraph_connect_neighborhood -- Connects every vertex to its neighborhood
-------------------------------------------------------------------------------

     int igraph_connect_neighborhood(igraph_t *graph, igraph_integer_t order,
     				igraph_neimode_t mode);

   This function adds new edges to graph. For each vertex vertices
reachable by at most `order' steps and not yet connected to the vertex
a new edge is created.

   Note that the input graph is modified in place, no new graph is
created, call `igraph_copy()' (see igraph_copy --- Creates an exact [deep] copy of a graph_)
if you want to keep the original graph as
well.

   For undirected graphs reachability is always symmetric, if vertex A
can be reached from vertex B in at most `order' steps, then the
opposite is also true. Only one undirected (A,B) edge will be added in
this case.

   *Arguments:. *

`graph':
     The input graph, this is the output graph as well.

`order':
     Integer constant, it gives the distance within which the vertices
     will be connected to the source vertex.

`mode':
     Constant, it specifies how the neighborhood search is performed
     for directed graphs. If `IGRAPH_OUT' then vertices reachable from
     the source vertex will be connected, `IGRAPH_IN' is the opposite.
     If `IGRAPH_ALL' then the directed graph is considered as an
     undirected one.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_lattice()' (see igraph_lattice --- Creates most kind of lattices_)
     uses this function to connect the neighborhood of the
     vertices.

   Time complexity: O(|V|*d^o), |V| is the number of vertices in the
graph, d is the average degree and o is the `order' argument.

7.2 Games: Randomized Graph Generators
======================================

Games are randomized graph generators. Randomization means that they
generate a different graph every time you call them.

7.2.1 igraph_grg_game -- Generating geometric random graphs.
------------------------------------------------------------

     int igraph_grg_game(igraph_t *graph, igraph_integer_t nodes,
     		    igraph_real_t radius, igraph_bool_t torus,
     		    igraph_vector_t *x, igraph_vector_t *y);

   A geometric random graph is created by dropping points (=vertices)
randomly to the unit square and then connecting all those pairs which
are less than `radius' apart in Euclidean norm.

   Original code contributed by Keith Briggs, thanks Keith.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object,

`nodes':
     The number of vertices in the graph.

`radius':
     The radius within which the vertices will be connected.

`torus':
     Logical constant, if true periodic boundary conditions will be
     used, ie. the vertices are assumed to be on a torus instead of a
     square.

   *Returns:. *

`'
     Error code.

   Time complexity: TODO, less than O(|V|^2+|E|).

7.2.2 igraph_barabasi_game -- Generates a graph based on the Baraba'si-Albert model.
------------------------------------------------------------------------------------

     int igraph_barabasi_game(igraph_t *graph, igraph_integer_t n, igraph_integer_t m,
     			 const igraph_vector_t *outseq, igraph_bool_t outpref,
     			 igraph_bool_t directed);

   *Arguments:. *

`graph':
     An uninitialized graph object.

`n':
     The number of vertices in the graph.

`m':
     The number of outgoing edges generated for each vertex. (Only if
     `outseq' is `NULL'.)

`outseq':
     Gives the (out-)degrees of the vertices. If this is constant, this
     can be a NULL pointer or an empty (but initialized!) vector, in
     this case `m' contains the constant out-degree. The very first
     vertex has by definition no outgoing edges, so the first number in
     this vector is ignored.

`outpref':
     Boolean, if true not only the in- but also the out-degree of a
     vertex increases its citation probability. Ie. the citation
     probability is determined by the total degree of the vertices.

`directed':
     Boolean, whether to generate a directed graph.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVAL': invalid `n', `m' or `outseq'
     parameter.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges.

7.2.3 igraph_nonlinear_barabasi_game -- Generates graph with non-linear preferential attachment
-----------------------------------------------------------------------------------------------

     int igraph_nonlinear_barabasi_game(igraph_t *graph, igraph_integer_t n,
     				   igraph_real_t power,
     				   igraph_integer_t m,
     				   const igraph_vector_t *outseq,
     				   igraph_bool_t outpref,
     				   igraph_real_t zeroappeal,
     				   igraph_bool_t directed);

   This function is very similar to `igraph_barabasi_game()' (see
igraph_barabasi_game --- Generates a graph based on the Baraba'si-Albert model_),
only in this game the probability that a
new vertex attaches to a given old vertex is not proportional to the
degree of the old node, but some power of the degree of the old node.

   More precisely the attachment probability is the degree to the power
of `power' plus `zeroappeal'.

   This function might generate graphs with multiple edges if the value
of `m' is at least two. You can call `igraph_simplify()' (see
igraph_simplify --- Removes loop and/or multiple edges from the graph_)
to get rid of the multiple edges.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object, the generated graph will
     be stored here.

`n':
     The number of vertices in the generated graph.

`power':
     The power of the preferential attachment.

`m':
     The number of edges to generate in each time step, if the `outseq'
     parameter is a null vector or a vector with length zero. It is
     ignored otherwise.

`outseq':
     The number of edges to generate in each time step. For directed
     graphs this is exactly the out-degree of the vertices. The first
     element of the vector is ignored. If this is a null vector or a
     vector of length zero then it is ignored and the value of the `m'
     argument is used.

`outpref':
     Logical constant, if TRUE then the preferential attachment is
     based on the total degree of the nodes instead of the in-degree.

`zeroappeal':
     Positive number, the attachment probability for vertices with
     degree zero.

`directed':
     Logical constant, whether to generate a directed graph.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|*m*log(|V|)+|E|), |V| is the number of
vertices, |E| is the number of edges and m is the average number of
edges added in a time step.

   *See also:. *

`'
     `igraph_barabasi_game()' (see igraph_barabasi_game --- Generates a graph based on the Baraba'si-Albert model_)
     for the slightly
     more efficient implementation of the special case `power'=1.

7.2.4 igraph_erdos_renyi_game -- Generates a random (Erdos-Renyi) graph.
------------------------------------------------------------------------

     int igraph_erdos_renyi_game(igraph_t *graph, igraph_erdos_renyi_t type,
     			    igraph_integer_t n, igraph_real_t p_or_m,
     			    igraph_bool_t directed, igraph_bool_t loops);

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`type':
     The type of the random graph, possible values:

    `IGRAPH_ERDOS_RENYI_GNM'
          G(n,m) graph, m edges are selected uniformly randomly in a
          graph with n vertices.

    `IGRAPH_ERDOS_RENYI_GNP'
          G(n,p) graph, every possible edge is included in the graph
          with probability p.

`n':
     The number of vertices in the graph.

`p_or_m':
     This is the p parameter for G(n,p) graphs and the m parameter for
     G(n,m) graphs.

`directed':
     Logical, whether to generate a directed graph.

`loops':
     Logical, whether to generate loops (self) edges.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVAL': invalid `type', `n', `p' or `m'
     parameter.  `IGRAPH_ENOMEM': there is not enought memory for the
     operation.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges in the graph.

   *See also:. *

`'
     `igraph_barabasi_game()' (see igraph_barabasi_game --- Generates a graph based on the Baraba'si-Albert model_),
     `igraph_growing_random_game()' (see igraph_growing_random_game --- Generates a growing random graph_)

7.2.5 igraph_watts_strogatz_game -- The Watts-Strogatz small-world model
------------------------------------------------------------------------

     int igraph_watts_strogatz_game(igraph_t *graph, igraph_integer_t dim,
     			       igraph_integer_t size, igraph_integer_t nei,
     			       igraph_real_t p);

   This function generates a graph according to the Watts-Strogatz
model of small-world networks. The graph is obtained by creating a
circular undirected lattice and then rewire the edges randomly with a
constant probability.

   See also: Duncan J Watts and Steven H Strogatz: Collective dynamics
of `small world' networks, Nature 393, 440-442, 1998.

   *Arguments:. *

`graph':
     The graph to initialize.

`dim':
     The dimension of the lattice.

`size':
     The size of the lattice along each dimension.

`nei':
     The size of the neighborhood for each vertex. This is the same as
     the `nei' argument of `igraph_connect_neighborhood()' (see
     igraph_connect_neighborhood --- Connects every vertex to its neighborhood).

`p':
     The rewiring probability. A real number between zero and one
     (inclusive).

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_lattice()' (see igraph_lattice --- Creates most kind of lattices_),
     `igraph_connect_neighborhood()' (see
     igraph_connect_neighborhood --- Connects every vertex to its neighborhood)
     and `igraph_rewire_edges()' (see
     igraph_rewire_edges --- Rewire the edges of a graph with constant probability)
     can be used if more flexibility is needed, eg. a
     different type of lattice.

   Time complexity: O(|V|*d^o+|E|), |V| ans |E| are the number of
vertices and edges, d is the average degree, o is the `nei' argument.

7.2.6 igraph_rewire_edges -- Rewire the edges of a graph with constant probability
----------------------------------------------------------------------------------

     int igraph_rewire_edges(igraph_t *graph, igraph_real_t prob);

   This function rewires the edges of a graph with a constant
probability. More precisely each end point of each edge is rewired to
an uniformly randomly chosen vertex with constant probability `prob'.

   Note that this function modifies the input `graph', call
`igraph_copy()' (see igraph_copy --- Creates an exact [deep] copy of a graph_)
if you want to keep it.

   *Arguments:. *

`graph':
     The input graph, this will be rewired, it can be directed or
     undirected.

`prob':
     The rewiring probability a constant between zero and one
     (inclusive).

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_watts_strogatz_game()' (see igraph_watts_strogatz_game --- The Watts-Strogatz small-world model)
     uses this function for
     the rewiring.

   Time complexity: O(|V|+|E|).

7.2.7 igraph_degree_sequence_game -- Generates a random graph with a given degree sequence
------------------------------------------------------------------------------------------

     int igraph_degree_sequence_game(igraph_t *graph, const igraph_vector_t *out_deg,
     				const igraph_vector_t *in_deg,
     				igraph_degseq_t method);

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`out_deg':
     The degree sequence for an undirected graph (if `in_seq' is of
     length zero), or the out-degree sequence of a directed graph (if
     `in_deq' is not of length zero.

`in_deg':
     It is either a zero-length vector or `NULL' (if an undirected
     graph is generated), or the in-degree sequence.

`method':
     The method to generate the graph. Possible values:
     `IGRAPH_DEGSEQ_SIMPLE', for undirected graphs this method puts all
     vertex ids in a bag, the multiplicity of a vertex in the bag is
     the same as its degree. Then it draws pairs from the bag, until it
     is empty. This method can generate both loop (self) edges and
     multiple edges.  For directed graphs, the algorithm is basically
     the same, but two separate bags are used for the in- and
     out-degrees.  `IGRAPH_DEGSEQ_VL' is a much more sophisticated
     generator, that can sample undirected, connected simple graphs
     uniformly.  It uses Monte-Carlo methods to randomize the graphs.
     This generator should be favoured if undirected and connected
     graphs are to be generated. igraph uses the original implementation
     Fabien Viger; see http://www-rp.lip6.fr/~latapy/FV/generation.html
     (http://www-rp.lip6.fr/~latapy/FV/generation.html) and the paper
     cited on it for the details of the algorithm.

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM': there is not enough memory to perform
     the operation.  `IGRAPH_EINVAL': invalid method parameter, or
     invalid in- and/or out-degree vectors. The degree vectors should
     be non-negative, `out_deg' should sum up to an even integer for
     undirected graphs; the length and sum of `out_deg' and `in_deg'
     should match for directed graphs.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges.

   *See also:. *

`'
     `igraph_barabasi_game()' (see igraph_barabasi_game --- Generates a graph based on the Baraba'si-Albert model_),
     `igraph_erdos_renyi_game()' (see igraph_erdos_renyi_game --- Generates a random [Erdos-Renyi] graph_)

7.2.8 igraph_forest_fire_game -- Generates a network according to the forest fire game
--------------------------------------------------------------------------------------

     int igraph_forest_fire_game(igraph_t *graph, igraph_integer_t nodes,
     			    igraph_real_t fw_prob, igraph_real_t bw_factor,
     			    igraph_integer_t pambs, igraph_bool_t directed);

   The forest fire model intends to reproduce the following network
characteristics, observed in real networks:

   * Heavy-tailed in-degree distribution.

   * Heavy-tailed out-degree distribution.

   * Communities.

   * Densification power-law. The network is densifying in time,
     according to a power-law rule.

   * Shrinking diameter. The diameter of the network decreases in time.

   The network is generated in the following way. One vertex is added at
a time. This vertex connects to (cites) ` ambs'  vertices already
present in the network, chosen uniformly random. Now, for each cited
vertex ` v'  we do the following procedure:

  1. We generate two random number, ` x'  and ` y' , that are
     geometrically distributed with means ` p/(1-p)'  and ` rp(1-rp)' .
     (` p'  is ` fw_prob' , ` r'  is ` bw_factor' .) The new vertex
     cites ` x'  outgoing neighbors and ` y'  incoming neighbors of `
     v' , from those which are not yet cited by the new vertex. If
     there are less than ` x'  or ` y'  such vertices available then we
     cite all of them.

  2. The same procedure is applied to all the newly cited vertices.

   See also: Jure Leskovec, Jon Kleinberg and Christos Faloutsos.
Graphs over time: densification laws, shrinking diameters and possible
explanations.  _ KDD '05: Proceeding of the eleventh ACM SIGKDD
international conference on Knowledge discovery in data mining _,
177-187, 2005.

   Note however, that the version of the model in the published paper
is incorrect in the sense that it cannot generate the kind of graphs
the authors claim. A corrected version is available from
http://www.cs.cmu.edu/~jure/pubs/powergrowth-tkdd.pdf, our
implementation is based on this.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`nodes':
     The number of vertices in the graph.

`fw_prob':
     The forward burning probability.

`bw_factor':
     The backward burning ratio. The backward burning probability is
     calculated as ` bw.factor*fw.prob' .

`pambs':
     The number of ambassador vertices.

`directed':
     Whether to create a directed graph.

   *Returns:. *

`'
     Error code.

   Time complexity: TODO.

7.2.9 igraph_rewire -- Randomly rewires a graph while preserving the degree distribution.
-----------------------------------------------------------------------------------------

     int igraph_rewire(igraph_t *graph, igraph_integer_t n, igraph_rewiring_t mode);

   This function generates a new graph based on the original one by
randomly rewiring edges while preserving the original graph's degree
distribution.  Please note that the rewiring is done "in place", so no
new graph will be allocated. If you would like to keep the original
graph intact, use `igraph_copy()' (see igraph_copy --- Creates an exact [deep] copy of a graph_)
before.

   *Arguments:. *

`graph':
     The graph object to be rewired.

`n':
     Number of rewiring trials to perform.

`mode':
     The rewiring algorithm to be used. It can be one of the following:
     `IGRAPH_REWIRING_SIMPLE': simple rewiring algorithm which chooses
     two arbitrary edges in each step (namely (a,b) and (c,d)) and
     substitutes them with (a,d) and (c,b) if they don't exist.  Time
     complexity: TODO.

   *Returns:. *

`'
     Error code:

    `IGRAPH_EINVMODE'
          Invalid rewiring mode.

    `IGRAPH_EINVAL'
          Graph unsuitable for rewiring (e.g. it has less than 4 nodes
          in case of `IGRAPH_REWIRING_SIMPLE')

    `IGRAPH_ENOMEM'
          Not enough memory for temporary data.

   Time complexity: TODO.

7.2.10 igraph_growing_random_game -- Generates a growing random graph.
----------------------------------------------------------------------

     int igraph_growing_random_game(igraph_t *graph, igraph_integer_t n,
     			       igraph_integer_t m, igraph_bool_t directed,
     			       igraph_bool_t citation);

   This function simulates a growing random graph. In each discrete
time step a new vertex is added and a number of new edges are also
added. These graphs are known to be different from standard (not
growing) random graphs.

   *Arguments:. *

`graph':
     Uninitialized graph object.

`n':
     The number of vertices in the graph.

`m':
     The number of edges to add in a time step (ie. after adding a
     vertex).

`directed':
     Boolean, whether to generate a directed graph.

`citation':
     Boolean, if `TRUE', the edges always originate from the most
     recently added vertex.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVAL': invalid `n' or `m' parameter.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges.

7.2.11 igraph_callaway_traits_game -- Simulate a growing network with vertex types.
-----------------------------------------------------------------------------------

     int igraph_callaway_traits_game (igraph_t *graph, igraph_integer_t nodes,
     				igraph_integer_t types, igraph_integer_t edges_per_step,
     				igraph_vector_t *type_dist,
     				igraph_matrix_t *pref_matrix,
     				igraph_bool_t directed);

   The different types of vertices prefer to connect other types of
vertices with a given probability.

   The simulation goes like this: in each discrete time step a new
vertex is added to the graph. The type of this vertex is generated
based on `type_dist'. Then two vertices are selected uniformly randomly
from the graph. The probability that they will be connected depends on
the types of these vertices and is taken from `pref_matrix'. Then
another two vertices are selected and this is repeated `edges_per_step'
times in each time step.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph.

`nodes':
     The number of nodes in the graph.

`types':
     Number of node types.

`edges_per_step':
     The number of edges to be add per time step.

`type_dist':
     Vector giving the distribution of the vertex types.

`pref_matrix':
     Matrix giving the connection probabilities for the vertex types.

`directed':
     Logical, whether to generate a directed graph.

   *Returns:. *

`'
     Error code.

   Added in version 0.2.

   Time complexity: O(|V|e*log(|V|)), |V| is the number of vertices, e
is `edges_per_step'.

7.2.12 igraph_establishment_game -- Generates a graph with a simple growing model with vertex types.
----------------------------------------------------------------------------------------------------

     int igraph_establishment_game(igraph_t *graph, igraph_integer_t nodes,
     			      igraph_integer_t types, igraph_integer_t k,
     			      igraph_vector_t *type_dist,
     			      igraph_matrix_t *pref_matrix,
     			      igraph_bool_t directed);

   The simulation goes like this: a single vertex is added at each time
step. This new vertex tries to connect to `k' vertices in the graph.
The probability that such a connection is realized depends on the types
of the vertices involved.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph.

`nodes':
     The number of vertices in the graph.

`types':
     The number of vertex types.

`k':
     The number of connections tried in each time step.

`type_dist':
     Vector giving the distribution of vertex types.

`pref_matrix':
     Matrix giving the connection probabilities for different vertex
     types.

`directed':
     Logical, whether to generate a directed graph.

   *Returns:. *

`'
     Error code.

   Added in version 0.2.

   Time complexity: O(|V|*k*log(|V|)), |V| is the number of vertices
and k is the `k' parameter.

7.2.13 igraph_preference_game -- Generates a graph with vertex types and connection preferences
-----------------------------------------------------------------------------------------------

     int igraph_preference_game(igraph_t *graph, igraph_integer_t nodes,
     			   igraph_integer_t types,
     			   igraph_vector_t *type_dist,
     			   igraph_matrix_t *pref_matrix,
     			   igraph_vector_t *node_type_vec,
     			   igraph_bool_t directed,
     			   igraph_bool_t loops);

   This is practically the nongrowing variant of
`igraph_establishment_game' (see igraph_establishment_game --- Generates a graph with a simple growing model with vertex types_)
.
A given number of vertices are generated. Every vertex is assigned to a
vertex type according to the given type probabilities. Finally, every
vertex pair is evaluated and an edge is created between them with a
probability depending on the types of the vertices involved.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph.

`nodes':
     The number of vertices in the graph.

`types':
     The number of vertex types.

`type_dist':
     Vector giving the distribution of vertex types. If `NULL' , all
     vertex types will have equal probability.

`pref_matrix':
     Matrix giving the connection probabilities for different vertex
     types. This should be symmetric if the requested graph is
     undirected.

`node_type_vec':
     A vector where the individual generated vertex types will be
     stored. If `NULL' , the vertex types won't be saved.

`directed':
     Logical, whether to generate a directed graph. If undirected
     graphs are requested, only the lower left triangle of the
     preference matrix is considered.

`loops':
     Logical, whether loop edges are allowed.

   *Returns:. *

`'
     Error code.

   Added in version 0.3.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges in the graph.

   *See also:. *

`'
     igraph_establishment_game()

7.2.14 igraph_asymmetric_preference_game -- Generates a graph with asymmetric vertex types and connection preferences
---------------------------------------------------------------------------------------------------------------------

     int igraph_asymmetric_preference_game(igraph_t *graph, igraph_integer_t nodes,
     				      igraph_integer_t types,
     				      igraph_matrix_t *type_dist_matrix,
     				      igraph_matrix_t *pref_matrix,
     				      igraph_vector_t *node_type_in_vec,
     				      igraph_vector_t *node_type_out_vec,
     				      igraph_bool_t loops);

   This is the asymmetric variant of `igraph_preference_game()' (see
igraph_preference_game --- Generates a graph with vertex types and connection preferences)
.  A given number of vertices are generated.
Every vertex is assigned to an "incoming" and an "outgoing" vertex type
according to the given joint type probabilities. Finally, every vertex
pair is evaluated and a directed edge is created between them with a
probability depending on the "outgoing" type of the source vertex and
the "incoming" type of the target vertex.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph.

`nodes':
     The number of vertices in the graph.

`types':
     The number of vertex types.

`type_dist_matrix':
     Matrix giving the joint distribution of vertex types.  If null,
     incoming and outgoing vertex types are independent and uniformly
     distributed.

`pref_matrix':
     Matrix giving the connection probabilities for different vertex
     types.

`node_type_in_vec':
     A vector where the individual generated "incoming" vertex types
     will be stored. If NULL, the vertex types won't be saved.

`node_type_out_vec':
     A vector where the individual generated "outgoing" vertex types
     will be stored. If NULL, the vertex types won't be saved.

`loops':
     Logical, whether loop edges are allowed.

   *Returns:. *

`'
     Error code.

   Added in version 0.3.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges in the graph.

   *See also:. *

`'
     `igraph_preference_game()' (see igraph_preference_game --- Generates a graph with vertex types and connection preferences)

7.2.15 igraph_recent_degree_game -- Stochastic graph generator based on the number of adjacent edges a node has gained recently
-------------------------------------------------------------------------------------------------------------------------------

     int igraph_recent_degree_game(igraph_t *graph, igraph_integer_t n,
     			      igraph_real_t power,
     			      igraph_integer_t window,
     			      igraph_integer_t m,
     			      const igraph_vector_t *outseq,
     			      igraph_bool_t outpref,
     			      igraph_real_t zero_appeal,
     			      igraph_bool_t directed);

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`n':
     The number of vertices in the graph, this is the same as the
     number of time steps.

`power':
     The exponent, the probability that a node gains a new edge is
     proportional to the number of edges it has gained recently (in the
     last `window' time steps) to `power'.

`window':
     Integer constant, the size of the time window to use to count the
     number of recent edges.

`m':
     Integer constant, the number of edges to add per time step if the
     `outseq' parameter is a null pointer or a zero-length vector.

`outseq':
     The number of edges to add in each time step. This argument is
     ignored if it is a null pointer or a zero length vector, is this
     case the constant `m' parameter is used.

`outpref':
     Logical constant, if true the edges originated by a vertex also
     count as recent adjacent edges. It is false in most cases.

`zero_appeal':
     Constant giving the attractiveness of the vertices which haven't
     gained any edge recently.

`directed':
     Logical constant, whether to generate a directed graph.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|*log(|V|)+|E|), |V| is the number of vertices,
|E| is the number of edges in the graph.

7.2.16 igraph_barabasi_aging_game -- Preferential attachment with aging of vertices
-----------------------------------------------------------------------------------

     int igraph_barabasi_aging_game(igraph_t *graph,
     			       igraph_integer_t nodes,
     			       igraph_integer_t m,
     			       const igraph_vector_t *outseq,
     			       igraph_bool_t outpref,
     			       igraph_real_t pa_exp,
     			       igraph_real_t aging_exp,
     			       igraph_integer_t aging_bin,
     			       igraph_real_t zero_deg_appeal,
     			       igraph_real_t zero_age_appeal,
     			       igraph_real_t deg_coef,
     			       igraph_real_t age_coef,
     			       igraph_bool_t directed);

   In this game, the probability that a node gains a new edge is given
by its (in-)degree (k) and age (l). This probability has a degree
dependent component multiplied by an age dependent component. The
degree dependent part is: `deg_coef' times k to the power of `pa_exp'
plus `zero_deg_appeal'; and the age dependent part is `age_coef' times
l to the power of `aging_exp' plus `zero_age_appeal'.

   The age is based on the number of vertices in the network and the
`aging_bin' argument: vertices grew one unit older after each
`aging_bin' vertices added to the network.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`nodes':
     The number of vertices in the graph.

`m':
     The number of edges to add in each time step. If the `outseq'
     argument is not a null vector and not a zero-length vector.

`outseq':
     The number of edges to add in each time step. If it is a null
     pointer or a zero-length vector then it is ignored and the `m'
     argument is used instead.

`outpref':
     Logical constant, whether the edges initiated by a vertex
     contribute to the probability to gain a new edge.

`pa_exp':
     The exponent of the preferential attachment, a small positive
     number usually, the value 1 yields the classic linear preferential
     attachment.

`aging_exp':
     The exponent of the aging, this is a negative number usually.

`aging_bin':
     Integer constant, the number of vertices to add before vertices in
     the network grew one unit older.

`zero_deg_appeal':
     The degree dependent part of the attractiveness of the zero degree
     vertices.

`zero_age_appeal':
     The age dependent part of the attractiveness of the vertices of
     age zero. This parameter is usually zero.

`deg_coef':
     The coefficient for the degree.

`age_coef':
     The coefficient for the age.

`directed':
     Logical constant, whether to generate a directed graph.

   *Returns:. *

`'
     Error code.

   Time complexity: O((|V|+|V|/aging_bin)*log(|V|)+|E|). |V| is the
number of vertices, |E| the number of edges.

7.2.17 igraph_recent_degree_aging_game -- Preferential attachment based on the number of edges gained recently, with aging of vertices
--------------------------------------------------------------------------------------------------------------------------------------

     int igraph_recent_degree_aging_game(igraph_t *graph,
     				    igraph_integer_t nodes,
     				    igraph_integer_t m,
     				    const igraph_vector_t *outseq,
     				    igraph_bool_t outpref,
     				    igraph_real_t pa_exp,
     				    igraph_real_t aging_exp,
     				    igraph_integer_t aging_bin,
     				    igraph_integer_t time_window,
     				    igraph_real_t zero_appeal,
     				    igraph_bool_t directed);

   This game is very similar to `igraph_barabasi_aging_game()' (see
igraph_barabasi_aging_game --- Preferential attachment with aging of vertices),
except that instead of the total number of adjacent edges
the number of edges gained in the last `time_window' time steps are
counted.

   The degree dependent part of the attractiveness is given by k to the
power of `pa_exp' plus `zero_appeal'; the age dependent part is l to
the power to `aging_exp'.  k is the number of edges gained in the last
`time_window' time steps, l is the age of the vertex.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`nodes':
     The number of vertices in the graph.

`m':
     The number of edges to add in each time step. If the `outseq'
     argument is not a null vector or a zero-length vector then it is
     ignored.

`outseq':
     Vector giving the number of edges to add in each time step. If it
     is a null pointer or a zero-length vector then it is ignored and
     the `m' argument is used.

`outpref':
     Logical constant, if true the edges initiated by a vertex are also
     counted. Normally it is false.

`pa_exp':
     The exponent for the preferential attachment.

`aging_exp':
     The exponent for the aging, normally it is negative: old vertices
     gain edges with less probability.

`aging_bin':
     Integer constant, gives the scale of the aging.  The age of the
     vertices is incremented by one after every `aging_bin' vertex
     added.

`time_window':
     The time window to use to count the number of adjacent edges for
     the vertices.

`zero_appeal':
     The degree dependent part of the attractiveness for zero degree
     vertices.

`directed':
     Logical constant, whether to create a directed graph.

   *Returns:. *

`'
     Error code.

   Time complexity: O((|V|+|V|/aging_bin)*log(|V|)+|E|). |V| is the
number of vertices, |E| the number of edges.

7.2.18 igraph_cited_type_game -- Simulate a citation based on vertex types.
---------------------------------------------------------------------------

     int igraph_cited_type_game(igraph_t *graph, igraph_integer_t nodes,
     			   const igraph_vector_t *types,
     			   const igraph_vector_t *pref,
     			   igraph_integer_t edges_per_step,
     			   igraph_bool_t directed);

   Function to create a network based on some vertex categories. This
function creates a citation network, in each step a single vertex and
`edges_per_step' citating edges are added, nodes with different
categories (may) have different probabilities to get cited, as given by
the `pref' vector.

   Note that this function might generate networks with multiple edges
if `edges_per_step' is greater than one. You might want to call
`igraph_simplify()' (see igraph_simplify --- Removes loop and/or multiple edges from the graph_)
on the result to remove multiple
edges.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`nodes':
     The number of vertices in the network.

`types':
     Numeric vector giving the categories of the vertices, so it should
     contain `nodes' non-negative integer numbers. Types are numbered
     from zero.

`pref':
     The attractivity of the different vertex categories in a vector.
     Its length should be the maximum element in `types' plus one
     (types are numbered from zero).

`edges_per_step':
     Integer constant, the number of edges to add in each time step.

`directed':
     Logical constant, whether to create a directed network.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_citing_cited_type_game()' (see
     igraph_citing_cited_type_game --- Simulate a citation network based on vertex types_)
     for a bit more general game.

   Time complexity: O((|V|+|E|)log|V|), |V| and |E| are number of
vertices and edges, respectively.

7.2.19 igraph_citing_cited_type_game -- Simulate a citation network based on vertex types.
------------------------------------------------------------------------------------------

     int igraph_citing_cited_type_game(igraph_t *graph, igraph_integer_t nodes,
     				  const igraph_vector_t *types,
     				  const igraph_matrix_t *pref,
     				  igraph_integer_t edges_per_step,
     				  igraph_bool_t directed);

   This game is similar to `igraph_cited_type_game()' (see
igraph_cited_type_game --- Simulate a citation based on vertex types_)
but here the category of the citing vertex is also considered.

   An evolving citation network is modeled here, a single vertex and
its `edges_per_step' citation are added in each time step. The odds the
a given vertex is cited by the new vertex depends on the category of
both the citing and the cited vertex and is given in the `pref' matrix.
The categories of the citing vertex correspond to the rows, the
categories of the cited vertex to the columns of this matrix. Ie. the
element in row `i' and column `j' gives the probability that a `j'
vertex is cited, if the category of the citing vertex is `i'.

   Note that this function might generate networks with multiple edges
if `edges_per_step' is greater than one. You might want to call
`igraph_simplify()' (see igraph_simplify --- Removes loop and/or multiple edges from the graph_)
on the result to remove multiple
edges.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`nodes':
     The number of vertices in the network.

`types':
     A numeric matrix of length `nodes', containing the categories of
     the vertices. The categories are numbered from zero.

`pref':
     The preference matrix, a square matrix is required, both the
     number of rows and columns should be the maximum element in
     `types' plus one (types are numbered from zero).

`directed':
     Logical constant, whether to create a directed network.

   *Returns:. *

`'
     Error code.

   Time complexity: O((|V|+|E|)log|V|), |V| and |E| are number of
vertices and edges, respectively.

8 Vertex and Edge Selectors and Sequences, Iterators
****************************************************

8.1 About selectors, iterators
==============================

Everything about vertices and vertex selectors also applies to edges
and edge selectors unless explicitly noted otherwise.

   The vertex (and edge) selector notion was introduced in igraph 0.2,
and it is a way to reference to sequence of vertices or edges
independently of the graph.

   While this might sound quite mysterious, it is actually very simple.
For example all vertex of graph can be selected by `igraph_vs_all()'
(see igraph_vs_all --- Vertex set; all vertices of a graph_), and
the graph independence means that `igraph_vs_all()' (see
igraph_vs_all --- Vertex set; all vertices of a graph_) is not
parametrized by a graph object. Ie.  `igraph_vs_all()' (see
igraph_vs_all --- Vertex set; all vertices of a graph_) is the
_concept_ of selecting all vertices of a graph.

   This means that for determining the actual vertex id's implied by a
vertex selector it needs to be instantiated with a graph object, the
instantiation results a vertex iterator.

   Some vertex selectors have _immediate_ versions, these have prefix `
igraph_vss'  instead of ` igraph_vs' , eg.  `igraph_vss_all()' (see
igraph_vss_all --- All vertices of a graph [immediate version]_)
instead of `igraph_vs_all()' (see igraph_vs_all --- Vertex set; all vertices of a graph_).
These immediate versions are to be used in
the parameter list of the igraph functions, like `igraph_degree()'
(see igraph_degree --- The degree of some vertices in a graph_).
These functions are not associated with any `igraph_vs_t' object, so
they have no separate constructors and destructors (destroy functions).

8.2 Vertex selector constructors
================================

Vertex selectors are created by vertex selector constructors, can be
instantiated with `igraph_vit_create()' (see igraph_vit_create --- Creates a vertex iterator from a vertex selector_),
and are destroyed
with `igraph_vs_destroy()' (see igraph_vs_destroy --- Destroy a vertex set_).

8.2.1 igraph_vs_all -- Vertex set, all vertices of a graph.
-----------------------------------------------------------

     int igraph_vs_all(igraph_vs_t *vs);

   *Arguments:. *

`vs':
     Pointer to an uninitialized `igraph_vs_t' object.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_vss_all()' (see igraph_vss_all --- All vertices of a graph [immediate version]_).

   This selector includes all vertices of a given graph in increasing
vertex id order.

   Time complexity: O(1).

8.2.2 igraph_vs_adj -- Adjacent vertices of a vertex.
-----------------------------------------------------

     int igraph_vs_adj(igraph_vs_t *vs,
     		  igraph_integer_t vid, igraph_neimode_t mode);

   All neighboring vertices of a given vertex are selected by this
selector. The `mode' argument controls the type of the neighboring
vertices to be selected. The vertices are visited in increasing vertex
id order, as of igraph version 0.4.

   *Arguments:. *

`vs':
     Pointer to an uninitialized vertex selector object.

`vid':
     Vertex id, the center of the neighborhood.

`mode':
     Decides the type of the neighborhood for directed graphs. Possible
     values: `IGRAPH_OUT',  all vertices to which there is a directed
     edge from `vid'.  `IGRAPH_IN', all vertices from which there is a
     directed edge from `vid'.  `IGRAPH_ALL', all vertices to which or
     from which there is a directed edge from/to `vid'.  This parameter
     is ignored for undirected graphs.

   *Returns:. *

`'
     Error code.

   Time complexity: O(1).

8.2.3 igraph_vs_nonadj -- Non-adjacent vertices of a vertex
-----------------------------------------------------------

     int igraph_vs_nonadj(igraph_vs_t *vs, igraph_integer_t vid,
     		     igraph_neimode_t mode);

   All non-neighboring vertices of a given vertex. The `mode' argument
controls the type of neighboring vertics _not_ to select.

   *Arguments:. *

`vs':
     Pointer to an uninitialized vertex selector object.

`vid':
     Vertex id, the `center' of the non-neighborhood.

`mode':
     The type of neighborhood not to select in directed graphs.
     Possible values: `IGRAPH_OUT', all vertices will be selected
     except those to which there is a directed edge from `vid'.
     `IGRAPH_IN', all vertices will be selected except those from which
     there is a directed edge to `vid'.  `IGRAPH_ALL', all vertices
     will be selected exvept those from or to which there is a directed
     edge to or from `vid'.

   *Returns:. *

`'
     Error code.

   Time complexity: O(1).

8.2.4 igraph_vs_none -- Empty vertex set.
-----------------------------------------

     int igraph_vs_none(igraph_vs_t *vs);

   Creates an empty vertex selector.

   *Arguments:. *

`vs':
     Pointer to an uninitialized vertex selector object.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_vss_none' (see igraph_vss_none --- Empty vertex set [immediate version]_).

   Time complexity: O(1).

8.2.5 igraph_vs_1 -- Vertex set with a single vertex.
-----------------------------------------------------

     int igraph_vs_1(igraph_vs_t *vs, igraph_integer_t vid);

   This vertex selector selects a single vertex.

   *Arguments:. *

`vs':
     Pointer to an uninitialized vertex selector object.

`vid':
     The vertex id to be selected.

   *Returns:. *

`'
     Error Code.

   *See also:. *

`'
     `igraph_vss_1()' (see igraph_vss_1 --- Vertex set with a single vertex [immediate version])

   Time complexity: O(1).

8.2.6 igraph_vs_vector -- Vertex set based on a vector.
-------------------------------------------------------

     int igraph_vs_vector(igraph_vs_t *vs,
     		     const igraph_vector_t *v);

   This function makes it possible to handle a `vector_t' temporarily
as a vertex selector. The vertex selector should be thought of like a
_view_ to the vector. If you make changes to the vector that also
affects the vertex selector. Destroying the vertex selector does not
destroy the vector. (Of course.) Do not destroy the vector before
destroying the vertex selector, or you might get strange behavior.

   *Arguments:. *

`vs':
     Pointer to an uninitialized vertex selector.

`v':
     Pointer to a `igraph_vector_t' object.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_vss_vector()' (see igraph_vss_vector --- Vertex set based on a vector [immediate version]_)

   Time complexity: O(1).

8.2.7 igraph_vs_vector_small -- Create a vertex set by giving its elements.
---------------------------------------------------------------------------

     int igraph_vs_vector_small(igraph_vs_t *vs, ...);

   This function can be used to create a vertex selector with a couple
of vertices. Do not forget to include a ` -1'  after the last vertex
id, the behavior of the function is undefined if you don't use a ` -1'
properly.

   Note that the vertex ids supplied will be parsed as ` int' 's so you
cannot supply arbitrarily large (too large for int) vertex ids here.

   *Arguments:. *

`vs':
     Pointer to an uninitialized vertex selector object.

`...':
     Additional parameters, these will be the vertex ids to be included
     in the vertex selector. Supply a ` -1' after the last vertex id.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), the number of vertex ids supplied.

8.2.8 igraph_vs_seq -- Vertex set, an interval of vertices.
-----------------------------------------------------------

     int igraph_vs_seq(igraph_vs_t *vs,
     		  igraph_integer_t from, igraph_integer_t to);

   Creates a vertex selector containing all vertices with vertex id
equal to or bigger than `from' and equal to or smaller than `to'.

   *Arguments:. *

`vs':
     Pointer to an uninitialized vertex selector object.

`from':
     The first vertex id to be included in the vertex selector.

`to':
     The last vertex id to be included in the vertex selector.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_vss_seq()' (see igraph_vss_seq --- An interval of vertices [immediate version]_)

   Time complexity: O(1).

8.3 Generic vertex selector operations
======================================

8.3.1 igraph_vs_destroy -- Destroy a vertex set.
------------------------------------------------

     void igraph_vs_destroy(igraph_vs_t *vs);

   This function should be called for all vertex selectors when they
are not needed. The memory allocated for the vertex selector will be
deallocated. Do not call this function on vertex selectors created with
the immediate versions of the vertex selector constructors (starting
with ` igraph_vss' ).

   *Arguments:. *

`vs':
     Pointer to a vertex selector object.

   Time complecity: operating system dependent, usually O(1).

8.3.2 igraph_vs_is_all -- Check whether all vertices are included.
------------------------------------------------------------------

     igraph_bool_t igraph_vs_is_all(const igraph_vs_t *vs);

   This function checks whether the vertex selector object was created
by `igraph_vs_all()' (see igraph_vs_all --- Vertex set; all vertices of a graph_)
of `igraph_vss_all()' (see igraph_vss_all --- All vertices of a graph [immediate version]_).
Note that the vertex
selector might contain all vertices in a given graph but if it wasn't
created by the two constructors mentioned here the return value will be
FALSE.

   *Arguments:. *

`vs':
     Pointer to a vertex selector object.

   *Returns:. *

`'
     TRUE (1) if the vertex selector contains all vertices and FALSE
     (1) otherwise.

   Time complexity: O(1).

8.3.3 igraph_vs_size -- Returns the size of the vertex selector
---------------------------------------------------------------

     int igraph_vs_size(const igraph_t *graph, const igraph_vs_t *vs,
       igraph_integer_t *result);

   The size of the vertex selector is the number of vertices it will
yield when it is iterated over.

   *Arguments:. *

`graph':
     the graph over which we will iterate

`result':
     the result will be returned here

8.4 Immediate vertex selectors
==============================

8.4.1 igraph_vss_all -- All vertices of a graph (immediate version).
--------------------------------------------------------------------

     igraph_vs_t igraph_vss_all(void);

   Immediate vertex selector for all vertices in a graph. It can be
used conveniently when some vertex property (eg. betweenness, degree,
etc.) should be calculated for all vertices.

   *Returns:. *

`'
     A vertex selector for all vertices in a graph.

   *See also:. *

`'
     `igraph_vs_all()' (see igraph_vs_all --- Vertex set; all vertices of a graph_)

   Time complexity: O(1).

8.4.2 igraph_vss_none -- Empty vertex set (immediate version).
--------------------------------------------------------------

     igraph_vs_t igraph_vss_none(void);

   The immediate version of the empty vertex selector.

   *Returns:. *

`'
     An empty vertex selector.

   *See also:. *

`'
     `igraph_vs_none()' (see igraph_vs_none --- Empty vertex set_)

   Time complexity: O(1).

8.4.3 igraph_vss_1 -- Vertex set with a single vertex (immediate version)
-------------------------------------------------------------------------

     igraph_vs_t igraph_vss_1(igraph_integer_t vid);

   The immediate version of the single-vertex selector.

   *Arguments:. *

`vid':
     The vertex to be selected.

   *Returns:. *

`'
     A vertex selector containing a single vertex.

   *See also:. *

`'
     `igraph_vs_1()' (see igraph_vs_1 --- Vertex set with a single vertex_)

   Time complexity: O(1).

8.4.4 igraph_vss_vector -- Vertex set based on a vector (immediate version).
----------------------------------------------------------------------------

     igraph_vs_t igraph_vss_vector(const igraph_vector_t *v);

   This is the immediate version of `igraph_vs_vector' (see
igraph_vs_vector --- Vertex set based on a vector_).

   *Arguments:. *

`v':
     Pointer to a `igraph_vector_t' object.

   *Returns:. *

`'
     A vertex selector object containing the vertices in the vector.

   *See also:. *

`'
     `igraph_vs_vector()' (see igraph_vs_vector --- Vertex set based on a vector_)

   Time complexity: O(1).

8.4.5 igraph_vss_seq -- An interval of vertices (immediate version).
--------------------------------------------------------------------

     igraph_vs_t igraph_vss_seq(igraph_integer_t from, igraph_integer_t to);

   The immediate version of `igraph_vs_seq()' (see igraph_vs_seq --- Vertex set; an interval of vertices_).

   *Arguments:. *

`from':
     The first vertex id to be included in the vertex selector.

`to':
     The last vertex id to be included in the vertex selector.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_vs_seq()' (see igraph_vs_seq --- Vertex set; an interval of vertices_)

   Time complexity: O(1).

8.5 Vertex iterators
====================

8.5.1 igraph_vit_create -- Creates a vertex iterator from a vertex selector.
----------------------------------------------------------------------------

     int igraph_vit_create(const igraph_t *graph,
     		      igraph_vs_t vs, igraph_vit_t *vit);

   This function instantiates a vertex selector object with a given
graph. This is the step when the actual vertex ids are created from the
_logical_ notion of the vertex selector based on the graph.  Eg. a
vertex selector created with `igraph_vs_all()' (see igraph_vs_all --- Vertex set; all vertices of a graph_)
contains knowledge that _all_
vertices are included in a (yet indefinite) graph. When instantiating
it a vertex iterator object is created, this contains the actual vertex
ids in the graph supplied as a parameter.

   The same vertex selector object can be used to instantiate any
number vertex iterators.

   *Arguments:. *

`graph':
     An `igraph_t' object, a graph.

`vs':
     A vertex selector object.

`vit':
     Pointer to an uninitialized vertex iterator object.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_vit_destroy()' (see igraph_vit_destroy --- Destroys a vertex iterator_).

   Time complexity: it depends on the vertex selector type. O(1) for
vertex selectors created with `igraph_vs_all()' (see igraph_vs_all --- Vertex set; all vertices of a graph_),
`igraph_vs_none()' (see
igraph_vs_none --- Empty vertex set_), `igraph_vs_1' (see
igraph_vs_1 --- Vertex set with a single vertex_), `igraph_vs_vector'
(see igraph_vs_vector --- Vertex set based on a vector_),
`igraph_vs_seq()' (see igraph_vs_seq --- Vertex set; an interval of vertices_),
`igraph_vs_vector()' (see igraph_vs_vector --- Vertex set based on a vector_),
`igraph_vs_vector_small()' (see
igraph_vs_vector_small --- Create a vertex set by giving its elements_).
O(d) for `igraph_vs_adj()' (see igraph_vs_adj --- Adjacent vertices of a vertex_),
d is the number of vertex ids to be
included in the iterator. O(|V|) for `igraph_vs_nonadj()' (see
igraph_vs_nonadj --- Non-adjacent vertices of a vertex), |V| is the
number of vertices in the graph.

8.5.2 igraph_vit_destroy -- Destroys a vertex iterator.
-------------------------------------------------------

     void igraph_vit_destroy(const igraph_vit_t *vit);

   Deallocates memory allocated for a vertex iterator.

   *Arguments:. *

`vit':
     Pointer to an initialized vertex iterator object.

   *See also:. *

`'
     `igraph_vit_create()' (see igraph_vit_create --- Creates a vertex iterator from a vertex selector_)

   Time complexity: operating system dependent, usually O(1).

8.5.3 Stepping over the vertices
--------------------------------

After creating an iterator with `igraph_vit_create()' (see
igraph_vit_create --- Creates a vertex iterator from a vertex selector_),
it points to the first vertex in the vertex determined by
the vertex selector (if there is any). The `IGRAPH_VIT_NEXT()' (see
IGRAPH_VIT_NEXT --- Next vertex_) macro steps to the next vertex,
`IGRAPH_VIT_END()' (see IGRAPH_VIT_END --- Are we at the end?)
checks whether there are more vertices to visit, `IGRAPH_VIT_SIZE()'
(see IGRAPH_VIT_SIZE --- Size of a vertex iterator_) gives the
total size of the vertices visited so far and to be visited.
`IGRAPH_VIT_RESET()' (see IGRAPH_VIT_RESET --- Reset a vertex iterator_)
resets the iterator, it will point to the first vertex
again. Finally `IGRAPH_VIT_GET()' (see IGRAPH_VIT_GET --- Query the current position_)
gives the current vertex pointed by the iterator
(call this only if `IGRAPH_VIT_END()' (see IGRAPH_VIT_END --- Are we at the end?)
is false).

   Here is an example on how to step over the neighbors of vertex 0:

     igraph_vs_t vs;
     igraph_vit_t vit;
     ...
     igraph_vs_adj(&vs, 0, IGRAPH_ALL);
     igraph_vit_create(&graph, vs, &vit);
     while (!IGRAPH_VIT_END(vit)) {
       printf(" %li", (long int) IGRAPH_VIT_GET(vit));
       IGRAPH_VIT_NEXT(vit);
     }
     printf("\n");
     ...
     igraph_vit_destroy(&vit);
     igraph_vs_destroy(&vs);

8.5.4 IGRAPH_VIT_NEXT -- Next vertex.
-------------------------------------

     #define IGRAPH_VIT_NEXT(vit)

   Steps the iterator to the next vertex. Only call this function if
`IGRAPH_VIT_END()' (see IGRAPH_VIT_END --- Are we at the end?)
returns false.

   *Arguments:. *

`vit':
     The vertex iterator to step.

   Time complexity: O(1).

8.5.5 IGRAPH_VIT_END -- Are we at the end?
------------------------------------------

     #define IGRAPH_VIT_END(vit)

   Checks whether there are more vertices to step to.

   *Arguments:. *

`vit':
     The vertex iterator to check.

   *Returns:. *

`'
     Logical value, if true there are no more vertices to step to.

   Time complexity: O(1).

8.5.6 IGRAPH_VIT_SIZE -- Size of a vertex iterator.
---------------------------------------------------

     #define IGRAPH_VIT_SIZE(vit)

   Gives the number of vertices in a vertex iterator.

   *Arguments:. *

`vit':
     The vertex iterator.

   *Returns:. *

`'
     The number of vertices.

   Time complexity: O(1).

8.5.7 IGRAPH_VIT_RESET -- Reset a vertex iterator.
--------------------------------------------------

     #define IGRAPH_VIT_RESET(vit)

   Resets a vertex iterator. After calling this macro the iterator will
point to the first vertex.

   *Arguments:. *

`vit':
     The vertex iterator.

   Time complexity: O(1).

8.5.8 IGRAPH_VIT_GET -- Query the current position.
---------------------------------------------------

     #define IGRAPH_VIT_GET(vit)

   Gives the vertex id of the current vertex poited to by the iterator.

   *Arguments:. *

`vit':
     The vertex iterator.

   *Returns:. *

`'
     The vertex id of the current vertex.

   Time complexity: O(1).

8.6 Edge selector constructors
==============================

8.6.1 igraph_es_all -- Edge set, all edges.
-------------------------------------------

     int igraph_es_all(igraph_es_t *es,
     		  igraph_edgeorder_type_t order);

   *Arguments:. *

`es':
     Pointer to an uninitialized edge selector object.

`order':
     Constant giving the order in which the edges will be included in
     the selector. Possible values: `IGRAPH_EDGEORDER_ID', edge id
     order.  `IGRAPH_EDGEORDER_FROM', vertex id order, the id of the
     _source_ vertex counts for directed graphs. The order of the
     adjacent edges of a given vertex is arbitrary.
     `IGRAPH_EDGEORDER_TO', vertex id order, the id of the _target_
     vertex counts for directed graphs. The order of the adjacent edges
     of a given vertex is arbitrary.  For undirected graph the latter
     two is the same.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_ess_all()' (see igraph_ess_all --- Edge set; all edges [immediate version])

   Time complexity: O(1).

8.6.2 igraph_es_adj -- Adjacent edges of a vertex.
--------------------------------------------------

     int igraph_es_adj(igraph_es_t *es,
     		  igraph_integer_t vid, igraph_neimode_t mode);

   *Arguments:. *

`es':
     Pointer to an uninitialized edge selector object.

`vid':
     Vertex id, of which the adjacent edges will be selected.

`mode':
     Constant giving the type of the adjacent edges to select. This is
     ignored for undirected graphs. Possible values: `IGRAPH_OUT',
     outgoing edges `IGRAPH_IN', incoming edges `IGRAPH_ALL', all edges

   *Returns:. *

`'
     Error code.

   Time complexity: O(1).

8.6.3 igraph_es_none -- Empty edge selector.
--------------------------------------------

     int igraph_es_none(igraph_es_t *es);

   *Arguments:. *

`es':
     Pointer to an uninitialized edge selector object to initialize.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_ess_none()' (see igraph_ess_none --- Immediate empty edge selector_)

   Time complexity: O(1).

8.6.4 igraph_es_1 -- Edge selector containing a single edge.
------------------------------------------------------------

     int igraph_es_1(igraph_es_t *es, igraph_integer_t eid);

   *Arguments:. *

`es':
     Pointer to an uninitialized edge selector object.

`eid':
     Edge id of the edge to select.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_ess_1()' (see igraph_ess_1 --- Immediate version of the single edge edge selector_)

   Time complexity: O(1).

8.6.5 igraph_es_vector -- Handle a vector as an edge selector.
--------------------------------------------------------------

     int igraph_es_vector(igraph_es_t *es,
     		     const igraph_vector_t *v);

   Creates an edge selector which serves as a view to a vector
containing edge ids. Do not destroy the vector before destroying the
view.  Many views can be created to the same vector.

   *Arguments:. *

`es':
     Pointer to an uninitialized edge selector.

`v':
     Vector containing edge ids.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_ess_vector()' (see igraph_ess_vector --- Immediate vector view edge selector_)

   Time complexity: O(1).

8.6.6 igraph_es_fromto -- Edge selector, all edges between two vertex sets.
---------------------------------------------------------------------------

     int igraph_es_fromto(igraph_es_t *es,
     		     igraph_vs_t from, igraph_vs_t to);

   This function is not implemented yet.

   *Arguments:. *

`es':
     Pointer to an uninitialized edge selector.

`from':
     Vertex selector, their outgoing edges will be selected.

`to':
     Vertex selector, their incoming edges will be selected from the
     previous selection.

   *Returns:. *

`'
     Error code.

   Time complexity: O(1).

8.6.7 igraph_es_seq -- Edge selector, a sequence of edge ids.
-------------------------------------------------------------

     int igraph_es_seq(igraph_es_t *es,
     		  igraph_integer_t from, igraph_integer_t to);

   All edge ids between ` from'  and ` to'  will be included in the
edge selection.

   *Arguments:. *

`es':
     Pointer to an uninitialized edge selector object.

`from':
     The first edge id to be included.

`to':
     The last edge id to be included.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_ess_seq()' (see igraph_ess_seq --- Immediate version of the sequence edge selector_)

   Time complexity: O(1).

8.6.8 igraph_es_pairs -- Edge selector, multiple edges defined by their endpoints in a vector
---------------------------------------------------------------------------------------------

     int igraph_es_pairs(igraph_es_t *es, const igraph_vector_t *v,
     		    igraph_bool_t directed);

   The edges between the given pairs of vertices will be included in the
edge selection. The vertex pairs must be defined in the vector ` v' ,
the first element of the vector is the first vertex of the first edge
to be selected, the second element is the second vertex of the first
edge, the third element is the first vertex of the second edge and so
on.

   *Arguments:. *

`es':
     Pointer to an uninitialized edge selector object.

`v':
     The vector containing the endpoints of the edges.

`directed':
     Whether the graph is directed or not.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_es_pairs_small()' (see igraph_es_pairs_small --- Edge selector; multiple edges defined by their endpoints as arguments)

   Time complexity: O(n), the number of edges being selected.

8.6.9 igraph_es_pairs_small -- Edge selector, multiple edges defined by their endpoints as arguments
----------------------------------------------------------------------------------------------------

     int igraph_es_pairs_small(igraph_es_t *es, igraph_bool_t directed, ...);

   The edges between the given pairs of vertices will be included in the
edge selection. The vertex pairs must be given as the arguments of the
function call, the third argument is the first vertex of the first edge,
the fourth argument is the second vertex of the first edge, the fifth
is the first vertex of the second edge and so on. The last element of
the argument list must be -1 to denote the end of the argument list.

   *Arguments:. *

`es':
     Pointer to an uninitialized edge selector object.

`directed':
     Whether the graph is directed or not.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_es_pairs()' (see igraph_es_pairs --- Edge selector; multiple edges defined by their endpoints in a vector)

   Time complexity: O(n), the number of edges being selected.

8.7 Immediate edge selectors
============================

8.7.1 igraph_ess_all -- Edge set, all edges (immediate version)
---------------------------------------------------------------

     igraph_es_t igraph_ess_all(igraph_edgeorder_type_t order);

   The immediate version of the all-vertices selector.

   *Arguments:. *

`order':
     Constant giving the order of the edges in the edge selector. See
     `igraph_es_all()' (see igraph_es_all --- Edge set; all edges_)
     for the possible values.

   *Returns:. *

`'
     The edge selector.

   *See also:. *

`'
     `igraph_es_all()' (see igraph_es_all --- Edge set; all edges_)

   Time complexity: O(1).

8.7.2 igraph_ess_none -- Immediate empty edge selector.
-------------------------------------------------------

     igraph_es_t igraph_ess_none(void);

   Immediate version of the empty edge selector.

   *Returns:. *

`'
     Initialized empty edge selector.

   *See also:. *

`'
     `igraph_es_none()' (see igraph_es_none --- Empty edge selector_)

   Time complexity: O(1).

8.7.3 igraph_ess_1 -- Immediate version of the single edge edge selector.
-------------------------------------------------------------------------

     igraph_es_t igraph_ess_1(igraph_integer_t eid);

   *Arguments:. *

`eid':
     The id of the edge.

   *Returns:. *

`'
     The edge selector.

   *See also:. *

`'
     `igraph_es_1()' (see igraph_es_1 --- Edge selector containing a single edge_)

   Time complexity: O(1).

8.7.4 igraph_ess_vector -- Immediate vector view edge selector.
---------------------------------------------------------------

     igraph_es_t igraph_ess_vector(const igraph_vector_t *v);

   This is the immediate version of the vector of edge ids edge
selector.

   *Arguments:. *

`v':
     The vector of edge ids.

   *Returns:. *

`'
     Edge selector, initialized.

   *See also:. *

`'
     `igraph_es_vector()' (see igraph_es_vector --- Handle a vector as an edge selector_)

   Time complexity: O(1).

8.7.5 igraph_ess_seq -- Immediate version of the sequence edge selector.
------------------------------------------------------------------------

     igraph_es_t igraph_ess_seq(igraph_integer_t from, igraph_integer_t to);

   *Arguments:. *

`from':
     The first edge id to include.

`to':
     The last edge id to include.

   *Returns:. *

`'
     The initialized edge selector.

   *See also:. *

`'
     `igraph_es_seq()' (see igraph_es_seq --- Edge selector; a sequence of edge ids_)

   Time complexity: O(1).

8.8 Generic edge selector operations
====================================

8.8.1 igraph_es_destroy -- Destroys an edge selector object.
------------------------------------------------------------

     void igraph_es_destroy(igraph_es_t *es);

   Call this function on an edge selector when it is not needed any
more. Do _not_ call this function on edge selectors created by
immediate constructors, those don't need to be destroyed.

   *Arguments:. *

`es':
     Pointer to an edge selector object.

   Time complexity: operating system dependent, usually O(1).

8.8.2 igraph_es_is_all -- Check whether an edge selector includes all edges.
----------------------------------------------------------------------------

     igraph_bool_t igraph_es_is_all(const igraph_es_t *es);

   *Arguments:. *

`es':
     Pointer to an edge selector object.

   *Returns:. *

`'
     TRUE (1) if ` es'  was created with `igraph_es_all()' (see
     igraph_es_all --- Edge set; all edges_) or `igraph_ess_all()'
     (see igraph_ess_all --- Edge set; all edges [immediate version]),
     and FALSE (0) otherwise.

   Time complexity: O(1).

8.9 Edge iterators
==================

8.9.1 igraph_eit_create -- Creates an edge iterator from an edge selector.
--------------------------------------------------------------------------

     int igraph_eit_create(const igraph_t *graph,
     		      igraph_es_t es, igraph_eit_t *eit);

   This function creates an edge iterator based on an edge selector and
a graph.

   The same edge selector can be used to create many edge iterators,
also for different graphs.

   *Arguments:. *

`graph':
     An `igraph_t' object for which the edge selector will be
     instantiated.

`es':
     The edge selector to instantiate.

`eit':
     Pointer to an uninitialized edge iterator.

   *Returns:. *

`'
     Error code.

   Time complexity: depends on the type of the edge selector. For edge
selectors created by `igraph_es_all()' (see igraph_es_all --- Edge set; all edges_),
`igraph_es_none()' (see igraph_es_none --- Empty edge selector_),
`igraph_es_1()' (see igraph_es_1 --- Edge selector containing a single edge_),
igraph_es_vector(), igraph_es_seq() it is
O(1). For `igraph_es_adj()' (see igraph_es_adj --- Adjacent edges of a vertex_)
it is O(d) where d is the number of adjacent edges of the
vertex.

8.9.2 igraph_eit_destroy -- Destroys an edge iterator
-----------------------------------------------------

     void igraph_eit_destroy(const igraph_eit_t *eit);

   *Arguments:. *

`eit':
     Pointer to an edge iterator to destroy.

   *See also:. *

`'
     `igraph_eit_create()' (see igraph_eit_create --- Creates an edge iterator from an edge selector_)

   Time complexity: operating system dependent, usually O(1).

8.9.3 Stepping over the edges
-----------------------------

Just like for vertex iterators, macros are provided for stepping over a
sequence of edges: `IGRAPH_EIT_NEXT()' (see IGRAPH_EIT_NEXT --- Next edge_)
goes to the next edge, `IGRAPH_EIT_END()' (see
IGRAPH_EIT_END --- Are we at the end?) checks whether there are more
edges to visit, `IGRAPH_EIT_SIZE()' (see IGRAPH_EIT_SIZE --- Number of edges in the iterator_)
gives the number of edges in the edge
sequence, `IGRAPH_EIT_RESET()' (see IGRAPH_EIT_RESET --- Reset an edge iterator_)
resets the iterator to the first edge and
`IGRAPH_EIT_GET()' (see IGRAPH_EIT_GET --- Query an edge iterator_)
returns the id of the current edge.

8.9.4 IGRAPH_EIT_NEXT -- Next edge.
-----------------------------------

     #define IGRAPH_EIT_NEXT(eit)

   Steps the iterator to the next edge. Call this function only if
`IGRAPH_EIT_END()' (see IGRAPH_EIT_END --- Are we at the end?)
returns false.

   *Arguments:. *

`eit':
     The edge iterator to step.

   Time complecity: O(1).

8.9.5 IGRAPH_EIT_END -- Are we at the end?
------------------------------------------

     #define IGRAPH_EIT_END(eit)

   Checks whether there are more edges to step to.

   *Arguments:. *

`wit':
     The edge iterator to check.

   *Returns:. *

`'
     Logical value, if true there are no more edges to step to.

   Time complexity: O(1).

8.9.6 IGRAPH_EIT_SIZE -- Number of edges in the iterator.
---------------------------------------------------------

     #define IGRAPH_EIT_SIZE(eit)

   Gives the number of edges in an edge iterator.

   *Arguments:. *

`eit':
     The edge iterator.

   *Returns:. *

`'
     The number of edges.

   Time complexity: O(1).

8.9.7 IGRAPH_EIT_RESET -- Reset an edge iterator.
-------------------------------------------------

     #define IGRAPH_EIT_RESET(eit)

   Resets an ege iterator. After calling this macro the iterator will
point to the first edge.

   *Arguments:. *

`eit':
     The edge iterator.

   Time complexity: O(1).

8.9.8 IGRAPH_EIT_GET -- Query an edge iterator.
-----------------------------------------------

     #define IGRAPH_EIT_GET(eit)

   Gives the edge id of the current edge pointed to by an iterator.

   *Arguments:. *

`eit':
     The edge iterator.

   *Returns:. *

`'
     The id of the current edge.

   Time complexity: O(1).

9 Graph, Vertex and Edge Attributes
***********************************

Attributes are numbers or strings (or basically any kind of data)
associated with the vertices or edges of a graph, or with the graph
itself. Eg. you may label vertices with symbolic names or attach
numeric weights to the edges of a graph.

   igraph attributes are designed to be flexible and extensible.  In
igraph attributes are implemented via an interface abstraction: any
type implementing the functions in the interface, can be used for
storing vertex, edge and graph attributes. This means that different
attribute implementations can be used together with igraph. This is
reasonable: if igraph is used from Python attributes can be of any
Python type, from GNU R all R types are allowed. There is an
experimental attribute implementation to be used when programming in C,
but by default it is currently turned off.

   First we briefly look over how attribute handlers can be
implemented. This is not something a user does every day. It is rather
typically the job of the high level interface writers. (But it is
possible to write an interface without implementing attributes.) Then
we show the experimental C attribute handler.

9.1 The Attribute Handler Interface
===================================

It is possible to attach an attribute handling interface to `igraph'.
This is simply a table of functions, of type `igraph_attribute_table_t'
(see igraph_attribute_table_t --- Table of functions to perform operations on attributes).
These functions are invoked to notify the
attribute handling code about the structural changes in a graph. See
the documentation of this type for details.

   By default there is no attribute interface attached to `igraph', to
attach one, call `igraph_i_set_attribute_table' (see
igraph_i_set_attribute_table --- Attach an attribute table_) with
your new table.

9.1.1 igraph_attribute_table_t -- Table of functions to perform operations on attributes
----------------------------------------------------------------------------------------

     typedef struct igraph_attribute_table_t {
       int (*init)(igraph_t *graph, igraph_vector_ptr_t *attr);
       void (*destroy)(igraph_t *graph);
       int (*copy)(igraph_t *to, const igraph_t *from, igraph_bool_t ga,
     	      igraph_bool_t va, igraph_bool_t ea);
       int (*add_vertices)(igraph_t *graph, long int nv, igraph_vector_ptr_t *attr);
       void (*delete_vertices)(igraph_t *graph, const igraph_vector_t *eidx,
     			  const igraph_vector_t *vidx);
       int (*add_edges)(igraph_t *graph, const igraph_vector_t *edges,
     		   igraph_vector_ptr_t *attr);
       void (*delete_edges)(igraph_t *graph, const igraph_vector_t *idx);
       int (*permute_edges)(igraph_t *graph, const igraph_vector_t *idx);
       int (*get_info)(const igraph_t *graph,
     		  igraph_strvector_t *gnames, igraph_vector_t *gtypes,
     		  igraph_strvector_t *vnames, igraph_vector_t *vtypes,
     		  igraph_strvector_t *enames, igraph_vector_t *etypes);
       igraph_bool_t (*has_attr)(const igraph_t *graph, igraph_attribute_elemtype_t type,
     			    const char *name);
       int (*gettype)(const igraph_t *graph, igraph_attribute_type_t *type,
     		 igraph_attribute_elemtype_t elemtype, const char *name);
       int (*get_numeric_graph_attr)(const igraph_t *graph, const char *name,
     				igraph_vector_t *value);
       int (*get_string_graph_attr)(const igraph_t *graph, const char *name,
     			       igraph_strvector_t *value);
       int (*get_numeric_vertex_attr)(const igraph_t *graph, const char *name,
     				 igraph_vs_t vs,
     				 igraph_vector_t *value);
       int (*get_string_vertex_attr)(const igraph_t *graph, const char *name,
     				igraph_vs_t vs,
     				igraph_strvector_t *value);
       int (*get_numeric_edge_attr)(const igraph_t *graph, const char *name,
     			       igraph_es_t es,
     			       igraph_vector_t *value);
       int (*get_string_edge_attr)(const igraph_t *graph, const char *name,
     			      igraph_es_t es,
     			      igraph_strvector_t *value);
     } igraph_attribute_table_t;

   This type collects the functions defining an attribute handler.  It
has the following members:

   *Values:. *

`init':
     This function is called whenever a new graph object is created,
     right after it is created but before any vertices or edges are
     added. It is supposed to set the `attr' member of the `igraph_t'
     object. It is expected to return an error code.

`destroy':
     This function is called whenever the graph object is destroyed,
     right before freeing the allocated memory.

`copy':
     This function is called when copying a graph with `igraph_copy'
     (see igraph_copy --- Creates an exact [deep] copy of a graph_),
     after the structure of the graph has been already
     copied. It is expected to return an error code.

`add_vertices':
     Called when vertices are added to a graph, before adding the
     vertices themselves.  The number of vertices to add is supplied as
     an argument. Expected to return an error code.

`delete_vertices':
     Called when vertices are deleted from the graph. Two additional
     parameters are supplied, the first is a recoding vector for edge
     ids, the second is one for the vertex ids. The edge recoding
     vector gives for each edge its id in the new graph. It contains
     one number for each edge (in the original graph): zero means that
     the edge has been deleted, otherwise the new id plus one is
     included. The vertex recoding vector contains the same for
     vertices.

`add_edges':
     Called when new edges have been added. The number of new edges are
     supplied as well. It is expected to return an error code.

`delete_edges':
     Called when edges were deleted. The edge recoding vector is
     supplied, in the same form as for the `delete_vertices' function.

`permute_edges':
     Typically called when a new graph is created and some of the new
     edges should carry the attributes of some of the old edges. The
     idx vector shows the mapping between the old edges and the new
     ones. Its length is the same as the number of edges in the new
     graph, and for each edge it gives the id of the old edge (the edge
     in the old graph).

`get_info':
     Query the attributes of a graph, the names and types should be
     returned.

`has_attr':
     Check whether a graph has the named graph/vertex/edge attribute.

`gettype':
     Query the type of a graph/vertex/edge attribute.

`get_numeric_graph_attr':
     Query a numeric graph attribute. The value should be placed as the
     first element of the `value' vector.

`get_string_graph_attr':
     Query a string graph attribute. The value should be placed as the
     first element of the `value' string vector.

`get_numeric_vertex_attr':
     Query a numeric vertex attribute, for the vertices included in
     `vs'.

`get_string_vertex_attr':
     Query a string vertex attribute, for the vertices included in `vs'.

`get_numeric_edge_attr':
     Query a numeric edge attribute, for the edges included in `es'.

`get_string_edge_attr':
     Query a string edge attribute, for the edge included in `es'.

   Note that the `get_*_*_attr' are allowed to convert the attributes
to numeric or string. E.g. if a vertex attribute is a GNU R complex
data type, then `get_string_vertex_attribute' may serialize it into a
string, but this probably makes sense only if `add_vertices' is able to
deserialize it.

9.1.2 igraph_i_set_attribute_table -- Attach an attribute table.
----------------------------------------------------------------

     igraph_attribute_table_t *
     igraph_i_set_attribute_table(igraph_attribute_table_t * table);

   This function attaches attribute handling code to the igraph library.

   *Arguments:. *

`table':
     Pointer to an `igraph_attribute_table_t' (see
     igraph_attribute_table_t --- Table of functions to perform operations on attributes)
     object containing the functions for
     attribute manipulation. Supply `NULL' here if you don't want
     attributes.

   *Returns:. *

`'
     Pointer to the old attribute handling table.

   Time complexity: O(1).

9.1.3 igraph_attribute_type_t -- The possible types of the attributes.
----------------------------------------------------------------------

     typedef enum { IGRAPH_ATTRIBUTE_DEFAULT=0,
     	       IGRAPH_ATTRIBUTE_NUMERIC=1,
     	       IGRAPH_ATTRIBUTE_STRING=2,
     	       IGRAPH_ATTRIBUTE_R_OBJECT=3,
     	       IGRAPH_ATTRIBUTE_PY_OBJECT=4 } igraph_attribute_type_t;

     typedef struct igraph_i_attribute_record_t {
       const char *name;
       igraph_attribute_type_t type;
       const void *value;
     } igraph_i_attribute_record_t;

     typedef enum { IGRAPH_ATTRIBUTE_GRAPH=0,
     	       IGRAPH_ATTRIBUTE_VERTEX,
     	       IGRAPH_ATTRIBUTE_EDGE } igraph_attribute_elemtype_t;

   Note that this is only the type communicated by the attribute
interface towards igraph functions. Eg. in the GNU R attribute handler,
it is safe to say that all complex R object attributes are strings, as
long as this interface is able to serialize them into strings. See also
`igraph_attribute_table_t' (see igraph_attribute_table_t --- Table of functions to perform operations on attributes).

   *Values:. *

`IGRAPH_ATTRIBUTE_DEFAULT':
     Currently not used for anything.

`IGRAPH_ATTRIBUTE_NUMERIC':
     Numeric attribute.

`IGRAPH_ATTRIBUTE_STRING':
     Attribute that can be converted to a string.

`IGRAPH_ATTRIBUTE_R_OBJECT':
     An R object. This is usually ignored by the igraph functions.

`IGRAPH_ATTRIBUTE_PY_OBJECT':
     A Python object. Usually ignored by the igraph functions.

9.2 Accessing attributes from C
===============================

There is an experimental attribute handler that can be used from C
code. In this section we show how this works. This attribute handler is
by default not attached (the default is no attribute handler), so we
first need to attach it:

     igraph_i_set_attribute_table(&igraph_cattribute_table);

   Now the attribute functions are available. Please note that the
attribute handler must be attached before you call any other igraph
functions, otherwise you might end up with graphs without attributes
and an active attribute handler, which might cause unexpected program
behaviour. The rule is that you attach the attribute handler in the
beginning of your `main()' and never touch it again. (Detaching the
attribute handler might lead to memory leaks.)

   It is not currently possible to have attribute handlers on a
per-graph basis. All graphs in an application must be managed with the
same attribute handler. (Including the default case when there is no
attribute handler at all.

   The C attribute handler supports attaching real numbers and
character strings as attributes. No vectors are allowed, ie. every
vertex might have an attribute called ` name' , but it is not possible
to have a ` coords'  graph (or other) attribute which is a vector of
numbers.

9.2.1 Query attributes
----------------------

9.2.1.1 igraph_cattribute_list -- List all attributes
.....................................................

     int igraph_cattribute_list(const igraph_t *graph,
     			   igraph_strvector_t *gnames, igraph_vector_t *gtypes,
     			   igraph_strvector_t *vnames, igraph_vector_t *vtypes,
     			   igraph_strvector_t *enames, igraph_vector_t *etypes);

   See `igraph_attribute_type_t' (see igraph_attribute_type_t --- The possible types of the attributes_)
for the various attribute types.

   *Arguments:. *

`graph':
     The input graph.

`gnames':
     String vector, the names of the graph attributes.

`gtypes':
     Numeric vector, the types of the graph attributes.

`vnames':
     String vector, the names of the vertex attributes.

`vtypes':
     Numeric vector, the types of the vertex attributes.

`enames':
     String vector, the names of the edge attributes.

`etypes':
     Numeric vector, the types of the edge attributes.

   *Returns:. *

`'
     Error code.

   Naturally, the string vector with the attribute names and the
numeric vector with the attribute types are in the right order, i.e.
the first name corresponds to the first type, etc.  Time complexity:
O(Ag+Av+Ae), the number of all attributes.

9.2.1.2 igraph_cattribute_GAN -- Query a numeric graph attribute.
.................................................................

     igraph_real_t igraph_cattribute_GAN(const igraph_t *graph, const char *name);

   Returns the value of the given numeric graph attribute.  The
attribute must exist, otherwise an error is triggered.

   *Arguments:. *

`graph':
     The input graph.

`name':
     The name of the attribute to query.

   *Returns:. *

`'
     The value of the attribute.

   *See also:. *

`'
     `GAN' (see GAN --- Query a numeric graph attribute_) for a
     simpler interface.

   Time complexity: O(Ag), the number of graph attributes.

9.2.1.3 GAN -- Query a numeric graph attribute.
...............................................

     #define GAN(graph,n)

   This is shorthand for `igraph_cattribute_GAN()' (see
igraph_cattribute_GAN --- Query a numeric graph attribute_).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

   *Returns:. *

`'
     The value of the attribute.

9.2.1.4 igraph_cattribute_GAS -- Query a string graph attribute.
................................................................

     const char* igraph_cattribute_GAS(const igraph_t *graph, const char *name);

   Returns a `const' pointer to the string graph attribute specified in
`name'.  The attribute must exist, otherwise an error is triggered.

   *Arguments:. *

`graph':
     The input graph.

`name':
     The name of the attribute to query.

   *Returns:. *

`'
     The value of the attribute.

   *See also:. *

`'
     `GAS' (see GAS --- Query a string graph attribute_) for a
     simpler interface.

   Time complexity: O(Ag), the number of graph attributes.

9.2.1.5 GAS -- Query a string graph attribute.
..............................................

     #define GAS(graph,n)

   This is shorthand for `igraph_cattribute_GAS()' (see
igraph_cattribute_GAS --- Query a string graph attribute_).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

   *Returns:. *

`'
     The value of the attribute.

9.2.1.6 igraph_cattribute_VAN -- Query a numeric vertex attribute.
..................................................................

     igraph_real_t igraph_cattribute_VAN(const igraph_t *graph, const char *name,
     				      igraph_integer_t vid);

   The attribute must exist, otherwise an error is triggered.

   *Arguments:. *

`graph':
     The input graph.

`name':
     The name of the attribute.

`vid':
     The id of the queried vertex.

   *Returns:. *

`'
     The value of the attribute.

   *See also:. *

`'
     `VAN' (see VAN --- Query a numeric vertex attribute_) macro
     for a simpler interface.

   Time complexity: O(Av), the number of vertex attributes.

9.2.1.7 VAN -- Query a numeric vertex attribute.
................................................

     #define VAN(graph,n,v)

   This is shorthand for `igraph_cattribute_VAN()' (see
igraph_cattribute_VAN --- Query a numeric vertex attribute_).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`v':
     The id of the vertex.

   *Returns:. *

`'
     The value of the attribute.

9.2.1.8 igraph_cattribute_VANV -- Query a numeric vertex attribute for many vertices
....................................................................................

     int igraph_cattribute_VANV(const igraph_t *graph, const char *name,
     			   igraph_vs_t vids, igraph_vector_t *result);

   *Arguments:. *

`graph':
     The input graph.

`name':
     The name of the attribute.

`vids':
     The vertices to query.

`result':
     Pointer to an initialized vector, the result is stored here. It
     will be resized, if needed.

   *Returns:. *

`'
     Error code.

   Time complexity: O(v), where v is the number of vertices in 'vids'.

9.2.1.9 VANV -- Query a numeric vertex attribute for all vertices.
..................................................................

     #define VANV(graph,n,vec)

   This is a shorthand for `igraph_cattribute_VANV()' (see
igraph_cattribute_VANV --- Query a numeric vertex attribute for many vertices).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`vec':
     Pointer to an initialized vector, the result is stored here. It
     will be resized, if needed.

   *Returns:. *

`'
     Error code.

9.2.1.10 igraph_cattribute_VAS -- Query a string vertex attribute.
..................................................................

     const char* igraph_cattribute_VAS(const igraph_t *graph, const char *name,
     				    igraph_integer_t vid);

   The attribute must exist, otherwise an error is triggered.

   *Arguments:. *

`graph':
     The input graph.

`name':
     The name of the attribute.

`vid':
     The id of the queried vertex.

   *Returns:. *

`'
     The value of the attribute.

   *See also:. *

`'
     The macro `VAS' (see VAS --- Query a string vertex attribute_)
     for a simpler interface.

   Time complexity: O(Av), the number of vertex attributes.

9.2.1.11 VAS -- Query a string vertex attribute.
................................................

     #define VAS(graph,n,v)

   This is shorthand for `igraph_cattribute_VAS()' (see
igraph_cattribute_VAS --- Query a string vertex attribute_).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`v':
     The id of the vertex.

   *Returns:. *

`'
     The value of the attribute.

9.2.1.12 igraph_cattribute_VASV -- Query a string vertex attribute for many vertices
....................................................................................

     int igraph_cattribute_VASV(const igraph_t *graph, const char *name,
     			   igraph_vs_t vids, igraph_strvector_t *result);

   *Arguments:. *

`graph':
     The input graph.

`name':
     The name of the attribute.

`vids':
     The vertices to query.

`result':
     Pointer to an initialized string vector, the result is stored
     here. It will be resized, if needed.

   *Returns:. *

`'
     Error code.

   Time complexity: O(v), where v is the number of vertices in 'vids'.
(We assume that the string attributes have a bounded length.)

9.2.1.13 VASV -- Query a string vertex attribute for all vertices.
..................................................................

     #define VASV(graph,n,vec)

   This is a shorthand for `igraph_cattribute_VASV()' (see
igraph_cattribute_VASV --- Query a string vertex attribute for many vertices).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`vec':
     Pointer to an initialized string vector, the result is stored
     here. It will be resized, if needed.

   *Returns:. *

`'
     Error code.

9.2.1.14 igraph_cattribute_EAN -- Query a numeric edge attribute.
.................................................................

     igraph_real_t igraph_cattribute_EAN(const igraph_t *graph, const char *name,
     				      igraph_integer_t eid);

   The attribute must exist, otherwise an error is triggered.

   *Arguments:. *

`graph':
     The input graph.

`name':
     The name of the attribute.

`eid':
     The id of the queried edge.

   *Returns:. *

`'
     The value of the attribute.

   *See also:. *

`'
     `EAN' (see EAN --- Query a numeric edge attribute_) for an
     easier interface.

   Time complexity: O(Ae), the number of edge attributes.

9.2.1.15 EAN -- Query a numeric edge attribute.
...............................................

     #define EAN(graph,n,e)

   This is shorthand for `igraph_cattribute_EAN()' (see
igraph_cattribute_EAN --- Query a numeric edge attribute_).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`e':
     The id of the edge.

   *Returns:. *

`'
     The value of the attribute.

9.2.1.16 igraph_cattribute_EANV -- Query a numeric edge attribute for many edges
................................................................................

     int igraph_cattribute_EANV(const igraph_t *graph, const char *name,
     			   igraph_es_t eids, igraph_vector_t *result);

   *Arguments:. *

`graph':
     The input graph.

`name':
     The name of the attribute.

`eids':
     The edges to query.

`result':
     Pointer to an initialized vector, the result is stored here. It
     will be resized, if needed.

   *Returns:. *

`'
     Error code.

   Time complexity: O(e), where e is the number of edges in 'eids'.

9.2.1.17 EANV -- Query a numeric edge attribute for all edges.
..............................................................

     #define EANV(graph,n,vec)

   This is a shorthand for `igraph_cattribute_EANV()' (see
igraph_cattribute_EANV --- Query a numeric edge attribute for many edges).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`vec':
     Pointer to an initialized vector, the result is stored here. It
     will be resized, if needed.

   *Returns:. *

`'
     Error code.

9.2.1.18 igraph_cattribute_EAS -- Query a string edge attribute.
................................................................

     const char* igraph_cattribute_EAS(const igraph_t *graph, const char *name,
     				    igraph_integer_t eid);

   The attribute must exist, otherwise an error is triggered.

   *Arguments:. *

`graph':
     The input graph.

`name':
     The name of the attribute.

`eid':
     The id of the queried edge.

   *Returns:. *

`'
     The value of the attribute.

   \se `EAS' (see EAS --- Query a string edge attribute_) if you
want to type less.  Time complexity: O(Ae), the number of edge
attributes.

9.2.1.19 EAS -- Query a string edge attribute.
..............................................

     #define EAS(graph,n,e)

   This is shorthand for `igraph_cattribute_EAS()' (see
igraph_cattribute_EAS --- Query a string edge attribute_).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`e':
     The id of the edge.

   *Returns:. *

`'
     The value of the attribute.

9.2.1.20 igraph_cattribute_EASV -- Query a string edge attribute for many edges
...............................................................................

     int igraph_cattribute_EASV(const igraph_t *graph, const char *name,
     			   igraph_es_t eids, igraph_strvector_t *result);

   *Arguments:. *

`graph':
     The input graph.

`name':
     The name of the attribute.

`vids':
     The edges to query.

`result':
     Pointer to an initialized string vector, the result is stored
     here. It will be resized, if needed.

   *Returns:. *

`'
     Error code.

   Time complexity: O(e), where e is the number of edges in 'eids'. (We
assume that the string attributes have a bounded length.)

9.2.1.21 EASV -- Query a string edge attribute for all edges.
.............................................................

     #define EASV(graph,n,vec)

   This is a shorthand for `igraph_cattribute_EASV()' (see
igraph_cattribute_EASV --- Query a string edge attribute for many edges).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`vec':
     Pointer to an initialized string vector, the result is stored
     here. It will be resized, if needed.

   *Returns:. *

`'
     Error code.

9.2.2 Set attributes
--------------------

9.2.2.1 igraph_cattribute_GAN_set -- Set a numeric graph attribute
..................................................................

     int igraph_cattribute_GAN_set(igraph_t *graph, const char *name,
     			      igraph_real_t value);

   *Arguments:. *

`graph':
     The graph.

`name':
     Name of the graph attribute. If there is no such attribute yet,
     then it will be added.

`value':
     The (new) value of the graph attribute.

   *Returns:. *

`'
     Error code.

   \se `SETGAN' (see SETGAN --- Set a numeric graph attribute) if
you want to type less.  Time complexity: O(1).

9.2.2.2 SETGAN -- Set a numeric graph attribute
...............................................

     #define SETGAN(graph,n,value)

   This is a shorthand for `igraph_cattribute_GAN_set()' (see
igraph_cattribute_GAN_set --- Set a numeric graph attribute).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`value':
     The new value of the attribute.

   *Returns:. *

`'
     Error code.

9.2.2.3 igraph_cattribute_GAS_set -- Set a string graph attribute.
..................................................................

     int igraph_cattribute_GAS_set(igraph_t *graph, const char *name,
     			      const char *value);

   *Arguments:. *

`graph':
     The graph.

`name':
     Name of the graph attribute. If there is no such attribute yet,
     then it will be added.

`value':
     The (new) value of the graph attribute. It will be copied.

   *Returns:. *

`'
     Error code.

   \se `SETGAS' (see SETGAS --- Set a string graph attribute) if
you want to type less.  Time complexity: O(1).

9.2.2.4 SETGAS -- Set a string graph attribute
..............................................

     #define SETGAS(graph,n,value)

   This is a shorthand for `igraph_cattribute_GAS_set()' (see
igraph_cattribute_GAS_set --- Set a string graph attribute_).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`value':
     The new value of the attribute.

   *Returns:. *

`'
     Error code.

9.2.2.5 igraph_cattribute_VAN_set -- Set a numeric vertex attribute
...................................................................

     int igraph_cattribute_VAN_set(igraph_t *graph, const char *name,
     			      igraph_integer_t vid, igraph_real_t value);

   The attribute will be added if not present already. If present it
will be overwritten. The same `value' is set for all vertices included
in `vid'.

   *Arguments:. *

`graph':
     The graph.

`name':
     Name of the attribute.

`vid':
     Vertices for which to set the attribute.

`value':
     The (new) value of the attribute.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `SETVAN' (see SETVAN --- Set a numeric vertex attribute) for a
     simpler way.

   Time complexity: O(n), the number of vertices if the attribute is
new, O(|vid|) otherwise.

9.2.2.6 SETVAN -- Set a numeric vertex attribute
................................................

     #define SETVAN(graph,n,vid,value)

   This is a shorthand for `igraph_cattribute_VAN_set()' (see
igraph_cattribute_VAN_set --- Set a numeric vertex attribute).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`vid':
     Ids of the vertices to set.

`value':
     The new value of the attribute.

   *Returns:. *

`'
     Error code.

9.2.2.7 igraph_cattribute_VAS_set -- Set a string vertex attribute
..................................................................

     int igraph_cattribute_VAS_set(igraph_t *graph, const char *name,
     			      igraph_integer_t vid, const char *value);

   The attribute will be added if not present already. If present it
will be overwritten. The same `value' is set for all vertices included
in `vid'.

   *Arguments:. *

`graph':
     The graph.

`name':
     Name of the attribute.

`vid':
     Vertices for which to set the attribute.

`value':
     The (new) value of the attribute.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `SETVAS' (see SETVAS --- Set a string vertex attribute) for a
     simpler way.

   Time complexity: O(n*l), n is the number of vertices, l is the
length of the string to set. If the attribute if not new then only
O(|vid|*l).

9.2.2.8 SETVAS -- Set a string vertex attribute
...............................................

     #define SETVAS(graph,n,vid,value)

   This is a shorthand for `igraph_cattribute_VAS_set()' (see
igraph_cattribute_VAS_set --- Set a string vertex attribute).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`vid':
     Ids of the vertices to set.

`value':
     The new value of the attribute.

   *Returns:. *

`'
     Error code.

9.2.2.9 igraph_cattribute_EAN_set -- Set a numeric edge attribute
.................................................................

     int igraph_cattribute_EAN_set(igraph_t *graph, const char *name,
     			      igraph_integer_t eid, igraph_real_t value);

   The attribute will be added if not present already. If present it
will be overwritten. The same `value' is set for all edges included in
`vid'.

   *Arguments:. *

`graph':
     The graph.

`name':
     Name of the attribute.

`eid':
     Edges for which to set the attribute.

`value':
     The (new) value of the attribute.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `SETEAN' (see SETEAN --- Set a numeric edge attribute) for a
     simpler way.

   Time complexity: O(e), the number of edges if the attribute is new,
O(|eid|) otherwise.

9.2.2.10 SETEAN -- Set a numeric edge attribute
...............................................

     #define SETEAN(graph,n,eid,value)

   This is a shorthand for `igraph_cattribute_EAN_set()' (see
igraph_cattribute_EAN_set --- Set a numeric edge attribute).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`eid':
     Ids of the edges to set.

`value':
     The new value of the attribute.

   *Returns:. *

`'
     Error code.

9.2.2.11 igraph_cattribute_EAS_set -- Set a string edge attribute
.................................................................

     int igraph_cattribute_EAS_set(igraph_t *graph, const char *name,
     			      igraph_integer_t eid, const char *value);

   The attribute will be added if not present already. If present it
will be overwritten. The same `value' is set for all edges included in
`vid'.

   *Arguments:. *

`graph':
     The graph.

`name':
     Name of the attribute.

`eid':
     Edges for which to set the attribute.

`value':
     The (new) value of the attribute.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `SETEAS' (see SETEAS --- Set a string edge attribute) for a
     simpler way.

   Time complexity: O(e*l), n is the number of edges, l is the length
of the string to set. If the attribute if not new then only O(|eid|*l).

9.2.2.12 SETEAS -- Set a string edge attribute
..............................................

     #define SETEAS(graph,n,eid,value)

   This is a shorthand for `igraph_cattribute_EAS_set()' (see
igraph_cattribute_EAS_set --- Set a string edge attribute).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`eid':
     Ids of the edges to set.

`value':
     The new value of the attribute.

   *Returns:. *

`'
     Error code.

9.2.2.13 igraph_cattribute_VAN_setv -- Set a numeric vertex attribute for all vertices.
.......................................................................................

     int igraph_cattribute_VAN_setv(igraph_t *graph, const char *name,
     			       const igraph_vector_t *v);

   The attribute will be added if not present yet.

   *Arguments:. *

`graph':
     The graph.

`name':
     Name of the attribute.

`v':
     The new attribute values. The length of this vector must match the
     number of vertices.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `SETVANV' (see SETVANV --- Set a numeric vertex attribute for all vertices)
     for a simpler way.

   Time complexity: O(n), the number of vertices.

9.2.2.14 SETVANV -- Set a numeric vertex attribute for all vertices
...................................................................

     #define SETVANV(graph,n,v)

   This is a shorthand for `igraph_cattribute_VAN_setv()' (see
igraph_cattribute_VAN_setv --- Set a numeric vertex attribute for all vertices_).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`v':
     Vector containing the new values of the attributes.

   *Returns:. *

`'
     Error code.

9.2.2.15 igraph_cattribute_VAS_setv -- Set a string vertex attribute for all vertices.
......................................................................................

     int igraph_cattribute_VAS_setv(igraph_t *graph, const char *name,
     			       const igraph_strvector_t *sv);

   The attribute will be added if not present yet.

   *Arguments:. *

`graph':
     The graph.

`name':
     Name of the attribute.

`sv':
     String vector, the new attribute values. The length of this vector
     must match the number of vertices.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `SETVASV' (see SETVASV --- Set a string vertex attribute for all vertices)
     for a simpler way.

   Time complexity: O(n+l), n is the number of vertices, l is the total
length of the strings.

9.2.2.16 SETVASV -- Set a string vertex attribute for all vertices
..................................................................

     #define SETVASV(graph,n,v)

   This is a shorthand for `igraph_cattribute_VAS_setv()' (see
igraph_cattribute_VAS_setv --- Set a string vertex attribute for all vertices_).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`v':
     Vector containing the new values of the attributes.

   *Returns:. *

`'
     Error code.

9.2.2.17 igraph_cattribute_EAN_setv -- Set a numeric edge attribute for all vertices.
.....................................................................................

     int igraph_cattribute_EAN_setv(igraph_t *graph, const char *name,
     			       const igraph_vector_t *v);

   The attribute will be added if not present yet.

   *Arguments:. *

`graph':
     The graph.

`name':
     Name of the attribute.

`v':
     The new attribute values. The length of this vector must match the
     number of edges.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `SETEANV' (see SETEANV --- Set a numeric edge attribute for all vertices)
     for a simpler way.

   Time complexity: O(e), the number of edges.

9.2.2.18 SETEANV -- Set a numeric edge attribute for all vertices
.................................................................

     #define SETEANV(graph,n,v)

   This is a shorthand for `igraph_cattribute_EAN_setv()' (see
igraph_cattribute_EAN_setv --- Set a numeric edge attribute for all vertices_).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`v':
     Vector containing the new values of the attributes.

9.2.2.19 igraph_cattribute_EAS_setv -- Set a string edge attribute for all vertices.
....................................................................................

     int igraph_cattribute_EAS_setv(igraph_t *graph, const char *name,
     			       const igraph_strvector_t *sv);

   The attribute will be added if not present yet.

   *Arguments:. *

`graph':
     The graph.

`name':
     Name of the attribute.

`sv':
     String vector, the new attribute values. The length of this vector
     must match the number of edges.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `SETEASV' (see SETEASV --- Set a string edge attribute for all vertices)
     for a simpler way.

   Time complexity: O(e+l), e is the number of edges, l is the total
length of the strings.

9.2.2.20 SETEASV -- Set a string edge attribute for all vertices
................................................................

     #define SETEASV(graph,n,v)

   This is a shorthand for `igraph_cattribute_EAS_setv()' (see
igraph_cattribute_EAS_setv --- Set a string edge attribute for all vertices_).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute.

`v':
     Vector containing the new values of the attributes.

9.2.3 Remove attributes
-----------------------

9.2.3.1 igraph_cattribute_remove_g -- Remove a graph attribute
..............................................................

     void igraph_cattribute_remove_g(igraph_t *graph, const char *name);

   *Arguments:. *

`graph':
     The graph object.

`name':
     Name of the graph attribute to remove.

   *See also:. *

`'
     `DELGA' (see DELGA --- Remove a graph attribute_) for a
     simpler way.

9.2.3.2 DELGA -- Remove a graph attribute.
..........................................

     #define DELGA(graph,n)

   A shorthand for `igraph_cattribute_remove_g()' (see
igraph_cattribute_remove_g --- Remove a graph attribute).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute to remove.

9.2.3.3 igraph_cattribute_remove_v -- Remove a vertex attribute
...............................................................

     void igraph_cattribute_remove_v(igraph_t *graph, const char *name);

   *Arguments:. *

`graph':
     The graph object.

`name':
     Name of the vertex attribute to remove.

   *See also:. *

`'
     `DELVA' (see DELVA --- Remove a vertex attribute_) for a
     simpler way.

9.2.3.4 DELVA -- Remove a vertex attribute.
...........................................

     #define DELVA(graph,n)

   A shorthand for `igraph_cattribute_remove_v()' (see
igraph_cattribute_remove_v --- Remove a vertex attribute).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute to remove.

9.2.3.5 igraph_cattribute_remove_e -- Remove an edge attribute
..............................................................

     void igraph_cattribute_remove_e(igraph_t *graph, const char *name);

   *Arguments:. *

`graph':
     The graph object.

`name':
     Name of the edge attribute to remove.

   *See also:. *

`'
     `DELEA' (see DELEA --- Remove an edge attribute_) for a
     simpler way.

9.2.3.6 DELEA -- Remove an edge attribute.
..........................................

     #define DELEA(graph,n)

   A shorthand for `igraph_cattribute_remove_e()' (see
igraph_cattribute_remove_e --- Remove an edge attribute).

   *Arguments:. *

`graph':
     The graph.

`n':
     The name of the attribute to remove.

9.2.3.7 igraph_cattribute_remove_all -- Remove all graph/vertex/edge attributes
...............................................................................

     void igraph_cattribute_remove_all(igraph_t *graph, igraph_bool_t g,
     				  igraph_bool_t v, igraph_bool_t e);

   *Arguments:. *

`graph':
     The graph object.

`g':
     Boolean, whether to remove graph attributes.

`v':
     Boolean, whether to remove vertex attributes.

`e':
     Boolean, whether to remove edge attributes.

   *See also:. *

`'
     `DELGAS' (see DELGAS --- Remove all graph attributes_),
     `DELVAS' (see DELVAS --- Remove all vertex attributes_),
     `DELEAS' (see DELEAS --- Remove all edge attributes_),
     `DELALL' (see DELALL --- Remove all attributes_) for simpler
     ways.

9.2.3.8 DELGAS -- Remove all graph attributes.
..............................................

     #define DELGAS(graph)

   Calls `igraph_cattribute_remove_all()' (see
igraph_cattribute_remove_all --- Remove all graph/vertex/edge attributes).

   *Arguments:. *

`graph':
     The graph.

9.2.3.9 DELVAS -- Remove all vertex attributes.
...............................................

     #define DELVAS(graph)

   Calls `igraph_cattribute_remove_all()' (see
igraph_cattribute_remove_all --- Remove all graph/vertex/edge attributes).

   *Arguments:. *

`graph':
     The graph.

9.2.3.10 DELEAS -- Remove all edge attributes.
..............................................

     #define DELEAS(graph)

   Calls `igraph_cattribute_remove_all()' (see
igraph_cattribute_remove_all --- Remove all graph/vertex/edge attributes).

   *Arguments:. *

`graph':
     The graph.

9.2.3.11 DELALL -- Remove all attributes.
.........................................

     #define DELALL(graph)

   All graph, vertex and edges attributes will be removed.  Calls
`igraph_cattribute_remove_all()' (see igraph_cattribute_remove_all --- Remove all graph/vertex/edge attributes).

   *Arguments:. *

`graph':
     The graph.

10 Structural Properties of Graphs
**********************************

These functions usually calculate some structural property of a graph,
like its diameter, the degree of the nodes, etc.

10.1 Basic Properties
=====================

10.1.1 igraph_are_connected -- Decides whether two vertices are connected
-------------------------------------------------------------------------

     int igraph_are_connected(const igraph_t *graph,
     			 igraph_integer_t v1, igraph_integer_t v2,
     			 igraph_bool_t *res);

   *Arguments:. *

`graph':
     The graph object.

`v1':
     The first vertex.

`v2':
     The second vertex.

`res':
     Boolean, `TRUE' if there is an edge from `v1' to `v2', `FALSE'
     otherwise.

   *Returns:. *

`'
     Error code.

   The function is of course symmetric for undirected graphs.

   Time complexity: O( min(log(d1), log(d2)) ), d1 is the (out-)degree
of `v1' and d2 is the (in-)degree of `v2'.

10.2 Shortest Path Related Functions
====================================

10.2.1 igraph_shortest_paths -- The length of the shortest paths between vertices.
----------------------------------------------------------------------------------

     int igraph_shortest_paths(const igraph_t *graph, igraph_matrix_t *res,
     			  const igraph_vs_t from, igraph_neimode_t mode);

   *Arguments:. *

`graph':
     The graph object.

`res':
     The result of the calculation, a matrix. It has the same number of
     rows as the length of the `from' argument, and its number of
     columns is the number of vertices in the graph. One row of the
     matrix shows the distances from/to a given vertex to all the
     others in the graph, the order is fixed by the vertex ids. For the
     unreachable vertices IGRAPH_INFINITY is returned.

`from':
     Vector of the vertex ids for which the path length calculations
     are done.

`mode':
     The type of shortest paths to be use for the calculation in
     directed graphs. Possible values:

    `IGRAPH_OUT '
          the lengths of the outgoing paths are calculated.

    `IGRAPH_IN '
          the lengths of the incoming paths are calculated.

    `IGRAPH_ALL '
          the directed graph is considered as an undirected one for the
          computation.

   *Returns:. *

`'
     Error code:

    `IGRAPH_ENOMEM '
          not enough memory for temporary data.

    `IGRAPH_EINVVID'
          invalid vertex id passed.

    `IGRAPH_EINVMODE '
          invalid mode argument.

   Time complexity: O(n(|V|+|E|)), n is the number of vertices to
calculate, |V| and |E| are the number of vertices and edges in the
graph.

   *See also:. *

`'
     `igraph_get_shortest_paths()' (see igraph_get_shortest_paths --- Calculates the shortest paths from/to one vertex_)
     to get the
     paths themselves, `igraph_shortest_paths_dijkstra()' (see
     igraph_shortest_paths_dijkstra --- Weighted shortest paths from some sources)
     for the weighted version.

10.2.2 igraph_shortest_paths_dijkstra -- Weighted shortest paths from some sources
----------------------------------------------------------------------------------

     int igraph_shortest_paths_dijkstra(const igraph_t *graph,
     				   igraph_matrix_t *res,
     				   const igraph_vs_t from,
     				   const igraph_vector_t *weights,
     				   igraph_neimode_t mode);

   This function is Dijkstra's algorithm to find the weighted shortest
paths to all vertices from a single source. (It is run independently
for the given sources.) It uses a binary heap for efficient
implementation.

   *Arguments:. *

`graph':
     The input graph, can be directed.

`res':
     The result, a matrix. Each row contains the distances from a
     single source, in the order of vertex ids.  Unreachable vertices
     has distance `IGRAPH_INFINITY'.

`from':
     The source vertices.

`weights':
     The edge weights. They must be all non-negative for Dijkstra's
     algorithm to work. An error code is returned if there is a
     negative edge weight in the weight vector. If this is a null
     pointer, then the unweighted version, `igraph_shortest_paths()'
     (see igraph_shortest_paths --- The length of the shortest paths between vertices_)
     is called.

`mode':
     For directed graphs; whether to follow paths along edge directions
     (`IGRAPH_OUT'), or the opposite (`IGRAPH_IN'), or ignore edge
     directions completely (`IGRAPH_ALL'). It is ignored for undirected
     graphs.

   *Returns:. *

`'
     Error code.

   Time complexity: O(s*|E|log|E|+|V|), where |V| is the number of
vertices, |E| the number of edges and s the number of sources.

   *See also:. *

`'
     `igraph_shortest_paths()' (see igraph_shortest_paths --- The length of the shortest paths between vertices_)
     for a (slightly)
     faster unweighted version or
     `igraph_shortest_paths_bellman_ford()' (see
     igraph_shortest_paths_bellman_ford --- Weighted shortest paths from some sources allowing negative weights)
     for a weighted
     variant that works in the presence of negative edge weights (but no
     negative loops).

10.2.3 igraph_shortest_paths_bellman_ford -- Weighted shortest paths from some sources allowing negative weights
----------------------------------------------------------------------------------------------------------------

     int igraph_shortest_paths_bellman_ford(const igraph_t *graph,
     				       igraph_matrix_t *res,
     				       const igraph_vs_t from,
     				       const igraph_vector_t *weights,
     				       igraph_neimode_t mode);

   This function is the Bellman-Ford algorithm to find the weighted
shortest paths to all vertices from a single source. (It is run
independently for the given sources.). If there are no negative
weights, you are better off with `igraph_shortest_paths_dijkstra()'
(see igraph_shortest_paths_dijkstra --- Weighted shortest paths from some sources)
.

   *Arguments:. *

`graph':
     The input graph, can be directed.

`res':
     The result, a matrix. Each row contains the distances from a
     single source, in the order of vertex ids.  Unreachable vertices
     has distance `IGRAPH_INFINITY'.

`from':
     The source vertices.

`weights':
     The edge weights. There mustn't be any closed loop in the graph
     that has a negative total weight (since this would allow us to
     decrease the weight of any path containing at least a single
     vertex of this loop infinitely). If this is a null pointer, then
     the unweighted version, `igraph_shortest_paths()' (see
     igraph_shortest_paths --- The length of the shortest paths between vertices_)
     is called.

`mode':
     For directed graphs; whether to follow paths along edge directions
     (`IGRAPH_OUT'), or the opposite (`IGRAPH_IN'), or ignore edge
     directions completely (`IGRAPH_ALL'). It is ignored for undirected
     graphs.

   *Returns:. *

`'
     Error code.

   Time complexity: O(s*|E|*|V|), where |V| is the number of vertices,
|E| the number of edges and s the number of sources.

   *See also:. *

`'
     `igraph_shortest_paths()' (see igraph_shortest_paths --- The length of the shortest paths between vertices_)
     for a faster
     unweighted version or `igraph_shortest_paths_dijkstra()' (see
     igraph_shortest_paths_dijkstra --- Weighted shortest paths from some sources)
     if you do not have negative edge weights.

10.2.4 igraph_shortest_paths_johnson -- Calculate shortest paths from some sources using Johnson's algorithm
------------------------------------------------------------------------------------------------------------

     int igraph_shortest_paths_johnson(const igraph_t *graph,
     				  igraph_matrix_t *res,
     				  const igraph_vs_t from,
     				  const igraph_vector_t *weights);

   See Wikipedia at http://en.wikipedia.org/wiki/Johnson's_algorithm
(http://en.wikipedia.org/wiki/Johnson's_algorithm) for Johnson's
algorithm. This algorithm works even if the graph contains negative
edge weights, and it is worth using it if we calculate the shortest
paths from many sources.

   If no edge weights are supplied, then the unweighted version,
`igraph_shortest_paths()' (see igraph_shortest_paths --- The length of the shortest paths between vertices_)
is called.

   If all the supplied edge weights are non-negative, then Dijkstra's
algorithm is used by calling `igraph_shortest_paths_dijkstra()' (see
igraph_shortest_paths_dijkstra --- Weighted shortest paths from some sources).

   *Arguments:. *

`graph':
     The input graph, typically it is directed.

`res':
     Pointer to an initialized matrix, the result will be stored here,
     one line for each source vertex.

`from':
     The source vertices.

`weights':
     Optional edge weights. If it is a null-pointer, then the
     unweighted breadth-first search based `igraph_shortest_paths()'
     (see igraph_shortest_paths --- The length of the shortest paths between vertices_)
     will be called.

   *Returns:. *

`'
     Error code.

   Time complexity: O(s|V|log|V|+|V||E|), |V| and |E| are the number of
vertices and edges, s is the number of source vertices.

   *See also:. *

`'
     `igraph_shortest_paths()' (see igraph_shortest_paths --- The length of the shortest paths between vertices_)
     for a faster
     unweighted version or `igraph_shortest_paths_dijkstra()' (see
     igraph_shortest_paths_dijkstra --- Weighted shortest paths from some sources)
     if you do not have negative edge weights,
     `igraph_shortest_paths_bellman_ford()' (see
     igraph_shortest_paths_bellman_ford --- Weighted shortest paths from some sources allowing negative weights)
     if you only need to
     calculate shortest paths from a couple of sources.

10.2.5 igraph_get_shortest_paths -- Calculates the shortest paths from/to one vertex.
-------------------------------------------------------------------------------------

     int igraph_get_shortest_paths(const igraph_t *graph, igraph_vector_ptr_t *res,
     			      igraph_integer_t from, const igraph_vs_t to,
     			      igraph_neimode_t mode);

   If there is more than one geodesic between two vertices, this
function gives only one of them.

   *Arguments:. *

`graph':
     The graph object.

`res':
     The result, this is a pointer vector, each element points to a
     vector object. These should be initialized before passing them to
     the function, which will properly clear and/or resize them and
     fill the ids of the vertices along the geodesics from/to the
     vertices.

`from':
     The id of the vertex from/to which the geodesics are calculated.

`to':
     Vertex sequence with the ids of the vertices to/from which the
     shortest paths will be calculated. A vertex might be given multiple
     times.

`mode':
     The type of shortest paths to be use for the calculation in
     directed graphs. Possible values:

    `IGRAPH_OUT '
          the outgoing paths are calculated.

    `IGRAPH_IN '
          the incoming paths are calculated.

    `IGRAPH_ALL '
          the directed graph is considered as an undirected one for the
          computation.

   *Returns:. *

`'
     Error code:

    `IGRAPH_ENOMEM '
          not enough memory for temporary data.

    `IGRAPH_EINVVID'
          `from' is invalid vertex id, or the length of `to' is not the
          same as the length of `res'.

    `IGRAPH_EINVMODE '
          invalid mode argument.

   Time complexity: O(|V|+|E|), |V| is the number of vertices, |E| the
number of edges in the graph.

   *See also:. *

`'
     `igraph_shortest_paths()' (see igraph_shortest_paths --- The length of the shortest paths between vertices_)
     if you only need
     the path length but not the paths themselves.

10.2.6 igraph_get_shortest_paths_dijkstra -- Calculates the weighted shortest paths from/to one vertex.
-------------------------------------------------------------------------------------------------------

     int igraph_get_shortest_paths_dijkstra(const igraph_t *graph,
                                            igraph_vector_ptr_t *res,
     				       igraph_integer_t from,
     				       igraph_vs_t to,
     				       const igraph_vector_t *weights,
     				       igraph_neimode_t mode);

   If there is more than one path with the smallest weight between two
vertices, this function gives only one of them.

   *Arguments:. *

`graph':
     The graph object.

`res':
     The result, this is a pointer vector, each element points to a
     vector object. These should be initialized before passing them to
     the function, which will properly clear and/or resize them and
     fill the ids of the vertices along the geodesics from/to the
     vertices.

`from':
     The id of the vertex from/to which the geodesics are calculated.

`to':
     Vertex sequence with the ids of the vertices to/from which the
     shortest paths will be calculated. A vertex might be given multiple
     times.

`weights':
     a vector holding the edge weights. All weights must be positive.

`mode':
     The type of shortest paths to be use for the calculation in
     directed graphs. Possible values:

    `IGRAPH_OUT '
          the outgoing paths are calculated.

    `IGRAPH_IN '
          the incoming paths are calculated.

    `IGRAPH_ALL '
          the directed graph is considered as an undirected one for the
          computation.

   *Returns:. *

`'
     Error code:

    `IGRAPH_ENOMEM '
          not enough memory for temporary data.

    `IGRAPH_EINVVID'
          `from' is invalid vertex id, or the length of `to' is not the
          same as the length of `res'.

    `IGRAPH_EINVMODE '
          invalid mode argument.

   Time complexity: O(|E|log|E|+|V|), where |V| is the number of
vertices and |E| is the number of edges

   *See also:. *

`'
     `igraph_shortest_paths_dijkstra()' (see
     igraph_shortest_paths_dijkstra --- Weighted shortest paths from some sources)
     if you only need the path length but not the paths
     themselves, `igraph_get_shortest_paths()' (see
     igraph_get_shortest_paths --- Calculates the shortest paths from/to one vertex_)
     if all edge weights are equal.

10.2.7 igraph_get_all_shortest_paths -- Finds all shortest paths (geodesics) from a vertex to all other vertices
----------------------------------------------------------------------------------------------------------------

     int igraph_get_all_shortest_paths(const igraph_t *graph,
     				  igraph_vector_ptr_t *res,
     				  igraph_vector_t *nrgeo,
     				  igraph_integer_t from, const igraph_vs_t to,
     				  igraph_neimode_t mode);

   *Arguments:. *

`graph':
     The graph object.

`res':
     Pointer to an initialized pointer vector, the result will be
     stored here in igraph_vector_t objects. Each vector object
     contains the vertices along a shortest path from `from' to another
     vertex. The vectors are ordered according to their target vertex:
     first the shortest paths to vertex 0, then to vertex 1, etc. No
     data is included for unreachable vertices.

`nrgeo':
     Pointer to an initialized igraph_vector_t object or NULL. If not
     NULL the number of shortest paths from `from' are is stored here
     for every vertex in the graph.

`from':
     The id of the vertex from/to which the geodesics are calculated.

`mode':
     The type of shortest paths to be use for the calculation in
     directed graphs. Possible values:

    `IGRAPH_OUT '
          the lengths of the outgoing paths are calculated.

    `IGRAPH_IN '
          the lengths of the incoming paths are calculated.

    `IGRAPH_ALL '
          the directed graph is considered as an undirected one for the
          computation.

   *Returns:. *

`'
     Error code:

    `IGRAPH_ENOMEM '
          not enough memory for temporary data.

    `IGRAPH_EINVVID'
          `from' is invalid vertex id.

    `IGRAPH_EINVMODE '
          invalid mode argument.

   Added in version 0.2.

   Time complexity: O(|V|+|E|) for most graphs, O(|V|^2) in the worst
case.

10.2.8 igraph_average_path_length -- Calculates the average geodesic length in a graph.
---------------------------------------------------------------------------------------

     int igraph_average_path_length(const igraph_t *graph, igraph_real_t *res,
     			       igraph_bool_t directed, igraph_bool_t unconn);

   *Arguments:. *

`graph':
     The graph object.

`res':
     Pointer to a real number, this will contain the result.

`directed':
     Boolean, whether to consider directed paths. Ignored for
     undirected graphs.

`unconn':
     What to do if the graph is not connected. If `TRUE' the average of
     thr geodesics within the components will be returned, otherwise
     the number of vertices is used for the length of non-existing
     geodesics. (The rationale behind this is that this is always
     longer than the longest possible geodesic in a graph.)

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM', not enough memory for data structures

   Time complexity: O(|V||E|), the number of vertices times the number
of edges.

10.2.9 igraph_path_length_hist -- Create a histogram of all shortest path lenghts
---------------------------------------------------------------------------------

     int igraph_path_length_hist(const igraph_t *graph, igraph_vector_t *res,
     			    igraph_real_t *unconnected, igraph_bool_t directed);

   This function calculates a histogram, by calculating the shortest
path length between each pair of vertices. For directed graphs both
directions might be considered and then every pair of vertices appears
twice in the histogram.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to an initialized vector, the result is stored here. The
     first (i.e. zeroth) element contains the number of shortest paths
     of length 1, etc. The supplied vector is resized as needed.

`unconnected':
     Pointer to a real number, the number of pairs for which the second
     vertex is not reachable from the first is stored here.

`directed':
     Whether to consider directed paths in a directed graph (if not
     zero). This argument is ignored for undirected graphs.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V||E|), the number of vertices times the number
of edges.

   *See also:. *

`'
     `igraph_average_path_length()' (see igraph_average_path_length --- Calculates the average geodesic length in a graph_)
     and
     `igraph_shortest_paths()' (see igraph_shortest_paths --- The length of the shortest paths between vertices_)

10.2.10 igraph_diameter -- Calculates the diameter of a graph (longest geodesic).
---------------------------------------------------------------------------------

     int igraph_diameter(const igraph_t *graph, igraph_integer_t *pres,
     		    igraph_integer_t *pfrom, igraph_integer_t *pto,
     		    igraph_vector_t *path,
     		    igraph_bool_t directed, igraph_bool_t unconn);

   *Arguments:. *

`graph':
     The graph object.

`pres':
     Pointer to an integer, if not `NULL' then it will contain the
     diameter (the actual distance).

`pfrom':
     Pointer to an integer, if not `NULL' it will be set to the source
     vertex of the diameter path.

`pto':
     Pointer to an integer, if not `NULL' it will be set to the target
     vertex of the diameter path.

`path':
     Pointer to an initialized vector. If not `NULL' the actual longest
     geodesic path will be stored here. The vector will be resized as
     needed.

`directed':
     Boolean, whether to consider directed paths. Ignored for
     undirected graphs.

`unconn':
     What to do if the graph is not connected. If `TRUE' the longest
     geodesic within a component will be returned, otherwise the number
     of vertices is returned. (The rationale behind the latter is that
     this is always longer than the longest possible diameter in a
     graph.)

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM', not enough memory for temporary data.

   Time complexity: O(|V||E|), the number of vertices times the number
of edges.

10.2.11 igraph_diameter_dijkstra -- Weighted diameter using Dijkstra's algorithm, non-negative weights only
-----------------------------------------------------------------------------------------------------------

     int igraph_diameter_dijkstra(const igraph_t *graph,
     			     const igraph_vector_t *weights,
     			     igraph_real_t *pres,
     			     igraph_integer_t *pfrom,
     			     igraph_integer_t *pto,
     			     igraph_vector_t *path,
     			     igraph_bool_t directed,
     			     igraph_bool_t unconn);

   The diameter of a graph is its longest geodesic. I.e. the (weighted)
shortest path is calculated for all pairs of vertices and the longest
one is the diameter.

   *Arguments:. *

`graph':
     The input graph, can be directed or undirected.

`pres':
     Pointer to a real number, if not `NULL' then it will contain the
     diameter (the actual distance).

`pfrom':
     Pointer to an integer, if not `NULL' it will be set to the source
     vertex of the diameter path.

`pto':
     Pointer to an integer, if not `NULL' it will be set to the target
     vertex of the diameter path.

`path':
     Pointer to an initialized vector. If not `NULL' the actual longest
     geodesic path will be stored here. The vector will be resized as
     needed.

`directed':
     Boolean, whether to consider directed paths. Ignored for
     undirected graphs.

`unconn':
     What to do if the graph is not connected. If `TRUE' the longest
     geodesic within a component will be returned, otherwise
     `IGRAPH_INFINITY' is returned.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V||E|*log|E|), |V| is the number of vertices,
|E| is the number of edges.

10.2.12 igraph_girth -- The girth of a graph is the length of the shortest circle in it.
----------------------------------------------------------------------------------------

     int igraph_girth(const igraph_t *graph, igraph_integer_t *girth,
     		 igraph_vector_t *circle);

   The current implementation works for undirected graphs only,
directed graphs are treated as undirected graphs. Loop edges and
multiple edges are ignored.

   If the graph is a forest (ie. acyclic), then zero is returned.

   This implementation is based on Alon Itai and Michael Rodeh: Finding
a minimum circuit in a graph _ Proceedings of the ninth annual ACM
symposium on Theory of computing _, 1-10, 1977. The first
implementation of this function was done by Keith Briggs, thanks Keith.

   *Arguments:. *

`graph':
     The input graph.

`girth':
     Pointer to an integer, if not `NULL' then the result will be
     stored here.

`circle':
     Pointer to an initialized vector, the vertex ids in the shortest
     circle will be stored here. If `NULL' then it is ignored.

   *Returns:. *

`'
     Error code.

   Time complexity: O((|V|+|E|)^2), |V| is the number of vertices, |E|
is the number of edges in the general case. If the graph has no circles
at all then the function needs O(|V|+|E|) time to realize this and then
it stops.

10.3 Neighborhood of a vertex
=============================

10.3.1 igraph_neighborhood_size -- Calculates the size of the neighborhood of a given vertex
--------------------------------------------------------------------------------------------

     int igraph_neighborhood_size(const igraph_t *graph, igraph_vector_t *res,
     			     igraph_vs_t vids, igraph_integer_t order,
     			     igraph_neimode_t mode);

   The neighborhood of a given order of a vertex includes all vertices
which are closer to the vertex than the order. Ie. order 0 is always
the vertex itself, order 1 is the vertex plus its immediate neighbors,
order 2 is order 1 plus the immediate neighbors of the vertices in
order 1, etc.

   This function calculates the size of the neighborhood of the given
order for the given vertices.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to an initialized vector, the result will be stored here.
     It will be resized as needed.

`vids':
     The vertices for which the calculation is performed.

`order':
     Integer giving the order of the neighborhood.

`mode':
     Specifies how to use the direction of the edges if a directed
     graph is analyzed. For `IGRAPH_OUT' only the outgoing edges are
     followed, so all vertices reachable from the source vertex in at
     most `order' steps are counted. For `IGRAPH_IN' all vertices from
     which the source vertex is reachable in at most `order' steps are
     counted. `IGRAPH_ALL' ignores the direction of the edges. This
     argument is ignored for undirected graphs.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_neighborhood()' (see igraph_neighborhood --- Calculate the neighborhood of vertices)
     for calculating the actual
     neighborhood, `igraph_neighborhood_graphs()' (see
     igraph_neighborhood_graphs --- Create graphs from the neighborhood[s] of some vertex/vertices)
     for creating separate
     graphs from the neighborhoods.

   Time complexity: O(n*d*o), where n is the number vertices for which
the calculation is performed, d is the average degree, o is the order.

10.3.2 igraph_neighborhood -- Calculate the neighborhood of vertices
--------------------------------------------------------------------

     int igraph_neighborhood(const igraph_t *graph, igraph_vector_ptr_t *res,
     			igraph_vs_t vids, igraph_integer_t order,
     			igraph_neimode_t mode);

   The neighborhood of a given order of a vertex includes all vertices
which are closer to the vertex than the order. Ie. order 0 is always
the vertex itself, order 1 is the vertex plus its immediate neighbors,
order 2 is order 1 plus the immediate neighbors of the vertices in
order 1, etc.

   This function calculates the vertices within the neighborhood of the
specified vertices.

   *Arguments:. *

`graph':
     The input graph.

`res':
     An initialized pointer vector. Note that the objects (pointers) in
     the vector will _not_ be freed, but the pointer vector will be
     resized as needed. The result of the calculation will be stored
     here in `vector_t' objects.

`vids':
     The vertices for which the calculation is performed.

`order':
     Integer giving the order of the neighborhood.

`mode':
     Specifies how to use the direction of the edges if a directed
     graph is analyzed. For `IGRAPH_OUT' only the outgoing edges are
     followed, so all vertices reachable from the source vertex in at
     most `order' steps are included. For `IGRAPH_IN' all vertices from
     which the source vertex is reachable in at most `order' steps are
     included. `IGRAPH_ALL' ignores the direction of the edges. This
     argument is ignored for undirected graphs.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_neighborhood_size()' (see igraph_neighborhood_size --- Calculates the size of the neighborhood of a given vertex)
     to
     calculate the size of the neighborhood,
     `igraph_neighborhood_graphs()' (*note igraph_neighborhood_graphs
     --- Create graphs from the neighborhood[s] of some
     vertex/vertices::) for creating graphs from the neighborhoods.

   Time complexity: O(n*d*o), n is the number of vertices for which the
calculation is performed, d is the average degree, o is the order.

10.3.3 igraph_neighborhood_graphs -- Create graphs from the neighborhood(s) of some vertex/vertices
---------------------------------------------------------------------------------------------------

     int igraph_neighborhood_graphs(const igraph_t *graph, igraph_vector_ptr_t *res,
     			       igraph_vs_t vids, igraph_integer_t order,
     			       igraph_neimode_t mode);

   The neighborhood of a given order of a vertex includes all vertices
which are closer to the vertex than the order. Ie. order 0 is always
the vertex itself, order 1 is the vertex plus its immediate neighbors,
order 2 is order 1 plus the immediate neighbors of the vertices in
order 1, etc.

   This function finds every vertex in the neighborhood of a given
parameter vertex and creates a graph from these vertices.

   The first version of this function was written by Vincent Matossian,
thanks Vincent.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to a pointer vector, the result will be stored here, ie.
     `res' will contain pointers to `igraph_t' objects. It will be
     resized if needed but note that the objects in the pointer vector
     will not be freed.

`vids':
     The vertices for which the calculation is performed.

`order':
     Integer giving the order of the neighborhood.

`mode':
     Specifies how to use the direction of the edges if a directed
     graph is analyzed. For `IGRAPH_OUT' only the outgoing edges are
     followed, so all vertices reachable from the source vertex in at
     most `order' steps are counted. For `IGRAPH_IN' all vertices from
     which the source vertex is reachable in at most `order' steps are
     counted. `IGRAPH_ALL' ignores the direction of the edges. This
     argument is ignored for undirected graphs.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_neighborhood_size()' (see igraph_neighborhood_size --- Calculates the size of the neighborhood of a given vertex)
     for
     calculating the neighborhood sizes only, `igraph_neighborhood()'
     (see igraph_neighborhood --- Calculate the neighborhood of vertices)
     for calculating the neighborhoods (but not creating
     graphs).

   Time complexity: O(n*(|V|+|E|)), where n is the number vertices for
which the calculation is performed, |V| and |E| are the number of
vertices and edges in the original input graph.

10.4 Graph Components
=====================

10.4.1 igraph_subcomponent -- The vertices in the same component as a given vertex.
-----------------------------------------------------------------------------------

     int igraph_subcomponent(const igraph_t *graph, igraph_vector_t *res, igraph_real_t vertex,
     			igraph_neimode_t mode);

   *Arguments:. *

`graph':
     The graph object.

`res':
     The result, vector with the ids of the vertices in the same
     component.

`vertex':
     The id of the vertex of which the component is searched.

`mode':
     Type of the component for directed graphs, possible values:

    `IGRAPH_OUT '
          the set of vertices reachable _from_ the `vertex',

    `IGRAPH_IN'
          the set of vertices from which the `vertex' is reachable.

    `IGRAPH_ALL '
          the graph is considered as an undirected graph. Note that
          this is _not_ the same as the union of the previous two.

   *Returns:. *

`'
     Error code:

    `IGRAPH_ENOMEM '
          not enough memory for temporary data.

    `IGRAPH_EINVVID '
          `vertex' is an invalid vertex id

    `IGRAPH_EINVMODE'
          invalid mode argument passed.

   Time complexity: O(|V|+|E|), |V| and |E| are the number of vertices
and edges in the graph.

   *See also:. *

`'
     `igraph_subgraph()' (see igraph_subgraph --- Creates a subgraph with the specified vertices_)
     if you want a graph object
     consisting only a given set of vertices and the edges between them.

10.4.2 igraph_subgraph -- Creates a subgraph with the specified vertices.
-------------------------------------------------------------------------

     int igraph_subgraph(const igraph_t *graph, igraph_t *res,
     		    const igraph_vs_t vids);

   This function collects the specified vertices and all edges between
them to a new graph.  As the vertex ids in a graph always start with
zero, this function very likely needs to reassign ids to the vertices.

   *Arguments:. *

`graph':
     The graph object.

`res':
     The subgraph, another graph object will be stored here, do _not_
     initialize this object before calling this function, and call
     `igraph_destroy()' (see igraph_destroy --- Frees the memory allocated for a graph object_)
     on it if you don't need it any
     more.

`vids':
     Vector with the vertex ids to put in the subgraph.

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM', not enough memory for temporary data.
     `IGRAPH_EINVVID', invalid vertex id in `vids'.

   Time complexity: O(|V|+|E|), |V| and |E| are the number of vertices
and edges in the original graph.

   *See also:. *

`'
     `igraph_delete_vertices()' (see igraph_delete_vertices --- Removes vertices [with all their edges] from the graph_)
     to
     delete the specified set of vertices from a graph, the opposite of
     this function.

10.4.3 igraph_clusters -- Calculates the (weakly or strongly) connected components in a graph.
----------------------------------------------------------------------------------------------

     int igraph_clusters(const igraph_t *graph, igraph_vector_t *membership,
     		    igraph_vector_t *csize, igraph_integer_t *no,
     		    igraph_connectedness_t mode);

   *Arguments:. *

`graph':
     The graph object to analyze.

`membership':
     First half of the result will be stored here. For every vertex the
     id of its component is given. The vector has to be preinitialized
     and will be resized. Alternatively this argument can be `NULL', in
     which case it is ignored.

`csize':
     The second half of the result. For every component it gives its
     size, the order is defined by the component ids.  The vector has
     to be preinitialized and will be resized.  Alternatively this
     argument can be `NULL', in which case it is ignored.

`no':
     Pointer to an integer, if not `NULL' then the number of clusters
     will be stored here.

`mode':
     For directed graph this specifies whether to calculate weakly or
     strongly connected components. Possible values: `IGRAPH_WEAK',
     `IGRAPH_STRONG'. This argument is ignored for undirected graphs.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVAL': invalid mode argument.

   Time complexity: O(|V|+|E|), |V| and |E| are the number of vertices
and edges in the graph.

10.4.4 igraph_is_connected -- Decides whether the graph is (weakly or strongly) connected.
------------------------------------------------------------------------------------------

     int igraph_is_connected(const igraph_t *graph, igraph_bool_t *res,
     			igraph_connectedness_t mode);

   *Arguments:. *

`graph':
     The graph object to analyze.

`res':
     Pointer to a logical variable, the result will be stored here.

`mode':
     For directed graph this specifies whether to calculate weak or
     strong connectedness. Possible values: `IGRAPH_WEAK',
     `IGRAPH_STRONG'. This argument is igrored for undirected graphs.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVAL': invalid mode argument.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges in the graph.

10.4.5 igraph_decompose -- Decompose a graph into connected components.
-----------------------------------------------------------------------

     int igraph_decompose(const igraph_t *graph, igraph_vector_ptr_t *components,
     		     igraph_connectedness_t mode,
     		     long int maxcompno, long int minelements);

   Create separate graph for each component of a graph. Note that the
vertex ids in the new graphs will be different than in the original
graph. (Except if there is only one component in the original graph.)

   *Arguments:. *

`graph':
     The original graph.

`components':
     This pointer vector will contain pointers to the subcomponent
     graphs. It should be initialized before calling this function and
     will be resized to hold the graphs. Don't forget to call
     `igraph_destroy()' (see igraph_destroy --- Frees the memory allocated for a graph object_)
     and free() on the elements of
     this pointer vector to free unneeded memory. Alternatively, you can
     simply call `igraph_decompose_destroy()' (see
     igraph_decompose_destroy --- Free the memory allocated by igraph_decompose[])
     that does this for you.

`mode':
     Either `IGRAPH_WEAK' or `IGRAPH_STRONG' for weakly and strongly
     connected components respectively. Right now only the former is
     implemented.

`maxcompno':
     The maximum number of components to return. The first `maxcompno'
     components will be returned (which hold at least `minelements'
     vertices, see the next parameter), the others will be ignored.
     Supply -1 here if you don't want to limit the number of components.

`minelements':
     The minimum number of vertices a component should contain in order
     to place it in the `components' vector. Eg. supply 2 here to
     ignore isolate vertices.

   *Returns:. *

`'
     Error code, `IGRAPH_ENOMEM' if there is not enough memory to
     perform the operation.

   Added in version 0.2.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges.

10.4.6 igraph_decompose_destroy -- Free the memory allocated by `igraph_decompose()'
------------------------------------------------------------------------------------

     void igraph_decompose_destroy(igraph_vector_ptr_t *complist);

   *Arguments:. *

`complist':
     The list of graph components, as returned by `igraph_decompose()'
     (see igraph_decompose --- Decompose a graph into connected components_).

   Time complexity: O(c), c is the number of components.

10.4.7 igraph_biconnected_components -- Calculate biconnected components
------------------------------------------------------------------------

     int igraph_biconnected_components(const igraph_t *graph,
     				  igraph_integer_t *no,
     				  igraph_vector_ptr_t *components,
     				  igraph_vector_t *articulation_points);

   A graph is biconnected if the removal of any single vertex (and its
adjacent edges) does not disconnect it.

   A biconnected component of a graph is a maximal biconnected subgraph
of it. The biconnected components of a graph can be given by the
partition of its edges: every edge is a member of exactly one
biconnected component. Note that this is not true for vertices: the
same vertex can be part of many biconnected components.

   *Arguments:. *

`graph':
     The input graph

`no':
     The number of biconnected components will be stored here.

`components':
     If not a NULL points, then the found components are stored here,
     in a list of vectors. Every vector in the list is a biconnected
     component, represented by its edges. More precisely, a spanning
     tree of the biconnected component is returned.  Note you'll have to
     destroy each vector first by calling `igraph_vector_destroy()'
     (see igraph_vector_destroy --- Destroys a vector object_) and
     then ` free()'  on it, plus you need to call
     `igraph_vector_ptr_destroy()' (see igraph_vector_ptr_destroy --- Destroys a pointer vector_)
     on the list to regain all allocated
     memory.

`articulation_points':
     If not a NULL pointer, then the articulation points of the graph
     are stored in this vector.  A vertex is an articulation point if
     its removal increases the number of (weakly) connected components
     in the graph.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), linear in the number of vertices and
edges.

   *See also:. *

`'
     `igraph_articulation_points()' (see igraph_articulation_points --- Find the articulation points in a graph_),
     `igraph_clusters()' (see igraph_clusters --- Calculates the [weakly or strongly] connected components in a graph_).

10.4.8 igraph_articulation_points -- Find the articulation points in a graph.
-----------------------------------------------------------------------------

     int igraph_articulation_points(const igraph_t *graph,
     			       igraph_vector_t *res);

   A vertex is an articulation point if its removal increases the
number of connected components in the graph.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to an initialized vector, the articulation points will be
     stored here.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), linear in the number of vertices and
edges.

   *See also:. *

`'
     `igraph_biconnected_components()' (see
     igraph_biconnected_components --- Calculate biconnected components),
     `igraph_clusters()' (*note igraph_clusters ---
     Calculates the [weakly or strongly] connected components in a
     graph_::)

10.5 Centrality Measures
========================

10.5.1 igraph_closeness -- Closeness centrality calculations for some vertices.
-------------------------------------------------------------------------------

     int igraph_closeness(const igraph_t *graph, igraph_vector_t *res,
                          const igraph_vs_t vids, igraph_neimode_t mode);

   The closeness centrality of a vertex measures how easily other
vertices can be reached from it (or the other way: how easily it can be
reached from the other vertices). It is defined as the number of the
number of vertices minus one divided by the sum of the lengths of all
geodesics from/to the given vertex.

   If the graph is not connected, and there is no path between two
vertices, the number of vertices is used instead the length of the
geodesic. This is always longer than the longest possible geodesic.

   *Arguments:. *

`graph':
     The graph object.

`res':
     The result of the computation, a vector containing the closeness
     centrality scores for the given vertices.

`vids':
     Vector giving the vertices for which the closeness centrality
     scores will be computed.

`mode':
     The type of shortest paths to be used for the calculation in
     directed graphs. Possible values:

    `IGRAPH_OUT '
          the lengths of the outgoing paths are calculated.

    `IGRAPH_IN '
          the lengths of the incoming paths are calculated.

    `IGRAPH_ALL'
          the directed graph is considered as an undirected one for the
          computation.

   *Returns:. *

`'
     Error code:

    `IGRAPH_ENOMEM'
          not enough memory for temporary data.

    `IGRAPH_EINVVID'
          invalid vertex id passed.

    `IGRAPH_EINVMODE'
          invalid mode argument.

   Time complexity: O(n|E|), n is the number of vertices for which the
calculation is done and |E| is the number of edges in the graph.

   *See also:. *

`'
     Other centrality types: `igraph_degree()' (see igraph_degree --- The degree of some vertices in a graph_),
     `igraph_betweenness()'
     (see igraph_betweenness --- Betweenness centrality of some vertices_).
     See `igraph_closeness_estimate()' (see
     igraph_closeness_estimate --- Closeness centrality estimations for some vertices_)
     to estimate closeness values.

10.5.2 igraph_betweenness -- Betweenness centrality of some vertices.
---------------------------------------------------------------------

     int igraph_betweenness(const igraph_t *graph, igraph_vector_t *res,
       const igraph_vs_t vids, igraph_bool_t directed);

   The betweenness centrality of a vertex is the number of geodesics
going through it. If there are more than one geodesic between two
vertices, the value of these geodesics are weighted by one over the
number of geodesics.

   *Arguments:. *

`graph':
     The graph object.

`res':
     The result of the computation, a vector containing the betweenness
     scores for the specified vertices.

`vids':
     The vertices of which the betweenness centrality scores will be
     calculated.

`directed':
     Logical, if true directed paths will be considered for directed
     graphs. It is ignored for undirected graphs.

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM', not enough memory for temporary data.
     `IGRAPH_EINVVID', invalid vertex id passed in `vids'.

   Time complexity: O(|V||E|), |V| and |E| are the number of vertices
and edges in the graph.  Note that the time complexity is independent
of the number of vertices for which the score is calculated.

   *See also:. *

`'
     Other centrality types: `igraph_degree()' (see igraph_degree --- The degree of some vertices in a graph_),
     `igraph_closeness()'
     (see igraph_closeness --- Closeness centrality calculations for some vertices_).
     See `igraph_edge_betweenness()' (see
     igraph_edge_betweenness --- Betweenness centrality of the edges_)
     for calculating the betweenness score of the edges in a
     graph. See `igraph_betweenness_estimate()' (see
     igraph_betweenness_estimate --- Estimated betweenness centrality of some vertices_)
     to estimate the betweenness score of the
     vertices in a graph.

10.5.3 igraph_edge_betweenness -- Betweenness centrality of the edges.
----------------------------------------------------------------------

     int igraph_edge_betweenness(const igraph_t *graph, igraph_vector_t *result,
                                 igraph_bool_t directed);

   The betweenness centrality of an edge is the number of geodesics
going through it. If there are more than one geodesics between two
vertices, the value of these geodesics are weighted by one over the
number of geodesics.

   *Arguments:. *

`graph':
     The graph object.

`result':
     The result of the computation, vector containing the betweenness
     scores for the edges.

`directed':
     Logical, if true directed paths will be considered for directed
     graphs. It is ignored for undirected graphs.

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM', not enough memory for temporary data.

   Time complexity: O(|V||E|), |V| and |E| are the number of vertices
and edges in the graph.

   *See also:. *

`'
     Other centrality types: `igraph_degree()' (see igraph_degree --- The degree of some vertices in a graph_),
     `igraph_closeness()'
     (see igraph_closeness --- Closeness centrality calculations for some vertices_).
     See `igraph_edge_betweenness()' (see
     igraph_edge_betweenness --- Betweenness centrality of the edges_)
     for calculating the betweenness score of the edges in a
     graph. See `igraph_edge_betweenness_estimate()' (see
     igraph_edge_betweenness_estimate --- Estimated betweenness centrality of the edges_)
     to estimate the betweenness score of
     the edges in a graph.

10.5.4 igraph_pagerank -- Calculates the Google PageRank for the specified vertices.
------------------------------------------------------------------------------------

     int igraph_pagerank(const igraph_t *graph, igraph_vector_t *vector,
     		    igraph_real_t *value, const igraph_vs_t vids,
     		    igraph_bool_t directed, igraph_real_t damping,
     		    const igraph_vector_t *weights,
     		    igraph_arpack_options_t *options);

   This is the new PageRank implementation, based on the ARPACK
library. The old, power-method based implementation can be used as
well, it is kept under the name `igraph_pagerank_old()' (see
igraph_pagerank_old --- Calculates the Google PageRank for the specified vertices_).

   Please note that the PageRank of a given vertex depends on the
PageRank of all other vertices, so even if you want to calculate the
PageRank for only some of the vertices, all of them must be calculated.
Requesting the PageRank for only some of the vertices does not result
in any performance increase at all.

   Since the calculation is an iterative process, the algorithm is
stopped after a given count of iterations or if the PageRank value
differences between iterations are less than a predefined value.

   For the explanation of the PageRank algorithm, see the following
webpage: http://www-db.stanford.edu/~backrub/google.html, or the
following reference:

   Sergey Brin and Larry Page: The Anatomy of a Large-Scale Hypertextual
Web Search Engine. Proceedings of the 7th World-Wide Web Conference,
Brisbane, Australia, April 1998.

   *Arguments:. *

`graph':
     The graph object.

`vector':
     Pointer to an initialized vector, the result is stored here. It is
     resized as needed.

`value':
     Pointer to a real variable, the eigenvalue corresponding to the
     PageRank vector is stored here. It should be always exactly one.

`vids':
     The vertex ids for which the PageRank is returned.

`directed':
     Boolean, whether to consider the directedness of the edges. This
     is ignored for undirected graphs.

`damping':
     The damping factor ("d" in the original paper)

`weights':
     Optional edge weights, it is either a null pointer, then the edges
     are not weighted, or a vector of the same length as the number of
     edges.

`options':
     Options to ARPACK. See `igraph_arpack_options_t' (see
     igraph_arpack_options_t --- Options for ARPACK) for details.
     Note that the function overwrites the ` n'  (number of vertices),
     ` nev'  (1), ` ncv'  (3) and ` which'  (LM) parameters and it
     always starts the calculation from a non-random vector calculated
     based on the degree of the vertices.

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM', not enough memory for temporary data.
     `IGRAPH_EINVVID', invalid vertex id in `vids'.

   Time complexity: TODO.

   *See also:. *

`'
     `igraph_pagerank_old()' (see igraph_pagerank_old --- Calculates the Google PageRank for the specified vertices_)
     for the old
     implementation, `igraph_arpack_rssolve()' (see
     igraph_arpack_rssolve --- ARPACK solver for symmetric matrices)
     and `igraph_arpack_rnsolve()' (see igraph_arpack_rnsolve --- ARPACK solver for non-symmetric matrices)
     for the underlying
     machinery.

10.5.5 igraph_pagerank_old -- Calculates the Google PageRank for the specified vertices.
----------------------------------------------------------------------------------------

     int igraph_pagerank_old(const igraph_t *graph, igraph_vector_t *res,
     			const igraph_vs_t vids, igraph_bool_t directed,
     			igraph_integer_t niter, igraph_real_t eps,
     			igraph_real_t damping, igraph_bool_t old);

   This is an old implementation, it is provided for compatibility with
igraph versions earlier than 0.5. Please use the new implementation
`igraph_pagerank()' (see igraph_pagerank --- Calculates the Google PageRank for the specified vertices_)
in new projects.

   Please note that the PageRank of a given vertex depends on the
PageRank of all other vertices, so even if you want to calculate the
PageRank for only some of the vertices, all of them must be calculated.
Requesting the PageRank for only some of the vertices does not result
in any performance increase at all.

   Since the calculation is an iterative process, the algorithm is
stopped after a given count of iterations or if the PageRank value
differences between iterations are less than a predefined value.

   For the explanation of the PageRank algorithm, see the following
webpage: http://www-db.stanford.edu/~backrub/google.html, or the
following reference:

   Sergey Brin and Larry Page: The Anatomy of a Large-Scale Hypertextual
Web Search Engine. Proceedings of the 7th World-Wide Web Conference,
Brisbane, Australia, April 1998.

   *Arguments:. *

`graph':
     The graph object.

`res':
     The result vector containing the PageRank values for the given
     nodes.

`vids':
     Vector with the vertex ids

`directed':
     Logical, if true directed paths will be considered for directed
     graphs. It is ignored for undirected graphs.

`niter':
     The maximum number of iterations to perform

`eps':
     The algorithm will consider the calculation as complete if the
     difference of PageRank values between iterations change less than
     this value for every node

`damping':
     The damping factor ("d" in the original paper)

`old':
     Boolean, whether to use the pre-igraph 0.5 way to calculate page
     rank. Not recommended for new applications, only included for
     compatibility. If this is non-zero then the damping factor is not
     divided by the number of vertices before adding it to the weighted
     page rank scores to calculate the new scores. I.e. the formula in
     the original PageRank paper is used. Furthermore, if this is
     non-zero then the PageRank vector is renormalized after each
     iteration.

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM', not enough memory for temporary data.
     `IGRAPH_EINVVID', invalid vertex id in `vids'.

   Time complexity: O(|V|+|E|) per iteration. A handful iterations
should be enough. Note that if the old-style dumping is used then the
iteration might not converge at all.

   *See also:. *

`'
     `igraph_pagerank()' (see igraph_pagerank --- Calculates the Google PageRank for the specified vertices_)
     for the new
     implementation.

10.5.6 igraph_constraint -- Burt's constraint scores
----------------------------------------------------

     int igraph_constraint(const igraph_t *graph, igraph_vector_t *res,
     		      igraph_vs_t vids, const igraph_vector_t *weights);

   This function calculates Burt's constraint scores for the given
vertices, also known as structural holes.

   Burt's constraint is higher if ego has less, or mutually stronger
related (i.e. more redundant) contacts. Burt's measure of constraint,
C[i], of vertex i's ego network V[i], is defined for directed and
valued graphs,

     C[i] = sum( sum( (p[i,q] p[q,j])^2, q in V[i], q != i,j ), j in
     V[], j != i)

for a graph of order (ie. number od vertices) N, where proportional tie
strengths are defined as

     p[i,j]=(a[i,j]+a[j,i]) / sum(a[i,k]+a[k,i], k in V[i], k != i),

a[i,j] are elements of A and the latter being the graph adjacency
matrix. For isolated vertices, constraint is undefined.

   Burt, R.S. (2004). Structural holes and good ideas. American Journal
of Sociology 110, 349-399.

   The first R version of this function was contributed by Jeroen
Bruggeman.

   *Arguments:. *

`graph':
     A graph object.

`res':
     Pointer to an initialized vector, the result will be stored here.
     The vector will be resized to have the appropriate size for
     holding the result.

`vids':
     Vertex selector containing the vertices for which the constraint
     should be calculated.

`weights':
     Vector giving the weights of the edges. If it is `NULL' then each
     edge is supposed to have the same weight.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+E|+n*d^2), n is the number of vertices for
which the constraint is calculated and d is the average degree, |V| is
the number of vertices, |E| the number of edges in the graph. If the
weights argument is `NULL' then the time complexity is O(|V|+n*d^2).

10.5.7 igraph_maxdegree -- Calculate the maximum degree in a graph (or set of vertices).
----------------------------------------------------------------------------------------

     int igraph_maxdegree(const igraph_t *graph, igraph_integer_t *res,
     		     igraph_vs_t vids, igraph_neimode_t mode,
     		     igraph_bool_t loops);

   The largest in-, out- or total degree of the specified vertices is
calculated.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to an integer (`igraph_integer_t'), the result will be
     stored here.

`mode':
     Defines the type of the degree.  `IGRAPH_OUT', out-degree,
     `IGRAPH_IN', in-degree, `IGRAPH_ALL', total degree (sum of the in-
     and out-degree).  This parameter is ignored for undirected graphs.

`loops':
     Boolean, gives whether the self-loops should be counted.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVVID': invalid vertex id.
     `IGRAPH_EINVMODE': invalid mode argument.

   Time complexity: O(v) if loops is TRUE, and O(v*d) otherwise. v is
the number vertices for which the degree will be calculated, and d is
their (average) degree.

10.5.8 igraph_strength -- Strength of the vertices, weighted vertex degree in other words
-----------------------------------------------------------------------------------------

     int igraph_strength(const igraph_t *graph, igraph_vector_t *res,
     		    const igraph_vs_t vids, igraph_neimode_t mode,
     		    igraph_bool_t loops, const igraph_vector_t *weights);

   In an weighted network the strength of a vertex is the sum of the
weights of all adjacent edges. In a non-weighted networks this is
exactly the vertex degree.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to an initialized vector, the result is stored here. It
     will be resized as needed.

`vids':
     The vertices for which the calculation is performed.

`mode':
     Gives whether to count only outgoing (`IGRAPH_OUT'), incoming
     (`IGRAPH_IN') edges or both (`IGRAPH_ALL').

`loops':
     A logical scalar, whether to count loop edges as well.

`weights':
     A vector giving the edge weights. If this is a NULL pointer, then
     `igraph_degree()' (see igraph_degree --- The degree of some vertices in a graph_)
     is called to perform the calculation.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), linear in the number vertices and edges.

   *See also:. *

`'
     `igraph_degree()' (see igraph_degree --- The degree of some vertices in a graph_)
     for the traditional, non-weighted version.

10.5.9 igraph_eigenvector_centrality -- Eigenvector centrality of the verices
-----------------------------------------------------------------------------

     int igraph_eigenvector_centrality(const igraph_t *graph, igraph_vector_t *vector,
     				  igraph_real_t *value, igraph_bool_t scale,
     				  const igraph_vector_t *weights,
     				  igraph_arpack_options_t *options);

   Eigenvector centrality is a measure of the importance of a node in a
network. It assigns relative scores to all nodes in the network based
on the principle that connections to high-scoring nodes contribute more
to the score of the node in question than equal connections to
low-scoring nodes.

   *Arguments:. *

`graph':
     The input graph. It might be directed, but it will be treated as
     undirected anyway.

`vector':
     Pointer to an initialized vector, it will be resized as needed.
     The result of the computation is stored here. It can be a null
     pointer, then it is ignored.

`value':
     If not a null pointer, then the eigenvalue corresponding to the
     found eigenvector is stored here.

`scale':
     If not zero then the result will be scaled, such that the absolute
     value of the maximum centrality is one.

`weights':
     A null pointer (=no edge weights), or a vector giving the weights
     of the edges.

`options':
     Options to ARPACK. See `igraph_arpack_options_t' (see
     igraph_arpack_options_t --- Options for ARPACK) for details.
     Note that the function overwrites the ` n'  (number of vertices)
     parameter and it always starts the calculation from a non-random
     vector calculated based on the degree of the vertices.

   *Returns:. *

`'
     Error code.

   Time complexity: depends on the input graph, usually it is O(|V|),
the number of vertices.

   *See also:. *

`'
     `igraph_pagerank' (see igraph_pagerank --- Calculates the Google PageRank for the specified vertices_)
     for a modification of
     eigenvector centrality.

10.5.10 igraph_hub_score -- Kleinberg's hub scores
--------------------------------------------------

     int igraph_hub_score(const igraph_t *graph, igraph_vector_t *vector,
     		     igraph_real_t *value, igraph_bool_t scale,
     		     igraph_arpack_options_t *options);

   The hub scores of the vertices are defined as the principal
eigenvector of ` A*A^T' , where ` A'  is the adjacency matrix of the
graph, ` A^T'  is its transposed.

   See the following reference on the meaning of this score: J.
Kleinberg. Authoritative sources in a hyperlinked environment. _ Proc.
9th ACM-SIAM Symposium on Discrete Algorithms, _ 1998. Extended version
in _ Journal of the ACM _ 46(1999). Also appears as IBM Research Report
RJ 10076, May 1997.

   *Arguments:. *

`graph':
     The input graph. Can be directed and undirected.

`vector':
     Pointer to an initialized vector, the result is stored here. If a
     null pointer then it is ignored.

`value':
     If not a null pointer then the eigenvalue corresponding to the
     calculated eigenvector is stored here.

`scale':
     If not zero then the result will be scaled, such that the absolute
     value of the maximum centrality is one.

`options':
     Options to ARPACK. See `igraph_arpack_options_t' (see
     igraph_arpack_options_t --- Options for ARPACK) for details.
     Note that the function overwrites the ` n'  (number of vertices)
     parameter and it always starts the calculation from a non-random
     vector calculated based on the degree of the vertices.

   *Returns:. *

`'
     Error code.

   Time complexity: depends on the input graph, usually it is O(|V|),
the number of vertices.

   *See also:. *

`'
     `igraph_authority_score()' (see igraph_authority_score --- Kleinerg's authority scores)
     for the companion measure,
     `igraph_pagerank()' (see igraph_pagerank --- Calculates the Google PageRank for the specified vertices_),
     `igraph_eigenvector_centrality()' (see
     igraph_eigenvector_centrality --- Eigenvector centrality of the verices)
     for similar measures.

10.5.11 igraph_authority_score -- Kleinerg's authority scores
-------------------------------------------------------------

     int igraph_authority_score(const igraph_t *graph, igraph_vector_t *vector,
     			   igraph_real_t *value, igraph_bool_t scale,
     			   igraph_arpack_options_t *options);

   The authority scores of the vertices are defined as the principal
eigenvector of ` A^T*A' , where ` A'  is the adjacency matrix of the
graph, ` A^T'  is its transposed.

   See the following reference on the meaning of this score: J.
Kleinberg. Authoritative sources in a hyperlinked environment. _ Proc.
9th ACM-SIAM Symposium on Discrete Algorithms, _ 1998. Extended version
in _ Journal of the ACM _ 46(1999). Also appears as IBM Research Report
RJ 10076, May 1997.

   *Arguments:. *

`graph':
     The input graph. Can be directed and undirected.

`vector':
     Pointer to an initialized vector, the result is stored here. If a
     null pointer then it is ignored.

`value':
     If not a null pointer then the eigenvalue corresponding to the
     calculated eigenvector is stored here.

`scale':
     If not zero then the result will be scaled, such that the absolute
     value of the maximum centrality is one.

`options':
     Options to ARPACK. See `igraph_arpack_options_t' (see
     igraph_arpack_options_t --- Options for ARPACK) for details.
     Note that the function overwrites the ` n'  (number of vertices)
     parameter and it always starts the calculation from a non-random
     vector calculated based on the degree of the vertices.

   *Returns:. *

`'
     Error code.

   Time complexity: depends on the input graph, usually it is O(|V|),
the number of vertices.

   *See also:. *

`'
     `igraph_hub_score()' (see igraph_hub_score --- Kleinberg's hub scores)
     for the companion measure, `igraph_pagerank()' (see
     igraph_pagerank --- Calculates the Google PageRank for the specified vertices_),
     `igraph_eigenvector_centrality()' (see
     igraph_eigenvector_centrality --- Eigenvector centrality of the verices)
     for similar measures.

10.6 Estimating Centrality Measures
===================================

10.6.1 igraph_closeness_estimate -- Closeness centrality estimations for some vertices.
---------------------------------------------------------------------------------------

     int igraph_closeness_estimate(const igraph_t *graph, igraph_vector_t *res,
     		              const igraph_vs_t vids, igraph_neimode_t mode,
                                   igraph_integer_t cutoff);

   The closeness centrality of a vertex measures how easily other
vertices can be reached from it (or the other way: how easily it can be
reached from the other vertices). It is defined as the number of the
number of vertices minus one divided by the sum of the lengths of all
geodesics from/to the given vertex. When estimating closeness
centrality, igraph considers paths having a length less than or equal
to a prescribed cutoff value.

   If the graph is not connected, and there is no such path between two
vertices, the number of vertices is used instead the length of the
geodesic. This is always longer than the longest possible geodesic.

   Since the estimation considers vertex pairs with a distance greater
than the given value as disconnected, the resulting estimation will
always be lower than the actual closeness centrality.

   *Arguments:. *

`graph':
     The graph object.

`res':
     The result of the computation, a vector containing the closeness
     centrality scores for the given vertices.

`vids':
     Vector giving the vertices for which the closeness centrality
     scores will be computed.

`mode':
     The type of shortest paths to be used for the calculation in
     directed graphs. Possible values:

    `IGRAPH_OUT '
          the lengths of the outgoing paths are calculated.

    `IGRAPH_IN '
          the lengths of the incoming paths are calculated.

    `IGRAPH_ALL'
          the directed graph is considered as an undirected one for the
          computation.

`cutoff':
     The maximal length of paths that will be considered.  If zero or
     negative, the exact closeness will be calculated (no upper limit
     on path lengths).

   *Returns:. *

`'
     Error code:

    `IGRAPH_ENOMEM'
          not enough memory for temporary data.

    `IGRAPH_EINVVID'
          invalid vertex id passed.

    `IGRAPH_EINVMODE'
          invalid mode argument.

   Time complexity: O(n|E|), n is the number of vertices for which the
calculation is done and |E| is the number of edges in the graph.

   *See also:. *

`'
     Other centrality types: `igraph_degree()' (see igraph_degree --- The degree of some vertices in a graph_),
     `igraph_betweenness()'
     (see igraph_betweenness --- Betweenness centrality of some vertices_).

10.6.2 igraph_betweenness_estimate -- Estimated betweenness centrality of some vertices.
----------------------------------------------------------------------------------------

     int igraph_betweenness_estimate(const igraph_t *graph, igraph_vector_t *res,
     			const igraph_vs_t vids, igraph_bool_t directed,
                             igraph_integer_t cutoff);

   The betweenness centrality of a vertex is the number of geodesics
going through it. If there are more than one geodesic between two
vertices, the value of these geodesics are weighted by one over the
number of geodesics. When estimating betweenness centrality, igraph
takes into consideration only those paths that are shorter than or
equal to a prescribed length. Note that the estimated centrality will
always be less than the real one.

   *Arguments:. *

`graph':
     The graph object.

`res':
     The result of the computation, a vector containing the estimated
     betweenness scores for the specified vertices.

`vids':
     The vertices of which the betweenness centrality scores will be
     estimated.

`directed':
     Logical, if true directed paths will be considered for directed
     graphs. It is ignored for undirected graphs.

`cutoff':
     The maximal length of paths that will be considered.  If zero or
     negative, the exact betweenness will be calculated (no upper limit
     on path lengths).

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM', not enough memory for temporary data.
     `IGRAPH_EINVVID', invalid vertex id passed in `vids'.

   Time complexity: O(|V||E|), |V| and |E| are the number of vertices
and edges in the graph.  Note that the time complexity is independent
of the number of vertices for which the score is calculated.

   *See also:. *

`'
     Other centrality types: `igraph_degree()' (see igraph_degree --- The degree of some vertices in a graph_),
     `igraph_closeness()'
     (see igraph_closeness --- Closeness centrality calculations for some vertices_).
     See `igraph_edge_betweenness()' (see
     igraph_edge_betweenness --- Betweenness centrality of the edges_)
     for calculating the betweenness score of the edges in a
     graph.

10.6.3 igraph_edge_betweenness_estimate -- Estimated betweenness centrality of the edges.
-----------------------------------------------------------------------------------------

     int igraph_edge_betweenness_estimate(const igraph_t *graph, igraph_vector_t *result,
                                          igraph_bool_t directed, igraph_integer_t cutoff);

   The betweenness centrality of an edge is the number of geodesics
going through it. If there are more than one geodesics between two
vertices, the value of these geodesics are weighted by one over the
number of geodesics. When estimating betweenness centrality, igraph
takes into consideration only those paths that are shorter than or
equal to a prescribed length. Note that the estimated centrality will
always be less than the real one.

   *Arguments:. *

`graph':
     The graph object.

`result':
     The result of the computation, vector containing the betweenness
     scores for the edges.

`directed':
     Logical, if true directed paths will be considered for directed
     graphs. It is ignored for undirected graphs.

`cutoff':
     The maximal length of paths that will be considered.  If zero or
     negative, the exact betweenness will be calculated (no upper limit
     on path lengths).

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM', not enough memory for temporary data.

   Time complexity: O(|V||E|), |V| and |E| are the number of vertices
and edges in the graph.

   *See also:. *

`'
     Other centrality types: `igraph_degree()' (see igraph_degree --- The degree of some vertices in a graph_),
     `igraph_closeness()'
     (see igraph_closeness --- Closeness centrality calculations for some vertices_).
     See `igraph_betweenness()' (see
     igraph_betweenness --- Betweenness centrality of some vertices_)
     for calculating the betweenness score of the vertices in a graph.

10.7 Similarity Measures
========================

10.7.1 igraph_bibcoupling -- Bibliographic coupling.
----------------------------------------------------

     int igraph_bibcoupling(const igraph_t *graph, igraph_matrix_t *res,
                            const igraph_vs_t vids);

   The bibliographic coupling of two vertices is the number of other
vertices they both cite, `igraph_bibcoupling()' (see
igraph_bibcoupling --- Bibliographic coupling_) calculates this.  The
bibliographic coupling  score for each given vertex and all other
vertices in the graph will be calculated.

   *Arguments:. *

`graph':
     The graph object to analyze.

`res':
     Pointer to a matrix, the result of the calculation will be stored
     here. The number of its rows is the same as the number of vertex
     ids in `vids', the number of columns is the number of vertices in
     the graph.

`vids':
     The vertex ids of the vertices for which the calculation will be
     done.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVVID': invalid vertex id.

   Time complexity: O(|V|d^2), |V| is the number of vertices in the
graph, d is the (maximum) degree of the vertices in the graph.

   *See also:. *

`'
     `igraph_cocitation()' (see igraph_cocitation --- Cocitation coupling_)

10.7.2 igraph_cocitation -- Cocitation coupling.
------------------------------------------------

     int igraph_cocitation(const igraph_t *graph, igraph_matrix_t *res,
                           const igraph_vs_t vids);

   Two vertices are cocited if there is another vertex citing both of
them. `igraph_cocitation()' (see igraph_cocitation --- Cocitation coupling_)
simply counts how many times two vertices are cocited.
The cocitation score for each given vertex and all other vertices in
the graph will be calculated.

   *Arguments:. *

`graph':
     The graph object to analyze.

`res':
     Pointer to a matrix, the result of the calculation will be stored
     here. The number of its rows is the same as the number of vertex
     ids in `vids', the number of columns is the number of vertices in
     the graph.

`vids':
     The vertex ids of the vertices for which the calculation will be
     done.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVVID': invalid vertex id.

   Time complexity: O(|V|d^2), |V| is the number of vertices in the
graph, d is the (maximum) degree of the vertices in the graph.

   *See also:. *

`'
     `igraph_bibcoupling()' (see igraph_bibcoupling --- Bibliographic coupling_)

10.7.3 igraph_similarity_jaccard -- Jaccard similarity coefficient.
-------------------------------------------------------------------

     int igraph_similarity_jaccard(const igraph_t *graph, igraph_matrix_t *res,
         const igraph_vs_t vids, igraph_neimode_t mode, igraph_bool_t loops);

   The Jaccard similarity coefficient of two vertices is the number of
common neighbors divided by the number of vertices that are neighbors
of at least one of the two vertices being considered. This function
calculates the pairwise Jaccard similarities for some (or all) of the
vertices.

   *Arguments:. *

`graph':
     The graph object to analyze

`res':
     Pointer to a matrix, the result of the calculation will be stored
     here. The number of its rows and columns is the same as the number
     of vertex ids in `vids'.

`vids':
     The vertex ids of the vertices for which the calculation will be
     done.

`mode':
     The type of neighbors to be used for the calculation in directed
     graphs. Possible values:

    `IGRAPH_OUT'
          the outgoing edges will be considered for each node.

    `IGRAPH_IN'
          the incoming edges will be considered for each node.

    `IGRAPH_ALL'
          the directed graph is considered as an undirected one for the
          computation.

`loops':
     Whether to include the vertices themselves in the neighbor sets.

   *Returns:. *

`'
     Error code:

    `IGRAPH_ENOMEM'
          not enough memory for temporary data.

    `IGRAPH_EINVVID'
          invalid vertex id passed.

    `IGRAPH_EINVMODE'
          invalid mode argument.

   Time complexity: O(|V|^2 d), |V| is the number of vertices in the
vertex iterator given, d is the (maximum) degree of the vertices in the
graph.

   *See also:. *

`'
     `igraph_similarity_dice()' (see igraph_similarity_dice --- Dice similarity coefficient_),
     a measure very similar to the Jaccard
     coefficient

10.7.4 igraph_similarity_dice -- Dice similarity coefficient.
-------------------------------------------------------------

     int igraph_similarity_dice(const igraph_t *graph, igraph_matrix_t *res,
         const igraph_vs_t vids, igraph_neimode_t mode, igraph_bool_t loops);

   The Dice similarity coefficient of two vertices is twice the number
of common neighbors divided by the sum of the degrees of the vertices.
This function calculates the pairwise Dice similarities for some (or
all) of the vertices.

   *Arguments:. *

`graph':
     The graph object to analyze

`res':
     Pointer to a matrix, the result of the calculation will be stored
     here. The number of its rows and columns is the same as the number
     of vertex ids in `vids'.

`vids':
     The vertex ids of the vertices for which the calculation will be
     done.

`mode':
     The type of neighbors to be used for the calculation in directed
     graphs. Possible values:

    `IGRAPH_OUT'
          the outgoing edges will be considered for each node.

    `IGRAPH_IN'
          the incoming edges will be considered for each node.

    `IGRAPH_ALL'
          the directed graph is considered as an undirected one for the
          computation.

`loops':
     Whether to include the vertices themselves as their own neighbors.

   *Returns:. *

`'
     Error code:

    `IGRAPH_ENOMEM'
          not enough memory for temporary data.

    `IGRAPH_EINVVID'
          invalid vertex id passed.

    `IGRAPH_EINVMODE'
          invalid mode argument.

   Time complexity: O(|V|^2 d), |V| is the number of vertices in the
vertex iterator given, d is the (maximum) degree of the vertices in the
graph.

   *See also:. *

`'
     `igraph_similarity_jaccard()' (see igraph_similarity_jaccard --- Jaccard similarity coefficient_),
     a measure very similar to the
     Dice coefficient

10.7.5 igraph_similarity_inverse_log_weighted -- Vertex similarity based on the inverse logarithm of vertex degrees.
--------------------------------------------------------------------------------------------------------------------

     int igraph_similarity_inverse_log_weighted(const igraph_t *graph,
       igraph_matrix_t *res, const igraph_vs_t vids, igraph_neimode_t mode);

   The inverse log-weighted similarity of two vertices is the number of
their common neighbors, weighted by the inverse logarithm of their
degrees.  It is based on the assumption that two vertices should be
considered more similar if they share a low-degree common neighbor,
since high-degree common neighbors are more likely to appear even by
pure chance.

   Isolated vertices will have zero similarity to any other vertex.
Self-similarities are not calculated.

   See the following paper for more details: Lada A. Adamic and Eytan
Adar: Friends and neighbors on the Web. Social Networks, 25(3):211-230,
2003.

   *Arguments:. *

`graph':
     The graph object to analyze.

`res':
     Pointer to a matrix, the result of the calculation will be stored
     here. The number of its rows is the same as the number of vertex
     ids in `vids', the number of columns is the number of vertices in
     the graph.

`vids':
     The vertex ids of the vertices for which the calculation will be
     done.

`mode':
     The type of neighbors to be used for the calculation in directed
     graphs. Possible values:

    `IGRAPH_OUT'
          the outgoing edges will be considered for each node. Nodes
          will be weighted according to their in-degree.

    `IGRAPH_IN'
          the incoming edges will be considered for each node. Nodes
          will be weighted according to their out-degree.

    `IGRAPH_ALL'
          the directed graph is considered as an undirected one for the
          computation. Every node is weighted according to its
          undirected degree.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVVID': invalid vertex id.

   Time complexity: O(|V|d^2), |V| is the number of vertices in the
graph, d is the (maximum) degree of the vertices in the graph.

10.8 Spanning Tree
==================

10.8.1 igraph_minimum_spanning_tree_unweighted -- Calculates one minimum spanning tree of an unweighted graph.
--------------------------------------------------------------------------------------------------------------

     int igraph_minimum_spanning_tree_unweighted(const igraph_t *graph,
     					    igraph_t *mst);

   If the graph has more minimum spanning trees (this is always the
case, except if it is a forest) this implementation returns only the
same one.

   Directed graphs are considered as undirected for this computation.

   If the graph is not connected then its minimum spanning forest is
returned. This is the set of the minimum spanning trees of each
component.

   *Arguments:. *

`graph':
     The graph object.

`mst':
     The minimum spanning tree, another graph object. Do _not_
     initialize this object before passing it to this function, but be
     sure to call `igraph_destroy()' (see igraph_destroy --- Frees the memory allocated for a graph object_)
     on it if you don't
     need it any more.

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM', not enough memory for temporary data.

   Time complexity: O(|V|+|E|), |V| is the number of vertices, |E| the
number of edges in the graph.

   *See also:. *

`'
     `igraph_minimum_spanning_tree_prim()' (see
     igraph_minimum_spanning_tree_prim --- Calculates one minimum spanning tree of a weighted graph_)
     for weighted graphs.

10.8.2 igraph_minimum_spanning_tree_prim -- Calculates one minimum spanning tree of a weighted graph.
-----------------------------------------------------------------------------------------------------

     int igraph_minimum_spanning_tree_prim(const igraph_t *graph, igraph_t *mst,
     				      const igraph_vector_t *weights);

   This function uses Prim's method for carrying out the computation,
see Prim, R.C.: Shortest connection networks and some generalizations,
Bell System Technical Journal, Vol. 36, 1957, 1389-1401.

   If the graph has more than one minimum spanning tree, the current
implementation returns always the same one.

   Directed graphs are considered as undirected for this computation.

   If the graph is not connected then its minimum spanning forest is
returned. This is the set of the minimum spanning trees of each
component.

   *Arguments:. *

`graph':
     The graph object.

`mst':
     The result of the computation, a graph object containing the
     minimum spanning tree of the graph.  Do _not_ initialize this
     object before passing it to this function, but be sure to call
     `igraph_destroy()' (see igraph_destroy --- Frees the memory allocated for a graph object_)
     on it if you don't need it any
     more.

`weights':
     A vector containing the weights of the the edges.  in the same
     order as the simple edge iterator visits them.

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM', not enough memory.  `IGRAPH_EINVAL',
     length of weight vector does not match number of edges.

   Time complexity: O(|V|+|E|), |V| is the number of vertices, |E| the
number of edges in the graph.

   *See also:. *

`'
     `igraph_minimum_spanning_tree_unweighted()' (see
     igraph_minimum_spanning_tree_unweighted --- Calculates one minimum spanning tree of an unweighted graph_)
     for unweighted graphs.

10.9 Transitivity or Clustering Coefficient
===========================================

10.9.1 igraph_transitivity_undirected -- Calculates the transitivity (clustering coefficient) of a graph.
---------------------------------------------------------------------------------------------------------

     int igraph_transitivity_undirected(const igraph_t *graph,
     				   igraph_real_t *res);

   The transitivity measures the probability that two neighbors of a
vertex are connected. More precisely this is the ratio of the triangles
and connected triples in the graph, the result is a single real number
or NaN (0/0) if there are no connected triples in the graph.  Directed
graphs are considered as undirected ones.

   *Arguments:. *

`graph':
     The graph object.

`res':
     Pointer to a real variable, the result will be stored here.

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM': not enough memory for temporary data.

   *See also:. *

`'
     `igraph_transitivity_local_undirected()' (see
     igraph_transitivity_local_undirected --- Calculates the local transitivity [clustering coefficient] of a graph),
     `igraph_transitivity_avglocal_undirected()' (see
     igraph_transitivity_avglocal_undirected --- Average local transitivity [clustering coefficient]).

   Time complexity: O(|V|*d^2), |V| is the number of vertices in the
graph, d is the average node degree.

10.9.2 igraph_transitivity_local_undirected -- Calculates the local transitivity (clustering coefficient) of a graph
--------------------------------------------------------------------------------------------------------------------

     int igraph_transitivity_local_undirected(const igraph_t *graph,
     					 igraph_vector_t *res,
     					 const igraph_vs_t vids);

   The transitivity measures the probability that two neighbors of a
vertex are connected. In case of the local transitivity, this
probability is calculated separately for each vertex.

   *Arguments:. *

`graph':
     The input graph, it can be directed but direction of the edges
     will be ignored.

`res':
     Pointer to an initialized vector, the result will be stored here.
     It will be resized as needed.

`vids':
     Vertex set, the vertices for which the local transitivity will be
     calculated.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_transitivity_undirected()' (see
     igraph_transitivity_undirected --- Calculates the transitivity [clustering coefficient] of a graph_),
     `igraph_transitivity_avglocal_undirected()' (see
     igraph_transitivity_avglocal_undirected --- Average local transitivity [clustering coefficient]).

   Time complexity: O(n*d^2), n is the number of vertices for which the
transitivity is calculated, d is the average vertex degree.

10.9.3 igraph_transitivity_avglocal_undirected -- Average local transitivity (clustering coefficient)
-----------------------------------------------------------------------------------------------------

     int igraph_transitivity_avglocal_undirected(const igraph_t *graph,
     					    igraph_real_t *res);

   The transitivity measures the probability that two neighbors of a
vertex are connected. In case of the average local transitivity this
probability if calculated for each vertex and then the average is taken
for those vertices which have at least two neighbors. If there are no
such vertices then `NaN' is returned.

   *Arguments:. *

`graph':
     The input graph, directed graphs are considered as undirected ones.

`res':
     Pointer to a real variable, the result will be stored here.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_transitivity_undirected()' (see
     igraph_transitivity_undirected --- Calculates the transitivity [clustering coefficient] of a graph_),
     `igraph_transitivity_local_undirected()' (see
     igraph_transitivity_local_undirected --- Calculates the local transitivity [clustering coefficient] of a graph).

   Time complexity: O(|V|*d^2), |V| is the number of vertices in the
graph and d is the average degree.

10.10 Directedness conversion
=============================

10.10.1 igraph_to_directed -- Convert an undirected graph to a directed one
---------------------------------------------------------------------------

     int igraph_to_directed(igraph_t *graph,
     		       igraph_to_directed_t mode);

   If the supplied graph is directed, this function does nothing.

   *Arguments:. *

`graph':
     The graph object to convert.

`mode':
     Constant, specifies the details of how exactly the conversion is
     done. Possible values: `IGRAPH_TO_DIRECTED_ARBITRARY': the number
     of edges in the graph stays the same, an arbitrarily directed edge
     is created for each undirected edge; `IGRAPH_TO_DIRECTED_MUTUAL':
     two directed edges are created for each undirected edge, one in
     each direction.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges.

10.10.2 igraph_to_undirected -- Convert a directed graph to an undirected one.
------------------------------------------------------------------------------

     int igraph_to_undirected(igraph_t *graph,
     			 igraph_to_undirected_t mode);

   If the supplied graph is undirected, this function does nothing.

   *Arguments:. *

`graph':
     The graph object to convert.

`mode':
     Constant, specifies the details of how exactly the convesion is
     done. Possible values: `IGRAPH_TO_UNDIRECTED_EACH': the number of
     edges remains constant, an undirected edge is created for each
     directed one, this version might create graphs with multiple edges;
     `IGRAPH_TO_UNDIRECTED_COLLAPSE': one undirected edge will be
     created for each pair of vertices which are connected with at
     least one directed edge, no multiple edges will be created.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges.

10.11 Spectral properties
=========================

10.11.1 igraph_laplacian -- Returns the Laplacian matrix of a graph
-------------------------------------------------------------------

     int igraph_laplacian(const igraph_t *graph, igraph_matrix_t *res,
                          igraph_bool_t normalized);

   The graph Laplacian matrix is similar to an adjacency matrix but
contains -1's instead of 1's and the vertex degrees are included in the
diagonal. So the result for edge i-j is -1 if i!=j and is equal to the
degree of vertex i if i==j. igraph_laplacian will work on a directed
graph; in this case, the diagonal will contain the out-degrees.  Loop
edges will be ignored.

   The normalized version of the Laplacian matrix has 1 in the diagonal
and -1/sqrt(d[i]d[j]) if there is an edge from i to j.

   The first version of this function was written by Vincent Matossian.

   *Arguments:. *

`graph':
     Pointer to the graph to convert.

`res':
     Pointer to an initialized matrix object, it will be resized if
     needed.

`normalized':
     Whether to create a normalized Laplacian matrix.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V||V|), |V| is the number of vertices in the
graph.

10.12 Non-simple graphs: multiple and loop edges
================================================

10.12.1 igraph_is_simple -- Decides whether the input graph is a simple graph
-----------------------------------------------------------------------------

     int igraph_is_simple(const igraph_t *graph, igraph_bool_t *res);

   A graph is a simple graph if it does not contain loop edges and
multiple edges.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to a boolean constant, the result is stored here.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_is_loop()' (see igraph_is_loop --- Find the loop edges in a graph)
     and `igraph_is_multiple()' (see igraph_is_multiple --- Find the multiple edges in a graph)
     to find the loops and
     multiple edges and `igraph_simplify()' (see igraph_simplify --- Removes loop and/or multiple edges from the graph_)
     to get rid
     of them.

   Time complexity: O(|V|+|E|).

10.12.2 igraph_is_loop -- Find the loop edges in a graph
--------------------------------------------------------

     int igraph_is_loop(const igraph_t *graph, igraph_vector_bool_t *res,
     		   igraph_es_t es);

   A loop edge is an edge from a vertex to itself.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to an initialized boolean vector for storing the result,
     it will be resized as needed.

`es':
     The edges to check, for all edges supply `igraph_ess_all()' (see
     igraph_ess_all --- Edge set; all edges [immediate version]) here.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_simplify()' (see igraph_simplify --- Removes loop and/or multiple edges from the graph_)
     to get rid of loop edges.

   Time complexity: O(e), the number of edges to check.

10.12.3 igraph_is_multiple -- Find the multiple edges in a graph
----------------------------------------------------------------

     int igraph_is_multiple(const igraph_t *graph, igraph_vector_bool_t *res,
     		       igraph_es_t es);

   An edge is a multiple edge if there is another edge with the same
head and tail vertices in the graph.

   Note that this function returns true only for the second or more
appereances of the multiple edges.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to a boolean vector, the result will be stored here. It
     will be resized as needed.

`es':
     The edges to check. Supply `igraph_ess_all()' (see
     igraph_ess_all --- Edge set; all edges [immediate version]) if
     you want to check all edges.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_count_multiple()' (see igraph_count_multiple --- Count the number of appearance of the edges in a graph)
     and
     `igraph_simplify()' (see igraph_simplify --- Removes loop and/or multiple edges from the graph_).

   Time complexity: O(e*d), e is the number of edges to check and d is
the average degree (out-degree in directed graphs) of the vertices at
the tail of the edges.

10.12.4 igraph_count_multiple -- Count the number of appearance of the edges in a graph
---------------------------------------------------------------------------------------

     int igraph_count_multiple(const igraph_t *graph, igraph_vector_t *res, igraph_es_t es);

   If the graph has no multiple edges then the result vector will be
filled with ones.  (An edge is a multiple edge if there is another edge
with the same head and tail vertices in the graph.)

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to a vector, the result will be stored here. It will be
     resized as needed.

`es':
     The edges to check. Supply `igraph_ess_all()' (see
     igraph_ess_all --- Edge set; all edges [immediate version]) if
     you want to check all edges.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_is_multiple()' (see igraph_is_multiple --- Find the multiple edges in a graph)
     and `igraph_simplify()' (see
     igraph_simplify --- Removes loop and/or multiple edges from the graph_).

   Time complexity: O(e*d), e is the number of edges to check and d is
the average degree (out-degree in directed graphs) of the vertices at
the tail of the edges.

10.12.5 igraph_simplify -- Removes loop and/or multiple edges from the graph.
-----------------------------------------------------------------------------

     int igraph_simplify(igraph_t *graph, igraph_bool_t multiple, igraph_bool_t loops);

   *Arguments:. *

`graph':
     The graph object.

`multiple':
     Logical, if true, multiple edges will be removed.

`loops':
     Logical, if true, loops (self edges) will be removed.

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM' if we are out of memory.

   Time complexity: O(|V|+|E|).

10.13 K-Cores
=============

10.13.1 igraph_coreness -- Finding the coreness of the vertices in a network.
-----------------------------------------------------------------------------

     int igraph_coreness(const igraph_t *graph, igraph_vector_t *cores,
     		    igraph_neimode_t mode);

   The k-core of a graph is a maximal subgraph in which each vertex has
at least degree k. (Degree here means the degree in the subgraph of
course.). The coreness of a vertex is the highest order of a k-core
containing the vertex.

   This function implements the algorithm presented in Vladimir
Batagelj, Matjaz Zaversnik: An O(m) Algorithm for Cores Decomposition
of Networks.

   *Arguments:. *

`graph':
     The input graph.

`cores':
     Pointer to an initialized vector, the result of the computation
     will be stored here. It will be resized as needed. For each vertex
     it contains the highest order of a core containing the vertex.

`mode':
     For directed graph it specifies whether to calculate in-cores,
     out-cores or the undirected version. It is ignored for undirected
     graphs. Possible values: `IGRAPH_ALL' undirected version,
     `IGRAPH_IN' in-cores, `IGRAPH_OUT' out-cores.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|E|), the number of edges.

10.14 Topological sorting
=========================

10.14.1 igraph_topological_sorting -- Calculate a possible topological sorting of the graph
-------------------------------------------------------------------------------------------

     int igraph_topological_sorting(const igraph_t* graph, igraph_vector_t *res,
     			       igraph_neimode_t mode);

   A topological sorting of a directed acyclic graph is a linear
ordering of its nodes where each node comes before all nodes to which
it has edges. Every DAG has at least one topological sort, and may have
many.  This function returns a possible topological sort among them. If
the graph is not acyclic (it has at least one cycle), a partial
topological sort is returned and a warning is issued.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to a vector, the result will be stored here.  It will be
     resized if needed.

`mode':
     Specifies how to use the direction of the edges.  For
     `IGRAPH_OUT', the sorting order ensures that each node comes
     before all nodes to which it has edges, so nodes with no incoming
     edges go first. For `IGRAPH_IN', it is quite the opposite: each
     node comes before all nodes from which it receives edges. Nodes
     with no outgoing edges go first.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), where |V| and |E| are the number of
vertices and edges in the original input graph.

10.15 Line graphs
=================

10.15.1 igraph_linegraph -- Create the line graph of a graph
------------------------------------------------------------

     int igraph_linegraph(const igraph_t *graph, igraph_t *linegraph);

   The line graph L(G) of a G undirected graph is defined as follows.
L(G) has one vertex for each edge in G and two vertices in L(G) are
connected by an edge if their corresponding edges share an end point.

   The line graph L(G) of a G directed graph is slightly different,
L(G) has one vertex for each edge in G and two vertices in L(G) are
connected by a directed edge if the target of the first vertex's
corresponding edge is the same as the source of the second vertex's
corresponding edge.

   The first version of this function was contributed by Vincent
Matossian, thanks.

   *Arguments:. *

`graph':
     The input graph, may be directed or undirected.

`linegraph':
     Pointer to an uninitialized graph object, the result is stored
     here.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), the number of edges plus the number of
vertices.

10.16 Unfolding a graph into a tree
===================================

10.16.1 igraph_unfold_tree -- Unfolding a graph into a tree, by possibly multiplicating its vertices
----------------------------------------------------------------------------------------------------

     int igraph_unfold_tree(const igraph_t *graph, igraph_t *tree,
     		       igraph_neimode_t mode, const igraph_vector_t *roots,
     		       igraph_vector_t *vertex_index);

   A graph is converted into a tree (or forest, if it is unconnected),
by performing a breadth-first search on it, and replicating vertices
that were found a second, third, etc. time.

   *Arguments:. *

`graph':
     The input graph, it can be either directed or undirected.

`tree':
     Pointer to an uninitialized graph object, the result is stored
     here.

`mode':
     For directed graphs; whether to follow paths along edge directions
     (`IGRAPH_OUT'), or the opposite (`IGRAPH_IN'), or ignore edge
     directions completely (`IGRAPH_ALL'). It is ignored for undirected
     graphs.

`roots':
     A numeric vector giving the root vertex, or vertices (if the graph
     is not connected), to start from.

`vertex_index':
     Pointer to an initialized vector, or a null pointer. If not a null
     pointer, then a mapping from the vertices in the new graph to the
     ones in the original is created here.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n+m), linear in the number vertices and edges.

10.17 Other Operations
======================

10.17.1 igraph_density -- Calculate the density of a graph.
-----------------------------------------------------------

     int igraph_density(const igraph_t *graph, igraph_real_t *res,
     		   igraph_bool_t loops);

   The density of a graph is simply the ratio number of edges and the
number of possible edges. Note that density is ill-defined for graphs
with multiple and/or loop edges, so consider calling
`igraph_simplify()' (see igraph_simplify --- Removes loop and/or multiple edges from the graph_)
on the graph if you know that it
contains multiple or loop edges.

   *Arguments:. *

`graph':
     The input graph object.

`res':
     Pointer to a real number, the result will be stored here.

`loops':
     Logical constant, whether to include loops in the calculation. If
     this constant is TRUE then loop edges are thought to be possible
     in the graph (this does not neccessary means that the graph really
     contains any loops). If this FALSE then the result is only correct
     if the graph does not contain loops.

   *Returns:. *

`'
     Error code.

   Time complexity: O(1).

10.17.2 igraph_reciprocity -- Calculates the reciprocity of a directed graph.
-----------------------------------------------------------------------------

     int igraph_reciprocity(const igraph_t *graph, igraph_real_t *res,
     		       igraph_bool_t ignore_loops);

   A vertex pair (A, B) is said to be reciprocal if there are edges
between them in both directions. The reciprocity of a directed graph is
the proportion of all possible (A, B) pairs which are reciprocal,
provided there is at least one edge between A and B. The reciprocity of
an empty graph is undefined (results in an error code). Undirected
graphs always have a reciprocity of 1.0 unless they are empty.

   *Arguments:. *

`graph':
     The graph object.

`res':
     Pointer to an `igraph_real_t' which will contain the result.

`ignore_loops':
     Whether to ignore loop edges.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVAL': graph has no edges `IGRAPH_ENOMEM':
     not enough memory for temporary data.

   Time complexity: O(|V|+|E|), |V| is the number of vertices, |E| is
the number of edges.

10.17.3 igraph_is_mutual -- Check whether the edges of a directed graph are mutual
----------------------------------------------------------------------------------

     int igraph_is_mutual(igraph_t *graph, igraph_vector_bool_t *res, igraph_es_t es);

   An (A,B) edge is mutual if the graph contains the (B,A) edge, too.

   An undirected graph only has mutual edges, by definition.

   Edge multiplicity is not considered here, e.g. if there are two
(A,B) edges and one (B,A) edge, then all three are considered to be
mutual.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to an initialized vector, the result is stored here.

`es':
     The sequence of edges to check. Supply ` igraph_ess_all()'  for
     all edges, see `igraph_ess_all()' (see igraph_ess_all --- Edge set; all edges [immediate version]).

   *Returns:. *

`'
     Error code.

   Time complexity: O(n log(d)), n is the number of edges supplied, d
is the maximum in-degree of the vertices that are targets of the
supplied edges. An upper limit of the time complexity is O(n log(|E|)),
|E| is the number of edges in the graph.

10.17.4 igraph_avg_nearest_neighbor_degree -- Average nearest neighbor degree
-----------------------------------------------------------------------------

     int igraph_avg_nearest_neighbor_degree(const igraph_t *graph,
     				       igraph_vs_t vids,
     				       igraph_vector_t *knn,
     				       igraph_vector_t *knnk,
     				       const igraph_vector_t *weights);

   Calculates the average degree of the neighbors for each vertex, and
optionally, the same quantity in the function of vertex degree.

   For isolate vertices `knn' is set to `IGRAPH_NAN'. The same is done
in `knnk' for vertex degrees that don't appear in the graph.

   *Arguments:. *

`graph':
     The input graph, it can be directed but the directedness of the
     edges is ignored.

`vids':
     The vertices for which the calculation is permformed.

`knn':
     Pointer to an initialized vector, the result will be stored here.
     It will be resized as needed. Supply a NULL pointer here, if you
     only want to calculate `knnk'.

`knnk':
     Pointer to an initialized vector, the average nearest neighbor
     degree in the function of vertex degree is stored here. The first
     (zeroth) element is for degree one vertices, etc. Supply a NULL
     pointer here if you don't want to calculate this.

`weights':
     Optional edge weights. Supply a null pointer here for the
     non-weighted version. If this is not a null pointer, then the
     strength of the vertices is used instead of the normal vertex
     degree, see `igraph_strength()' (see igraph_strength --- Strength of the vertices; weighted vertex degree in other words).

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), linear in the number of vertices and
edges.

10.17.5 igraph_get_adjacency -- Returns the adjacency matrix of a graph
-----------------------------------------------------------------------

     int igraph_get_adjacency(const igraph_t *graph, igraph_matrix_t *res,
     			 igraph_get_adjacency_t type);

   The result is an incidence matrix, it contains numbers greater than
one if there are multiple edges in the graph.

   *Arguments:. *

`graph':
     Pointer to the graph to convert

`res':
     Pointer to an initialized matrix object, it will be resized if
     needed.

`type':
     Constant giving the type of the adjacency matrix to create for
     undirected graphs. It is ignored for directed graphs. Possible
     values:

    `IGRAPH_GET_ADJACENCY_UPPER '
          the upper right triangle of the matrix is used.

    `IGRAPH_GET_ADJACENCY_LOWER '
          the lower left triangle of the matrix is used.

    `IGRAPH_GET_ADJACENCY_BOTH '
          the whole matrix is used, a symmetric matrix is returned.

   *Returns:. *

`'
     Error code: `IGRAPH_EINVAL' invalid type argument.

   *See also:. *

`'
     igraph_get_adjacency_sparse if you want a sparse matrix
     representation

   Time complexity: O(|V||V|), |V| is the number of vertices in the
graph.

10.17.6 igraph_get_edgelist -- Returns the list of edges in a graph
-------------------------------------------------------------------

     int igraph_get_edgelist(const igraph_t *graph, igraph_vector_t *res, igraph_bool_t bycol);

   The order of the edges is given by the edge ids.

   *Arguments:. *

`graph':
     Pointer to the graph object

`res':
     Pointer to an initialized vector object, it will be resized.

`bycol':
     Logical, if true, the edges will be returned columnwise, eg. the
     first edge is ` res[0]->res[|E|]' , the second is `
     res[1]->res[|E|+1]' , etc.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|E|), the number of edges in the graph.

11 Cliques and Independent Vertex Sets
**************************************

These functions calculate various graph properties related to cliques
and independent vertex sets.

11.1 Cliques
============

11.1.1 igraph_cliques -- Find all or some cliques in a graph
------------------------------------------------------------

     int igraph_cliques(const igraph_t *graph, igraph_vector_ptr_t *res,
                        igraph_integer_t min_size, igraph_integer_t max_size);

   Cliques are fully connected subgraphs of a graph.

   If you are only interested in the size of the largest clique in the
graph, use `igraph_clique_number()' (see igraph_clique_number --- Find the clique number of the graph)
instead.

   The current implementation of this function searches for maximal
independent vertex sets (see `igraph_maximal_independent_vertex_sets()'
(see igraph_maximal_independent_vertex_sets --- Find all maximal independent vertex sets of a graph))
in the complementer graph using
the algorithm published in: S. Tsukiyama, M. Ide, H. Ariyoshi and I.
Shirawaka. A new algorithm for generating all the maximal independent
sets. SIAM J Computing, 6:505-517, 1977.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to a pointer vector, the result will be stored here, ie.
     `res' will contain pointers to `igraph_vector_t' objects which
     contain the indices of vertices involved in a clique.  The pointer
     vector will be resized if needed but note that the objects in the
     pointer vector will not be freed.

`min_size':
     Integer giving the minimum size of the cliques to be returned. If
     negative or zero, no lower bound will be used.

`max_size':
     Integer giving the maximum size of the cliques to be returned. If
     negative or zero, no upper bound will be used.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_largest_cliques()' (see igraph_largest_cliques --- Finds the largest clique[s] in a graph_)
     and `igraph_clique_number()'
     (see igraph_clique_number --- Find the clique number of the graph).

   Time complexity: TODO

11.1.2 igraph_largest_cliques -- Finds the largest clique(s) in a graph.
------------------------------------------------------------------------

     int igraph_largest_cliques(const igraph_t *graph, igraph_vector_ptr_t *res);

   A clique is largest (quite intuitively) if there is no other clique
in the graph which contains more vertices.

   Note that this is not neccessarily the same as a maximal clique, ie.
the largest cliques are always maximal but a maximal clique is not
always largest.

   The current implementation of this function searches for maximal
independent vertex sets (see `igraph_maximal_independent_vertex_sets()'
(see igraph_maximal_independent_vertex_sets --- Find all maximal independent vertex sets of a graph))
in the complementer graph using
the algorithm published in: S. Tsukiyama, M. Ide, H. Ariyoshi and I.
Shirawaka. A new algorithm for generating all the maximal independent
sets. SIAM J Computing, 6:505-517, 1977.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to an initialized pointer vector, the result will be
     stored here. It will be resized as needed.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_cliques()' (see igraph_cliques --- Find all or some cliques in a graph),
     `igraph_maximal_cliques()' (see
     igraph_maximal_cliques --- Find all maximal cliques of a graph)

   Time complexity: TODO.

11.1.3 igraph_maximal_cliques -- Find all maximal cliques of a graph
--------------------------------------------------------------------

     int igraph_maximal_cliques(const igraph_t *graph, igraph_vector_ptr_t *res);

   A maximal clique is a clique which can't be extended any more by
adding a new vertex to it. This is actually implemented by looking for
a maximal independent vertex set in the complementer of the graph.

   If you are only interested in the size of the largest clique in the
graph, use `igraph_clique_number()' (see igraph_clique_number --- Find the clique number of the graph)
instead.

   The current implementation was ported to igraph from the Very Nauty
Graph Library by Keith Briggs and uses the algorithm from the paper S.
Tsukiyama, M. Ide, H. Ariyoshi and I. Shirawaka. A new algorithm for
generating all the maximal independent sets. SIAM J Computing,
6:505-517, 1977.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to a pointer vector, the result will be stored here, ie.
     `res' will contain pointers to `igraph_vector_t' objects which
     contain the indices of vertices involved in a clique.  The pointer
     vector will be resized if needed but note that the objects in the
     pointer vector will not be freed.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_maximal_independent_vertex_sets()' (see
     igraph_maximal_independent_vertex_sets --- Find all maximal independent vertex sets of a graph),
     `igraph_clique_number()'
     (see igraph_clique_number --- Find the clique number of the graph)

   Time complexity: TODO.

11.1.4 igraph_clique_number -- Find the clique number of the graph
------------------------------------------------------------------

     int igraph_clique_number(const igraph_t *graph, igraph_integer_t *no);

   The clique number of a graph is the size of the largest clique.

   *Arguments:. *

`graph':
     The input graph.

`no':
     The clique number will be returned to the `igraph_integer_t'
     pointed by this variable.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_cliques()' (see igraph_cliques --- Find all or some cliques in a graph),
     `igraph_largest_cliques()' (see
     igraph_largest_cliques --- Finds the largest clique[s] in a graph_).

   Time complexity: TODO.

11.2 Independent Vertex Sets
============================

11.2.1 igraph_independent_vertex_sets -- Find all independent vertex sets in a graph
------------------------------------------------------------------------------------

     int igraph_independent_vertex_sets(const igraph_t *graph,
     				   igraph_vector_ptr_t *res,
     				   igraph_integer_t min_size,
     				   igraph_integer_t max_size);

   A vertex set is considered independent if there are no edges between
them.

   If you are interested in the size of the largest independent vertex
set, use `igraph_independence_number()' (see
igraph_independence_number --- Find the independence number of the graph)
instead.

   The current implementation was ported to igraph from the Very Nauty
Graph Library by Keith Briggs and uses the algorithm from the paper S.
Tsukiyama, M. Ide, H. Ariyoshi and I. Shirawaka. A new algorithm for
generating all the maximal independent sets. SIAM J Computing,
6:505-517, 1977.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to a pointer vector, the result will be stored here, ie.
     `res' will contain pointers to `igraph_vector_t' objects which
     contain the indices of vertices involved in an independent vertex
     set. The pointer vector will be resized if needed but note that the
     objects in the pointer vector will not be freed.

`min_size':
     Integer giving the minimum size of the sets to be returned. If
     negative or zero, no lower bound will be used.

`max_size':
     Integer giving the maximum size of the sets to be returned. If
     negative or zero, no upper bound will be used.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_largest_independent_vertex_sets()' (see
     igraph_largest_independent_vertex_sets --- Finds the largest independent vertex set[s] in a graph_),
     `igraph_independence_number()' (see igraph_independence_number --- Find the independence number of the graph).

   Time complexity: TODO

11.2.2 igraph_largest_independent_vertex_sets -- Finds the largest independent vertex set(s) in a graph.
--------------------------------------------------------------------------------------------------------

     int igraph_largest_independent_vertex_sets(const igraph_t *graph,
     					   igraph_vector_ptr_t *res);

   An independent vertex set is largest if there is no other
independent vertex set with more vertices in the graph.

   The current implementation was ported to igraph from the Very Nauty
Graph Library by Keith Briggs and uses the algorithm from the paper S.
Tsukiyama, M. Ide, H. Ariyoshi and I. Shirawaka. A new algorithm for
generating all the maximal independent sets. SIAM J Computing,
6:505-517, 1977.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to a pointer vector, the result will be stored here. It
     will be resized as needed.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_independent_vertex_sets()' (see
     igraph_independent_vertex_sets --- Find all independent vertex sets in a graph),
     `igraph_maximal_independent_vertex_sets()'
     (see igraph_maximal_independent_vertex_sets --- Find all maximal independent vertex sets of a graph).

   Time complexity: TODO

11.2.3 igraph_maximal_independent_vertex_sets -- Find all maximal independent vertex sets of a graph
----------------------------------------------------------------------------------------------------

     int igraph_maximal_independent_vertex_sets(const igraph_t *graph,
     					   igraph_vector_ptr_t *res);

   A maximal independent vertex set is an independent vertex set which
can't be extended any more by adding a new vertex to it.

   The algorithm used here is based on the following paper: S.
Tsukiyama, M. Ide, H. Ariyoshi and I. Shirawaka. A new algorithm for
generating all the maximal independent sets. SIAM J Computing,
6:505-517, 1977.

   The implementation was originally written by Kevin O'Neill and
modified by K M Briggs in the Very Nauty Graph Library. I simply
re-wrote it to use igraph's data structures.

   If you are interested in the size of the largest independent vertex
set, use `igraph_independence_number()' (see
igraph_independence_number --- Find the independence number of the graph)
instead.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to a pointer vector, the result will be stored here, ie.
     `res' will contain pointers to `igraph_vector_t' objects which
     contain the indices of vertices involved in an independent vertex
     set. The pointer vector will be resized if needed but note that the
     objects in the pointer vector will not be freed.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_maximal_cliques()' (see igraph_maximal_cliques --- Find all maximal cliques of a graph),
     `igraph_independence_number()'
     (see igraph_independence_number --- Find the independence number of the graph)

   Time complexity: TODO.

11.2.4 igraph_independence_number -- Find the independence number of the graph
------------------------------------------------------------------------------

     int igraph_independence_number(const igraph_t *graph, igraph_integer_t *no);

   The independence number of a graph is the cardinality of the largest
independent vertex set.

   The current implementation was ported to igraph from the Very Nauty
Graph Library by Keith Briggs and uses the algorithm from the paper S.
Tsukiyama, M. Ide, H. Ariyoshi and I. Shirawaka. A new algorithm for
generating all the maximal independent sets. SIAM J Computing,
6:505-517, 1977.

   *Arguments:. *

`graph':
     The input graph.

`no':
     The independence number will be returned to the `igraph_integer_t'
     pointed by this variable.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_independent_vertex_sets()' (see
     igraph_independent_vertex_sets --- Find all independent vertex sets in a graph).

   Time complexity: TODO.

12 Graph Isomorphism
********************

12.1 The simple interface
=========================

igraph provides four set of functions to deal with graph isomorphism
problems.

   The `igraph_isomorphic()' (see igraph_isomorphic --- Decides whether two graphs are isomorphic)
and `igraph_subisomorphic()'
(see igraph_subisomorphic --- Decide subgraph isomorphism)
functions make up the first set (in addition with the
`igraph_permute_vertices()' (see igraph_permute_vertices --- Permute the vertices)
function). These functions choose the algorithm which
is best for the supplied input graph. (The choice is not very
sophisticated though, see their documentation for details.)

   The VF2 graph (and subgraph) isomorphism algorithm is implemented in
igraph, these functions are the second set. See
`igraph_isomorphic_vf2()' (see igraph_isomorphic_vf2 --- Isomorphism via VF2)
and `igraph_subisomorphic_vf2()' (see
igraph_subisomorphic_vf2 --- Decide subgraph isomorphism using VF2)
for starters.

   Functions for the BLISS algorithm constitute the third set, see
`igraph_isomorphic_bliss()' (see igraph_isomorphic_bliss --- Graph isomorphism via BLISS).
This implementation only works for undirected
graphs.

   Finally, the isomorphism classes of all graphs with three and four
vertices are precomputed and stored in igraph, so for these small
graphs there is a very simple fast way to decide isomorphism.  See
`igraph_isomorphic_34()' (see igraph_isomorphic_34 --- Graph isomorphism for 3-4 vertices).

12.1.1 igraph_permute_vertices -- Permute the vertices
------------------------------------------------------

     int igraph_permute_vertices(const igraph_t *graph, igraph_t *res,
     			    const igraph_vector_t *permutation);

   This function creates a new graph from the input graph by permuting
its vertices according to the specified mapping. Call this function
with the output of `igraph_canonical_permutation()' (see
igraph_canonical_permutation --- Canonical permutation using BLISS)
to create the canonical form of a graph.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to an uninitialized graph object. The new graph is created
     here.

`permutation':
     The permutation to apply. Vertex 0 is mapped to the first element
     of the vector, vertex 1 to the second, etc. Note that it is not
     checked that the vector contains every element only once, and no
     range checking is performed either.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), linear in terms of the number of
vertices and edges.

12.1.2 igraph_isomorphic -- Decides whether two graphs are isomorphic
---------------------------------------------------------------------

     int igraph_isomorphic(const igraph_t *graph1, const igraph_t *graph2,
     		      igraph_bool_t *iso);

   From Wikipedia: The graph isomorphism problem or GI problem is the
graph theory problem of determining whether, given two graphs G1 and
G2, it is possible to permute (or relabel) the vertices of one graph so
that it is equal to the other. Such a permutation is called a graph
isomorphism.

   This function decides which graph isomorphism algorithm to be used
based on the input graphs. Right now it does the following:

  1. If one graph is directed and the other undirected then an error is
     triggered.

  2. If the two graphs does not have the same number of vertices and
     edges it returns with `FALSE'.

  3. Otherwise, if the graphs have three or four vertices then an O(1)
     algorithm is used with precomputed data.

  4. Otherwise, if the graphs are directed then VF2 is used, see
     `igraph_isomorphic_vf2()' (see igraph_isomorphic_vf2 --- Isomorphism via VF2).

  5. Otherwise BLISS is used, see `igraph_isomorphic_bliss()' (see
     igraph_isomorphic_bliss --- Graph isomorphism via BLISS).

   Please call the VF2 and BLISS functions directly if you need
something more sophisticated, e.g. you need the isomorphic mapping.

   *Arguments:. *

`graph1':
     The first graph.

`graph2':
     The second graph.

`iso':
     Pointer to a logical variable, will be set to TRUE (1) if the two
     graphs are isomorphic, and FALSE (0) otherwise.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_isoclass()' (see igraph_isoclass --- Determine the isomorphism class of a graph with 3 or 4 vertices),
     `igraph_isoclass_subgraph()' (see igraph_isoclass_subgraph --- The isomorphism class of a subgraph of a graph_),
     `igraph_isoclass_create()' (see igraph_isoclass_create --- Creates a graph from the given isomorphism class_).

   Time complexity: exponential.

12.1.3 igraph_subisomorphic -- Decide subgraph isomorphism
----------------------------------------------------------

     int igraph_subisomorphic(const igraph_t *graph1, const igraph_t *graph2,
     			 igraph_bool_t *iso);

   Check whether `graph2' is isomorphic to a subgraph of `graph1'.
Currently this function just calls `igraph_subisomorphic_vf2()' (see
igraph_subisomorphic_vf2 --- Decide subgraph isomorphism using VF2)
for all graphs.

   *Arguments:. *

`graph1':
     The first input graph, may be directed or undirected. This is
     supposed to be the bigger graph.

`graph2':
     The second input graph, it must have the same directedness as
     `graph2', or an error is triggered. This is supposed to be the
     smaller graph.

`iso':
     Pointer to a boolean, the result is stored here.

   *Returns:. *

`'
     Error code.

   Time complexity: exponential.

12.2 The BLISS algorithm
========================

BLISS is a successor of the famous NAUTY algorithm and implementation.
While using the same ideas in general, with better heuristics and data
structure BLISS outperforms NAUTY on most graphs.

   BLISS was developed and implemented by Tommi Junttila and Petteri
Kaski at Helsinki University of Technology, Finland. See Tommi
Juntilla's homepage at http://www.tcs.hut.fi/~tjunttil/
(http://www.tcs.hut.fi/~tjunttil/) and the publication at
http://www.siam.org/proceedings/alenex/2007/alx07_013junttilat.pdf
(http://www.siam.org/proceedings/alenex/2007/alx07_013junttilat.pdf)
for more information.

   BLISS version 0.35 is included in igraph.

12.2.1 igraph_bliss_sh_t -- Splitting heuristics for BLISS
----------------------------------------------------------

     typedef enum { IGRAPH_BLISS_F=0, IGRAPH_BLISS_FL,
     	       IGRAPH_BLISS_FS, IGRAPH_BLISS_FM,
     	       IGRAPH_BLISS_FLM, IGRAPH_BLISS_FSM } igraph_bliss_sh_t;

   *Values:. *

`IGRAPH_BLISS_F':
     First non-singleton cell.

`IGRAPH_BLISS_FL':
     First largest non-singleton cell.

`IGRAPH_BLISS_FS':
     First smallest non-singleton cell.

`IGRAPH_BLISS_FM':
     First maximally non-trivially connected non-singleton cell.

`IGRAPH_BLISS_FLM':
     Largest maximally non-trivially connected non-singleton cell.

`IGRAPH_BLISS_FSM':
     Smallest maximally non-trivially connected non-singletion cell.

12.2.2 igraph_bliss_info_t -- Information about a BLISS run
-----------------------------------------------------------

     typedef struct igraph_bliss_info_t {
       unsigned long nof_nodes;
       unsigned long nof_leaf_nodes;
       unsigned long nof_bad_nodes;
       unsigned long nof_canupdates;
       unsigned long max_level;
       char *group_size;
     } igraph_bliss_info_t;

   Some secondary information found by the BLISS algorithm is stored
here. It is useful if you wany to study the internal working of the
algorithm.

   *Values:. *

`nof_nodes':
     The number of nodes in the search tree.

`nof_leaf_nodes':
     The number of leaf nodes in the search tree.

`nof_bad_nodes':
     Number of bad nodes.

`nof_canupdates':
     Number of canrep updates.

`max_level':
     Maximum level.

`group_size':
     The size of the automorphism group of the graph, given as a
     string. It should be deallocated via `free()' if not needed any
     more.

   See http://www.tcs.hut.fi/Software/bliss/index.html
(http://www.tcs.hut.fi/Software/bliss/index.html) for details about the
algorithm and these parameters.

12.2.3 igraph_canonical_permutation -- Canonical permutation using BLISS
------------------------------------------------------------------------

     int igraph_canonical_permutation(const igraph_t *graph, igraph_vector_t *labeling,
     				 igraph_bliss_sh_t sh, igraph_bliss_info_t *info);

   This function computes the canonical permutation which transforms
the graph into a canonical form by using the BLISS algorithm.

   *Arguments:. *

`graph':
     The input graph, it is treated as undirected and the multiple
     edges are ignored.

`labeling':
     Pointer to a vector, the result is stored here. The permutation
     takes vertex 0 to the first element of the vector, vertex 1 to the
     second, etc. The vector will be resized as needed.

`sh':
     The split heuristics to be used in BLISS. See `igraph_bliss_sh_t'
     (see igraph_bliss_sh_t --- Splitting heuristics for BLISS).

`info':
     If not `NULL' then information on BLISS internals is stored here.
     See `igraph_bliss_info_t' (see igraph_bliss_info_t --- Information about a BLISS run).

   *Returns:. *

`'
     Error code.

   Time complexity: exponential, in practice it is fast for many graphs.

12.2.4 igraph_isomorphic_bliss -- Graph isomorphism via BLISS
-------------------------------------------------------------

     int igraph_isomorphic_bliss(const igraph_t *graph1, const igraph_t *graph2,
     			    igraph_bool_t *iso, igraph_vector_t *map12,
     			    igraph_vector_t *map21,
     			    igraph_bliss_sh_t sh1, igraph_bliss_sh_t sh2,
     			    igraph_bliss_info_t *info1, igraph_bliss_info_t *info2);

   This function uses the BLISS graph isomorphism algorithm, a
successor of the famous NAUTY algorithm and implementation. BLISS is
open source and licensed according to the GNU GPL. See
http://www.tcs.hut.fi/Software/bliss/index.html
(http://www.tcs.hut.fi/Software/bliss/index.html) for details.
Currently the 0.35 version of BLISS is included in igraph.

   *Arguments:. *

`graph1':
     The first input graph, it is assumed to be undirected, directed
     graphs are treated as undirected too.  The algorithm eliminates
     multiple edges from the graph first.

`graph2':
     The second input graph, it is assumed to be undirected, directed
     graphs are treated as undirected too.  The algorithm eliminates
     multiple edges from the graph first.

`iso':
     Pointer to a boolean, the result is stored here.

`map12':
     A vector or `NULL' pointer. If not `NULL' then an isomorphic
     mapping from `graph1' to `graph2' is stored here.  If the input
     graphs are not isomorphic then this vector is cleared, i.e. it
     will have length zero.

`map21':
     Similar to `map12', but for the mapping from `graph2' to `graph1'.

`sh1':
     Splitting heuristics to be used for the first graph. See
     `igraph_bliss_sh_t' (see igraph_bliss_sh_t --- Splitting heuristics for BLISS).

`sh2':
     Splitting heuristics to be used for the second graph. See
     `igraph_bliss_sh_t' (see igraph_bliss_sh_t --- Splitting heuristics for BLISS).

`info1':
     If not `NULL', information about the canonization of the first
     input graph is stored here. See `igraph_bliss_info_t' (see
     igraph_bliss_info_t --- Information about a BLISS run) for
     details.

`info2':
     Same as `info1', but for the second graph.

   *Returns:. *

`'
     Error code.

   Time complexity: exponential, but in practice it is quite fast.

12.2.5 igraph_automorphisms -- Number of automorphisms using BLISS
------------------------------------------------------------------

     int igraph_automorphisms(const igraph_t *graph,
     			 igraph_bliss_sh_t sh, igraph_bliss_info_t *info);

   The number of automorphisms of a graph is computed using BLISS. The
result is returned as part of the `info' structure, in tag
`group_size'. It is returned as a string, as it can be very high even
for relatively small graphs. If the GNU MP library is used then this
number is exact, otherwise a `long double' is used and it is only
approximate. See also `igraph_bliss_info_t' (see igraph_bliss_info_t --- Information about a BLISS run).

   *Arguments:. *

`graph':
     The input graph, it is treated as undirected and the multiple
     edges are ignored.

`sh':
     The split heuristics to be used in BLISS. See `igraph_bliss_sh_t'
     (see igraph_bliss_sh_t --- Splitting heuristics for BLISS).

`info':
     The result is stored here, in particular in the `group_size' tag
     of `info'.

   *Returns:. *

`'
     Error code.

   Time complexity: exponential, in practice it is fast for many graphs.

12.3 The VF2 algorithm
======================

12.3.1 igraph_isomorphic_vf2 -- Isomorphism via VF2
---------------------------------------------------

     int igraph_isomorphic_vf2(const igraph_t *graph1, const igraph_t *graph2,
     			  igraph_bool_t *iso, igraph_vector_t *map12,
     			  igraph_vector_t *map21);

   This function performs the VF2 algorithm via calling
`igraph_isomorphic_function_vf2()' (see
igraph_isomorphic_function_vf2 --- The generic VF2 interface).

   Note that this function cannot be used for deciding subgraph
isomorphism, use `igraph_subisomorphic_vf2()' (see
igraph_subisomorphic_vf2 --- Decide subgraph isomorphism using VF2)
for that.

   *Arguments:. *

`graph1':
     The first graph, may be directed or undirected.

`graph2':
     The second graph. It must have the same directedness as `graph1',
     otherwise an error is reported.

`iso':
     Pointer to a logical constant, the result of the algorithm will be
     placed here.

`map12':
     Pointer to an initialized vector or a NULL pointer. If not a NULL
     pointer then the mapping from `graph1' to `graph2' is stored here.
     If the graphs are not isomorphic then the vector is cleared (ie.
     has zero elements).

`map21':
     Pointer to an initialized vector or a NULL pointer. If not a NULL
     pointer then the mapping from `graph2' to `graph1' is stored here.
     If the graphs are not isomorphic then the vector is cleared (ie.
     has zero elements).

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_subisomorphic_vf2()' (see igraph_subisomorphic_vf2 --- Decide subgraph isomorphism using VF2),
     `igraph_count_isomorphisms_vf2()' (see
     igraph_count_isomorphisms_vf2 --- Number of isomorphisms via VF2),
     `igraph_get_isomorphisms_vf2()' (see
     igraph_get_isomorphisms_vf2 --- Collect the isomorphic mappings),

   Time complexity: exponential, what did you expect?

12.3.2 igraph_count_isomorphisms_vf2 -- Number of isomorphisms via VF2
----------------------------------------------------------------------

     int igraph_count_isomorphisms_vf2(const igraph_t *graph1, const igraph_t *graph2,
     				  igraph_integer_t *count);

   This function counts the number of isomorphic mappings between two
graphs. It uses the generic `igraph_isomorphic_function_vf2()' (see
igraph_isomorphic_function_vf2 --- The generic VF2 interface)
function.

   *Arguments:. *

`graph1':
     The first input graph, may be directed or undirected.

`graph2':
     The second input graph, it must have the same directedness as
     `graph1', or an error will be reported.

`count':
     Point to an integer, the result will be stored here.

   *Returns:. *

`'
     Error code.

   Time complexity: exponential.

12.3.3 igraph_get_isomorphisms_vf2 -- Collect the isomorphic mappings
---------------------------------------------------------------------

     int igraph_get_isomorphisms_vf2(const igraph_t *graph1,
     				const igraph_t *graph2,
     				igraph_vector_ptr_t *maps);

   This function finds all the isomorphic mappings between two graphs.
It uses the `igraph_isomorphic_function_vf2()' (see
igraph_isomorphic_function_vf2 --- The generic VF2 interface)
function. Call the function with the same graph as `graph1' and
`graph2' to get automorphisms.

   *Arguments:. *

`graph1':
     The first input graph, may be directed or undirected.

`graph2':
     The second input graph, it must have the same directedness as
     `graph1', or an error will be reported.

`maps':
     Pointer vector. On return it is empty if the input graphs are no
     isomorphic. Otherwise it contains pointers to `igraph_vector_t'
     objects, each vector is an isomorphic mapping of `graph2' to
     `graph1'. Please note that you need to 1) Destroy the vectors via
     `igraph_vector_destroy()' (see igraph_vector_destroy --- Destroys a vector object_),
     2) free them via `free()' and then
     3) call `igraph_vector_ptr_destroy()' (see
     igraph_vector_ptr_destroy --- Destroys a pointer vector_) on the
     pointer vector to deallocate all memory when `maps' is no longer
     needed.

   *Returns:. *

`'
     Error code.

   Time complexity: exponential.

12.3.4 igraph_isohandler_t -- Callback type, called when an isomorphism was found
---------------------------------------------------------------------------------

     typedef igraph_bool_t igraph_isohandler_t(const igraph_vector_t *map12,
     					  const igraph_vector_t *map21, void *arg);

   See the details at the documentation of
`igraph_isomorphic_function_vf2()' (see
igraph_isomorphic_function_vf2 --- The generic VF2 interface).

   *Arguments:. *

`map12':
     The mapping from the first graph to the second.

`map21':
     The mapping from the second graph to the first, the inverse of
     `map12' basically.

`arg':
     This extra argument was passed to
     `igraph_isomorphic_function_vf2()' (see
     igraph_isomorphic_function_vf2 --- The generic VF2 interface)
     when it was called.

   *Returns:. *

`'
     Boolean, whether to continue with the isomorphism search.

12.3.5 igraph_isomorphic_function_vf2 -- The generic VF2 interface
------------------------------------------------------------------

     int igraph_isomorphic_function_vf2(const igraph_t *graph1, const igraph_t *graph2,
     				   igraph_vector_t *map12,
     				   igraph_vector_t *map21,
     				   igraph_isohandler_t *function,
      				   void *arg);

   This function is an implementation of the VF2 isomorphism algorithm,
see P. Foggia, C. Sansone, M. Vento, An Improved algorithm for matching
large graphs, Proc. of the 3rd IAPR-TC-15 International Workshop on
Graph-based Representations, Italy, 2001.

   For using it you need to define a calback function of type
`igraph_isohandler_t' (see igraph_isohandler_t --- Callback type; called when an isomorphism was found).
This function will be called
whenever VF2 finds an isomorphism between the two graphs. The mapping
between the two graphs will be also provided to this function. If the
callback returns a nonzero value then the search is continued,
otherwise it stops.

   *Arguments:. *

`graph1':
     The first input graph.

`graph2':
     The second input graph.

`map12':
     Pointer to an initialized vector or `NULL'. If not `NULL' and the
     supplied graphs are isomorphic then the permutation taking
     `graph1' to `graph' is stored here. If not `NULL' and the graphs
     are not isomorphic then a zero-length vector is returned.

`map21':
     This is the same as `map12', but for the permutation taking
     `graph2' to `graph1'.

`function':
     The callback function to be called if an isomorphism is found. See
     also `igraph_isohandler_t' (see igraph_isohandler_t --- Callback type; called when an isomorphism was found).

`arg':
     An extra argument to pass to `function'. E.g. if `function' needs
     to store the isomorphisms found, then `arg' may point to a
     container for them.

   *Returns:. *

`'
     Error code.

   Time complexity: exponential.

12.3.6 igraph_subisomorphic_vf2 -- Decide subgraph isomorphism using VF2
------------------------------------------------------------------------

     int igraph_subisomorphic_vf2(const igraph_t *graph1, const igraph_t *graph2,
     			     igraph_bool_t *iso, igraph_vector_t *map12,
     			     igraph_vector_t *map21);

   Decides whether a subgraph of `graph1' is isomorphic to `graph2'. It
uses `igraph_subisomorphic_function_vf2()' (see
igraph_subisomorphic_function_vf2 --- Generic VF2 function for subgraph isomorphism problems).

   *Arguments:. *

`graph1':
     The first input graph, may be directed or undirected. This is
     supposed to be the larger graph.

`graph2':
     The second input graph, it must have the same directedness as
     `graph1'. This is supposed to be the smaller graph.

`iso':
     Pointer to a boolean. The result of the decision problem is stored
     here.

`map12':
     Pointer to a vector or `NULL'. If not `NULL', then an isomorphic
     mapping from `graph1' to `graph2' is stored here.

`map21':
     Pointer to a vector ot `NULL'. If not `NULL', then an isomorphic
     mapping from `graph2' to `graph1' is stored here.

   *Returns:. *

`'
     Error code.

   Time complexity: exponential.

12.3.7 igraph_count_subisomorphisms_vf2 -- Number of subgraph isomorphisms using VF2
------------------------------------------------------------------------------------

     int igraph_count_subisomorphisms_vf2(const igraph_t *graph1, const igraph_t *graph2,
     				     igraph_integer_t *count);

   Count the number of isomorphisms between subgraphs of `graph1' and
`graph2'. This function uses `igraph_subisomorphic_function_vf2()'
(see igraph_subisomorphic_function_vf2 --- Generic VF2 function for subgraph isomorphism problems).

   *Arguments:. *

`graph1':
     The first input graph, may be directed or undirected. This is
     supposed to be the larger graph.

`graph2':
     The second input graph, it must have the same directedness as
     `graph1'. This is supposed to be the smaller graph.

`count':
     Pointer to an integer. The number of subgraph isomorphisms is
     stored here.

   *Returns:. *

`'
     Error code.

   Time complexity: exponential.

12.3.8 igraph_get_subisomorphisms_vf2 -- Return all subgraph isomorphic mappings
--------------------------------------------------------------------------------

     int igraph_get_subisomorphisms_vf2(const igraph_t *graph1,
     				   const igraph_t *graph2,
     				   igraph_vector_ptr_t *maps);

   This function collects all isomorphic mappings of `graph2' to a
subgraph of `graph1'. It uses the `igraph_subisomorphic_function_vf2()'
(see igraph_subisomorphic_function_vf2 --- Generic VF2 function for subgraph isomorphism problems)
function.

   *Arguments:. *

`graph1':
     The first input graph, may be directed or undirected. This is
     supposed to be the larger graph.

`graph2':
     The second input graph, it must have the same directedness as
     `graph1'. This is supposed to be the smaller graph.

`maps':
     Pointer vector. On return it contains pointers to
     `igraph_vector_t' objects, each vector is an isomorphic mapping of
     `graph2' to a subgraph of `graph1'. Please note that you need to
     1) Destroy the vectors via `igraph_vector_destroy()' (see
     igraph_vector_destroy --- Destroys a vector object_), 2) free
     them via `free()' and then 3) call `igraph_vector_ptr_destroy()'
     (see igraph_vector_ptr_destroy --- Destroys a pointer vector_)
     on the pointer vector to deallocate all memory when `maps' is no
     longer needed.

   *Returns:. *

`'
     Error code.

   Time complexity: exponential.

12.3.9 igraph_subisomorphic_function_vf2 -- Generic VF2 function for subgraph isomorphism problems
--------------------------------------------------------------------------------------------------

     int igraph_subisomorphic_function_vf2(const igraph_t *graph1,
     				      const igraph_t *graph2,
     				      igraph_vector_t *map12,
     				      igraph_vector_t *map21,
     				      igraph_isohandler_t *function,
     				      void *arg);

   This function is the pair of `igraph_isomorphic_function_vf2()'
(see igraph_isomorphic_function_vf2 --- The generic VF2 interface),
for subgraph isomorphism problems. It searches for subgraphs of
`graph1' which are isomorphic to `graph2'. When it founds an isomorphic
mapping it calls the supplied callback `function'.  The mapping (and
its inverse) and the additional `arg' argument are supplied to the
callback.

   *Arguments:. *

`graph1':
     The first input graph, may be directed or undirected. This is
     supposed to be the larger graph.

`graph2':
     The second input graph, it must have the same directedness as
     `graph1'. This is supposed to be the smaller graph.

`map12':
     Pointer to a vector or `NULL'. If not `NULL', then an isomorphic
     mapping from `graph1' to `graph2' is stored here.

`map21':
     Pointer to a vector ot `NULL'. If not `NULL', then an isomorphic
     mapping from `graph2' to `graph1' is stored here.

`function':
     A pointer to a function of type `igraph_isohandler_t' (see
     igraph_isohandler_t --- Callback type; called when an isomorphism was found).
     This will be called whenever a subgraph isomorphism
     is found. If the function returns with a non-zero value then the
     search is continued, otherwise it stops and the function returns.

`arg':
     Extra argument to supply to the callback `function'.

   *Returns:. *

`'
     Error code.

   Time complexity: exponential.

12.4 Functions for graphs with 3 or 4 vertices
==============================================

12.4.1 igraph_isomorphic_34 -- Graph isomorphism for 3-4 vertices
-----------------------------------------------------------------

     int igraph_isomorphic_34(const igraph_t *graph1, const igraph_t *graph2,
     			 igraph_bool_t *iso);

   This function uses precomputed indices to decide isomorphism
problems for graphs with only 3 or 4 vertices.

   *Arguments:. *

`graph1':
     The first input graph.

`graph2':
     The second input graph. Must have the same directedness as
     `graph1'.

`iso':
     Pointer to a boolean, the result is stored here.

   *Returns:. *

`'
     Error code.

   Time complexity: O(1).

12.4.2 igraph_isoclass -- Determine the isomorphism class of a graph with 3 or 4 vertices
-----------------------------------------------------------------------------------------

     int igraph_isoclass(const igraph_t *graph, igraph_integer_t *isoclass);

   All graphs with a given number of vertices belong to a number of
isomorpism classes, with every graph in a given class being isomorphic
to each other.

   This function gives the isomorphism class (a number) of a graph. Two
graphs have the same isomorphism class if and only if they are
isomorphic.

   The first isomorphism class is numbered zero and it is the empty
graph, the last isomorphism class is the full graph. The number of
isomorphism class for directed graphs with three vertices is 16
(between 0 and 15), for undirected graph it is only 4. For graphs with
four vertices it is 218 (directed) and 11 (undirected).

   *Arguments:. *

`graph':
     The graph object.

`isoclass':
     Pointer to an integer, the isomorphism class will be stored here.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_isomorphic()' (see igraph_isomorphic --- Decides whether two graphs are isomorphic),
     `igraph_isoclass_subgraph()' (see
     igraph_isoclass_subgraph --- The isomorphism class of a subgraph of a graph_),
     `igraph_isoclass_create()' (see
     igraph_isoclass_create --- Creates a graph from the given isomorphism class_),
     `igraph_motifs_randesu()' (see
     igraph_motifs_randesu --- Count the number of motifs in a graph).

   Because of some limitations this function works only for graphs with
three of four vertices.

   Time complexity: O(|E|), the number of edges in the graph.

12.4.3 igraph_isoclass_subgraph -- The isomorphism class of a subgraph of a graph.
----------------------------------------------------------------------------------

     int igraph_isoclass_subgraph(const igraph_t *graph, igraph_vector_t *vids,
     			     igraph_integer_t *isoclass);

   This function is only implemented for subgraphs with three or four
vertices.

   *Arguments:. *

`graph':
     The graph object.

`vids':
     A vector containing the vertex ids to be considered as a subgraph.
     Each vertex id should be included at most once.

`isoclass':
     Pointer to an integer, this will be set to the isomorphism class.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_isoclass()' (see igraph_isoclass --- Determine the isomorphism class of a graph with 3 or 4 vertices),
     `igraph_isomorphic()' (see igraph_isomorphic --- Decides whether two graphs are isomorphic),
     `igraph_isoclass_create()' (see
     igraph_isoclass_create --- Creates a graph from the given isomorphism class_).

   Time complexity: O((d+n)*n), d is the average degree in the network,
and n is the number of vertices in `vids'.

12.4.4 igraph_isoclass_create -- Creates a graph from the given isomorphism class.
----------------------------------------------------------------------------------

     int igraph_isoclass_create(igraph_t *graph, igraph_integer_t size,
     			   igraph_integer_t number, igraph_bool_t directed);

   This function is implemented only for graphs with three or four
vertices.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`size':
     The number of vertices to add to the graph.

`number':
     The isomorphism class.

`directed':
     Logical constant, whether to create a directed graph.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_isoclass()' (see igraph_isoclass --- Determine the isomorphism class of a graph with 3 or 4 vertices),
     `igraph_isoclass_subgraph()' (see igraph_isoclass_subgraph --- The isomorphism class of a subgraph of a graph_),
     `igraph_isomorphic()' (see igraph_isomorphic --- Decides whether two graphs are isomorphic).

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges in the graph to create.

13 Graph Motifs, Dyad Census and Triad Census
*********************************************

This section deals with functions which find small induced subgraphs in
a graph. These were first defined for subgraphs of two and three
vertices by Holland and Leinhardt, and named dyad census and triad
census.

13.1 igraph_dyad_census -- Calculating the dyad census as defined by Holland and Leinhardt
==========================================================================================

     int igraph_dyad_census(const igraph_t *graph, igraph_integer_t *mut,
     		       igraph_integer_t *asym, igraph_integer_t *null);

   Dyad census means classifying each pair of vertices of a directed
graph into three categories: mutual, there is an edge from `a' to `b'
and also from `b' to `a'; asymmetric, there is an edge either from `a'
to `b' or from `b' to `a' but not the other way and null, no edges
between `a' and `b'.

   Holland, P.W. and Leinhardt, S.  (1970).  A Method for Detecting
Structure in Sociometric Data.  American Journal of Sociology, 70,
492-513.

   *Arguments:. *

`graph':
     The input graph, a warning is given if undirected as the results
     are undefined for undirected graphs.

`mut':
     Pointer to an integer, the number of mutual dyads is stored here.

`asym':
     Pointer to an integer, the number of asymmetric dyads is stored
     here.

`null':
     Pointer to an integer, the number of null dyads is stored here.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_reciprocity()' (see igraph_reciprocity --- Calculates the reciprocity of a directed graph_),
     `igraph_triad_census()'
     (see igraph_triad_census --- Triad census; as defined by Davis and Leinhardt).

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges.

13.2 igraph_triad_census -- Triad census, as defined by Davis and Leinhardt
===========================================================================

     int igraph_triad_census(const igraph_t *graph, igraph_vector_t *res);

   Calculating the triad census means classifying every triple of
vertices in a directed graph. A triple can be in one of 16 states:

`003 '
     A, B, C, the empty graph.

`012 '
     A->B, C, a graph with a single directed edge.

`102 '
     A<->B, C, a graph with a mutual connection between two vertices.

`021D '
     A<-B->C, the binary out-tree.

`021U '
     A->B<-C, the binary in-tree.

`021C '
     A->B->C, the directed line.

`111D '
     A<->B<-C.

`111U '
     A<->B->C.

`030T '
     A->B<-C, A->C.

`030C '
     A<-B<-C, A->C.

`201 '
     A<->B<->C.

`120D '
     A<-B->C, A<->C.

`120U '
     A->B<-C, A<->C.

`120C '
     A->B->C, A<->C.

`210 '
     A->B<->C, A<->C.

`300 '
     A<->B<->C, A<->C, the complete graph.

   See also Davis, J.A. and Leinhardt, S.  (1972).  The Structure of
Positive Interpersonal Relations in Small Groups.  In J. Berger (Ed.),
Sociological Theories in Progress, Volume 2, 218-251.  Boston: Houghton
Mifflin.

   This function calls `igraph_motifs_randesu()' (see
igraph_motifs_randesu --- Count the number of motifs in a graph)
which is an implementation of the FANMOD motif finder tool, see
`igraph_motifs_randesu()' (see igraph_motifs_randesu --- Count the number of motifs in a graph)
for details. Note that the order of the
triads is not the same for `igraph_triad_census()' (see
igraph_triad_census --- Triad census; as defined by Davis and Leinhardt)
and `igraph_motifs_randesu()' (see igraph_motifs_randesu --- Count the number of motifs in a graph).

   *Arguments:. *

`graph':
     The input graph. A warning is given for undirected graphs, as the
     result is undefined for those.

`res':
     Pointer to an initialized vector, the result is stored here in the
     same order as given in the list above. Note that this order is
     different than the one used by `igraph_motifs_randesu()' (see
     igraph_motifs_randesu --- Count the number of motifs in a graph).

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_motifs_randesu()' (see igraph_motifs_randesu --- Count the number of motifs in a graph),
     `igraph_dyad_census()' (see
     igraph_dyad_census --- Calculating the dyad census as defined by Holland and Leinhardt).

   Time complexity: TODO.

13.3 Graph motifs
=================

13.3.1 igraph_motifs_randesu -- Count the number of motifs in a graph
---------------------------------------------------------------------

     int igraph_motifs_randesu(const igraph_t *graph, igraph_vector_t *hist,
     			  int size, const igraph_vector_t *cut_prob);

   Motifs are small subgraphs of a given structure in a graph. It is
argued that the motif profile (ie. the number of different motifs in
the graph) is characteristic for different types of networks and
network function is related to the motifs in the graph.

   This function is able to find the different motifs of size three and
four (ie. the number of different subgraphs with three and four
vertices) in the network. (This limitation is the result of the lack of
code to decide graph isomorphism for larger graphs.)

   In a big network the total number of motifs can be very large, so it
takes a lot of time to find all of them, a sampling method can be used.
This function is capable of doing sampling via the `cut_prob' argument.
This argument gives the probability that a branch of the motif search
tree will not be explored. See S. Wernicke and F. Rasche: FANMOD: a
tool for fast network motif detection, Bioinformatics 22(9), 1152-1153,
2006 for details.

   Set the `cut_prob' argument to a zero vector for finding all motifs.

   Directed motifs will be counted in directed graphs and undirected
motifs in undirected graphs.

   *Arguments:. *

`graph':
     The graph to find the motifs in.

`hist':
     The result of the computation, it gives the number of motifs found
     for each isomorphism class. See `igraph_isoclass()' (see
     igraph_isoclass --- Determine the isomorphism class of a graph with 3 or 4 vertices)
     for help about isomorphism classes.

`size':
     The size of the motifs to search for. Only three and four are
     implemented currently. The limitation is not in the motif finding
     code, but the graph isomorphism code.

`cut_prob':
     Vector of probabilities for cutting the search tree at a given
     level. The first element is the first level, etc.  Supply all
     zeros here (of length `size') to find all motifs in a graph.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_motifs_randesu_estimate()' (see
     igraph_motifs_randesu_estimate --- Estimate the total number of motifs in a graph)
     for estimating the number of motifs in a
     graph, this can help to set the `cut_prob' parameter;
     `igraph_motifs_randesu_no()' (see igraph_motifs_randesu_no --- Count the total number of motifs in a graph)
     to calculate the
     total number of motifs of a given size in a graph.

   Time complexity: TODO.

13.3.2 igraph_motifs_randesu_no -- Count the total number of motifs in a graph
------------------------------------------------------------------------------

     int igraph_motifs_randesu_no(const igraph_t *graph, igraph_integer_t *no,
     			     int size, const igraph_vector_t *cut_prob);

   This function counts the total number of motifs in a graph without
assigning isomorphism classes to them.

   Directed motifs will be counted in directed graphs and undirected
motifs in undirected graphs.

   *Arguments:. *

`graph':
     The graph object to study.

`no':
     Pointer to an integer type, the result will be stored here.

`size':
     The size of the motifs to count.

`cut_prob':
     Vector giving the probabilities that a branch of the search tree
     will be cut at a given level.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_motifs_randesu()' (see igraph_motifs_randesu --- Count the number of motifs in a graph),
     `igraph_motifs_randesu_estimate()' (see
     igraph_motifs_randesu_estimate --- Estimate the total number of motifs in a graph).

   Time complexity: TODO.

13.3.3 igraph_motifs_randesu_estimate -- Estimate the total number of motifs in a graph
---------------------------------------------------------------------------------------

     int igraph_motifs_randesu_estimate(const igraph_t *graph, igraph_integer_t *est,
     				   int size, const igraph_vector_t *cut_prob,
     				   igraph_integer_t sample_size,
     				   const igraph_vector_t *parsample);

   This function is useful for large graphs for which it is not
feasible to count all the different motifs, because there is very many
of them.

   The total number of motifs is estimated by taking a sample of
vertices and counts all motifs in which these vertices are included.
(There is also a `cut_prob' parameter which gives the probabilities to
cut a branch of the search tree.)

   Directed motifs will be counted in directed graphs and undirected
motifs in undirected graphs.

   *Arguments:. *

`graph':
     The graph object to study.

`est':
     Pointer to an integer type, the result will be stored here.

`size':
     The size of the motif to look for.

`cut_prob':
     Vector giving the probabilities to cut a branch of the search tree
     and omit counting the motifs in that branch.  It contains a
     probability for each level. Supply `size' zeros here to count all
     the motifs in the sample.

`sample_size':
     The number of vertices to use as the sample. This parameter is
     only used if the `parsample' argument is a null pointer.

`parsample':
     Either pointer to an initialized vector or a null pointer. If a
     vector then the vertex ids in the vector are used as a sample. If
     a null pointer then the `sample_size' argument is used to create a
     sample of vertices drawn with uniform probability.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_motifs_randesu()' (see igraph_motifs_randesu --- Count the number of motifs in a graph),
     `igraph_motifs_randesu_no()'
     (see igraph_motifs_randesu_no --- Count the total number of motifs in a graph).

   Time complexity: TODO.

14 Generating Layouts for Graph Drawing
***************************************

14.1 2D layout generators
=========================

Layout generator functions (or at least most of them) try to place the
vertices and edges of a graph on a 2D plane or in 3D space in a way
which visually pleases the human eye.

   They take a graph object and a number of parameters as arguments and
return an `igraph_matrix_t', in which each row gives the coordinates of
a vertex.

14.1.1 igraph_layout_random -- Places the vertices uniform randomly on a plane.
-------------------------------------------------------------------------------

     int igraph_layout_random(const igraph_t *graph, igraph_matrix_t *res);

   *Arguments:. *

`graph':
     Pointer to an initialized graph object.

`res':
     Pointer to an initialized graph object. This will contain the
     result and will be resized in needed.

   *Returns:. *

`'
     Error code. The current implementation always returns with success.

   Time complexity: O(|V|), the number of vertices.

14.1.2 igraph_layout_circle -- Places the vertices uniformly on a circle, in the order of vertex ids.
-----------------------------------------------------------------------------------------------------

     int igraph_layout_circle(const igraph_t *graph, igraph_matrix_t *res);

   *Arguments:. *

`graph':
     Pointer to an initialized graph object.

`res':
     Pointer to an initialized graph object. This will contain the
     result and will be resized in needed.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|), the number of vertices.

14.1.3 igraph_layout_star -- Generate a star-like layout
--------------------------------------------------------

     int igraph_layout_star(const igraph_t *graph, igraph_matrix_t *res,
     		       igraph_integer_t center, const igraph_vector_t *order);

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to an initialized matrix, the layout is stored here.

`center':
     The id of the vertex to put in the center.

`order':
     A numeric vector giving the order of the vertices (including the
     center vertex!). If a null pointer, then the vertices are placed
     in increasing vertex id order.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|), linear in the number of vertices.

   *See also:. *

`'
     `igraph_layout_circle()' (see igraph_layout_circle --- Places the vertices uniformly on a circle; in the order of vertex ids_)
     and other layout generators.

14.1.4 igraph_layout_graphopt -- Optimizes vertex layout via the graphopt algorithm.
------------------------------------------------------------------------------------

     int igraph_layout_graphopt(const igraph_t *graph, igraph_matrix_t *res,
     			   igraph_integer_t niter,
     			   igraph_real_t node_charge, igraph_real_t node_mass,
     			   igraph_integer_t spring_length,
     			   igraph_real_t spring_constant,
     			   igraph_real_t max_sa_movement,
     			   igraph_bool_t use_seed);

   This is a port of the graphopt layout algorithm by Michael Schmuhl.
graphopt version 0.4.1 was rewritten in C and the support for layers
was removed (might be added later) and a code was a bit reorganized to
avoid some unneccessary steps is the node charge (see below) is zero.

   graphopt uses physical analogies for defining attracting and
repelling forces among the vertices and then the physical system is
simulated until it reaches an equilibrium. (There is no simulated
annealing or anything like that, so a stable fixed point is not
guaranteed.)

   See also http://www.schmuhl.org/graphopt/
(http://www.schmuhl.org/graphopt/) for the original graphopt.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to an initialized matrix, the result will be stored here
     and its initial contents is used the starting point of the
     simulation if the `use_seed' argument is true. Note that in this
     case the matrix should have the proper size, otherwise a warning
     is issued and the supplied values are ignored. If no starting
     positions are given (or they are invalid) then a random staring
     position is used.  The matrix will be resized if needed.

`niter':
     Integer constant, the number of iterations to perform.  Should be
     a couple of hundred in general. If you have a large graph then you
     might want to only do a few iterations and then check the result.
     If it is not good enough you can feed it in again in the `res'
     argument. The original graphopt default if 500.

`node_charge':
     The charge of the vertices, used to calculate electric repulsion.
     The original graphopt default is 0.001.

`node_mass':
     The mass of the vertices, used for the spring forces.  The
     original graphopt defaults to 30.

`spring_length':
     The length of the springs, an integer number.  The original
     graphopt defaults to zero.

`spring_constant':
     The spring constant, the original graphopt defaults to one.

`max_sa_movement':
     Real constant, it gives the maximum amount of movement allowed in
     a single step along a single axis. The original graphopt default
     is 5.

`use_seed':
     Logical scalar, whether to use the positions in `res' as a
     starting configuration. See also `res' above.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n (|V|^2+|E|) ), n is the number of iterations,
|V| is the number of vertices, |E| the number of edges. If
`node_charge' is zero then it is only O(n|E|).

14.1.5 The DrL layout generator
-------------------------------

DrL is a sophisticated layout generator developed and implemented by
Shawn Martin et al., see
http://www.cs.sandia.gov/~smartin/software.html
(http://www.cs.sandia.gov/~smartin/software.html) for details. Only a
subset of the complete DrL functionality is included in igraph,
parallel runs and recursive, multi-level layouting is not supported.

   The parameters of the layout are stored in an
`igraph_layout_drl_options_t' (see igraph_layout_drl_options_t --- Parameters for the DrL layout generator)
structure, this can be
initialized by calling the function `igraph_layout_drl_options_init()'
(see igraph_layout_drl_options_init --- Initialize parameters for the DrL layout generator).
The fields of this structure can then be
adjusted by hand if needed.  The layout is calculated by an
`igraph_layout_drl()' (see igraph_layout_drl --- The DrL layout generator)
call.

14.1.5.1 igraph_layout_drl_options_t -- Parameters for the DrL layout generator
...............................................................................

     typedef struct igraph_layout_drl_options_t {
       igraph_real_t    edge_cut;
       igraph_integer_t init_iterations;
       igraph_real_t    init_temperature;
       igraph_real_t    init_attraction;
       igraph_real_t    init_damping_mult;
       igraph_integer_t liquid_iterations;
       igraph_real_t    liquid_temperature;
       igraph_real_t    liquid_attraction;
       igraph_real_t    liquid_damping_mult;
       igraph_integer_t expansion_iterations;
       igraph_real_t    expansion_temperature;
       igraph_real_t    expansion_attraction;
       igraph_real_t    expansion_damping_mult;
       igraph_integer_t cooldown_iterations;
       igraph_real_t    cooldown_temperature;
       igraph_real_t    cooldown_attraction;
       igraph_real_t    cooldown_damping_mult;
       igraph_integer_t crunch_iterations;
       igraph_real_t    crunch_temperature;
       igraph_real_t    crunch_attraction;
       igraph_real_t    crunch_damping_mult;
       igraph_integer_t simmer_iterations;
       igraph_real_t    simmer_temperature;
       igraph_real_t    simmer_attraction;
       igraph_real_t    simmer_damping_mult;
     } igraph_layout_drl_options_t;

   *Values:. *

`edge_cut':
     The edge cutting parameter.  Edge cutting is done in the late
     stages of the algorithm in order to achieve less dense layouts.
     Edges are cut if there is a lot of stress on them (a large value
     in the objective function sum).  The edge cutting parameter is a
     value between 0 and 1 with 0 representing no edge cutting and 1
     representing maximal edge cutting. The default value is 32/40.

`init_iterations':
     Number of iterations, initial phase.

`init_temperature':
     Start temperature, initial phase.

`init_attraction':
     Attraction, initial phase.

`init_damping_mult':
     Damping factor, initial phase.

`liquid_iterations':
     Number of iterations in the liquid phase.

`liquid_temperature':
     Start temperature in the liquid phase.

`liquid_attraction':
     Attraction in the liquid phase.

`liquid_damping_mult':
     Multiplicatie damping factor, liquid phase.

`expansion_iterations':
     Number of iterations in the expansion phase.

`expansion_temperature':
     Start temperature in the expansion phase.

`expansion_attraction':
     Attraction, expansion phase.

`expansion_damping_mult':
     Damping factor, expansion phase.

`cooldown_iterations':
     Number of iterations in the cooldown phase.

`cooldown_temperature':
     Start temperature in the cooldown phase.

`cooldown_attraction':
     Attraction in the cooldown phase.

`cooldown_damping_mult':
     Damping fact int the cooldown phase.

`crunch_iterations':
     Number of iterations in the crunch phase.

`crunch_temperature':
     Start temperature in the crunch phase.

`crunch_attraction':
     Attraction in the crunch phase.

`crunch_damping_mult':
     Damping factor in the crunch phase.

`simmer_iterations':
     Number of iterations in the simmer phase.

`simmer_temperature':
     Start temperature in te simmer phase.

`simmer_attraction':
     Attraction in the simmer phase.

`simmer_damping_mult':
     Multiplicative damping factor in the simmer phase.

14.1.5.2 igraph_layout_drl_default_t -- Predefined parameter templates for the DrL layout generator
...................................................................................................

     typedef enum { IGRAPH_LAYOUT_DRL_DEFAULT=0,
     	       IGRAPH_LAYOUT_DRL_COARSEN,
     	       IGRAPH_LAYOUT_DRL_COARSEST,
     	       IGRAPH_LAYOUT_DRL_REFINE,
     	       IGRAPH_LAYOUT_DRL_FINAL } igraph_layout_drl_default_t;

   These constants can be used to initialize a set of DrL parameters.
These can then be modified according to the user's needs.

   *Values:. *

`IGRAPH_LAYOUT_DRL_DEFAULT':
     The deafult parameters.

`IGRAPH_LAYOUT_DRL_COARSEN':
     Slightly modified parameters to get a coarser layout.

`IGRAPH_LAYOUT_DRL_COARSEST':
     An even coarser layout.

`IGRAPH_LAYOUT_DRL_REFINE':
     Refine an already calculated layout.

`IGRAPH_LAYOUT_DRL_FINAL':
     Finalize an already refined layout.

14.1.5.3 igraph_layout_drl_options_init -- Initialize parameters for the DrL layout generator
.............................................................................................

     int igraph_layout_drl_options_init(igraph_layout_drl_options_t *options,
     				   igraph_layout_drl_default_t templ);

   This function can be used to initialize the struct holding the
parameters for the DrL layout generator. There are a number of
predefined templates available, it is a good idea to start from one of
these by modifying some parameters.

   *Arguments:. *

`options':
     The struct to initialize.

`templ':
     The template to use. Currently the following templates are
     supplied: `IGRAPH_LAYOUT_DRL_DEFAULT',
     `IGRAPH_LAYOUT_DRL_COARSEN', `IGRAPH_LAYOUT_DRL_COARSEST',
     `IGRAPH_LAYOUT_DRL_REFINE' and `IGRAPH_LAYOUT_DRL_FINAL'.

   *Returns:. *

`'
     Error code.

   Time complexity: O(1).

14.1.5.4 igraph_layout_drl -- The DrL layout generator
......................................................

     int igraph_layout_drl(const igraph_t *graph, igraph_matrix_t *res,
     		      igraph_bool_t use_seed,
     		      igraph_layout_drl_options_t *options,
     		      const igraph_vector_t *weights,
     		      const igraph_vector_bool_t *fixed);

   This function implements the force-directed DrL layout generator.
Please see more at http://www.cs.sandia.gov/~smartin/software.html
(http://www.cs.sandia.gov/~smartin/software.html)

   *Arguments:. *

`graph':
     The input graph.

`use_seed':
     Logical scalar, if true, then the coordinates supplied in the
     `res' argument are used as starting points.

`res':
     Pointer to a matrix, the result layout is stored here. It will be
     resized as needed.

`options':
     The parameters to pass to the layout generator.

`weights':
     Edge weights, pointer to a vector. If this is a null pointer then
     every edge will have the same weight.

`fixed':
     Pointer to a logical vector, or a null pointer. This can be used
     to fix the position of some vertices. Vertices for which it is
     true will not be moved, but stay at the coordinates given in the
     `res' matrix. This argument is ignored if it is a null pointer or
     if use_seed is false.

   *Returns:. *

`'
     Error code.

   Time complexity: ???.

14.1.5.5 igraph_layout_drl_3d -- The DrL layout generator, 3d version.
......................................................................

     int igraph_layout_drl_3d(const igraph_t *graph, igraph_matrix_t *res,
     			 igraph_bool_t use_seed,
     			 igraph_layout_drl_options_t *options,
     			 const igraph_vector_t *weights,
     			 const igraph_vector_bool_t *fixed);

   This function implements the force-directed DrL layout generator.
Please see more at http://www.cs.sandia.gov/~smartin/software.html
(http://www.cs.sandia.gov/~smartin/software.html)

   This function uses a modified DrL generator that does the layout in
three dimensions.

   *Arguments:. *

`graph':
     The input graph.

`use_seed':
     Logical scalar, if true, then the coordinates supplied in the
     `res' argument are used as starting points.

`res':
     Pointer to a matrix, the result layout is stored here. It will be
     resized as needed.

`options':
     The parameters to pass to the layout generator.

`weights':
     Edge weights, pointer to a vector. If this is a null pointer then
     every edge will have the same weight.

`fixed':
     Pointer to a logical vector, or a null pointer. This can be used
     to fix the position of some vertices. Vertices for which it is
     true will not be moved, but stay at the coordinates given in the
     `res' matrix. This argument is ignored if it is a null pointer or
     if use_seed is false.

   *Returns:. *

`'
     Error code.

   Time complexity: ???.

   *See also:. *

`'
     `igraph_layout_drl()' (see igraph_layout_drl --- The DrL layout generator)
     for the standard 2d version.

14.1.6 igraph_layout_fruchterman_reingold -- Places the vertices on a plane according to the Fruchterman-Reingold algorithm.
----------------------------------------------------------------------------------------------------------------------------

     int igraph_layout_fruchterman_reingold(const igraph_t *graph, igraph_matrix_t *res,
     				       igraph_integer_t niter, igraph_real_t maxdelta,
     				       igraph_real_t area, igraph_real_t coolexp,
     				       igraph_real_t repulserad, igraph_bool_t use_seed,
     				       const igraph_vector_t *weight);

   This is a force-directed layout, see Fruchterman, T.M.J. and
Reingold, E.M.: Graph Drawing by Force-directed Placement.  Software -
Practice and Experience, 21/11, 1129-1164, 1991.  This function was
ported from the SNA R package.

   *Arguments:. *

`graph':
     Pointer to an initialized graph object.

`res':
     Pointer to an initialized matrix object. This will contain the
     result and will be resized in needed.

`niter':
     The number of iterations to do. A reasonable default value is 500.

`maxdelta':
     The maximum distance to move a vertex in an iteration. A
     reasonable default value is the number of vertices.

`area':
     The area parameter of the algorithm. A reasonable default is the
     square of the number of vertices.

`coolexp':
     The cooling exponent of the simulated annealing.  A reasonable
     default is 1.5.

`repulserad':
     Determines the radius at which vertex-vertex repulsion cancels out
     attraction of adjacent vertices. A reasonable default is `area'
     times the number of vertices.

`use_seed':
     Logical, if true the supplied values in the `res' argument are
     used as an initial layout, if false a random initial layout is
     used.

`weight':
     Pointer to a vector containing edge weights, the attraction along
     the edges will be multiplied by these.  It will be ignored if it
     is a null-pointer.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|^2) in each iteration, |V| is the number of
vertices in the graph.

14.1.7 igraph_layout_kamada_kawai -- Places the vertices on a plane according the Kamada-Kawai algorithm.
---------------------------------------------------------------------------------------------------------

     int igraph_layout_kamada_kawai(const igraph_t *graph, igraph_matrix_t *res,
     			       igraph_integer_t niter, igraph_real_t sigma,
     			       igraph_real_t initemp, igraph_real_t coolexp,
     			       igraph_real_t kkconst, igraph_bool_t use_seed);

   This is a force directed layout, see  Kamada, T. and Kawai, S.: An
Algorithm for Drawing General Undirected Graphs. Information Processing
Letters, 31/1, 7-15, 1989.  This function was ported from the SNA R
package.

   *Arguments:. *

`graph':
     A graph object.

`res':
     Pointer to an initialized matrix object. This will contain the
     result and will be resized if needed.

`niter':
     The number of iterations to perform. A reasonable default value is
     1000.

`sigma':
     Sets the base standard deviation of position change proposals. A
     reasonable default value is the number of vertices / 4.

`initemp':
     Sets the initial temperature for the annealing.  A reasonable
     default value is 10.

`coolexp':
     The cooling exponent of the annealing.  A reasonable default value
     is 0.99.

`kkconst':
     The Kamada-Kawai vertex attraction constant.

`use_seed':
     Boolean, whether to use the values cupplied in the `res' argument
     as the initial configuration. If zero then a random initial
     configuration is used.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|^2) for each iteration, |V| is the number of
vertices in the graph.

14.1.8 igraph_layout_reingold_tilford -- Reingold-Tilford layout for tree graphs
--------------------------------------------------------------------------------

     int igraph_layout_reingold_tilford(const igraph_t *graph,
     				   igraph_matrix_t *res, long int root);

   Arranges the nodes in a tree where the given node is used as the
root.  The tree is directed downwards and the parents are centered
above its children. For the exact algorithm, see:

   Reingold, E and Tilford, J: Tidier drawing of trees.  IEEE Trans.
Softw. Eng., SE-7(2):223-228, 1981

   If the given graph is not a tree, a breadth-first search is executed
first to obtain a possible spanning tree.

   *Arguments:. *

`graph':
     The graph object.

`res':
     The result, the coordinates in a matrix. The parameter should
     point to an initialized matrix object and will be resized.

`root':
     The index of the root vertex.

   *Returns:. *

`'
     Error code.

   Added in version 0.2.

   TODO: decompose and merge for not fully connected graphs TODO:
possible speedup could be achieved if we use a table for storing the
children of each node in the tree. (Now the implementation uses a
single array containing the parent of each node and a node's children
are determined by looking for other nodes that have this node as parent)

   *See also:. *

`'
     `igraph_layout_reingold_tilford_circular()' (see
     igraph_layout_reingold_tilford_circular --- Circular Reingold-Tilford layout for trees).

14.1.9 igraph_layout_reingold_tilford_circular -- Circular Reingold-Tilford layout for trees
--------------------------------------------------------------------------------------------

     int igraph_layout_reingold_tilford_circular(const igraph_t *graph,
     					    igraph_matrix_t *res, long int root);

   This layout is almost the same as `igraph_layout_reingold_tilford()'
(see igraph_layout_reingold_tilford --- Reingold-Tilford layout for tree graphs),
but the tree is drawn in a circular way, with the root
vertex in the center.

   *Arguments:. *

`graph':
     The graph object.

`res':
     The result, the coordinates in a matrix. The parameter should
     point to an initialized matrix object and will be resized.

`root':
     The index of the root vertex.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_layout_reingold_tilford()' (see
     igraph_layout_reingold_tilford --- Reingold-Tilford layout for tree graphs).

14.1.10 igraph_layout_grid_fruchterman_reingold -- Force based layout generator for large graphs.
-------------------------------------------------------------------------------------------------

     int igraph_layout_grid_fruchterman_reingold(const igraph_t *graph,
     					    igraph_matrix_t *res,
     					    igraph_integer_t niter, igraph_real_t maxdelta,
     					    igraph_real_t area, igraph_real_t coolexp,
     					    igraph_real_t repulserad,
     					    igraph_real_t cellsize,
     					    igraph_bool_t use_seed);

   This algorithm is the same as the Fruchterman-Reingold layout
generator, but it partitions the 2d space to a grid and and vertex
repulsion is calculated only for vertices nearby.

   *Arguments:. *

`graph':
     The graph object.

`res':
     The result, the coordinates in a matrix. The parameter should
     point to an initialized matrix object and will be resized.

`niter':
     The number of iterations to do. A reasonable default value is 500.

`maxdelta':
     The maximum distance to move a vertex in an iteration. A
     reasonable default value is the number of vertices.

`area':
     The area parameter of the algorithm. A reasonable default is the
     square of the number of vertices.

`coolexp':
     The cooling exponent of the simulated annealing.  A reasonable
     default is 1.5.

`repulserad':
     Determines the radius at which vertex-vertex repulsion cancels out
     attraction of adjacent vertices. A reasonable default is `area'
     times the number of vertices.

`cellsize':
     The size of the grid cells. A reasonable default is the fourth
     root of `area' (or the square root of the number of vertices if
     `area' is also left at its default value)

`use_seed':
     Logical, if true, the coordinates passed in `res' (should have the
     appropriate size) will be used for the first iteration.

   *Returns:. *

`'
     Error code.

   Added in version 0.2.

   Time complexity: ideally (constant number of vertices in each cell)
O(niter*(|V|+|E|)), in the worst case O(niter*(|V|^2+|E|)).

14.1.11 igraph_layout_lgl -- Force based layout algorithm for large graphs.
---------------------------------------------------------------------------

     int igraph_layout_lgl(const igraph_t *graph, igraph_matrix_t *res,
     		      igraph_integer_t maxit, igraph_real_t maxdelta,
     		      igraph_real_t area, igraph_real_t coolexp,
     		      igraph_real_t repulserad, igraph_real_t cellsize,
     		      igraph_integer_t proot);

   This is a layout generator similar to the Large Graph Layout
algorithm and program (http://bioinformatics.icmb.utexas.edu/lgl/
(http://bioinformatics.icmb.utexas.edu/lgl/)). But unlike LGL, this
version uses a Fruchterman-Reingold style simulated annealing algorithm
for placing the vertices. The speedup is achived by placing the
vertices on a grid and calculating the repulsion only for vertices
which are closer to each other than a limit.

   *Arguments:. *

`graph':
     The (initialized) graph object to place.

`res':
     Pointer to an initialized matrix object to hold the result. It
     will be resized if needed.

`maxit':
     The maximum number of cooling iterations to perform for each
     layout step. A reasonable default is 150.

`maxdelta':
     The maximum length of the move allowed for a vertex in a single
     iteration. A reasonable default is the number of vertices.

`area':
     This parameter gives the area of the square on which the vertices
     will be placed. A reasonable default value is the number of
     vertices squared.

`coolexp':
     The cooling exponent. A reasonable default value is 1.5.

`repulserad':
     Determines the radius at which vertex-vertex repulsion cancels out
     attraction of adjacenct vertices. A reasonable default value is
     `area' times the number of vertices.

`cellsize':
     The size of the grid cells, one side of the square. A reasonable
     default value is the fourth root of `area' (or the square root of
     the number of vertices if `area' is also left at its default
     value).

`proot':
     The root vertex, this is placed first, its neighbors in the first
     iteration, second neighbors in the second, etc. If negative then a
     random vertex is chosen.

   *Returns:. *

`'
     Error code.

   Added in version 0.2.

   Time complexity: ideally O(dia*maxit*(|V|+|E|)), |V| is the number
of vertices, dia is the diameter of the graph, worst case complexity is
still O(dia*maxit*(|V|^2+|E|)), this is the case when all vertices
happen to be in the same grid cell.

14.2 3D layout generators
=========================

14.2.1 igraph_layout_random_3d -- Random layout in 3D
-----------------------------------------------------

     int igraph_layout_random_3d(const igraph_t *graph, igraph_matrix_t *res);

   *Arguments:. *

`graph':
     The graph to place.

`res':
     Pointer to an initialized matrix object. It will be resized to
     hold the result.

   *Returns:. *

`'
     Error code. The current implementation always returns with success.

   Added in version 0.2.

   Time complexity: O(|V|), the number of vertices.

14.2.2 igraph_layout_sphere -- Places vertices (more or less) uniformly on a sphere.
------------------------------------------------------------------------------------

     int igraph_layout_sphere(const igraph_t *graph, igraph_matrix_t *res);

   The algorithm was described in the following paper: Distributing
many points on a sphere by E.B. Saff and A.B.J. Kuijlaars, _
Mathematical Intelligencer _ 19.1 (1997) 5-11.

   *Arguments:. *

`graph':
     Pointer to an initialized graph object.

`res':
     Pointer to an initialized matrix object, the will be stored here.
     It will be resized.

   *Returns:. *

`'
     Error code. The current implementation always returns with success.

   Added in version 0.2.

   Time complexity: O(|V|), the number of vertices in the graph.

14.2.3 igraph_layout_fruchterman_reingold_3d -- 3D Fruchterman-Reingold algorithm.
----------------------------------------------------------------------------------

     int igraph_layout_fruchterman_reingold_3d(const igraph_t *graph,
     					  igraph_matrix_t *res,
     					  igraph_integer_t niter, igraph_real_t maxdelta,
     					  igraph_real_t volume, igraph_real_t coolexp,
     					  igraph_real_t repulserad,
     					  igraph_bool_t use_seed,
     					  const igraph_vector_t *weight);

   This is the 3D version of the force based Fruchterman-Reingold
layout (see `igraph_layout_fruchterman_reingold' (see
igraph_layout_fruchterman_reingold --- Places the vertices on a plane according to the Fruchterman-Reingold algorithm_)
for the 2D version

   This function was ported from the SNA R package.

   *Arguments:. *

`graph':
     Pointer to an initialized graph object.

`res':
     Pointer to an initialized matrix object. This will contain the
     result and will be resized in needed.

`niter':
     The number of iterations to do. A reasonable default value is 500.

`maxdelta':
     The maximum distance to move a vertex in an iteration. A
     reasonable default value is the number of vertices.

`volume':
     The volume parameter of the algorithm. A reasonable default is the
     number of vertices^3.

`coolexp':
     The cooling exponent of the simulated annealing.  A reasonable
     default is 1.5.

`repulserad':
     Determines the radius at which vertex-vertex repulsion cancels out
     attraction of adjacent vertices. A reasonable default is `volume'
     times the number of vertices.

`use_seed':
     Logical, if true the supplied values in the `res' argument are
     used as an initial layout, if false a random initial layout is
     used.

`weight':
     Pointer to a vector containing edge weights, the attraction along
     the edges will be multiplied by these.  It will be ignored if it
     is a null-pointer.

   *Returns:. *

`'
     Error code.

   Added in version 0.2.

   Time complexity: O(|V|^2) in each iteration, |V| is the number of
vertices in the graph.

14.2.4 igraph_layout_kamada_kawai_3d -- 3D version of the force based Kamada-Kawai layout.
------------------------------------------------------------------------------------------

     int igraph_layout_kamada_kawai_3d(const igraph_t *graph, igraph_matrix_t *res,
     				  igraph_integer_t niter, igraph_real_t sigma,
     				  igraph_real_t initemp, igraph_real_t coolexp,
     				  igraph_real_t kkconst, igraph_bool_t use_seed);

   The pair of the `igraph_layout_kamada_kawai' (see
igraph_layout_kamada_kawai --- Places the vertices on a plane according the Kamada-Kawai algorithm_)
2D layout generator

   This function was ported from the SNA R package.

   *Arguments:. *

`graph':
     A graph object.

`res':
     Pointer to an initialized matrix object. This will contain the
     result and will be resized if needed.

`niter':
     The number of iterations to perform. A reasonable default value is
     1000.

`sigma':
     Sets the base standard deviation of position change proposals. A
     reasonable default value is the number of vertices / 4.

`initemp':
     Sets the initial temperature for the annealing.  A reasonable
     default value is 10.

`coolexp':
     The cooling exponent of the annealing.  A reasonable default value
     is 0.99.

`kkconst':
     The Kamada-Kawai vertex attraction constant.  Typical value:
     (number of vertices)^2

`use_seed':
     Boolean, whether to use the values cupplied in the `res' argument
     as the initial configuration. If zero then a random initial
     configuration is used.

   *Returns:. *

`'
     Error code.

   Added in version 0.2.

   Time complexity: O(|V|^2) for each iteration, |V| is the number of
vertices in the graph.

14.3 Merging layouts
====================

14.3.1 igraph_layout_merge_dla -- Merge multiple layouts by using a DLA algorithm
---------------------------------------------------------------------------------

     int igraph_layout_merge_dla(igraph_vector_ptr_t *thegraphs,
     			    igraph_vector_ptr_t *coords,
     			    igraph_matrix_t *res);

   First each layout is covered by a circle. Then the layout of the
largest graph is placed at the origin. Then the other layouts are
placed by the DLA algorithm, larger ones first and smaller ones last.

   *Arguments:. *

`thegraphs':
     Pointer vector containing the graph object of which the layouts
     will be merged.

`coords':
     Pointer vector containing matrix objects with the 2d layouts of
     the graphs in `thegraphs'.

`res':
     Pointer to an initialized matrix object, the result will be stored
     here. It will be resized if needed.

   *Returns:. *

`'
     Error code.

   Added in version 0.2. This function is experimental.

   Time complexity: TODO.

15 Reading and Writing Graphs from and to Files
***********************************************

These functions can write a graph to a file, or read a graph from a
file.

   Note that as `igraph' uses the traditional C streams, it is possible
to read/write files from/to memory, at least on GNU operating systems
supporting `non-standard' streams.

15.1 Simple edge list and similar formats
=========================================

15.1.1 igraph_read_graph_edgelist -- Reads an edge list from a file and creates a graph.
----------------------------------------------------------------------------------------

     int igraph_read_graph_edgelist(igraph_t *graph, FILE *instream,
     			       igraph_integer_t n, igraph_bool_t directed);

   This format is simply a series of even number integers separated by
whitespace. The one edge (ie. two integers) per line format is thus not
required (but recommended for readability). Edges of directed graphs
are assumed to be in from, to order.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`instream':
     Pointer to a stream, it should be readable.

`n':
     The number of vertices in the graph. If smaller than the largest
     integer in the file it will be ignored. It is thus safe to supply
     zero here.

`directed':
     Logical, if true the graph is directed, if false it will be
     undirected.

   *Returns:. *

`'
     Error code: `IGRAPH_PARSEERROR': if there is a problem reading the
     file, or the file is syntactically incorrect.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges. It is assumed that reading an integer requires O(1) time.

15.1.2 igraph_write_graph_edgelist -- Writes the edge list of a graph to a file.
--------------------------------------------------------------------------------

     int igraph_write_graph_edgelist(const igraph_t *graph, FILE *outstream);

   One edge is written per line, separated by a single space.  For
directed graphs edges are written in from, to order.

   *Arguments:. *

`graph':
     The graph object to write.

`outstream':
     Pointer to a stream, it should be writable.

   *Returns:. *

`'
     Error code: `IGRAPH_EFILE' if there is an error writing the file.

   Time complexity: O(|E|), the number of edges in the  graph. It is
assumed that writing an integer to the file requires O(1) time.

15.1.3 igraph_read_graph_ncol -- Reads a .ncol file used by LGL.
----------------------------------------------------------------

     int igraph_read_graph_ncol(igraph_t *graph, FILE *instream,
     			   igraph_strvector_t *predefnames,
     			   igraph_bool_t names, igraph_bool_t weights, igraph_bool_t directed);

   Also useful for creating graphs from `named' (and optionally
weighted) edge lists.

   This format is used by the Large Graph Layout program
(http://bioinformatics.icmb.utexas.edu/lgl/
(http://bioinformatics.icmb.utexas.edu/lgl/)), and it is simply a
symbolic weighted edge list. It is a simple text file with one edge per
line. An edge is defined by two symbolic vertex names separated by
whitespace. (The symbolic vertex names themselves cannot contain
whitespace. They might follow by an optional number, this will be the
weight of the edge; the number can be negative and can be in scientific
notation. If there is no weight specified to an edge it is assumed to
be zero.

   The resulting graph is always undirected.  LGL cannot deal with
files which contain multiple or loop edges, this is however not checked
here, as `igraph' is happy with these.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`instream':
     Pointer to a stream, it should be readable.

`predefnames':
     Pointer to the symbolic names of the vertices in the file. If
     `NULL' is given here then vertex ids will be assigned to vertex
     names in the order of their appearence in the \c .ncol file. If it
     is not `NULL' and some unknown vertex names are found in the \c
     .ncol file then new vertex ids will be assigned to them.

`names':
     Logical value, if TRUE the symbolic names of the vertices will be
     added to the graph as a vertex attribute called `name'.

`weights':
     Logical value, if TRUE the weights of the edges is added to the
     graph as an edge attribute called `weight'.

`directed':
     Whether to create a directed graph. As this format was originally
     used only for undirected graphs there is no information in the
     file about the directedness of the graph.  Set this parameter to
     `IGRAPH_DIRECTED' or `IGRAPH_UNDIRECTED' to create a directed or
     undirected graph.

   *Returns:. *

`'
     Error code: `IGRAPH_PARSEERROR': if there is a problem reading the
     file, or the file is syntactically incorrect.

   Time complexity: O(|V|+|E|log(|V|)) if we neglect the time required
by the parsing. As usual |V| is the number of vertices, while |E| is
the number of edges.

   *See also:. *

`'
     `igraph_read_graph_lgl()' (see igraph_read_graph_lgl --- Reads a graph from an _lgl file),
     `igraph_write_graph_ncol()' (see
     igraph_write_graph_ncol --- Writes the graph to a file in _ncol format)

15.1.4 igraph_write_graph_ncol -- Writes the graph to a file in .ncol format
----------------------------------------------------------------------------

     int igraph_write_graph_ncol(const igraph_t *graph, FILE *outstream,
     			    const char *names, const char *weights);

   ` .ncol'  is a format used by LGL, see `igraph_read_graph_ncol()'
(see igraph_read_graph_ncol --- Reads a _ncol file used by LGL_)
for details.

   Note that having multiple or loop edges in an ` .ncol'  file breaks
the  LGL software but `igraph' does not check for this condition.

   *Arguments:. *

`graph':
     The graph to write.

`outstream':
     The stream object to write to, it should be writable.

`names':
     The name of the vertex attribute, if symbolic names are written to
     the file. If not, supply 0 here.

`weights':
     The name of the edge attribute, if they are also written to the
     file. If you don't want weights, supply 0 here.

   *Returns:. *

`'
     Error code: `IGRAPH_EFILE' if there is an error writing the file.

   Time complexity: O(|E|), the number of edges. All file operations
are expected to have time complexity O(1).

   *See also:. *

`'
     `igraph_read_graph_ncol()' (see igraph_read_graph_ncol --- Reads a _ncol file used by LGL_),
     `igraph_write_graph_lgl()' (see
     igraph_write_graph_lgl --- Writes the graph to a file in _lgl format)

15.1.5 igraph_read_graph_lgl -- Reads a graph from an .lgl file
---------------------------------------------------------------

     int igraph_read_graph_lgl(igraph_t *graph, FILE *instream,
     			  igraph_bool_t names, igraph_bool_t weights);

   The ` .lgl'  format is used by the Large Graph Layout visualization
software (http://bioinformatics.icmb.utexas.edu/lgl/
(http://bioinformatics.icmb.utexas.edu/lgl/)), it can describe
undirected optionally weighted graphs. From the LGL manual:

     The second format is the LGL file format (` .lgl'  file suffix).
     This is yet another graph file format that tries to be as stingy
     as possible with space, yet keeping the edge file in a human
     readable (not binary) format. The format itself is like the
     following:

           # vertex1name
          vertex2name [optionalWeight]
          vertex3name [optionalWeight]

     Here, the first vertex of an edge is preceded with a pound sign
     '#'.  Then each vertex that shares an edge with that vertex is
     listed one per line on subsequent lines.

   LGL cannot handle loop and multiple edges or directed graphs, but in
`igraph' it is not an error to have multiple and loop edges.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`instream':
     A stream, it should be readable.

`names':
     Logical value, if TRUE the symbolic names of the vertices will be
     added to the graph as a vertex attribute called `name'.

`weights':
     Logical value, if TRUE the weights of the edges is added to the
     graph as an edge attribute called `weight'.

   *Returns:. *

`'
     Error code: `IGRAPH_PARSEERROR': if there is a problem reading the
     file, or the file is syntactically incorrect.

   Time complexity: O(|V|+|E|log(|V|)) if we neglect the time required
by the parsing. As usual |V| is the number of vertices, while |E| is
the number of edges.

   *See also:. *

`'
     `igraph_read_graph_ncol()' (see igraph_read_graph_ncol --- Reads a _ncol file used by LGL_),
     `igraph_write_graph_lgl()' (see
     igraph_write_graph_lgl --- Writes the graph to a file in _lgl format)

15.1.6 igraph_write_graph_lgl -- Writes the graph to a file in .lgl format
--------------------------------------------------------------------------

     int igraph_write_graph_lgl(const igraph_t *graph, FILE *outstream,
     			   const char *names, const char *weights,
     			   igraph_bool_t isolates);

   ` .lgl'  is a format used by LGL, see `igraph_read_graph_lgl()'
(see igraph_read_graph_lgl --- Reads a graph from an _lgl file) for
details.

   Note that having multiple or loop edges in an ` .lgl'  file breaks
the  LGL software but `igraph' does not check for this condition.

   *Arguments:. *

`graph':
     The graph to write.

`outstream':
     The stream object to write to, it should be writable.

`names':
     The name of the vertex attribute, if symbolic names are written to
     the file. If not supply 0 here.

`weights':
     The name of the edge attribute, if they are also written to the
     file. If you don't want weights supply 0 here.

`isolates':
     Logical, if TRUE isolated vertices are also written to the file.
     If FALSE they will be omitted.

   *Returns:. *

`'
     Error code: `IGRAPH_EFILE' if there is an error writing the file.

   Time complexity: O(|E|), the number of edges if `isolates' is FALSE,
O(|V|+|E|) otherwise. All file operations are expected to have time
complexity O(1).

   *See also:. *

`'
     `igraph_read_graph_ncol()' (see igraph_read_graph_ncol --- Reads a _ncol file used by LGL_),
     `igraph_write_graph_lgl()' (see
     igraph_write_graph_lgl --- Writes the graph to a file in _lgl format)

15.1.7 igraph_read_graph_dimacs -- Read a graph in DIMACS format.
-----------------------------------------------------------------

     int igraph_read_graph_dimacs(igraph_t *graph, FILE *instream,
     			     igraph_strvector_t *problem,
     			     igraph_vector_t *label,
     			     igraph_integer_t *source,
     			     igraph_integer_t *target,
     			     igraph_vector_t *capacity,
     			     igraph_bool_t directed);

   This function reads the DIMACS file format, more specifically the
version for network flow problems, see the files at
ftp://dimacs.rutgers.edu/pub/netflow/general-info/

   This is a line-oriented text file (ASCII) format. The first
character of each line defines the type of the line. If the first
character is ` c'  the line is a comment line and it is ignored. There
is one problem line (` p'  in the file, it must appear before any node
and arc descriptor lines. The problem line has three fields separated
by spaces: the problem type (` min' , ` max'  or ` asn' ), the number
of vertices and number of edges in the graph.  Exactly two node
identification lines are expected (` n' ), one for the source, one for
the target vertex.  These have two fields: the id of the vertex and the
type of the vertex, either ` s'  (=source) or ` t' (=target). Arc lines
start with ` a'  and have three fields: the source vertex, the target
vertex and the edge capacity.

   Vertex ids are numbered from 1.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`instream':
     The file to read from.

`source':
     Pointer to an integer, the id of the source node will be stored
     here. (The igraph vertex id, which is one less than the actual
     number in the file.) It is ignored if ` NULL' .

`target':
     Pointer to an integer, the (igraph) id of the target node will be
     stored here. It is ignored if ` NULL' .

`capacity':
     Pointer to an initialized vector, the capacity of the edges will
     be stored here if not ` NULL' .

`directed':
     Boolean, whether to create a directed graph.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|+c), the number of vertices plus the
number of edges, plus the size of the file in characters.

   *See also:. *

`'
     `igraph_write_graph_dimacs()' (see igraph_write_graph_dimacs --- Write a graph in DIMACS format_)

15.1.8 igraph_write_graph_dimacs -- Write a graph in DIMACS format.
-------------------------------------------------------------------

     int igraph_write_graph_dimacs(const igraph_t *graph, FILE *outstream,
     			      long int source, long int target,
     			      const igraph_vector_t *capacity);

   This function writes a graph to an output stream in DIMACS format,
describing a maximum flow problem.  See
ftp://dimacs.rutgers.edu/pub/netflow/general-info/

   This file format is discussed in the documentation of
`igraph_read_graph_dimacs()' (see igraph_read_graph_dimacs --- Read a graph in DIMACS format_),
see that for more information.

   *Arguments:. *

`graph':
     The graph to write to the stream.

`outstream':
     The stream.

`source':
     Integer, the id of the source vertex for the maximum flow.

`target':
     Integer, the id of the target vertex.

`capacity':
     Pointer to an initialized vector containing the edge capacity
     values.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|E|), the number of edges in the graph.

   *See also:. *

`'
     igraph_read_graph_dimacs()

15.2 Binary formats
===================

15.2.1 igraph_read_graph_graphdb -- Read a graph in the binary graph database format.
-------------------------------------------------------------------------------------

     int igraph_read_graph_graphdb(igraph_t *graph, FILE *instream,
     			      igraph_bool_t directed);

   This is a binary format, used in the graph database for isomorphism
testing (http://amalfi.dis.unina.it/graph/
(http://amalfi.dis.unina.it/graph/)) From the graph database homepage
(http://amalfi.dis.unina.it/graph/db/doc/graphdbat-2.html
(http://amalfi.dis.unina.it/graph/db/doc/graphdbat-2.html)):

     The graphs are stored in a compact binary format, one graph per
     file. The file is composed of 16 bit words, which are represented
     using the so-called little-endian convention, i.e. the least
     significant byte of the word is stored first.

     Then, for each node, the file contains the list of edges coming
     out of the node itself. The list is represented by a word encoding
     its length, followed by a word for each edge, representing the
     destination node of the edge. Node numeration is 0-based, so the
     first node of the graph has index 0.

   Only unlabelled graphs are implemented.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`instream':
     The stream to read from.

`directed':
     Logical scalar, whether to create a directed graph.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges.

15.3 GraphML format
===================

15.3.1 igraph_read_graph_graphml -- Reads a graph from a GraphML file.
----------------------------------------------------------------------

     int igraph_read_graph_graphml(igraph_t *graph, FILE *instream,
     			      int index);

   GraphML is an XML-based file format for representing various types of
graphs. Currently only the most basic import functionality is
implemented in igraph: it can read GraphML files without nested graphs
and hyperedges.  Attributes of the graph are loaded only if an
attribute interface is attached, ie. if you use igraph from R or Python.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`instream':
     A stream, it should be readable.

`index':
     If the GraphML file contains more than one graph, the one
     specified by this index will be loaded. Indices start from zero,
     so supply zero here if your GraphML file contains only a single
     graph.

   *Returns:. *

`'
     Error code: `IGRAPH_PARSEERROR': if there is a problem reading the
     file, or the file is syntactically incorrect.
     `IGRAPH_UNIMPLEMENTED': the GraphML functionality was disabled at
     compile-time

15.3.2 igraph_write_graph_graphml -- Writes the graph to a file in GraphML format
---------------------------------------------------------------------------------

     int igraph_write_graph_graphml(const igraph_t *graph, FILE *outstream);

   GraphML is an XML-based file format for representing various types of
graphs. See the GraphML Primer
(http://graphml.graphdrawing.org/primer/graphml-primer.html
(http://graphml.graphdrawing.org/primer/graphml-primer.html)) for
detailed format description.

   *Arguments:. *

`graph':
     The graph to write.

`outstream':
     The stream object to write to, it should be writable.

   *Returns:. *

`'
     Error code: `IGRAPH_EFILE' if there is an error writing the file.

   Time complexity: O(|V|+|E|) otherwise. All file operations are
expected to have time complexity O(1).

15.4 GML format
===============

15.4.1 igraph_read_graph_gml -- Read a graph in GML format.
-----------------------------------------------------------

     int igraph_read_graph_gml(igraph_t *graph, FILE *instream);

   GML is a simple textual format, see
http://www.infosun.fim.uni-passau.de/Graphlet/GML/
(http://www.infosun.fim.uni-passau.de/Graphlet/GML/) for details.

   Although all syntactically correct GML can be parsed, we implement
only a subset of this format, some attributes might be ignored. Here is
a list of all the differences:

  1. Only ` node'  and ` edge'  attributes are used, and only if they
     have a simple type: integer, real or string. So if an attribute is
     an array or a record, then it is ignored. This is also true if
     only some values of the attribute are complex.

  2. Top level attributes except for ` Version'  and the first ` graph'
     attribute are completely ignored.

  3. Graph attributes except for ` node'  and ` edge'  are completely
     ignored.

  4. There is no maximum line length.

  5. There is no maximum keyword length.

  6. Character entities in strings are not interpreted.

  7. We allow ` inf'  (infinity) and ` nan' (not a number) as a real
     number. This is case insensitive, so ` nan' , ` NaN'  and ` NAN'
     are equal.

   Please contact us if you cannot live with these limitations of the
GML parser.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`instream':
     The stream to read the GML file from.

   *Returns:. *

`'
     Error code.

   Time complexity: should be proportional to the length of the file.

   *See also:. *

`'
     `igraph_read_graph_graphml()' (see igraph_read_graph_graphml --- Reads a graph from a GraphML file_)
     for a more modern format,
     `igraph_write_graph_gml()' (see igraph_write_graph_gml --- Write the graph to a stream in GML format)
     for writing GML files.

15.4.2 igraph_write_graph_gml -- Write the graph to a stream in GML format
--------------------------------------------------------------------------

     int igraph_write_graph_gml(const igraph_t *graph, FILE *outstream,
     			   const igraph_vector_t *id, const char *creator);

   GML is a quite general textual format, see
http://www.infosun.fim.uni-passau.de/Graphlet/GML/
(http://www.infosun.fim.uni-passau.de/Graphlet/GML/) for details.

   The graph, vertex and edges attributes are written to the file as
well, if they are numeric of string.

   As igraph is more forgiving about attribute names, it might be
neccessary to simplify the them before writing to the GML file.  This
way we'll have a syntactically correct GML file. The following simple
procedure is performed on each attribute name: first the alphanumeric
characters are extracted, the others are ignored. Then if the first
character is not a letter then the attribute name is prefixed with
`igraph'.  Note that this might result identical names for two
attributes, igraph does not check this.

   The `id' vertex attribute is treated specially.  If the `id'
argument is not 0 then it should be a numeric vector with the vertex
ids and the `id' vertex attribute is ignored (if there is one). If `id'
is 0 and there is a numeric `id' vertex attribute that is used instead.
If ids are not specified in either way then the regular igraph vertex
ids are used.

   Note that whichever way vertex ids are specified, their uniqueness
is not checked.

   If the graph has edge attributes named `source' or `target' they're
silently ignored. GML uses these attributes to specify the edges, so we
cannot write them to the file. Rename them before calling this function
if you want to preserve them.

   *Arguments:. *

`graph':
     The graph to write to the stream.

`outstream':
     The stream to write the file to.

`id':
     Either ` NULL'  or a numeric vector with the vertex ids.  See
     details above.

`creator':
     An optional string to write to the stream in the creator line.  If
     this is 0 then the current date and time is added.

   *Returns:. *

`'
     Error code.

   Time complexity: should be proportional to the number of characters
written to the file.

   *See also:. *

`'
     `igraph_read_graph_gml()' (see igraph_read_graph_gml --- Read a graph in GML format_)
     for reading GML files,
     `igraph_read_graph_graphml()' (see igraph_read_graph_graphml --- Reads a graph from a GraphML file_)
     for a more modern format.

15.5 Pajek format
=================

15.5.1 igraph_read_graph_pajek -- Reads a file in Pajek format
--------------------------------------------------------------

     int igraph_read_graph_pajek(igraph_t *graph, FILE *instream);

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`file':
     An already opened file handler.

   *Returns:. *

`'
     Error code.

   Only a subset of the Pajek format is implemented. This is partially
because this format is not very well documented, but also because
`igraph' does not support some Pajek features, like multigraphs.

   The list of the current limitations:

  1. Only `.net' files are supported, Pajek project files (`.paj') are
     not. These might be supported in the future if there is need for
     it.

  2. Time events networks are not supported.

  3. Hypergraphs (ie. graphs with non-binary edges) are not supported.

  4. Graphs with both directed and non-directed edges are not
     supported, are they cannot be represented in `igraph'.

  5. Bipartite or affiliation networks are not supported. They can be
     imported but the vertex type information is omitted.

  6. Only Pajek networks are supported, permutations, hierarchies,
     clusters and vectors are not.

  7. Graphs with multiple edge sets are not supported.

   If there are attribute handlers installed, `igraph' also reads the
vertex and edge attributes from the file. Most attributes are renamed
to be more informative: ``color'' instead of ``c'', ``xfact'' instead
of ``x_fact'', ``yfact'' instead of `y_fact', ``labeldist'' instead of
``lr'', ``labeldegree2'' instead of ``lphi'', ``framewidth'' instead of
``bw'', ``fontsize'' instead of ``fos'', ``rotation'' instead of
``phi'', ``radius'' instead of ``r'', ``diamondratio'' instead of
``q'', ``labeldegree'' instead of ``la'', ``vertexsize'' instead of
``size'', ``color'' instead of ``ic'', ``framecolor'' instead of
``bc'', ``labelcolor'' instead of ``lc'', these belong to vertices.

   Edge attributes are also renamed, ``s'' to ``arrowsize'', ``w'' to
``edgewidth'', ``h1'' to ``hook1'', ``h2'' to ``hook2'', ``a1'' to
``angle1'', ``a2'' to ``angle2'', ``k1'' to ``velocity1'', ``k2'' to
``velocity2'', ``ap'' to ``arrowpos'', ``lp'' to ``labelpos'', ``lr'' to
``labelangle'', ``lphi'' to ``labelangle2'', ``la'' to ``labeldegree'',
``fos'' to ``fontsize'', ``a'' to ``arrowtype'', ``p'' to
``linepattern'', ``l'' to ``label'', ``lc'' to ``labelcolor'', ``c'' to
``color''.

   In addition the following vertex attributes might be added: ``id''
if there are vertex ids in the file, ``x'' and ``y'' or ``x'' and ``y''
and ``z'' if there are vertex coordinates in the file, ``color-red'',
``color-green'' and ``color-blue'' if the vertex color is given in RGB
notation, ``framecolor-red'', ``framecolor-green'' and
``framecolor-blue'` if the frame color is given in RGB notation and
finally ``labelcolor-red'', ``labelcolor-green'' and
``labelcolor-blue'' if the label color is given in RGB notation.

   The following additional edge attributes might be added: ``weight''
if there are edge weights present, ``color-red'', ``color-green'' and
``color-blue'' if the edge color is given in RGB notation.

   See the pajek homepage:
http://vlado.fmf.uni-lj.si/pub/networks/pajek/
(http://vlado.fmf.uni-lj.si/pub/networks/pajek/) for more info on Pajek
and the Pajek manual:
http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/pajekman.pdf
(http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/pajekman.pdf) for
information on the Pajek file format.

   Time complexity: O(|V|+|E|+|A|), |V| is the number of vertices, |E|
the number of edges, |A| the number of attributes (vertex + edge) in
the graph if there are attribute handlers installed.

   *See also:. *

`'
     `igraph_write_graph_pajek()' (see igraph_write_graph_pajek --- Writes a graph to a file in Pajek format_)
     for writing Pajek
     files, `igraph_read_graph_graphml()' (see
     igraph_read_graph_graphml --- Reads a graph from a GraphML file_)
     for reading GraphML files.

15.5.2 igraph_write_graph_pajek -- Writes a graph to a file in Pajek format.
----------------------------------------------------------------------------

     int igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream);

   The Pajek vertex and edge parameters (like color) are determined by
the attributes of the vertices and edges, of course this requires an
attribute handler to be installed. The names of the corresponding
vertex and edge attributes are listed at `igraph_read_graph_pajek()'
(see igraph_read_graph_pajek --- Reads a file in Pajek format), eg.
the ``color'' vertex attributes determines the color (``c'' in Pajek)
parameter.

   *Arguments:. *

`graph':
     The graph object to write.

`outstream':
     The file to write to. It should be opened and writable. Make sure
     that you open the file in binary format if you use MS Windows,
     otherwise end of line characters will be messed up. (igraph will
     be able to read back these messed up files, but Pajek won't.)

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|+|A|), |V| is the number of vertices, |E|
is the number of edges, |A| the number of attributes (vertex + edge) in
the graph if there are attribute handlers installed.

   *See also:. *

`'
     `igraph_read_graph_pajek()' (see igraph_read_graph_pajek --- Reads a file in Pajek format)
     for reading Pajek graphs,
     `igraph_write_graph_graphml()' (see igraph_write_graph_graphml --- Writes the graph to a file in GraphML format)
     for writing a
     graph in GraphML format, this suites `igraph' graphs better.

15.6 Graphviz format
====================

15.6.1 igraph_write_graph_dot -- Write the graph to a stream in DOT format
--------------------------------------------------------------------------

     int igraph_write_graph_dot(const igraph_t *graph, FILE* outstream);

   DOT is the format used by the widely known GraphViz software, see
http://www.graphviz.org (http://www.graphviz.org) for details. The
grammar of the DOT format can be found here:
http://www.graphviz.org/doc/info/lang.html
(http://www.graphviz.org/doc/info/lang.html)

   This is only a preliminary implementation, only the vertices and the
edges are written but not the attributes or any visualization
information.

   *Arguments:. *

`graph':
     The graph to write to the stream.

`outstream':
     The stream to write the file to.

   Time complexity: should be proportional to the number of characters
written to the file.

   *See also:. *

`'
     `igraph_write_graph_graphml()' (see igraph_write_graph_graphml --- Writes the graph to a file in GraphML format)
     for a more
     modern format.

16 Maximum Flows, Minimum Cuts and related measures
***************************************************

16.1 Maximum Flows
==================

16.1.1 igraph_maxflow_value -- Maximum flow in a network with the push/relabel algorithm
----------------------------------------------------------------------------------------

     int igraph_maxflow_value(const igraph_t *graph, igraph_real_t *value,
     			 igraph_integer_t source, igraph_integer_t target,
     			 const igraph_vector_t *capacity);

   This function implements the Goldberg-Tarjan algorithm for
calculating value of the maximum flow in a directed or undirected
graph. The algorithm was given in Andrew V. Goldberg, Robert E. Tarjan:
A New Approach to the Maximum-Flow Problem, Journal of the ACM, 35(4),
921-940, 1988.

   The input of the function is a graph, a vector of real numbers
giving the capacity of the edges and two vertices of the graph, the
source and the target. A flow is a function assigning positive real
numbers to the edges and satisfying two requirements: (1) the flow
value is less than the capacity of the edge and (2) at each vertex
except the source and the target, the incoming flow (ie. the sum of the
flow on the incoming edges) is the same as the outgoing flow (ie. the
sum of the flow on the outgoing edges). The value of the flow is the
incoming flow at the target vertex. The maximum flow is the flow with
the maximum value.

   This function can only calculate the value of the maximum flow, but
not the flow itself (may be added later).

   According to a theorem by Ford and Furkelson (L. R. Ford Jr. and D.
R. Fulkerson. Maximal flow through a network. Canadian J. Math.,
8:399-404, 1956.) the maximum flow between two vertices is the same as
the minimum cut between them (also called the minimum s-t cut). So
`igraph_st_mincut_value()' (see igraph_st_mincut_value --- The minimum s-t cut in a graph)
gives the same result in all cases as
`igraph_maxflow_value'().

   Note that the value of the maximum flow is the same as the minimum
cut in the graph.

   *Arguments:. *

`graph':
     The input graph, either directed or undirected.

`value':
     Pointer to a real number, the result will be placed here.

`source':
     The id of the source vertex.

`target':
     The id of the target vertex.

`capacity':
     Vector containing the capacity of the edges. If NULL, then every
     edge is considered to have capacity 1.0.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|^3). In practice it is much faster, but i
cannot prove a better lower bound for the data structure i've used. In
fact, this implementation runs much faster than the `hi_pr'
implementation discussed in B. V. Cherkassky and A. V. Goldberg: On
implementing the push-relabel method for the maximum flow problem,
(Algorithmica, 19:390-410, 1997) on all the graph classes i've tried.

   *See also:. *

`'
     `igraph_mincut_value()' (see igraph_mincut_value --- The minimum edge cut in a graph),
     `igraph_edge_connectivity()' (see
     igraph_edge_connectivity --- The minimum edge connectivity in a graph_),
     `igraph_vertex_connectivity()' (see
     igraph_vertex_connectivity --- The vertex connectivity of a graph)
     for properties based on the maximum flow.

16.2 Minimum cuts
=================

16.2.1 igraph_st_mincut_value -- The minimum s-t cut in a graph
---------------------------------------------------------------

     int igraph_st_mincut_value(const igraph_t *graph, igraph_real_t *value,
     			   igraph_integer_t source, igraph_integer_t target,
     			   const igraph_vector_t *capacity);

   The minimum s-t cut in a weighted (=valued) graph is the total
minimum edge weight needed to remove from the graph to eliminate all
paths from a given vertex (`source') to another vertex (`target').
Directed paths are considered in directed graphs, and undirected paths
in undirected graphs.

   The minimum s-t cut between two vertices is known to be same as the
maximum flow between these two vertices. So this function calls
`igraph_maxflow_value()' (see igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm)
to do the calculation.

   *Arguments:. *

`graph':
     The input graph.

`value':
     Pointer to a real variable, the result will be stored here.

`source':
     The id of the source vertex.

`target':
     The id of the target vertex.

`capacity':
     Pointer to the capacity vector, it should contain non-negative
     numbers and its length should be the same the the number of edges
     in the graph. It can be a null pointer, then every edge has unit
     capacity.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|^3), see also the discussion for
`igraph_maxflow_value()' (see igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm),
|V| is the number of
vertices.

16.2.2 igraph_mincut_value -- The minimum edge cut in a graph
-------------------------------------------------------------

     int igraph_mincut_value(const igraph_t *graph, igraph_real_t *res,
     			const igraph_vector_t *capacity);

   The minimum edge cut in a graph is the total minimum weight of the
edges needed to remove from the graph to make the graph _not_ strongly
connected. (If the original graph is not strongly connected then this
is zero.) Note that in undirected graphs strong connectedness is the
same as weak connectedness.

   The minimum cut can be calculated with maximum flow techniques,
although the current implementation does this only for directed graphs
and a separate non-flow based implementation is used for undirected
graphs. See Mechthild Stoer and Frank Wagner: A simple min-cut
algorithm, Journal of the ACM 44 585-591, 1997.  For directed graphs
the maximum flow is calculated between a fixed vertex and all the other
vertices in the graph and this is done in both directions. Then the
minimum is taken to get the minimum cut.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to a real variable, the result will be stored here.

`capacity':
     Pointer to the capacity vector, it should contain the same number
     of non-negative numbers as the number of edges in the graph. If a
     null pointer then all edges will have unit capacity.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_mincut()' (see igraph_mincut --- Calculates the minimum cut in a graph_),
     `igraph_maxflow_value()' (see
     igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm),
     `igraph_st_mincut_value()' (see
     igraph_st_mincut_value --- The minimum s-t cut in a graph).

   Time complexity: O(log(|V|)*|V|^2) for undirected graphs and
O(|V|^4) for directed graphs, but see also the discussion at the
documentation of `igraph_maxflow_value()' (see igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm).

16.2.3 igraph_mincut -- Calculates the minimum cut in a graph.
--------------------------------------------------------------

     int igraph_mincut(const igraph_t *graph,
     		  igraph_real_t *value,
     		  igraph_vector_t *partition,
     		  igraph_vector_t *partition2,
     		  igraph_vector_t *cut,
     		  const igraph_vector_t *capacity);

   This function calculates the minimum cut in a graph. Right now it is
implemented only for undirected graphs, in which case it uses the
Stoer-Wagner algorithm, as described in M. Stoer and F. Wagner: A
simple min-cut algorithm, Journal of the ACM, 44 585-591, 1997.

   The minimum cut is the minimum set of edges which needs to be
removed to disconnect the graph. The minimum is calculated using the
weigths (`capacity') of the edges, so the cut with the minimum total
capacity is calculated.

   The first implementation of the actual cut calculation was made by
Gregory Benison, thanks Greg.

   *Arguments:. *

`graph':
     The input graph.

`value':
     Pointer to an integer, the value of the cut will be stored here.

`partition':
     Pointer to an initialized vector, the ids of the vertices in the
     first partition after separating the graph will be stored here.
     The vector will be resized as needed. This argument is ignored if
     it is a NULL pointer.

`partition2':
     Pointer to an initialized vector the ids of the vertices in the
     second partition will be stored here.  The vector will be resized
     as needed. This argument is ignored if it is a NULL pointer.

`cut':
     Pointer to an initialized vector, the ids of the edges in the cut
     will be stored here. This argument is ignored if it is a NULL
     pointer.

`capacity':
     A numeric vector giving the capacities of the edges. If a null
     pointer then all edges have unit capacity.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_mincut_value()' (see igraph_mincut_value --- The minimum edge cut in a graph),
     a simpler interface for calculating the
     value of the cut only.

   Time complexity: for undirected graphs it is O(|V|E|+|V|^2 log|V|),
|V| and |E| are the number of vertices and edges respectively.

16.3 Connectivity
=================

16.3.1 igraph_st_edge_connectivity -- Edge connectivity of a pair of vertices
-----------------------------------------------------------------------------

     int igraph_st_edge_connectivity(const igraph_t *graph, igraph_integer_t *res,
     				igraph_integer_t source,
     				igraph_integer_t target);

   The edge connectivity of two vertices (`source' and `target') in a
graph is the minimum number of edges that have to be deleted from the
graph to eliminate all paths from `source' to `target'.

   This function uses the maximum flow algorithm to calculate the edge
connectivity.

   *Arguments:. *

`graph':
     The input graph, it has to be directed.

`res':
     Pointer to an integer, the result will be stored here.

`source':
     The id of the source vertex.

`target':
     The id of the target vertex.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|^3).

   *See also:. *

`'
     `igraph_maxflow_value()' (see igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm),
     `igraph_edge_connectivity()' (see igraph_edge_connectivity --- The minimum edge connectivity in a graph_),
     `igraph_st_vertex_connectivity()' (see
     igraph_st_vertex_connectivity --- The vertex connectivity of a pair of vertices),
     `igraph_vertex_connectivity()' (see
     igraph_vertex_connectivity --- The vertex connectivity of a graph).

16.3.2 igraph_edge_connectivity -- The minimum edge connectivity in a graph.
----------------------------------------------------------------------------

     int igraph_edge_connectivity(const igraph_t *graph, igraph_integer_t *res,
     			     igraph_bool_t checks);

   This is the minimum of the edge connectivity over all pairs of
vertices in the graph.

   The edge connectivity of a graph is the same as group adhesion as
defined in Douglas R. White and Frank Harary: The cohesiveness of
blocks in social networks: node connectivity and conditional density,
Sociological Methodology 31:305-359, 2001.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to an integer, the result will be stored here.

`checks':
     Logical constant. Whether to check that the graph is connected and
     also the degree of the vertices. If the graph is not (strongly)
     connected then the connectivity is obviously zero. Otherwise if
     the minimum degree is one then the edge connectivity is also one.
     It is a good idea to perform these checks, as they can be done
     quickly compared to the connectivity calculation itself.  They
     were suggested by Peter McMahan, thanks Peter.

   *Returns:. *

`'
     Error code.

   Time complexity: O(log(|V|)*|V|^2) for undirected graphs and
O(|V|^4) for directed graphs, but see also the discussion at the
documentation of `igraph_maxflow_value()' (see igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm).

   *See also:. *

`'
     `igraph_st_edge_connectivity()' (see igraph_st_edge_connectivity --- Edge connectivity of a pair of vertices),
     `igraph_maxflow_value()' (see igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm),
     `igraph_vertex_connectivity()' (see igraph_vertex_connectivity --- The vertex connectivity of a graph).

16.3.3 igraph_st_vertex_connectivity -- The vertex connectivity of a pair of vertices
-------------------------------------------------------------------------------------

     int igraph_st_vertex_connectivity(const igraph_t *graph,
     				  igraph_integer_t *res,
     				  igraph_integer_t source,
     				  igraph_integer_t target,
     				  igraph_vconn_nei_t neighbors);

   The vertex connectivity of two vertices (`source' and `target') is
the minimum number of vertices that have to be deleted to eliminate all
paths from `source' to `target'. Directed paths are considered in
directed graphs.

   The vertex connectivity of a pair is the same as the number of
different (ie. node-independent) paths from source to target.

   The current implementation uses maximum flow calculations to obtain
the result.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to an integer, the result will be stored here.

`source':
     The id of the source vertex.

`target':
     The id of the target vertex.

`neighbors':
     A constant giving what to do if the two vertices are connected.
     Possible values: `IGRAPH_VCONN_NEI_ERROR', stop with an error
     message, `IGRAPH_VCONN_INFINITY', return infinity (ie. 1.0/0.0).
     `IGRAPH_VCONN_IGNORE', ignore the fact that the two vertices are
     connected and calculated the number of vertices needed to
     aliminate all paths except for the trivial (direct) paths between
     `source' and `vertex'. TOOD: what about neighbors?

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|^3), but see the discussion at
`igraph_maxflow_value()' (see igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm).

   *See also:. *

`'
     `igraph_vertex_connectivity()' (see igraph_vertex_connectivity --- The vertex connectivity of a graph),
     `igraph_edge_connectivity()' (see igraph_edge_connectivity --- The minimum edge connectivity in a graph_),
     `igraph_maxflow_value()' (see igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm).

16.3.4 igraph_vertex_connectivity -- The vertex connectivity of a graph
-----------------------------------------------------------------------

     int igraph_vertex_connectivity(const igraph_t *graph, igraph_integer_t *res,
     			       igraph_bool_t checks);

   The vertex connectivity of a graph is the minimum vertex
connectivity along each pairs of vertices in the graph.

   The vertex connectivity of a graph is the same as group cohesion as
defined in Douglas R. White and Frank Harary: The cohesiveness of
blocks in social networks: node connectivity and conditional density,
Sociological Methodology 31:305-359, 2001.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to an integer, the result will be stored here.

`checks':
     Logical constant. Whether to check that the graph is connected and
     also the degree of the vertices. If the graph is not (strongly)
     connected then the connectivity is obviously zero. Otherwise if
     the minimum degree is one then the vertex connectivity is also
     one. It is a good idea to perform these checks, as they can be
     done quickly compared to the connectivity calculation itself.
     They were suggested by Peter McMahan, thanks Peter.

   *Returns:. *

`'
     Error code.

   Time complecity: O(|V|^5).

   *See also:. *

`'
     `igraph_st_vertex_connectivity()' (see
     igraph_st_vertex_connectivity --- The vertex connectivity of a pair of vertices),
     `igraph_maxflow_value()' (see
     igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm),
     and `igraph_edge_connectivity()' (see
     igraph_edge_connectivity --- The minimum edge connectivity in a graph_).

16.4 Edge- and Vertex-Disjoint Paths
====================================

16.4.1 igraph_edge_disjoint_paths -- The maximum number of edge-disjoint paths between two vertices.
----------------------------------------------------------------------------------------------------

     int igraph_edge_disjoint_paths(const igraph_t *graph, igraph_integer_t *res,
     			       igraph_integer_t source,
     			       igraph_integer_t target);

   A set of paths between two vertices is called edge-disjoint if they
do not share any edges. The maximum number of edge-disjoint paths are
calculated by this function using maximum flow techniques. Directed
paths are considered in directed graphs.

   Note that the number of disjoint paths is the same as the edge
connectivity of the two vertices using uniform edge weights.

   *Arguments:. *

`graph':
     The input graph, can be directed or undirected.

`res':
     Pointer to an integer variable, the result will be stored here.

`source':
     The id of the source vertex.

`target':
     The id of the target vertex.

   *Returns:. *

`'
     Error code.

   Time complecity: O(|V|^3), but see the discussion at
`igraph_maxflow_value()' (see igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm).

   *See also:. *

`'
     `igraph_vertex_disjoint_paths()' (see
     igraph_vertex_disjoint_paths --- Maximum number of vertex-disjoint paths between two vertices_),
     `igraph_st_edge_connectivity()'
     (see igraph_st_edge_connectivity --- Edge connectivity of a pair of vertices),
     `igraph_maxflow_value()' (see
     igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm).

16.4.2 igraph_vertex_disjoint_paths -- Maximum number of vertex-disjoint paths between two vertices.
----------------------------------------------------------------------------------------------------

     int igraph_vertex_disjoint_paths(const igraph_t *graph, igraph_integer_t *res,
     				 igraph_integer_t source,
     				 igraph_integer_t target);

   A set of paths between two vertices is called vertex-disjoint if
they share no vertices. The calculation is performed by using maximum
flow techniques.

   Note that the number of vertex-disjoint paths is the same as the
vertex connectivity of the two vertices in most cases (if the two
vertices are not connected by an edge).

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to an integer variable, the result will be stored here.

`source':
     The id of the source vertex.

`target':
     The id of the target vertex.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|^3).

   *See also:. *

`'
     `igraph_edge_disjoint_paths()' (*note igraph_edge_disjoint_paths
     --- The maximum number of edge-disjoint paths between two
     vertices_::), `igraph_vertex_connectivity()' (see
     igraph_vertex_connectivity --- The vertex connectivity of a graph),
     `igraph_maxflow_value()' (see igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm).

16.5 Graph Adhesion and Cohesion
================================

16.5.1 igraph_adhesion -- Graph adhesion, this is (almost) the same as edge connectivity.
-----------------------------------------------------------------------------------------

     int igraph_adhesion(const igraph_t *graph, igraph_integer_t *res,
     		    igraph_bool_t checks);

   This quantity is defined by White and Harary in The cohesiveness of
blocks in social networks: node connectivity and conditional density,
(Sociological Methodology 31:305-359, 2001) and basically it is the
edge connectivity of the graph with uniform edge weights.

   *Arguments:. *

`graph':
     The input graph, either directed or undirected.

`res':
     Pointer to an integer, the result will be stored here.

`checks':
     Logical constant. Whether to check that the graph is connected and
     also the degree of the vertices. If the graph is not (strongly)
     connected then the adhesion is obviously zero. Otherwise if the
     minimum degree is one then the adhesion is also one. It is a good
     idea to perform these checks, as they can be done quickly compared
     to the edge connectivity calculation itself.  They were suggested
     by Peter McMahan, thanks Peter.  *

   *Returns:. *

`'
     Error code.

   Time complexity: O(log(|V|)*|V|^2) for undirected graphs and
O(|V|^4) for directed graphs, but see also the discussion at the
documentation of `igraph_maxflow_value()' (see igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm).

   *See also:. *

`'
     `igraph_cohesion()' (see igraph_cohesion --- Graph cohesion; this is the same as vertex connectivity_),
     `igraph_maxflow_value()' (see igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm),
     `igraph_edge_connectivity()' (see igraph_edge_connectivity --- The minimum edge connectivity in a graph_),
     `igraph_mincut_value()' (see igraph_mincut_value --- The minimum edge cut in a graph).

16.5.2 igraph_cohesion -- Graph cohesion, this is the same as vertex connectivity.
----------------------------------------------------------------------------------

     int igraph_cohesion(const igraph_t *graph, igraph_integer_t *res,
     		    igraph_bool_t checks);

   This quantity was defined by White and Harary in `The cohesiveness
of blocks in social networks: node connectivity and conditional
density', (Sociological Methodology 31:305-359, 2001) and it is the
same as the vertex connectivity of a graph.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to an integer variable, the result will be stored here.

`checks':
     Logical constant. Whether to check that the graph is connected and
     also the degree of the vertices. If the graph is not (strongly)
     connected then the cohesion is obviously zero. Otherwise if the
     minimum degree is one then the cohesion is also one. It is a good
     idea to perform these checks, as they can be done quickly compared
     to the vertex connectivity calculation itself.  They were
     suggested by Peter McMahan, thanks Peter.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|^4), |V| is the number of vertices. In
practice it is more like O(|V|^2), see `igraph_maxflow_value()' (see
igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm).

   *See also:. *

`'
     `igraph_vertex_connectivity()' (see igraph_vertex_connectivity --- The vertex connectivity of a graph),
     `igraph_adhesion()'
     (see igraph_adhesion --- Graph adhesion; this is [almost] the same as edge connectivity_),
     `igraph_maxflow_value()' (see
     igraph_maxflow_value --- Maximum flow in a network with the push/relabel algorithm).

17 Detecting Community Structure
********************************

17.1 Common functions related to community structure
====================================================

17.1.1 igraph_modularity -- Calculate the modularity of a graph with respect to some vertex types
-------------------------------------------------------------------------------------------------

     int igraph_modularity(const igraph_t *graph,
     		      const igraph_vector_t *membership,
     		      igraph_real_t *modularity,
     			  const igraph_vector_t *weights);

   The modularity of a graph with respect to some division (or vertex
types) measures how good the division is, or how separated are the
different vertex types from each other. It defined as Q=1/(2m) *
sum(Aij-ki*kj/(2m)delta(ci,cj),i,j), here `m' is the number of edges,
`Aij' is the element of the `A' adjacency matrix in row `i' and column
`j', `ki' is the degree of `i', `kj' is the degree of `j', `ci' is the
type (or component) of `i', `cj' that of `j', the sum goes over all `i'
and `j' pairs of vertices, and `delta(x,y)' is one if x=y and zero
otherwise.

   Modularity on weighted graphs is also meaningful. When taking edge
weights into account, `Aij' becomes the weight of the corresponding
edge (or 0 if there is no edge), `ki' is the total weight of edges
adjacent to vertex `i', `kj' is the total weight of edges adjacent to
vertex `j' and `m' is the total weight of all edges.

   See also MEJ Newman and M Girvan: Finding and evaluating community
structure in networks. Physical Review E 69 026113, 2004.

   *Arguments:. *

`graph':
     The input graph.

`membership':
     Numeric vector which gives the type of each vertex, ie. the
     component to which it belongs.

`modularity':
     Pointer to a real number, the result will be stored here.

`weights':
     Weight vector or NULL if no weights are specified.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges.

17.1.2 igraph_community_to_membership -- Create membership vector from community structure dendrogram
-----------------------------------------------------------------------------------------------------

     int igraph_community_to_membership(const igraph_matrix_t *merges,
     				   igraph_integer_t nodes,
     				   igraph_integer_t steps,
     				   igraph_vector_t *membership,
     				   igraph_vector_t *csize);

   This function creates a membership vector from a community structure
dendrogram. A membership vector contains for each vertex the id of its
graph component, the graph components are numbered from zero, see the
same argument of `igraph_clusters()' (see igraph_clusters --- Calculates the [weakly or strongly] connected components in a graph_)
for an example of a membership vector.

   Many community detection algorithms return with a _merges_ matrix,
`igraph_community_walktrap()' (see igraph_community_walktrap --- This function is the implementation of the Walktrap community)
an
`igraph_community_edge_betweenness()' (see
igraph_community_edge_betweenness --- Community findinf based on edge betweenness)
are two examples. The matrix contains the merge
operations performed while mapping the hierarchical structure of a
network. If the matrix has `n-1' rows, where `n' is the number of
vertices in the graph, then it contains the hierarchical structure of
the whole network and it is called a dendrogram.

   This function performs `steps' merge operations as prescribed by the
`merges' matrix and returns the current state of the network.

   If if `merges' is not a complete dendrogram, it is possible to take
`steps' steps if `steps' is not bigger than the number lines in
`merges'.

   *Arguments:. *

`merges':
     The two-column matrix containing the merge operations. See
     `igraph_community_walktrap()' (see igraph_community_walktrap --- This function is the implementation of the Walktrap community)
     for the detailed syntax.

`nodes':
     The number of leaf nodes in the dendrogram

`steps':
     Integer constant, the number of steps to take.

`membership':
     Pointer to an initialied vector, the membership results will be
     stored here, if not NULL. The vector will be resized as needed.

`csize':
     Pointer to an initialized vector, or NULL. If not NULL then the
     sizes of the components will be stored here, the vector will be
     resized as needed.

   *See also:. *

`'
     `igraph_community_walktrap()' (see igraph_community_walktrap --- This function is the implementation of the Walktrap community),
     `igraph_community_edge_betweenness()' (see
     igraph_community_edge_betweenness --- Community findinf based on edge betweenness),
     `igraph_community_fastgreedy()' (see
     igraph_community_fastgreedy --- Finding community structure by greedy optimization of modularity)
     for community structure
     detection algorithms.

   Time complexity: O(|V|), the number of vertices in the graph.

17.2 Community structure based on statistical mechanics
=======================================================

17.2.1 igraph_community_spinglass -- Community detection based on statistical mechanics
---------------------------------------------------------------------------------------

     int igraph_community_spinglass(const igraph_t *graph,
     			       const igraph_vector_t *weights,
     			       igraph_real_t *modularity,
     			       igraph_real_t *temperature,
     			       igraph_vector_t *membership,
     			       igraph_vector_t *csize,
     			       igraph_integer_t spins,
     			       igraph_bool_t parupdate,
     			       igraph_real_t starttemp,
     			       igraph_real_t stoptemp,
     			       igraph_real_t coolfact,
     			       igraph_spincomm_update_t update_rule,
     			       igraph_real_t gamma);

   This function implements the community structure detection algorithm
proposed by Joerg Reichardt and Stefan Bornholdt.  The algorithm is
described in their paper: Statistical Mechanics of Community Detection,
http://arxiv.org/abs/cond-mat/0603718.
(http://arxiv.org/abs/cond-mat/0603718.)

   *Arguments:. *

`graph':
     The input graph, it may be directed but the direction of the edge
     is not used in the algorithm.

`weights':
     The vector giving the edge weights, it may be `NULL', in which
     case all edges are weighted equally. Edge weights should be
     positive, altough this is not tested.

`modularity':
     Pointer to a real number, if not `NULL' then the modularity score
     of the solution will be stored here. This is the gereralized
     modularity that simplifies to the one defined in M. E. J. Newman
     and M. Girvan, Phys. Rev. E 69, 026113 (2004), if the gamma
     parameter is one.

`temperature':
     Pointer to a real number, if not `NULL' then the temperature at
     the end of the algorithm will be stored here.

`membership':
     Pointer to an initialized vector or `NULL'. If not `NULL' then the
     result of the clustering will be stored here, for each vertex the
     number of its cluster is given, the first cluster is numbered
     zero. The vector will be resized as needed.

`csize':
     Pointer to an initialized vector or `NULL'. If not `NULL' then the
     sizes of the clusters will stored here in cluster number order.
     The vector will be resized as needed.

`spins':
     Integer giving the number of spins, ie. the maximum number of
     clusters. Usually it is not a program to give a high number here,
     the default was 25 in the original code. Even if the number of
     spins is high the number of clusters in the result might small.

`parupdate':
     A logical constant, whether to update all spins in parallel. The
     default for this argument was `FALSE' (ie. 0) in the original code.

`starttemp':
     Real number, the temperature at the start. The value of this
     argument was 1.0 in the original code.

`stoptemp':
     Real number, the algorithm stops at this temperature. The default
     was 0.01 in the original code.

`coolfact':
     Real number, the coolinf factor for the simulated annealing. The
     default was 0.99 in the original code.

`update_rule':
     The type of the update rule. Possible values:
     `IGRAPH_SPINCOMM_UPDATE_SIMPLE' and
     `IGRAPH_SPINCOMM_UPDATE_CONFIG'. Basically this parameter defined
     the null model based on which the actual clustering is done. If
     this is `IGRAPH_SPINCOMM_UPDATE_SIMPLE' then the random graph (ie.
     G(n,p)), if it is `IGRAPH_SPINCOMM_UPDATE' then the configuration
     model is used. The configuration means that the baseline for the
     clustering is a random graph with the same degree distribution as
     the input graph.

`gamma':
     Real number. The gamma parameter of the algorithm. This defined
     the weight of the missing and existing links in the quality
     function for the clustering. The default value in the original
     code was 1.0, which is equal weight to missing and existing edges.
     Smaller values make the existing links contibute more to the
     energy function which is minimized in the algorithm. Bigger values
     make the missing links more important. (If my understanding is
     correct.)

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     igraph_community_spinglass_single() for calculating the community
     of a single vertex.

   Time complexity: TODO.

17.2.2 igraph_community_spinglass_single -- Community of a single node based on statistical mechanics
-----------------------------------------------------------------------------------------------------

     int igraph_community_spinglass_single(const igraph_t *graph,
     				      const igraph_vector_t *weights,
     				      igraph_integer_t vertex,
     				      igraph_vector_t *community,
     				      igraph_real_t *cohesion,
     				      igraph_real_t *adhesion,
     				      igraph_integer_t *inner_links,
     				      igraph_integer_t *outer_links,
     				      igraph_integer_t spins,
     				      igraph_spincomm_update_t update_rule,
     				      igraph_real_t gamma);

   This function implements the community structure detection algorithm
proposed by Joerg Reichardt and Stefan Bornholdt. It is described in
their paper: Statistical Mechanics of Community Detection,
http://arxiv.org/abs/cond-mat/0603718.
(http://arxiv.org/abs/cond-mat/0603718.)

   This function calculates the community of a single vertex without
calculating all the communities in the graph.

   *Arguments:. *

`graph':
     The input graph, it may be directed but the direction of the edges
     is not used in the algorithm.

`weights':
     Pointer to a vector with the weights of the edges.  Alternatively
     `NULL' can be supplied to have the same weight for every edge.

`vertex':
     The vertex id of the vertex of which ths community is calculated.

`community':
     Pointer to an initialized vector, the result, the ids of the
     vertices in the community of the input vertex will be stored here.
     The vector will be resized as needed.

`cohesion':
     Pointer to a real variable, if not `NULL' the cohesion index of
     the community will be stored here.

`adhesion':
     Pointer to a real variable, if not `NULL' the adhesion index of
     the community will be stored here.

`inner_links':
     Pointer to an integer, if not `NULL' the number of edges within
     the community is stored here.

`outer_links':
     Pointer to an integer, if not `NULL' the number of edges between
     the community and the rest of the graph will be stored here.

`spins':
     The number of spins to use, this can be higher than the actual
     number of clusters in the network, in which case some clusters
     will contain zero vertices.

`update_rule':
     The type of the update rule. Possible values:
     `IGRAPH_SPINCOMM_UPDATE_SIMPLE' and
     `IGRAPH_SPINCOMM_UPDATE_CONFIG'. Basically this parameter defined
     the null model based on which the actual clustering is done. If
     this is `IGRAPH_SPINCOMM_UPDATE_SIMPLE' then the random graph (ie.
     G(n,p)), if it is `IGRAPH_SPINCOMM_UPDATE' then the configuration
     model is used. The configuration means that the baseline for the
     clustering is a random graph with the same degree distribution as
     the input graph.

`gamma':
     Real number. The gamma parameter of the algorithm. This defined
     the weight of the missing and existing links in the quality
     function for the clustering. The default value in the original
     code was 1.0, which is equal weight to missing and existing edges.
     Smaller values make the existing links contibute more to the
     energy function which is minimized in the algorithm. Bigger values
     make the missing links more important. (If my understanding is
     correct.)

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     igraph_community_spinglass() for the traditional version of the
     algorithm.

   Time complexity: TODO.

17.3 Community structure based on eigenvectors of matrices
==========================================================

The functions documented in these section implement the `leading
eigenvector' method developed by Mark Newman and published in MEJ
Newman: Finding community structure using the eigenvectors of matrices,
arXiv:physics/0605087. TODO: proper citation.

   The heart of the method is the definition of the modularity matrix,
B, which is B=A-P, A being the adjacency matrix of the (undirected)
network, and P contains the probability that certain edges are present
according to the `configuration model' In other words, a Pij element of
P is the probability that there is an edge between vertices i and j in
a random network in which the degrees of all vertices are the same as
in the input graph.

   The leading eigenvector method works by calculating the eigenvector
of the modularity matrix for the largest positive eigenvalue and then
separating vertices into two community based on the sign of the
corresponding element in the eigenvector. If all elements in the
eigenvector are of the same sign that means that the network has no
underlying comuunity structure.  Check Newman's paper to understand why
this is a good method for detecting community structure.

   Three function are implemented, they all work accoding to the same
principles. The simplest is perhaps
`igraph_community_leading_eigenvector_naive()' (see
igraph_community_leading_eigenvector_naive --- Leading eigenvector community finding [naive version]_).
This function splits the network
as described above and then recursively splits the two components after
the split as individual networks, if possible.  This however is not a
good way for maximizing moduilarity, again see the paper for
explanation and the proper definition of modularity.

   The correct recursive community structure detection method is
implemented in `igraph_community_leading_eigenvector()' (see
igraph_community_leading_eigenvector --- Leading eigenvector community finding [proper version]_).
Here, after the initial split, the
following splits are done in a way to optimize modularity regarding the
original network.  I can't say it enough, see the paper, particularly
section VI.

   The third function is `igraph_community_leading_eigenvector_step()'
(see igraph_community_leading_eigenvector_step --- Leading eigenvector community finding [make one step]_),
this starts from a
division of the network and tries to split a given community into two
subcommunities via the same (correct) method as
`igraph_community_leading_eigenvector()' (see
igraph_community_leading_eigenvector --- Leading eigenvector community finding [proper version]_).

17.3.1 igraph_community_leading_eigenvector -- Leading eigenvector community finding (proper version).
------------------------------------------------------------------------------------------------------

     int igraph_community_leading_eigenvector(const igraph_t *graph,
     					 igraph_matrix_t *merges,
     					 igraph_vector_t *membership,
     					 igraph_integer_t steps,
     					 igraph_arpack_options_t *options);

   Newman's leading eigenvector method for detecting community
structure. This is the proper implementation of the recursive, divisive
algorithm: each split is done by maximizing the modularity regarding
the original network, see MEJ Newman: Finding community structure in
networks using the eigenvectors of matrices, arXiv:physics/0605087.

   *Arguments:. *

`graph':
     The undirected input graph.

`merges':
     The result of the algorithm, a matrix containing the information
     about the splits performed. The matrix is built in the opposite
     way however, it is like the result of an agglomerative algorithm.
     If at the end of the algorithm (after `steps' steps was done)
     there are `p' communities, then these are numbered from zero to
     `p-1'. The first line of the matrix contains the first `merge'
     (which is in reality the last split) of two communities into
     community `p', the merge in the second line forms community `p+1',
     etc. The matrix should be initialized before calling and will be
     resized as needed.  This argument is ignored of it is `NULL'.

`membership':
     The membership of the vertices after all the splits were performed
     will be stored here. The vector must be initialized  before
     calling and will be resized as needed.  This argument is ignored
     if it is `NULL'.

`steps':
     The maximum number of steps to perform. It might happen that some
     component (or the whole network) has no underlying community
     structure and no further steps can be done. If you wany as many
     steps as possible then supply the number of vertices in the
     network here.

`options':
     The options for ARPACK. `n' is always overwritten. `ncv' is set to
     at least 3.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_community_walktrap()' (see igraph_community_walktrap --- This function is the implementation of the Walktrap community)
     and `igraph_community_spinglass()' (see
     igraph_community_spinglass --- Community detection based on statistical mechanics)
     for other community structure detection
     methods.

   Time complexity: O(|E|+|V|^2*steps), |V| is the number of vertices,
|E| the number of edges, `steps' the number of splits performed.

17.3.2 igraph_community_leading_eigenvector_naive -- Leading eigenvector community finding (naive version).
-----------------------------------------------------------------------------------------------------------

     int igraph_community_leading_eigenvector_naive(const igraph_t *graph,
     					       igraph_matrix_t *merges,
     					       igraph_vector_t *membership,
     					       igraph_integer_t steps,
     					       igraph_arpack_options_t *options);

   A naive implementation of Newman's eigenvector community structure
detection. This function splits the network into two components
according to the leading eigenvector of the modularity matrix and then
recursively takes `steps' steps by splitting the components as
individual network. This is not the correct way however, see MEJ
Newman: Finding community structure in networks using the eigenvectors
of matrices, arXiv:physics/0605087. Consider using the correct
`igraph_community_leading_eigenvector()' (see
igraph_community_leading_eigenvector --- Leading eigenvector community finding [proper version]_)
function instead.

   *Arguments:. *

`graph':
     The input graph, should be undirected to make sense.

`merges':
     The merge matrix. The splits done by the algorithm are stored
     here, its structure is the same ad for
     `igraph_community_leading_eigenvector()' (see
     igraph_community_leading_eigenvector --- Leading eigenvector community finding [proper version]_).
     This argument is ignored
     if it is `NULL'.

`membership':
     The membership vector, for each vertex it gives the id of its
     community after all the splits are performed.  This argument is
     ignored if it is `NULL'.

`steps':
     The number of splits to do, if possible. Supply the number of
     vertices in the network here to perform as many steps as possible.

`options':
     The options for ARPACK. `n' is always overwritten. `ncv' is set to
     at least 3.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_community_leading_eigenvector()' (see
     igraph_community_leading_eigenvector --- Leading eigenvector community finding [proper version]_)
     for the proper way,
     `igraph_community_leading_eigenvector_step()' (see
     igraph_community_leading_eigenvector_step --- Leading eigenvector community finding [make one step]_)
     to do just one split.

   Time complexity: O(E|+|V|^2*steps), |V| is the number of vertices,
|E| is the number of edges.

17.3.3 igraph_community_leading_eigenvector_step -- Leading eigenvector community finding (make one step).
----------------------------------------------------------------------------------------------------------

     int igraph_community_leading_eigenvector_step(const igraph_t *graph,
     					      igraph_vector_t *membership,
     					      igraph_integer_t community,
     					      igraph_bool_t *split,
     					      igraph_vector_t *eigenvector,
     					      igraph_real_t *eigenvalue,
     					      igraph_arpack_options_t *options,
     					      igraph_arpack_storage_t *storage);

   Do one split according to Mark Newman's leading eigenvector
community detection method. See MEJ Newman: Finding community structure
in networks using the eigenvectors of matrices, arXiv:phyisics/0605087
for the details.

   Use this function instead of
`igraph_community_leading_eigenvector()' (see
igraph_community_leading_eigenvector --- Leading eigenvector community finding [proper version]_)
if you want to have full control over and
information about each split performed along community structure
detection. `igraph_community_leading_eigenvector()' (see
igraph_community_leading_eigenvector --- Leading eigenvector community finding [proper version]_)
can be simulated by repeatedly calling
this function.

   *Arguments:. *

`graph':
     The undirected input graph.

`membership':
     Numeric vector giving a division of `graph'.  The result will be
     also stored here. The vector contains the community ids for each
     vertex, these are numbered from 0.

`community':
     The id of the community to split.

`split':
     Pointer to a logical variable, if it was possible to split
     community `community' then 1, otherwise 0 will be stored here.
     This argument is ignored if it is `NULL'.

`eigenvector':
     Pointer to an initialized vector, the eigenvector on which the
     split was done will be stored here.  It will be resised to have
     the same length as the number of vertices in community
     `community'. This argument is ignored if it is `NULL'.

`eigenvalue':
     Pointer to a real variable, the eigenvalue associated with
     `eigenvector' will be stored here.  This argument is ignored if it
     is `NULL'.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_community_leading_eigenvector()' (see
     igraph_community_leading_eigenvector --- Leading eigenvector community finding [proper version]_).

   Time complexity: O(|E|+|V|^2), |E| is the number of edges, |V| is
the number of vertices.

17.3.4 igraph_le_community_to_membership -- Vertex membership from the leading eigenvector community structure
--------------------------------------------------------------------------------------------------------------

     int igraph_le_community_to_membership(const igraph_matrix_t *merges,
     				      igraph_integer_t steps,
     				      igraph_vector_t *membership,
     				      igraph_vector_t *csize);

   This function creates a membership vector from the result of
`igraph_community_leading_eigenvector()' (see
igraph_community_leading_eigenvector --- Leading eigenvector community finding [proper version]_)
or
`igraph_community_leading_eigenvector_naive()' (see
igraph_community_leading_eigenvector_naive --- Leading eigenvector community finding [naive version]_).
It takes `membership' and
permformes `steps' merges, according to the supplied `merges' matrix.

   *Arguments:. *

`merges':
     The matrix defining the merges to make.  This is usually from the
     output of the leading eigenvector community structure detection
     routines.

`steps':
     The number of steps to make according to `merges'.

`membership':
     Initially the starting membership vector, on output the resulting
     membership vector, after performing `steps' merges.

`csize':
     Optionally the sizes of the commmunities is stored here, if this
     is not a null pointer, but an initialized vector.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|), the number of vertices.

17.4 Walktrap: community structure based on random walks
========================================================

17.4.1 igraph_community_walktrap -- This function is the implementation of the Walktrap community
-------------------------------------------------------------------------------------------------

     int igraph_community_walktrap(const igraph_t *graph,
     			      const igraph_vector_t *weights,
     			      int steps,
     			      igraph_matrix_t *merges,
     			      igraph_vector_t *modularity);

   finding algorithm, see Pascal Pons, Matthieu Latapy: Computing
communities in large networks using random walks,
http://arxiv.org/abs/physics/0512106
(http://arxiv.org/abs/physics/0512106)

   Currently the original C++ implementation is used in igraph, see
http://www.liafa.jussieu.fr/~pons/index.php?item=prog&item2=walktrap&lang=en
(http://www.liafa.jussieu.fr/~pons/index.php?item=prog&item2=walktrap&lang=en)
I'm grateful to Matthieu Latapy and Pascal Pons for providing this
source code.

   Note that the graph must not contain isolated vertices in order to
use this method.

   *Arguments:. *

`graph':
     The input graph.

`weights':
     Numeric vector giving the weights of the edges.  If it is a NULL
     pointer then all edges will have equal weights. The weights are
     expected to be positive.

`steps':
     Integer constant, the length of the random walks.

`merges':
     Pointer to a matrix, the merges performed by the algorithm will be
     stored here (if not NULL). Each merge is a row in a two-column
     matrix and contains the ids of the merged clusters. Clusters are
     numbered from zero and cluster number smaller than the number of
     nodes in the network belong to the individual vertices as
     singleton clusters. In each step a new cluster is created from two
     other clusters and its id will be one larger than the largest
     cluster id so far. This means that before the first merge we have
     `n' clusters (the number of vertices in the graph) numbered from
     zero to `n-1'. The first merge created cluster `n', the second
     cluster `n'+1, etc.

`modularity':
     Pointer to a vector. If not NULL then the modularity score of the
     current clustering is stored here after each merge operation.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_community_spinglass()' (see igraph_community_spinglass --- Community detection based on statistical mechanics),
     `igraph_community_edge_betweenness()' (see
     igraph_community_edge_betweenness --- Community findinf based on edge betweenness).

   Time complexity: O(|E||V|^2) in the worst case, O(|V|^2 log|V|)
typically, |V| is the number of vertices, |E| is the number of edges.

17.5 Edge betweenness based community detection
===============================================

17.5.1 igraph_community_edge_betweenness -- Community findinf based on edge betweenness
---------------------------------------------------------------------------------------

     int igraph_community_edge_betweenness(const igraph_t *graph,
     				      igraph_vector_t *result,
     				      igraph_vector_t *edge_betweenness,
     				      igraph_matrix_t *merges,
     				      igraph_vector_t *bridges,
     				      igraph_bool_t directed);

   Community structure detection based on the betweenness of the edges
in the network. The algorithm was invented by M. Girvan and M. Newman,
see: M. Girvan and M. E. J. Newman: Community structure in social and
biological networks, Proc. Nat. Acad. Sci. USA 99, 7821-7826 (2002).

   The idea is that the betweenness of the edges connecting two
communities is typically high, as many of the shortest paths between
nodes in separate communities go through them. So we gradually remove
the edge with highest betweenness from the network, and recalculate
edge betweenness after every removal.  This way sooner or later the
network falls off to two components, then after a while one of these
components falls off to two smaller components, etc. until all edges
are removed. This is a divisive hieararchical approach, the result is a
dendrogram.

   *Arguments:. *

`graph':
     The input graph.

`result':
     Pointer to an initialized vector, the result will be stored here,
     the ids of the removed edges in the order of their removal. It
     will be resized as needed.

`edge_betweenness':
     Pointer to an initialized vector or NULL. In the former case the
     edge betweenness of the removed edge is stored here. The vector
     will be resized as needed.

`merges':
     Pointer to an initialized matrix or NULL. If not NULL then merges
     performed by the algorithm are stored here. Even if this is a
     divisive algorithm, we can replay it backwards and note which two
     clusters were merged. Clusters are numbered from zero, see the
     `merges' argument of `igraph_community_walktrap()' (see
     igraph_community_walktrap --- This function is the implementation of the Walktrap community)
     for details. The matrix will be
     resized as needed.

`bridges':
     Pointer to an initialized vector of NULL. If not NULL then all
     edge removals which separated the network into more components are
     marked here.

`directed':
     Logical constant, whether to calculate directed betweenness (ie.
     directed paths) for directed graphs. It is ignored for undirected
     graphs.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_community_eb_get_merges()' (see
     igraph_community_eb_get_merges --- Calculating the merges; ie_ the dendrogram for an edge betweenness community structure),
     `igraph_community_spinglass()' (see igraph_community_spinglass --- Community detection based on statistical mechanics),
     `igraph_community_walktrap()' (see igraph_community_walktrap --- This function is the implementation of the Walktrap community).

   Time complexity: O(|V|^3), as the betweenness calculation requires
O(|V|^2) and we do it |V|-1 times.

17.5.2 igraph_community_eb_get_merges -- Calculating the merges, ie. the dendrogram for an edge betweenness community structure
-------------------------------------------------------------------------------------------------------------------------------

     int igraph_community_eb_get_merges(const igraph_t *graph,
     				   const igraph_vector_t *edges,
     				   igraph_matrix_t *res,
     				   igraph_vector_t *bridges);

   This function is handy if you have a sequence of edge which are
gradually removed from the network and you would like to know how the
network falls apart into separate components. The edge sequence may
come from the `igraph_community_edge_betweenness()' (see
igraph_community_edge_betweenness --- Community findinf based on edge betweenness)
function, but this is not neccessary. Note that
`igraph_community_edge_betweenness' (see
igraph_community_edge_betweenness --- Community findinf based on edge betweenness)
can also calculate the dendrogram, via its `merges'
argument.

   *Arguments:. *

`graph':
     The input graph.

`edges':
     Vector containing the edges to be removed from the network, all
     edges are expected to appear exactly once in the vector.

`res':
     Pointer to an initialized matrix, if not NULL then the dendrogram
     will be stored here, in the same form as for the
     `igraph_community_walktrap()' (see igraph_community_walktrap --- This function is the implementation of the Walktrap community)
     function: the matrix has two columns and each line is a merge
     given by the ids of the merged components. The component ids are
     number from zero and component ids smaller than the number of
     vertices in the graph belong to individual vertices. The
     non-trivial components containing at least two vertices are
     numbered from `n', `n' is the number of vertices in the graph. So
     if the first line contains `a' and `b' that means that components
     `a' and `b' are merged into component `n', the second line creates
     component `n'+1, etc. The matrix will be resized as needed.

`bridges':
     Pointer to an initialized vector or NULL. If not null then the
     index of the edge removals which split the network will be stored
     here. The vector will be resized as needed.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_community_edge_betweenness()' (see
     igraph_community_edge_betweenness --- Community findinf based on edge betweenness).

   Time complexity: O(|E|+|V|log|V|), |V| is the number of vertices,
|E| is the number of edges.

17.6 Community structure based on fast greedy optimization of modularity
========================================================================

17.6.1 igraph_community_fastgreedy -- Finding community structure by greedy optimization of modularity
------------------------------------------------------------------------------------------------------

     int igraph_community_fastgreedy(const igraph_t *graph,
       const igraph_vector_t *weights,
       igraph_matrix_t *merges, igraph_vector_t *modularity);

   This function implements the fast greedy modularity optimization
algorithm for finding community structure, see A Clauset, MEJ Newman, C
Moore: Finding community structure in very large networks,
http://www.arxiv.org/abs/cond-mat/0408187
(http://www.arxiv.org/abs/cond-mat/0408187) for the details.

   Some improvements proposed in K Wakita, T Tsurumi: Finding community
structure in mega-scale social networks,
http://www.arxiv.org/abs/cs.CY/0702048v1
(http://www.arxiv.org/abs/cs.CY/0702048v1) have also been implemented.

   *Arguments:. *

`graph':
     The input graph. It must be a simple graph, i.e. a graph without
     multiple and without loop edges. This is checked and an error
     message is given for non-simple graphs.

`weights':
     Potentially a numeric vector containing edge weights. Supply a
     null pointer here for unweighted graphs. The weights are expected
     to be non-negative.

`merges':
     Pointer to an initialized matrix or NULL, the result of the
     computation is stored here. The matrix has two columns and each
     merge corresponds to one merge, the ids of the two merged
     components are stored. The component ids are numbered from zero and
     the first `n' components are the individual vertices, `n' is the
     number of vertices in the graph. Component `n' is created in the
     first merge, component `n'+1 in the second merge, etc.  The matrix
     will be resized as needed. If this argument is NULL then it is
     ignored completely.

`modularity':
     Pointer to an initialized matrix or NULL pointer, in the former
     case the modularity scores along the stages of the computation are
     recorded here. The vector will be resized as needed.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_community_walktrap()' (see igraph_community_walktrap --- This function is the implementation of the Walktrap community),
     `igraph_community_edge_betweenness()' (see
     igraph_community_edge_betweenness --- Community findinf based on edge betweenness)
     for other community detection algorithms,
     `igraph_community_to_membership()' (see
     igraph_community_to_membership --- Create membership vector from community structure dendrogram)
     to convert the dendrogram to a
     membership vector.

   Time complexity: O(|E||V|log|V|) in the worst case,
O(|E|+|V|log^2|V|) typically, |V| is the number of vertices, |E| is the
number of edges.

17.7 Label propagation
======================

17.7.1 igraph_community_label_propagation --
--------------------------------------------

     int igraph_community_label_propagation(const igraph_t *graph,
                                            igraph_vector_t *membership,
                                            const igraph_vector_t *weights,
                                            const igraph_vector_t *initial,
                                            igraph_vector_bool_t *fixed);

   Community detection based on label propagation This function
implements the community detection method described in: Raghavan, U.N.
and Albert, R. and Kumara, S.: Near linear time algorithm to detect
community structures in large-scale networks. Phys Rev E 76, 036106.
(2007). This version extends the original method by the ability to take
edge weights into consideration and also by allowing some labels to be
fixed.

   *Arguments:. *

`graph':
     The input graph, should be undirected to make sense.

`membership':
     The membership vector, the result is returned here.  For each
     vertex it gives the ID of its community (label).

`weights':
     The weight vector, it should contain a positive weight for all the
     edges.

`initial':
     The initial state. If NULL, every vertex will have a different
     label at the beginning. Otherwise it must be a vector with an
     entry for each vertex. Non-negative values denote different
     labels, negative entries denote vertices without labels.

`fixed':
     Boolean vector denoting which labels are fixed. Of course this
     makes sense only if you provided an initial state, otherwise this
     element will be ignored. Also note that vertices without labels
     cannot be fixed.

   *Returns:. *

`'
     Error code.

   Time complexity: O(m+n)

18 Graph Operators
******************

18.1 Union and intersection
===========================

18.1.1 igraph_disjoint_union -- Creates the union of two disjoint graphs
------------------------------------------------------------------------

     int igraph_disjoint_union(igraph_t *res, const igraph_t *left,
     			  const igraph_t *right);

   First the vertices of the second graph will be relabeled with new
vertex ids to have two disjoint sets of vertex ids, then the union of
the two graphs will be formed.  If the two graphs have |V1| and |V2|
vertices and |E1| and |E2| edges respectively then the new graph will
have |V1|+|V2| vertices and |E1|+|E2| edges.

   Both graphs need to have the same directedness, ie. either both
directed or both undirected.

   The current version of this function cannot handle graph, vertex and
edge attributes, they will be lost.

   *Arguments:. *

`res':
     Pointer to an uninitialized graph object, the result will stored
     here.

`left':
     The first graph.

`right':
     The second graph.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_disjoint_union_many()' (see igraph_disjoint_union_many --- The disjint union of many graphs_)
     for creating the disjoint
     union of more than two graphs, `igraph_union()' (see
     igraph_union --- Calculates the union of two graphs_) for
     non-disjoint union.

   Time complexity: O(|V1|+|V2|+|E1|+|E2|).

18.1.2 igraph_disjoint_union_many -- The disjint union of many graphs.
----------------------------------------------------------------------

     int igraph_disjoint_union_many(igraph_t *res,
     			       const igraph_vector_ptr_t *graphs);

   First the vertices in the graphs will be relabed with new vertex ids
to have pairwise disjoint vertex id sets and then the union of the
graphs is formed.  The number of vertices and edges in the result is
the total number of vertices and edges in the graphs.

   Both graphs need to have the same directedness, ie. either both
directed or both undirected.

   The current version of this function cannot handle graph, vertex and
edge attributes, they will be lost.

   *Arguments:. *

`res':
     Pointer to an uninitialized graph object, the result of the
     operation will be stored here.

`graphs':
     Pointer vector, contains pointers to initialized graph objects.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_disjoint_union()' (see igraph_disjoint_union --- Creates the union of two disjoint graphs)
     for an easier syntax if you
     have only two graphs, `igraph_union_many()' (see
     igraph_union_many --- Creates the union of many graphs_) for
     non-disjoint union.

   Time complexity: O(|V|+|E|), the number of vertices plus the number
of edges in the result.

18.1.3 igraph_union -- Calculates the union of two graphs.
----------------------------------------------------------

     int igraph_union(igraph_t *res,
     		 const igraph_t *left, const igraph_t *right);

   The number of vertices in the result is that of the larger graph
from the two arguments. The result graph contains edges which are
present in at least one of the operand graphs.

   *Arguments:. *

`res':
     Pointer to an uninitialized graph object, the result will be
     stored here.

`left':
     The first graph.

`right':
     The second graph.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_union_many()' (see igraph_union_many --- Creates the union of many graphs_)
     for the union of many graphs,
     `igraph_intersection()' (see igraph_intersection --- Collect the common edges from two graphs_)
     and `igraph_difference()' (see
     igraph_difference --- Calculate the difference of two graphs)
     for other operators.

   Time complexity: O(|V|+|E|), |V| is the number of vertices, |E| the
number of edges in the result graph.

18.1.4 igraph_union_many -- Creates the union of many graphs.
-------------------------------------------------------------

     int igraph_union_many(igraph_t *res, const igraph_vector_ptr_t *graphs);

   The result graph will contain as many vertices as the largest graph
among the agruments does, and an edge will be included in it if it is
part of at least one operand graph.

   The directedness of the operand graphs must be the same.

   *Arguments:. *

`res':
     Pointer to an uninitialized graph object, this will contain the
     result.

`graphs':
     Pointer vector, contains pointers to the operands of the union
     operator, graph objects of course.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_union()' (see igraph_union --- Calculates the union of two graphs_)
     for the union of two graphs,
     `igraph_intersection_many()' (see igraph_intersection_many --- The intersection of more than two graphs_),
     `igraph_intersection()' (see igraph_intersection --- Collect the common edges from two graphs_)
     and `igraph_difference' (see
     igraph_difference --- Calculate the difference of two graphs)
     for other operators.

   Time complexity: O(|V|+|E|), |V| is the number of vertices in
largest graph and |E| is the number of edges in the result graph.

18.1.5 igraph_intersection -- Collect the common edges from two graphs.
-----------------------------------------------------------------------

     int igraph_intersection(igraph_t *res,
     			const igraph_t *left, const igraph_t *right);

   The result graph contains only edges present both in the first and
the second graph. The number of vertices in the result graph is the
same as the larger from the two arguments.

   *Arguments:. *

`res':
     Pointer to an uninitialized graph object. This will contain the
     result of the operation.

`left':
     The first operand, a graph object.

`right':
     The second operand, a graph object.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_intersection_many()' (see igraph_intersection_many --- The intersection of more than two graphs_)
     to calculate the
     intersection of many graphs at once, `igraph_union()' (see
     igraph_union --- Calculates the union of two graphs_),
     `igraph_difference()' (see igraph_difference --- Calculate the difference of two graphs)
     for other operators.

   Time complexity: O(|V|+|E|), |V| is the number of nodes, |E| is the
number of edges in the smaller graph of the two. (The one containing
less vertices is considered smaller.)

18.1.6 igraph_intersection_many -- The intersection of more than two graphs.
----------------------------------------------------------------------------

     int igraph_intersection_many(igraph_t *res,
     			     const igraph_vector_ptr_t *graphs);

   This function calculates the intersection of the graphs stored in
the `graphs' argument. Only those edges will be included in the result
graph which are part of every graph in `graphs'.

   The number of vertices in the result graph will be the maximum
number of vertices in the argument graphs.

   *Arguments:. *

`res':
     Pointer to an uninitialized graph object, the result of the
     operation will be stored here.

`graphs':
     Pointer vector, contains pointers to graphs objects, the operands
     of the intersection operator.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_intersection()' (see igraph_intersection --- Collect the common edges from two graphs_)
     for the intersection of two
     graphs, `igraph_union_many()' (see igraph_union_many --- Creates the union of many graphs_),
     `igraph_union()' (see igraph_union --- Calculates the union of two graphs_)
     and
     `igraph_difference()' (see igraph_difference --- Calculate the difference of two graphs)
     for other operators.

   Time complexity: O(|V|+|E|), |V| is the number of vertices, |E| is
the number of edges in the smallest graph (ie. the graph having the
less vertices).

18.2 Other set-like operators
=============================

18.2.1 igraph_difference -- Calculate the difference of two graphs
------------------------------------------------------------------

     int igraph_difference(igraph_t *res,
     		      const igraph_t *orig, const igraph_t *sub);

   The number of vertices in the result is the number of vertices in
the original graph, ie. the left, first operand. In the results graph
only edges will be included from `orig' which are not present in `sub'.

   *Arguments:. *

`res':
     Pointer to an uninitialized graph object, the result will be
     stored here.

`orig':
     The left operand of the operator, a graph object.

`sub':
     The right operand of the operator, a graph object.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_intersection()' (see igraph_intersection --- Collect the common edges from two graphs_)
     and `igraph_union()' (see
     igraph_union --- Calculates the union of two graphs_) for other
     operators.

   Time complexity: O(|V|+|E|), |V| is the number vertices in the
smaller graph, |E| is the number of edges in the result graph.

18.2.2 igraph_complementer -- Create the complementer of a graph
----------------------------------------------------------------

     int igraph_complementer(igraph_t *res, const igraph_t *graph,
     			igraph_bool_t loops);

   The complementer graph means that all edges which are not part of
the original graph will be included in the result.

   *Arguments:. *

`res':
     Pointer to an uninitialized graph object.

`graph':
     The original graph.

`loops':
     Whether to add loop edges to the complementer graph.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_union()' (see igraph_union --- Calculates the union of two graphs_),
     `igraph_intersection()' (see igraph_intersection --- Collect the common edges from two graphs_)
     and
     `igraph_difference()' (see igraph_difference --- Calculate the difference of two graphs).

   Time complexity: O(|V|+|E1|+|E2|), |V| is the number of vertices in
the graph, |E1| is the number of edges in the original and |E2| in the
complementer graph.

18.2.3 igraph_compose -- Calculates the composition of two graphs
-----------------------------------------------------------------

     int igraph_compose(igraph_t *res, const igraph_t *g1, const igraph_t *g2);

   The composition of graphs contains the same number of vertices as
the bigger graph of the two operands. It contains an (i,j) edge if and
only if there is a k vertex, such that the first graphs contains an
(i,k) edge and the second graph a (k,j) edge.

   This is of course exactly the composition of two binary relations.

   Two two graphs must have the same directedness, otherwise the
function returns with an error message.  Note that for undirected
graphs the two relations are by definition symmetric.

   *Arguments:. *

`res':
     Pointer to an uninitialized graph object, the result will be
     stored here.

`g1':
     The firs operarand, a graph object.

`g2':
     The second operand, another graph object.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|*d1*d2), |V| is the number of vertices in the
first graph, d1 and d2 the average degree in the first and second
graphs.

19 Using ARPACK for igraph graphs
*********************************

19.1 About the ARPACK interface in igraph
=========================================

ARPACK is a library for solving large scale eigenvalue problems.  The
package is designed to compute a few eigenvalues and corresponding
eigenvectors of a general `n' by `n' matrix `A'. It is most appropriate
for large sparse or structured matrices `A' where structured means that
a matrix-vector product ` w <- Av'  requires order `n' rather than the
usual order ` n^2'  floating point operations. Please see
http://www.caam.rice.edu/software/ARPACK/
(http://www.caam.rice.edu/software/ARPACK/) for details.

   The eigenvalue calculation in ARPACK (in the simplest case) involves
the calculation of the `Av' product where `A' is the matrix we work
with and `v' is an arbitrary vector. A user-defined function of type
`igraph_arpack_function_t' (see igraph_arpack_function_t --- Type of the ARPACK callback function)
is expected to perform this product. If
the product can be done efficiently, e.g. if the matrix is sparse, then
ARPACK is usually able to calculate the eigenvalues very quickly.

   In igraph, eigenvalue/eigenvector calculations usually involve the
following steps:

  1. Initialization of an `igraph_arpack_options_t' (see
     igraph_arpack_options_t --- Options for ARPACK) data structure
     using `igraph_arpack_options_init' (see
     igraph_arpack_options_init --- Initialize ARPACK options).

  2. Setting some options in the initialized `igraph_arpack_options_t'
     (see igraph_arpack_options_t --- Options for ARPACK) object.

  3. Defining a function of type `igraph_arpack_function_t' (see
     igraph_arpack_function_t --- Type of the ARPACK callback function).
     The input of this function is a vector, and the
     output should be the output matrix multiplied by the input vector.

  4. Calling `igraph_arpack_rssolve()' (see igraph_arpack_rssolve --- ARPACK solver for symmetric matrices)
     (is the matrix is
     symmetric), or `igraph_arpack_rnsolve()' (see
     igraph_arpack_rnsolve --- ARPACK solver for non-symmetric matrices).

The `igraph_arpack_options_t' (see igraph_arpack_options_t --- Options for ARPACK)
object can be used multiple times.

   If we have many eigenvalue problems to solve, then it might worth to
create an `igraph_arpack_storage_t' (see igraph_arpack_storage_t --- Storage for ARPACK)
object, and initialize it via
`igraph_arpack_storage_init()' (see igraph_arpack_storage_init --- Initialize ARPACK storage).
This structure contains all memory needed
for ARPACK (with the given upper limit regerding to the size of the
eigenvalue problem). Then many problems can be solved using the same
`igraph_arpack_storage_t' (see igraph_arpack_storage_t --- Storage for ARPACK)
object, without always reallocating the required memory.
The `igraph_arpack_storage_t' (see igraph_arpack_storage_t --- Storage for ARPACK)
object needs to be destroyed by calling
`igraph_arpack_storage_destroy()' (see igraph_arpack_storage_destroy --- Deallocate ARPACK storage)
on it, when it is not needed any more.

   igraph does not contain all ARPACK routines, only the ones dealing
with symmetric and non-symmetric eigenvalue problems using double
precision real numbers.

19.2 Data structures
====================

19.2.1 igraph_arpack_options_t -- Options for ARPACK
----------------------------------------------------

     typedef struct igraph_arpack_options_t {
       /* INPUT */
       char bmat[1];			/* I-standard problem, G-generalized */
       long int n; 			/* Dimension of the eigenproblem */
       char which[2];		/* LA, SA, LM, SM, BE */
       long int nev;                 /* Number of eigenvalues to be computed */
       igraph_real_t tol;		/* Stopping criterion */
       long int ncv;			/* Number of columns in V */
       long int ldv;			/* Leading dimension of V */
       long int ishift;		/* 0-reverse comm., 1-exact with tridiagonal */
       long int mxiter;              /* Maximum number of update iterations to take */
       long int nb;			/* Block size on the recurrence, only 1 works */
       long int mode;		/* The kind of problem to be solved (1-5)
     				   1: A*x=l*x, A symmetric
     				   2: A*x=l*M*x, A symm. M pos. def.
     				   3: K*x = l*M*x, K symm., M pos. semidef.
     				   4: K*x = l*KG*x, K s. pos. semidef. KG s. indef.
     				   5: A*x = l*M*x, A symm., M symm. pos. semidef. */
       long int start;		/* 0: random, 1: use the supplied vector */
       long int lworkl;		/* Size of temporary storage, default is fine */
       igraph_real_t sigma;          /* The shift for modes 3,4,5 */
       igraph_real_t sigmai;		/* The imaginary part of shift for rnsolve */
       /* OUTPUT */
       long int info;		/* What happened, see docs */
       long int ierr;		/* What happened  in the dseupd call */
       long int noiter;		/* The number of iterations taken */
       long int nconv;
       long int numop;		/* Number of OP*x operations */
       long int numopb;		/* Number of B*x operations if BMAT='G' */
       long int numreo;		/* Number of steps of re-orthogonalizations */
       /* INTERNAL */
       long int iparam[11];
       long int ipntr[14];
     } igraph_arpack_options_t;

   This data structure contains the options of thee ARPACK eigenvalue
solver routines. It must be initialized by calling
`igraph_arpack_options_init()' (see igraph_arpack_options_init --- Initialize ARPACK options)
on it. Then it can be used for multiple
ARPACK calls, as the ARPACK solvers do not modify it.  Input options:

   *Values:. *

`bmat':
     Character. Whether to solve a standard ('I') ot a generalized
     problem ('B').

`n':
     Dimension of the eigenproblem.

`which':
     Specifies which eigenvalues/vectors to compute. Possible values
     for symmetric matrices:

    `LA '
          Compute `nev' largest (algebraic) eigenvalues.

    `SA '
          Compute `nev' smallest (algebraic) eigenvalues.

    `LM '
          Compute `nev' largest (in magnitude) eigenvalues.

    `SM '
          Compute `nev' smallest (in magnitude) eigenvalues.

    `BE '
          Compute `nev' eigenvalues, half from each end of the
          spectrum. When `nev' is odd, compute one more from the high
          en than from the low end.

     Possible values for non-symmetric matrices:

    `LM '
          Compute `nev' largest (in magnitude) eigenvalues.

    `SM '
          Compute `nev' smallest (in magnitude) eigenvalues.

    `LR '
          Compute `nev' eigenvalues of largest real part.

    `SR '
          Compute `nev' eigenvalues of smallest real part.

    `LI '
          Compute `nev' eigenvalues of largest imaginary part.

    `SI '
          Compute `nev' eigenvalues of smallest imaginary part.

`nev':
     The number of eigenvalues to be computed.

`tol':
     Stopping criterion: the relative accuracy of the Ritz value is
     considered acceptable if its error is less than `tol' times its
     estimated value. If this is set to zero then machine precision is
     used.

`ncv':
     Number of Lanczos vectors to be generated.

`ldv':
     Numberic scalar. It should be set to zero in the current igraph
     implementation.

`ishift':
     Either zero or one. If zero then the shifts are provided by the
     user via reverse communication. If one then exact shifts with
     respect to the reduced tridiagonal matrix `T'.  Please always set
     this to one.

`mxiter':
     Maximum number of Arnoldi update iterations allowed.

`nb':
     Blocksize to be used in the recurrence. Please always leave this
     on the default value, one.

`mode':
     The type of the eigenproblem to be solved.  Possible values if the
     input matrix is symmetric:

       1. A*x=lambda*x, A is symmetric.

       2. A*x=lambda*M*x, A is symmetric, M is symmetric positive
          definite.

       3. K*x=lambda*M*x, K is symmetric, M is symmetric positive
          semi-definite.

       4. K*x=lambda*KG*x, K is symmetric positive semi-definite, KG is
          symmetric indefinite.

       5. A*x=lambda*M*x, A is symmetric, M is symmetric positive
          semi-definite. (Cayley transformed mode.)

     Please note that only `mode' ==1 was tested and other values might
     not work properly.  Possible values if the input matrix is not
     symmetric:

       1. A*x=lambda*x.

       2. A*x=lambda*M*x, M is symmetric positive definite.

       3. A*x=lambda*M*x, M is symmetric semi-definite.

       4. A*x=lambda*M*x, M is symmetric semi-definite.

     Please note that only `mode' == 1 was tested and other values
     might not work properly.

`start':
     Whether to use the supplied starting vector (1), or use a random
     starting vector (0). The starting vector must be supplied in the
     first column of the `vectors' argument of the
     `igraph_arpack_rssolve()' (see igraph_arpack_rssolve --- ARPACK solver for symmetric matrices)
     of `igraph_arpack_rnsolve()'
     (see igraph_arpack_rnsolve --- ARPACK solver for non-symmetric matrices)
     call.

   Output options:

   *Values:. *

`info':
     Error flag of ARPACK. Possible values:

    `0 '
          Normal exit.

    `1 '
          Maximum number of iterations taken.

    `3 '
          No shifts could be applied during a cycle of the Implicitly
          restarted Arnoldi iteration. One possibility is to increase
          the size of \ ncv relative to `nev'.

     ARPACK can return other error flags as well, but these are
     converted to igraph errors, see `igraph_error_type_t' (see
     igraph_error_type_t --- Error code type_).

`ierr':
     Error flag of the second ARPACK call (one eigenvalue computation
     usually involves two calls to ARPACK). This is always zero, as
     other error codes are converted to igraph errors.

`noiter':
     Number of Arnoldi iterations taken.

`nconv':
     Number of converged Ritz values. This represents the number of
     Ritz values that satisfy the convergence critetion.

`numop':
     Total number of matrix-vector multiplications.

`numopb':
     Not used currently.

`numreo':
     Total number of steps of re-orthogonalization.

   Internal options:

   *Values:. *

`lworkl':
     Do not modify this option.

`sigma':
     Do not modify this option.

`sigmai':
     Do not modify this option.

`iparam':
     Do not modify this option.

`ipntr':
     Do not modify this option.

19.2.2 igraph_arpack_storage_t -- Storage for ARPACK
----------------------------------------------------

     typedef struct igraph_arpack_storage_t {
       long int maxn, maxncv, maxldv;
       igraph_real_t *v;
       igraph_real_t *workl;
       igraph_real_t *workd;
       igraph_real_t *d;
       igraph_real_t *resid;
       igraph_real_t *ax;
       long int *select;
       igraph_real_t *di;		/* These two only for non-symmetric problems */
       igraph_real_t *workev;
     } igraph_arpack_storage_t;

   Public members, do not modify them directly, these are considered to
be read-only.

   *Values:. *

`maxn':
     Maximum rank of matrix.

`maxncv':
     Maximum NCV.

`maxldv':
     Maximum LDV.

   These members are considered to be private:

   *Values:. *

`workl':
     Working memory.

`workd':
     Working memory.

`d':
     Memory for eigenvalues.

`resid':
     Memory for residuals.

`ax':
     Working memory.

`select':
     Working memory.

`di':
     Memory for eigenvalues, non-symmetric case only.

`workev':
     Working memory, non-symmetric case only.

19.2.3 igraph_arpack_function_t -- Type of the ARPACK callback function
-----------------------------------------------------------------------

     typedef int igraph_arpack_function_t(igraph_real_t *to, const igraph_real_t *from,
     				     long int n, void *extra);

   *Arguments:. *

`to':
     Pointer to an `igraph_real_t', the result of the matrix-vector
     product is expected to be stored here.

`from':
     Pointer to an `igraph_real_t', the input matrix should be
     multiplied by the vector stored here.

`n':
     The length of the vector (which is the same as the order of the
     input matrix).

`extra':
     Extra argument to the matrix-vector calculation function. This is
     coming from the `igraph_arpack_rssolve()' (see
     igraph_arpack_rssolve --- ARPACK solver for symmetric matrices)
     or `igraph_arpack_rnsolve()' (see igraph_arpack_rnsolve --- ARPACK solver for non-symmetric matrices)
     function.

   *Returns:. *

`'
     Error code, if not zero, then the ARPACK solver considers this as
     an error, stops and calls the igraph error handler.

19.2.4 igraph_arpack_options_init -- Initialize ARPACK options
--------------------------------------------------------------

     void igraph_arpack_options_init(igraph_arpack_options_t *o);

   Initializes ARPACK options, set them to default values.  You can
always pass the initialized `igraph_arpack_options_t' (see
igraph_arpack_options_t --- Options for ARPACK) object to built-in
igraph functions without any modification. The built-in igraph
functions modify the options to perform their calculation, e.g.
`igraph_pagerank()' (see igraph_pagerank --- Calculates the Google PageRank for the specified vertices_)
always searches for the
eigenvalue with the largest magnitude, regardless of the supplied value.

   If you want to implement your own function involving eigenvalue
calculation using ARPACK, however, you will likely need to set up the
fields for yourself.

   *Arguments:. *

`o':
     The `igraph_arpack_options_t' (see igraph_arpack_options_t --- Options for ARPACK)
     object to initialize.

   Time complexity: O(1).

19.2.5 igraph_arpack_storage_init -- Initialize ARPACK storage
--------------------------------------------------------------

     int igraph_arpack_storage_init(igraph_arpack_storage_t *s, long int maxn,
     			       long int maxncv, long int maxldv,
     			       igraph_bool_t symm);

   You only need this function if you want to run multiple eigenvalue
calculations using ARPACK, and want to spare the memory
allocation/deallocation between each two runs. Otherwise it is safe to
supply a null pointer as the `storage' argument of both
`igraph_arpack_rssolve()' (see igraph_arpack_rssolve --- ARPACK solver for symmetric matrices)
and `igraph_arpack_rnsolve()' (see
igraph_arpack_rnsolve --- ARPACK solver for non-symmetric matrices)
to make memory allocated and deallocated automatically.

   Don't forget to call the `igraph_arpack_storage_destroy()' (see
igraph_arpack_storage_destroy --- Deallocate ARPACK storage) function
on the storage object if you don't need it any more.

   *Arguments:. *

`s':
     The `igraph_arpack_storage_t' (see igraph_arpack_storage_t --- Storage for ARPACK)
     object to initialize.

`maxn':
     The maximum order of the matrices.

`maxncv':
     The maximum NCV parameter intended to use.

`maxldv':
     The maximum LDV parameter intended to use.

`symm':
     Whether symmetric or non-symmetric problems will be solved using
     this `igraph_arpack_storage_t' (see igraph_arpack_storage_t --- Storage for ARPACK).
     (You cannot use the same storage both with
     symmetric and non-symmetric solvers.)

   *Returns:. *

`'
     Error code.

   Time complexity: O(maxncv*(maxldv+maxn)).

19.2.6 igraph_arpack_storage_destroy -- Deallocate ARPACK storage
-----------------------------------------------------------------

     void igraph_arpack_storage_destroy(igraph_arpack_storage_t *s);

   *Arguments:. *

`s':
     The `igraph_arpack_storage_t' (see igraph_arpack_storage_t --- Storage for ARPACK)
     object for which the memory will be
     deallocated.

   Time complexity: operating system dependent.

19.3 ARPACK solvers
===================

19.3.1 igraph_arpack_rssolve -- ARPACK solver for symmetric matrices
--------------------------------------------------------------------

     int igraph_arpack_rssolve(igraph_arpack_function_t *fun, void *extra,
     			  igraph_arpack_options_t *options,
     			  igraph_arpack_storage_t *storage,
     			  igraph_vector_t *values, igraph_matrix_t *vectors);

   This is the ARPACK solver for symmetric matrices. Please use
`igraph_arpack_rnsolve()' (see igraph_arpack_rnsolve --- ARPACK solver for non-symmetric matrices)
for non-symmetric matrices.

   *Arguments:. *

`fun':
     Pointer to an `igraph_arpack_function_t' (see
     igraph_arpack_function_t --- Type of the ARPACK callback function)
     object, the function that performs the matrix-vector
     multiplication.

`extra':
     An extra argument to be passed to `fun'.

`options':
     An `igraph_arpack_options_t' (see igraph_arpack_options_t --- Options for ARPACK)
     object.

`storage':
     An `igraph_arpack_storage_t' (see igraph_arpack_storage_t --- Storage for ARPACK)
     object, or a null pointer. In the latter
     case memory allocation and deallocation is performed automatically.

`values':
     If not a null pointer, then it should be a pointer to an
     initialized vector. The eigenvalues will be stored here. The
     vector will be resized as needed.

`vectors':
     If not a null pointer, then it must be a pointer to an initialized
     matrix. The eigenvectors will be stored in the columns of the
     matrix. The matrix will be resized as needed.

   *Returns:. *

`'
     Error code.

   Time complexity: depends on the matrix-vector multiplication.
Usually a small number of iterations is enough, so if the matrix is
sparse and the matrix-vector multiplication can be done in O(n) time
(the number of vertices), then the eigenvalues are found in O(n) time
as well.

19.3.2 igraph_arpack_rnsolve -- ARPACK solver for non-symmetric matrices
------------------------------------------------------------------------

     int igraph_arpack_rnsolve(igraph_arpack_function_t *fun, void *extra,
     			  igraph_arpack_options_t *options,
     			  igraph_arpack_storage_t *storage,
     			  igraph_matrix_t *values, igraph_matrix_t *vectors);

   Please always consider calling `igraph_arpack_rssolve()' (see
igraph_arpack_rssolve --- ARPACK solver for symmetric matrices) if
your matrix is symmetric, it is much faster.  `igraph_arpack_rnsolve()'
(see igraph_arpack_rnsolve --- ARPACK solver for non-symmetric matrices)
for non-symmetric matrices.

   *Arguments:. *

`fun':
     Pointer to an `igraph_arpack_function_t' (see
     igraph_arpack_function_t --- Type of the ARPACK callback function)
     object, the function that performs the matrix-vector
     multiplication.

`extra':
     An extra argument to be passed to `fun'.

`options':
     An `igraph_arpack_options_t' (see igraph_arpack_options_t --- Options for ARPACK)
     object.

`storage':
     An `igraph_arpack_storage_t' (see igraph_arpack_storage_t --- Storage for ARPACK)
     object, or a null pointer. In the latter
     case memory allocation and deallocation is performed automatically.

`values':
     If not a null pointer, then it should be a pointer to an
     initialized matrix. The (possibly complex) eigenvalues will be
     stored here. The matrix will have two columns, the first column
     contains the real, the second the imaginary parts of the
     eigenvalues.  The matrix will be resized as needed.

`vectors':
     If not a null pointer, then it must be a pointer to an initialized
     matrix. The eigenvectors will be stored in the columns of the
     matrix. The matrix will be resized as needed.

   *Returns:. *

`'
     Error code.

   Time complexity: depends on the matrix-vector multiplication.
Usually a small number of iterations is enough, so if the matrix is
sparse and the matrix-vector multiplication can be done in O(n) time
(the number of vertices), then the eigenvalues are found in O(n) time
as well.

19.3.3 igraph_arpack_unpack_complex -- Make the result of the non-symmetric ARPACK solver more readable
-------------------------------------------------------------------------------------------------------

     int igraph_arpack_unpack_complex(igraph_matrix_t *vectors, igraph_matrix_t *values,
     				 long int nev);

   This function works on the output of `igraph_arpack_rnsolve' (see
igraph_arpack_rnsolve --- ARPACK solver for non-symmetric matrices)
and brushes it up a bit: it only keeps `nev' eigenvalues/vectors and
every eigenvector is stored in two columns of the `vectors' matrix.

   The output of the non-symmetric ARPACK solver is somewhat hard to
parse, as real eigenvectors occupy only one column in the matrix, and
the complex conjugate eigenvectors are not stored at all (usually). The
other problem is that the solver might return more eigenvalues than
requested. The common use of this function is to call it directly after
`igraph_arpack_rnsolve' (see igraph_arpack_rnsolve --- ARPACK solver for non-symmetric matrices)
with its `vectors' and `values' argument
and `options'->nev as `nev'.

   *Arguments:. *

`vectors':
     The eigenvector matrix, as returned by `igraph_arpack_rnsolve'
     (see igraph_arpack_rnsolve --- ARPACK solver for non-symmetric matrices).
     It will be resized, typically it will be larger.

`values':
     The eigenvalue matrix, as returned by `igraph_arpack_rnsolve'
     (see igraph_arpack_rnsolve --- ARPACK solver for non-symmetric matrices).
     It will be resized, typically extra, unneeded rows
     (=eigenvalues) will be removed.

`nev':
     The number of eigenvalues/vectors to keep. Can be less or equal
     than the number originally requested from ARPACK.

   *Returns:. *

`'
     Error code.

   Time complexity: linear in the number of elements in the `vectors'
matrix.

20 Bipartite, i.e. two-mode graphs
**********************************

20.1 Bipartite networks in igraph
=================================

A bipartite network contains two kinds of vertices and connections are
only possible between two vertices of different kind. There are many
natural examples, e.g. movies and actors as vertices and a movie is
connected to all participating actors, etc.

   igraph does not have direct support for bipartite networks, at least
not at the C language level. In other words the igraph_t structure does
not contain information about the vertex types.  The C functions for
bipartite networks usually have an additional input argument to graph,
called `types', a boolean vector giving the vertex types.

   Most functions creating bipartite networks are able to create this
extra vector, you just need to supply an initialized boolean vector to
them.

20.2 Create two-mode networks
=============================

20.2.1 igraph_create_bipartite -- Create a bipartite graph
----------------------------------------------------------

     int igraph_create_bipartite(igraph_t *graph, const igraph_vector_bool_t *types,
     			    const igraph_vector_t *edges,
     			    igraph_bool_t directed);

   This is a simple wrapper function to create a bipartite graph. It
does a little more than `igraph_create()' (see igraph_create --- Creates a graph with the specified edges_),
e.g. it checks that the
graph is indeed bipartite with respect to the given `types' vector. If
there is an edge connecting two vertices of the same kind, then an
error is reported.

   *Arguments:. *

`graph':
     Pointer to an uninitlized graph object, the result is created here.

`types':
     Boolean vector giving the vertex types. The length of the vector
     defines the number of vertices in the graph.

`edges':
     Vector giving the edges of the graph. The highest vertex id in
     this vector must be smaller than the length of the `types' vector.

`directed':
     Boolean scalar, whether to create a directed graph.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), linear in the number of vertices and
edges.

20.2.2 igraph_full_bipartite -- Create a full bipartite network
---------------------------------------------------------------

     int igraph_full_bipartite(igraph_t *graph,
     			  igraph_vector_bool_t *types,
     			  igraph_integer_t n1, igraph_integer_t n2,
     			  igraph_bool_t directed,
     			  igraph_neimode_t mode);

   A bipartite network contains two kinds of vertices and connections
are only possible between two vertices of different kind. There are
many natural examples, e.g. movies and actors as vertices and a movie
is connected to all participating actors, etc.

   igraph does not have direct support for bipartite networks, at least
not at the C language level. In other words the igraph_t structure does
not contain information about the vertex types.  The C functions for
bipartite networks usually have an additional input argument to graph,
called `types', a boolean vector giving the vertex types.

   Most functions creating bipartite networks are able to create this
extra vector, you just need to supply an initialized boolean vector to
them.

   *Arguments:. *

`graph':
     Pointer to an igraph_t object, the graph will be created here.

`types':
     Pointer to a boolean vector. If not a null pointer, then the
     vertex types will be stored here.

`n1':
     Integer, the number of vertices of the first kind.

`n2':
     Integer, the number of vertices of the second kind.

`directed':
     Boolean, whether to create a directed graph.

`mode':
     A constant that gives the type of connections for directed graphs.
     If `IGRAPH_OUT', then edges point from vertices of the first kind
     to vertices of the second kind; if `IGRAPH_IN', then the opposite
     direction is realized; if `IGRAPH_ALL', then mutual edges will be
     created.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), linear in the number of vertices and
edges.

   *See also:. *

`'
     `igraph_full()' (see igraph_full --- Creates a full graph [directed or undirected; with or without loops]_)
     for
     non-bipartite full graphs.

20.3 Incidence matrices
=======================

20.3.1 igraph_incidence -- Create a bipartite graph from an incidence matrix
----------------------------------------------------------------------------

     int igraph_incidence(igraph_t *graph, igraph_vector_bool_t *types,
     		     const igraph_matrix_t *incidence,
     		     igraph_bool_t directed,
     		     igraph_neimode_t mode, igraph_bool_t multiple);

   A bipartite (or two-mode) graph contains two types of vertices and
edges always connect vertices of different types. An incidence matrix
is an nxm matrix, n and m are the number of vertices of the two types,
respectively. Nonzero elements in the matrix denote edges between the
two corresponding vertices.

   Note that this function can operate in two modes, depending on the
`multiple' argument. If it is FALSE (i.e. 0), then a single edge is
created for every non-zero element in the incidence matrix. If
`multiple' is TRUE (i.e. 1), then the matrix elements are rounded up to
the closest non-negative integer to get the number of edges to create
between a pair of vertices.

   This function does not create multiple edges if `multiple' is FALSE,
but might create some if it is TRUE.

   *Arguments:. *

`graph':
     Pointer to an uninitialized graph object.

`types':
     Pointer to an initialized boolean vector, or a null pointer. If
     not a null pointer, then the vertex types are stored here. It is
     resized as needed.

`incidence':
     The incidence matrix.

`directed':
     Gives whether to create an undirected or a directed graph.

`mode':
     Specifies the direction of the edges in a directed graph. If
     `IGRAPH_OUT', then edges point from vertices of the first kind
     (corresponding to rows) to vertices of the second kind
     (corresponding to columns); if `IGRAPH_IN', then the opposite
     direction is realized; if `IGRAPH_ALL', then mutual edges will be
     created.

`multiple':
     How to interpret the incidence matrix elements. See details below.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n*m), the size of the incidence matrix.

20.3.2 igraph_get_incidence -- Convert a bipartite graph into an incidence matrix
---------------------------------------------------------------------------------

     int igraph_get_incidence(const igraph_t *graph,
     			 const igraph_vector_bool_t *types,
     			 igraph_matrix_t *res,
     			 igraph_vector_t *row_ids,
     			 igraph_vector_t *col_ids);

   *Arguments:. *

`graph':
     The input graph, edge directions are ignored.

`types':
     Boolean vector containing the vertex types.

`res':
     Pointer to an initialized matrix, the result is stored here. An
     element of the matrix gives the number of edges (irrespectively of
     their direction) between the two corresponding vertices.

`row_ids':
     Pointer to an initialized vector or a null pointer. If not a null
     pointer, then the vertex ids (in the graph) corresponding to the
     rows of the result matrix are stored here.

`col_ids':
     Pointer to an initialized vector or a null pointer. If not a null
     pointer, then the vertex ids corresponding to the columns of the
     result matrix are stored here.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n*m), n and m are number of vertices of the two
different kind.

   *See also:. *

`'
     `igraph_incidence()' (see igraph_incidence --- Create a bipartite graph from an incidence matrix)
     for the opposite
     operation.

20.4 Project a two-mode graphs
==============================

20.4.1 igraph_bipartite_projection_size -- Calculate the number of vertices and edges in the bipartite projections
------------------------------------------------------------------------------------------------------------------

     int igraph_bipartite_projection_size(const igraph_t *graph,
     				     const igraph_vector_bool_t *types,
     				     igraph_integer_t *vcount1,
     				     igraph_integer_t *ecount1,
     				     igraph_integer_t *vcount2,
     				     igraph_integer_t *ecount2);

   This function calculates the number of vertices and edges in the two
projections of a bipartite network. This is useful if you have a big
bipartite network and you want to estimate the amount of memory you
would need to calculate the projections themselves.

   *Arguments:. *

`graph':
     The input graph.

`types':
     Boolean vector giving the vertex types of the graph.

`vcount1':
     Pointer to an `igraph_integer_t', the number of vertices in the
     first projection is stored here.

`ecount1':
     Pointer to an `igraph_integer_t', the number of edges in the first
     projection is stored here.

`vcount2':
     Pointer to an `igraph_integer_t', the number of vertices in the
     second projection is stored here.

`ecount2':
     Pointer to an `igraph_integer_t', the number of edges in the
     second projection is stored here.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_bipartite_projection()' (*note igraph_bipartite_projection
     --- Create one or both projections of a bipartite [two-mode]
     network::) to calculate the actual projection.

   Time complexity: O(|V|*d^2+|E|), |V| is the number of vertices, |E|
is the number of edges, d is the average (total) degree of the graphs.

20.4.2 igraph_bipartite_projection -- Create one or both projections of a bipartite (two-mode) network
------------------------------------------------------------------------------------------------------

     int igraph_bipartite_projection(const igraph_t *graph,
     				const igraph_vector_bool_t *types,
     				igraph_t *proj1,
     				igraph_t *proj2,
     				igraph_integer_t probe1);

   Creates one or both projections of a bipartite graph.

   *Arguments:. *

`graph':
     The bipartite input graph. Directedness of the edges is ignored.

`types':
     Boolean vector giving the vertex types of the graph.

`proj1':
     Pointer to an uninitialized graph object, the first projection
     will be created here. It a null pointer, then it is ignored, see
     also the `probe1' argument.

`proj2':
     Pointer to an uninitialized graph object, the second projection is
     created here, if it is not a null pointer. See also the `probe1'
     argument.

   *Returns:. *

`'
     Error code.

   *See also:. *

`'
     `igraph_bipartite_projection_size()' (see
     igraph_bipartite_projection_size --- Calculate the number of vertices and edges in the bipartite projections)
     to calculate
     the number of vertices and edges in the projections, without
     creating the projection graphs themselves.

   Time complexity: O(|V|*d^2+|E|), |V| is the number of vertices, |E|
is the number of edges, d is the average (total) degree of the graphs.

20.5 Other operations on bipartite graphs
=========================================

20.5.1 igraph_is_bipartite -- Check whether a graph is bipartite
----------------------------------------------------------------

     int igraph_is_bipartite(const igraph_t *graph,
     			igraph_bool_t *res,
     			igraph_vector_bool_t *type);

   This function simply checks whether a graph \emph{could} be
bipartite. It tries to find a mapping that gives a possible division of
the vertices into two classes, such that no two vertices of the same
class are connected by an edge.

   The existence of such a mapping is equivalent of having no circuits
of odd length in the graph. A graph with loop edges cannot bipartite.

   Note that the mapping is not necessarily unique, e.g. if the graph
has at least two components, then the vertices in the separate
components can be mapped independently.

   *Arguments:. *

`graph':
     The input graph.

`res':
     Pointer to a boolean, the result is stored here.

`type':
     Pointer to an initialized boolean vector, or a null pointer. If
     not a null pointer and a mapping was found, then it is stored
     here. If not a null pointer, but no mapping was found, the
     contents of this vector is invalid.

   *Returns:. *

`'
     Error code.

   Time complexity: O(|V|+|E|), linear in the number of vertices and
edges.

21 Not Graph Related Functions
******************************

21.1 Running Mean of a Time Series
==================================

21.1.1 igraph_running_mean -- Calculates the running mean of a vector.
----------------------------------------------------------------------

     int igraph_running_mean(const igraph_vector_t *data, igraph_vector_t *res,
     			igraph_integer_t binwidth);

   The running mean is defined by the mean of the previous `binwidth'
values.

   *Arguments:. *

`data':
     The vector containing the data.

`res':
     The vector containing the result. This should be initialized
     before calling this function and will be resized.

`binwidth':
     Integer giving the width of the bin for the running mean
     calculation.

   *Returns:. *

`'
     Error code.

   Time complexity: O(n), n is the length of the data vector.

21.2 Random Sampling from Very Long Sequences
=============================================

21.2.1 igraph_random_sample -- Generates an increasing random sequence of integers.
-----------------------------------------------------------------------------------

     int igraph_random_sample(igraph_vector_t *res, igraph_integer_t l, igraph_integer_t h,
     			 igraph_integer_t length);

   This function generates an incresing sequence of random integer
numbers from a given interval. The algorithm is taken literally from
Jeffrey Scott Vitter: 'An Efficient Algorithm for Sequential Random
Sampling', ACM Transactions on Mathematical Software, 13/1, 58-67. This
method can be used for generating numbers from a _very_ large interval,
it is primilarly created for randomly selecting some edges from the
sometimes huge set of possible edges in a large graph.

   *Arguments:. *

`res':
     Pointer to an initialized vector, this will hold the result. It
     will be resized to the proper size.

`l':
     The lower limit of the generation interval (inclusive).

`h':
     The upper limit of the generation interval (inclusive).

`length':
     The number of random integers to generate.

   *Returns:. *

`'
     Error code.

   Time complexity: according to the referenced paper, the expected
running time is O(length).

21.3 Convex hull of a set of points on a plane
==============================================

21.3.1 igraph_convex_hull -- Determines the convex hull of a given set of points in the 2D plane
------------------------------------------------------------------------------------------------

     int igraph_convex_hull(const igraph_matrix_t *data, igraph_vector_t *resverts,
     		       igraph_matrix_t *rescoords);

   The convex hull is determined by the Graham scan algorithm.  See the
following reference for details:

   Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and
Clifford Stein. Introduction to Algorithms, Second Edition. MIT Press
and McGraw-Hill, 2001. ISBN 0262032937. Pages 949-955 of section 33.3:
Finding the convex hull.

   *Arguments:. *

`data':
     vector containing the coordinates. The length of the vector must
     be even, since it contains X-Y coordinate pairs.

`resverts':
     the vector containing the result, e.g. the vector of vertex
     indices used as the corners of the convex hull. Supply `NULL' here
     if you are only interested in the coordinates of the convex hull
     corners.

`rescoords':
     the matrix containing the coordinates of the selected corner
     vertices. Supply `NULL' here if you are only interested in the
     vertex indices.

   *Returns:. *

`'
     Error code: `IGRAPH_ENOMEM': not enough memory

   Time complexity: O(n log(n)) where n is the number of vertices

22 Licenses for igraph and this manual
**************************************

22.1 THE GNU GENERAL PUBLIC LICENSE
===================================

22.1.1 Preamble
---------------

The licenses for most software are designed to take away your freedom
to share and change it.  By contrast, the GNU General Public License is
intended to guarantee your freedom to share and change free software-to
make sure the software is free for all its users.  This General Public
License applies to most of the Free Software Foundation's software and
to any other program whose authors commit to using it.  (Some other
Free Software Foundation software is covered by the GNU Library General
Public License instead.)  You can apply it to your programs, too.

   When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it in
new free programs; and that you know you can do these things.

   To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

   For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

   We protect your rights with two steps: (1) copyright the software,
and (2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

   Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

   Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

   The precise terms and conditions for copying, distribution and
modification follow.

22.1.2 GNU GENERAL PUBLIC LICENSE
---------------------------------

0. This License applies to any program or other work which contains a
notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

   Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the Program
(independent of having been made by running the Program).  Whether that
is true depends on what the Program does.

   1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

   You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

   2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

  1. You must cause the modified files to carry prominent notices
     stating that you changed the files and the date of any change.

  2. You must cause any work that you distribute or publish, that in
     whole or in part contains or is derived from the Program or any
     part thereof, to be licensed as a whole at no charge to all third
     parties under the terms of this License.

  3. If the modified program normally reads commands interactively when
     run, you must cause it, when started running for such interactive
     use in the most ordinary way, to print or display an announcement
     including an appropriate copyright notice and a notice that there
     is no warranty (or else, saying that you provide a warranty) and
     that users may redistribute the program under these conditions,
     and telling the user how to view a copy of this License.
     (Exception: if the Program itself is interactive but does not
     normally print such an announcement, your work based on the
     Program is not required to print an announcement.)

   These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.

   Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

   In addition, mere aggregation of another work not based on the
Program with the Program (or with a work based on the Program) on a
volume of a storage or distribution medium does not bring the other
work under the scope of this License.

   3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

  1. Accompany it with the complete corresponding machine-readable
     source code, which must be distributed under the terms of Sections
     1 and 2 above on a medium customarily used for software
     interchange; or,

  2. Accompany it with a written offer, valid for at least three years,
     to give any third party, for a charge no more than your cost of
     physically performing source distribution, a complete
     machine-readable copy of the corresponding source code, to be
     distributed under the terms of Sections 1 and 2 above on a medium
     customarily used for software interchange; or,

  3. Accompany it with the information you received as to the offer to
     distribute corresponding source code.  (This alternative is
     allowed only for noncommercial distribution and only if you
     received the program in object code or executable form with such
     an offer, in accord with Subsection b above.)

   The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to control
compilation and installation of the executable.  However, as a special
exception, the source code distributed need not include anything that
is normally distributed (in either source or binary form) with the
major components (compiler, kernel, and so on) of the operating system
on which the executable runs, unless that component itself accompanies
the executable.

   If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent access
to copy the source code from the same place counts as distribution of
the source code, even though third parties are not compelled to copy
the source along with the object code.

   4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt otherwise
to copy, modify, sublicense or distribute the Program is void, and will
automatically terminate your rights under this License.  However,
parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such parties
remain in full compliance.

   5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying the
Program or works based on it.

   6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

   7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

   If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

   It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

   This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

   8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License may
add an explicit geographical distribution limitation excluding those
countries, so that distribution is permitted only in or among countries
not thus excluded.  In such case, this License incorporates the
limitation as if written in the body of this License.

   9. The Free Software Foundation may publish revised and/or new
versions of the General Public License from time to time.  Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.

   Each version is given a distinguishing version number.  If the
Program specifies a version number of this License which applies to it
and "any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation.  If the Program does not specify a
version number of this License, you may choose any version ever
published by the Free Software Foundation.

   10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the
author to ask for permission.  For software which is copyrighted by the
Free Software Foundation, write to the Free Software Foundation; we
sometimes make exceptions for this.  Our decision will be guided by the
two goals of preserving the free status of all derivatives of our free
software and of promoting the sharing and reuse of software generally.

   NO WARRANTY

   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS
WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

   12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.

   END OF TERMS AND CONDITIONS

22.1.3 How to Apply These Terms to Your New Programs
----------------------------------------------------

If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these
terms.

   To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

         <one line to give the program's name and a brief idea of what it does.>
         Copyright (C) <year>  <name of author>

         This program is free software; you can redistribute it and/or modify
         it under the terms of the GNU General Public License as published by
         the Free Software Foundation; either version 2 of the License, or
         (at your option) any later version.

         This program is distributed in the hope that it will be useful,
         but WITHOUT ANY WARRANTY; without even the implied warranty of
         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
         GNU General Public License for more details.

         You should have received a copy of the GNU General Public License
         along with this program; if not, write to the Free Software
         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

   Also add information on how to contact you by electronic and paper
mail.

   If the program is interactive, make it output a short notice like
this when it starts in an interactive mode:

         Gnomovision version 69, Copyright (C) year name of author
         Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
         This is free software, and you are welcome to redistribute it
         under certain conditions; type `show c' for details.

   The hypothetical commands `show w' and `show c' should show the
appropriate parts of the General Public License.  Of course, the
commands you use may be called something other than `show w' and `show
c'; they could even be mouse-clicks or menu items-whatever suits your
program.

   You should also get your employer (if you work as a programmer) or
your school, if any, to sign a "copyright disclaimer" for the program,
if necessary.  Here is a sample; alter the names:

       Yoyodyne, Inc., hereby disclaims all copyright interest in the program
       `Gnomovision' (which makes passes at compilers) written by James Hacker.

       <signature of Ty Coon>, 1 April 1989
       Ty Coon, President of Vice

   This General Public License does not permit incorporating your
program into proprietary programs.  If your program is a subroutine
library, you may consider it more useful to permit linking proprietary
applications with the library.  If this is what you want to do, use the
GNU Library General Public License instead of this License.

22.2 The GNU Free Documentation License
=======================================

22.2.1 0. PREAMBLE
------------------

The purpose of this License is to make a manual, textbook, or other
functional and useful document "free" in the sense of freedom: to
assure everyone the effective freedom to copy and redistribute it, with
or without modifying it, either commercially or noncommercially.
Secondarily, this License preserves for the author and publisher a way
to get credit for their work, while not being considered responsible
for modifications made by others.

   This License is a kind of "copyleft", which means that derivative
works of the document must themselves be free in the same sense.  It
complements the GNU General Public License, which is a copyleft license
designed for free software.

   We have designed this License in order to use it for manuals for free
software, because free software needs free documentation: a free
program should come with manuals providing the same freedoms that the
software does.  But this License is not limited to software manuals; it
can be used for any textual work, regardless of subject matter or
whether it is published as a printed book.  We recommend this License
principally for works whose purpose is instruction or reference.

22.2.2 1. APPLICABILITY AND DEFINITIONS
---------------------------------------

This License applies to any manual or other work, in any medium, that
contains a notice placed by the copyright holder saying it can be
distributed under the terms of this License.  Such a notice grants a
world-wide, royalty-free license, unlimited in duration, to use that
work under the conditions stated herein.  The "Document", below, refers
to any such manual or work.  Any member of the public is a licensee,
and is addressed as "you".  You accept the license if you copy, modify
or distribute the work in a way requiring permission under copyright
law.

   A "Modified Version" of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.

   A "Secondary Section" is a named appendix or a front-matter section
of the Document that deals exclusively with the relationship of the
publishers or authors of the Document to the Document's overall subject
(or to related matters) and contains nothing that could fall directly
within that overall subject.  (Thus, if the Document is in part a
textbook of mathematics, a Secondary Section may not explain any
mathematics.)  The relationship could be a matter of historical
connection with the subject or with related matters, or of legal,
commercial, philosophical, ethical or political position regarding them.

   The "Invariant Sections" are certain Secondary Sections whose titles
are designated, as being those of Invariant Sections, in the notice
that says that the Document is released under this License.  If a
section does not fit the above definition of Secondary then it is not
allowed to be designated as Invariant.  The Document may contain zero
Invariant Sections.  If the Document does not identify any Invariant
Sections then there are none.

   The "Cover Texts" are certain short passages of text that are listed,
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
the Document is released under this License.  A Front-Cover Text may be
at most 5 words, and a Back-Cover Text may be at most 25 words.

   A "Transparent" copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the general
public, that is suitable for revising the document straightforwardly
with generic text editors or (for images composed of pixels) generic
paint programs or (for drawings) some widely available drawing editor,
and that is suitable for input to text formatters or for automatic
translation to a variety of formats suitable for input to text
formatters.  A copy made in an otherwise Transparent file format whose
markup, or absence of markup, has been arranged to thwart or discourage
subsequent modification by readers is not Transparent.  An image format
is not Transparent if used for any substantial amount of text.  A copy
that is not "Transparent" is called "Opaque".

   Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, LaTeX input format, SGML or
XML using a publicly available DTD, and standard-conforming simple
HTML, PostScript or PDF designed for human modification.  Examples of
transparent image formats include PNG, XCF and JPG.  Opaque formats
include proprietary formats that can be read and edited only by
proprietary word processors, SGML or XML for which the DTD and/or
processing tools are not generally available, and the machine-generated
HTML, PostScript or PDF produced by some word processors for output
purposes only.

   The "Title Page" means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page.  For works in
formats which do not have any title page as such, "Title Page" means
the text near the most prominent appearance of the work's title,
preceding the beginning of the body of the text.

   A section "Entitled XYZ" means a named subunit of the Document whose
title either is precisely XYZ or contains XYZ in parentheses following
text that translates XYZ in another language.  (Here XYZ stands for a
specific section name mentioned below, such as "Acknowledgements",
"Dedications", "Endorsements", or "History".)  To "Preserve the Title"
of such a section when you modify the Document means that it remains a
section "Entitled XYZ" according to this definition.

   The Document may include Warranty Disclaimers next to the notice
which states that this License applies to the Document.  These Warranty
Disclaimers are considered to be included by reference in this License,
but only as regards disclaiming warranties: any other implication that
these Warranty Disclaimers may have is void and has no effect on the
meaning of this License.

22.2.3 2. VERBATIM COPYING
--------------------------

You may copy and distribute the Document in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License applies
to the Document are reproduced in all copies, and that you add no other
conditions whatsoever to those of this License.  You may not use
technical measures to obstruct or control the reading or further
copying of the copies you make or distribute.  However, you may accept
compensation in exchange for copies.  If you distribute a large enough
number of copies you must also follow the conditions in section 3.

   You may also lend copies, under the same conditions stated above, and
you may publicly display copies.

22.2.4 3. COPYING IN QUANTITY
-----------------------------

If you publish printed copies (or copies in media that commonly have
printed covers) of the Document, numbering more than 100, and the
Document's license notice requires Cover Texts, you must enclose the
copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
the back cover.  Both covers must also clearly and legibly identify you
as the publisher of these copies.  The front cover must present the
full title with all words of the title equally prominent and visible.
You may add other material on the covers in addition.  Copying with
changes limited to the covers, as long as they preserve the title of
the Document and satisfy these conditions, can be treated as verbatim
copying in other respects.

   If the required texts for either cover are too voluminous to fit
legibly, you should put the first ones listed (as many as fit
reasonably) on the actual cover, and continue the rest onto adjacent
pages.

   If you publish or distribute Opaque copies of the Document numbering
more than 100, you must either include a machine-readable Transparent
copy along with each Opaque copy, or state in or with each Opaque copy
a computer-network location from which the general network-using public
has access to download using public-standard network protocols a
complete Transparent copy of the Document, free of added material.  If
you use the latter option, you must take reasonably prudent steps, when
you begin distribution of Opaque copies in quantity, to ensure that
this Transparent copy will remain thus accessible at the stated
location until at least one year after the last time you distribute an
Opaque copy (directly or through your agents or retailers) of that
edition to the public.

   It is requested, but not required, that you contact the authors of
the Document well before redistributing any large number of copies, to
give them a chance to provide you with an updated version of the
Document.

22.2.5 4. MODIFICATIONS
-----------------------

You may copy and distribute a Modified Version of the Document under
the conditions of sections 2 and 3 above, provided that you release the
Modified Version under precisely this License, with the Modified
Version filling the role of the Document, thus licensing distribution
and modification of the Modified Version to whoever possesses a copy of
it.  In addition, you must do these things in the Modified Version:

  1. Use in the Title Page (and on the covers, if any) a title distinct
     from that of the Document, and from those of previous versions
     (which should, if there were any, be listed in the History section
     of the Document).  You may use the same title as a previous version
     if the original publisher of that version gives permission.

  2. List on the Title Page, as authors, one or more persons or entities
     responsible for authorship of the modifications in the Modified
     Version, together with at least five of the principal authors of
     the Document (all of its principal authors, if it has fewer than
     five), unless they release you from this requirement.

  3. State on the Title page the name of the publisher of the Modified
     Version, as the publisher.

  4. Preserve all the copyright notices of the Document.

  5. Add an appropriate copyright notice for your modifications
     adjacent to the other copyright notices.

  6. Include, immediately after the copyright notices, a license notice
     giving the public permission to use the Modified Version under the
     terms of this License, in the form shown in the Addendum below.

  7. Preserve in that license notice the full lists of Invariant
     Sections and required Cover Texts given in the Document's license
     notice.

  8. Include an unaltered copy of this License.

  9. Preserve the section Entitled "History", Preserve its Title, and
     add to it an item stating at least the title, year, new authors,
     and publisher of the Modified Version as given on the Title Page.
     If there is no section Entitled "History" in the Document, create
     one stating the title, year, authors, and publisher of the
     Document as given on its Title Page, then add an item describing
     the Modified Version as stated in the previous sentence.

 10. Preserve the network location, if any, given in the Document for
     public access to a Transparent copy of the Document, and likewise
     the network locations given in the Document for previous versions
     it was based on.  These may be placed in the "History" section.
     You may omit a network location for a work that was published at
     least four years before the Document itself, or if the original
     publisher of the version it refers to gives permission.

 11. For any section Entitled "Acknowledgements" or "Dedications",
     Preserve the Title of the section, and preserve in the section all
     the substance and tone of each of the contributor acknowledgements
     and/or dedications given therein.

 12. Preserve all the Invariant Sections of the Document, unaltered in
     their text and in their titles.  Section numbers or the equivalent
     are not considered part of the section titles.

 13. Delete any section Entitled "Endorsements".  Such a section may
     not be included in the Modified Version.

 14. Do not retitle any existing section to be Entitled "Endorsements"
     or to conflict in title with any Invariant Section.

 15. Preserve any Warranty Disclaimers.

   If the Modified Version includes new front-matter sections or
appendices that qualify as Secondary Sections and contain no material
copied from the Document, you may at your option designate some or all
of these sections as invariant.  To do this, add their titles to the
list of Invariant Sections in the Modified Version's license notice.
These titles must be distinct from any other section titles.

   You may add a section Entitled "Endorsements", provided it contains
nothing but endorsements of your Modified Version by various
parties-for example, statements of peer review or that the text has
been approved by an organization as the authoritative definition of a
standard.

   You may add a passage of up to five words as a Front-Cover Text, and
a passage of up to 25 words as a Back-Cover Text, to the end of the list
of Cover Texts in the Modified Version.  Only one passage of
Front-Cover Text and one of Back-Cover Text may be added by (or through
arrangements made by) any one entity.  If the Document already includes
a cover text for the same cover, previously added by you or by
arrangement made by the same entity you are acting on behalf of, you
may not add another; but you may replace the old one, on explicit
permission from the previous publisher that added the old one.

   The author(s) and publisher(s) of the Document do not by this License
give permission to use their names for publicity for or to assert or
imply endorsement of any Modified Version.

22.2.6 5. COMBINING DOCUMENTS
-----------------------------

You may combine the Document with other documents released under this
License, under the terms defined in section 4 above for modified
versions, provided that you include in the combination all of the
Invariant Sections of all of the original documents, unmodified, and
list them all as Invariant Sections of your combined work in its
license notice, and that you preserve all their Warranty Disclaimers.

   The combined work need only contain one copy of this License, and
multiple identical Invariant Sections may be replaced with a single
copy.  If there are multiple Invariant Sections with the same name but
different contents, make the title of each such section unique by
adding at the end of it, in parentheses, the name of the original
author or publisher of that section if known, or else a unique number.
Make the same adjustment to the section titles in the list of Invariant
Sections in the license notice of the combined work.

   In the combination, you must combine any sections Entitled "History"
in the various original documents, forming one section Entitled
"History"; likewise combine any sections Entitled "Acknowledgements",
and any sections Entitled "Dedications".  You must delete all sections
Entitled "Endorsements".

22.2.7 6. COLLECTIONS OF DOCUMENTS
----------------------------------

You may make a collection consisting of the Document and other documents
released under this License, and replace the individual copies of this
License in the various documents with a single copy that is included in
the collection, provided that you follow the rules of this License for
verbatim copying of each of the documents in all other respects.

   You may extract a single document from such a collection, and
distribute it individually under this License, provided you insert a
copy of this License into the extracted document, and follow this
License in all other respects regarding verbatim copying of that
document.

22.2.8 7. AGGREGATION WITH INDEPENDENT WORKS
--------------------------------------------

A compilation of the Document or its derivatives with other separate
and independent documents or works, in or on a volume of a storage or
distribution medium, is called an "aggregate" if the copyright
resulting from the compilation is not used to limit the legal rights of
the compilation's users beyond what the individual works permit.  When
the Document is included in an aggregate, this License does not apply
to the other works in the aggregate which are not themselves derivative
works of the Document.

   If the Cover Text requirement of section 3 is applicable to these
copies of the Document, then if the Document is less than one half of
the entire aggregate, the Document's Cover Texts may be placed on
covers that bracket the Document within the aggregate, or the
electronic equivalent of covers if the Document is in electronic form.
Otherwise they must appear on printed covers that bracket the whole
aggregate.

22.2.9 8. TRANSLATION
---------------------

Translation is considered a kind of modification, so you may distribute
translations of the Document under the terms of section 4.  Replacing
Invariant Sections with translations requires special permission from
their copyright holders, but you may include translations of some or
all Invariant Sections in addition to the original versions of these
Invariant Sections.  You may include a translation of this License, and
all the license notices in the Document, and any Warranty Disclaimers,
provided that you also include the original English version of this
License and the original versions of those notices and disclaimers.  In
case of a disagreement between the translation and the original version
of this License or a notice or disclaimer, the original version will
prevail.

   If a section in the Document is Entitled "Acknowledgements",
"Dedications", or "History", the requirement (section 4) to Preserve
its Title (section 1) will typically require changing the actual title.

22.2.10 9. TERMINATION
----------------------

You may not copy, modify, sublicense, or distribute the Document except
as expressly provided for under this License.  Any other attempt to
copy, modify, sublicense or distribute the Document is void, and will
automatically terminate your rights under this License.  However,
parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such parties
remain in full compliance.

22.2.11 10. FUTURE REVISIONS OF THIS LICENSE
--------------------------------------------

The Free Software Foundation may publish new, revised versions of the
GNU Free Documentation License from time to time.  Such new versions
will be similar in spirit to the present version, but may differ in
detail to address new problems or concerns.  See
http://www.gnu.org/copyleft/.

   Each version of the License is given a distinguishing version number.
If the Document specifies that a particular numbered version of this
License "or any later version" applies to it, you have the option of
following the terms and conditions either of that specified version or
of any later version that has been published (not as a draft) by the
Free Software Foundation.  If the Document does not specify a version
number of this License, you may choose any version ever published (not
as a draft) by the Free Software Foundation.

22.2.12 G.1.1 ADDENDUM: How to use this License for your documents
------------------------------------------------------------------

To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and license
notices just after the title page:

         Copyright (c)  YEAR  YOUR NAME.
         Permission is granted to copy, distribute and/or modify this document
         under the terms of the GNU Free Documentation License, Version 1.2
         or any later version published by the Free Software Foundation;
         with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
         A copy of the license is included in the section entitled "GNU
         Free Documentation License".

   If you have Invariant Sections, Front-Cover Texts and Back-Cover
Texts, replace the "with...Texts." line with this:

         with the Invariant Sections being LIST THEIR TITLES, with the
         Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.

   If you have Invariant Sections without Cover Texts, or some other
combination of the three, merge those two alternatives to suit the
situation.

   If your document contains nontrivial examples of program code, we
recommend releasing these examples in parallel under your choice of
free software license, such as the GNU General Public License, to
permit their use in free software.