1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
|
<?xml version="1.0"?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
<!ENTITY igraph "igraph">
<!ENTITY tut_simple SYSTEM "../examples/doc/tut_simple.c">
]>
<chapter id="igraph-Tutorial">
<title>Tutorial</title>
<section id="tut-lesson-1"><title>Lesson 1. Compiling programs using igraph</title>
<para>
The following short example program demonstrates the basic usage of
the <command>igraph</command> library.
<programlisting>
<![CDATA[#include <igraph.h>
int main(void)
{
igraph_integer_t diameter;
igraph_t graph;
igraph_rng_seed(igraph_rng_default(), 42);
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: %d\n",
(int) diameter);
igraph_destroy(&graph);
return 0;
}]]>
</programlisting>
</para>
<para>
This example illustrates a couple of points. First, programs
using the <command>igraph</command> library should include the
<filename>igraph.h</filename> header
file. Second, <command>igraph</command> uses the
<type>igraph_real_t</type> type for real numbers instead of
<type>double</type>. Third, <command>igraph</command> graph objects
are represented by the <type>igraph_t</type> data
type. Fourth, the <link
linkend="igraph_erdos_renyi_game"><function>igraph_erdos_renyi_game()</function></link>
creates a graph and <link
linkend="igraph_destroy"><function>igraph_destroy()</function></link>
destroys it, i.e. deallocates the memory associated to it.
</para>
<para>
For compiling this program you need a C compiler, if this is called
<command>gcc</command> and the previous code is saved in file
<filename>igraph_test.c</filename>, you will need a command like this:
<programlisting>
gcc igraph_test.c -I/usr/local/igraph -L/usr/local/lib -ligraph -o igraph_test
</programlisting>
</para>
<para>
The exact form depends on where <command>igraph</command> was installed on your
system. The directory after the <option>-I</option> switch is the one
containing the <filename>igraph.h</filename> file, while the one
following <option>-L</option> should contain the
library file itself, usually a file called
<filename>libigraph.so</filename>, <filename>libigraph.a</filename> or
<filename>igraph.dll</filename>.
It your system has the <command>pkg-config</command> utility you are
likely to get the necessary compile options by issuing the command
<programlisting>
pkg-config --libs --cflags igraph
</programlisting>
</para>
<para>
The executable can be run by simply typing its name like this:
<programlisting>
./igraph_test
</programlisting>
on most systems. If you use dynamic linking and the <command>igraph</command>
libraries are not at a standard place, you may need to set the
<envar>LD_LIBRARY_PATH</envar> variable, the syntax depends on the
shell use are using. In <command>bash</command> it goes like this:
<programlisting>
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/user/libs/igraph
./igraph_test
</programlisting>
Here we assumed that the <command>igraph</command> library is installed in
<filename>/home/user/libs/igraph</filename>. Alternatively, you can use
the <envar>LD_PRELOAD</envar> variable to preload the
<command>igraph</command> library before invoking your program:
<programlisting>
LD_PRELOAD=/home/user/libs/igraph/libigraph.so ./igraph_test
</programlisting>
Please note that <envar>LD_PRELOAD</envar> and
<envar>LD_LIBRARY_PATH</envar> are usually available only on
Un*x-like systems. On Windows using Cygwin it is usually enough to set the
<envar>PATH</envar> environment variable to include the folder in which
the <command>igraph</command> library is installed, look for the
<filename>cygigraph-0.dll</filename> or similar file.
</para>
</section>
<section id="tut-lesson-2"><title>Lesson 2. Creating your first graphs</title>
<para>
The functions generating graph objects are called graph
generators. Stochastic (i.e. randomized) graph generators are called
<quote>games</quote>.
</para>
<para>
<command>igraph</command> 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. E.g. <link linkend="igraph_shortest_paths"><function>igraph_shortest_paths()</function></link>
which (surprisingly) calculates
shortest paths from a vertex to other vertices can calculate
directed or undirected paths.
</para>
<para>
<command>igraph</command> has sophisticated ways for creating graphs. The simplest
graphs are deterministic regular structures like star graphs
(<link linkend="igraph_star"><function>igraph_star()</function></link>),
ring graphs (<link linkend="igraph_ring"><function>igraph_ring()</function></link>), lattices
(<link linkend="igraph_lattice"><function>igraph_lattice()</function></link>) or trees
(<link linkend="igraph_tree"><function>igraph_tree()</function></link>).
</para>
<para>
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.)
<programlisting>
<![CDATA[#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);
igraph_rng_seed(igraph_rng_default(), 42);
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;
}]]>
</programlisting>
</para>
<para>
This example illustrates some new points. <command>igraph</command> uses
<link linkend="igraph_vector_t"><type>igraph_vector_t</type></link>
instead of plain C arrays. <type>igraph_vector_t</type> is superior to
regular arrays in almost every sense. Vectors are created by the
<link linkend="igraph_vector_init"><function>igraph_vector_init()</function></link>
function and, like graphs, they should be destroyed if not
needed any more by calling
<link linkend="igraph_vector_destroy"><function>igraph_vector_destroy()</function></link>
on them. A vector can be indexed by the
<link linkend="VECTOR"><function>VECTOR()</function></link> function
(right now it is a macro). Vectors
can be resized, e.g. most <command>igraph</command> functions returning the result in a
vector resize it to the size of the result.
</para>
<para>
<link linkend="igraph_lattice"><function>igraph_lattice()</function></link>
takes a vector argument specifying the dimensions of
the lattice. In this example we generate a 30x30 two dimensional
lattice. See the documentation of
<link linkend="igraph_lattice"><function>igraph_lattice()</function></link> in
the reference manual for the other arguments.
</para>
<para>
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
<link linkend="igraph_vcount"><function>igraph_vcount()</function></link>,
as in the example).
</para>
<para>
The <link
linkend="igraph_add_edges"><function>igraph_add_edges()</function></link>
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.
</para>
<para>
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.
<type>igraph_t</type> can of course
represent loops and
multiple edges, although some routines expect simple graphs,
i.e. 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
<link linkend="igraph_simplify"><function>igraph_simplify()</function></link>.
</para>
</section>
<section id="tut-lesson-3"><title>Lesson 3. Calculating various properties of graphs</title>
<para>
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.
<programlisting>
<![CDATA[#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,
/*weights=*/ 0, /*normalized=*/ 0);
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, /*weights=*/ 0, /*nobigint=*/ 1);
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;
}]]>
</programlisting>
</para>
<para>
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 <link
linkend="igraph_vector_view"><function>igraph_vector_view()</function></link>
creates a <emphasis>view</emphasis> of a C
array. It does not copy any data, this also means that you should not
call <link linkend="igraph_vector_destroy"><function>igraph_vector_destroy()</function></link>
on a vector created this way. This vector is then used to create the
undirected graph.
</para>
<para>
Then the degree, closeness and betweenness centrality of the vertices
is calculated and the highest values are printed. Note that the vector
(<varname>result</varname>) 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.
</para>
<para>
The <constant>igraph_vss_all()</constant> argument tells the functions to
calculate the property for every vertex in the graph, it is shorthand
for a <emphasis>vertex selector</emphasis> (<type>igraph_vs_t</type>).
Vertex selectors help to perform operations on a subset of vertices,
you can read more about them in <link linkend="igraph-Iterators">one
of the following chapters.</link>
</para>
</section>
</chapter>
|