# Tutorial

## Compiling programs using igraph

The following short example program demonstrates the basic usage of the `igraph` library. Save it into a file named `igraph_test.c`.

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_integer_t` type for integers instead of `int` or `long int`, and it also uses the `igraph_real_t` type for real numbers instead of `double`. Depending on how `igraph` was compiled, and whether you are using a 32-bit or 64-bit system, `igraph_integer_t` may be a 32-bit or 64-bit integer.

- Third, `igraph` graph objects are represented by the `igraph_t` data type.

- Fourth, the `igraph_erdos_renyi_game_gnm()` creates a graph and `igraph_destroy()` destroys it, i.e. deallocates the memory associated to it.

For compiling this program you need a C compiler. Optionally, CMake can be used to automate the compilation.

### Compiling with CMake

It is convenient to use CMake because it can automatically discover the necessary compilation flags on all operating systems. Many IDEs support CMake, and can work with CMake projects directly. To create a CMake project for this example program, create a file name `CMakeLists.txt` with the following contents:

    cmake_minimum_required(VERSION 3.18)
    project(igraph_test)

    find_package(igraph REQUIRED)

    add_executable(igraph_test igraph_test.c)
    target_link_libraries(igraph_test PUBLIC igraph::igraph)

To compile the project, create a new directory called `build` in the root of the `igraph` source tree, and switch to it:

    mkdir build
    cd build

Run CMake to configure the project:

    cmake ..

If `igraph` was installed at a non-standard location, specify its prefix using the `-DCMAKE_PREFIX_PATH=...` option. The prefix must be the same directory that was specified as the `CMAKE_INSTALL_PREFIX` when compiling igraph.

If configuration has succeeded, build the program using

    cmake --build .

#### C++ must be enabled in igraph projects

Parts of `igraph` are implemented in C++; therefore, any CMake target that depends on `igraph` should use the C++ linker. Furthermore, OpenMP support in igraph works correctly only if C++ is enabled in the CMake project. The script that finds `igraph` on the host machine will throw an error if C++ support is not enabled in the CMake project.

C++ support is enabled by default when no languages are explicitly specified in CMake's `project` command, e.g. `project(igraph_test)`. If you do specify some languages explicitly, make sure to also include `CXX`, e.g. `project(igraph_test C CXX)`.

### Compiling without CMake

On most Unix-like systems, the default C compiler is called `cc`. To compile the test program, you will need a command similar to the following:

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

The exact form depends on where `igraph` was installed on your system, whether it was compiled as a shared or static library, and the external libraries it was linked to. 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.a` (static library on macOS and Linux), `libigraph.so` (shared library on Linux), `libigraph.dylib` (shared library on macOS), `igraph.lib` (static library on Windows) or `igraph.dll` (shared library on Windows). If `igraph` was compiled as a static library, it is also necessary to manually link to all of its dependencies.

If your system has the `pkg-config` utility you are likely to get the necessary compile options by issuing the command

    pkg-config --libs --cflags igraph

(if `igraph` was built as a shared library) or

    pkg-config --static --libs --cflags igraph

(if `igraph` was built as a static library).

### Running the program

On most systems, the executable can be run by simply typing its name like this:

    ./igraph_test

If you use dynamic linking and the `igraph` library is not installed in a standard place, you may need to add its location to the `LD_LIBRARY_PATH` (Linux), `DYLD_LIBRARY_PATH` (macOS) or `PATH` (Windows) environment variables. This is typically necessary on Windows systems.

## Creating your first graphs

The functions generating graph objects are called graph generators. Stochastic (i.e. 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. E.g., `igraph_get_shortest_paths()`, which calculates shortest paths from a vertex to other 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_square_lattice()`) or trees (`igraph_kary_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.)

This example illustrates some new points. `igraph` uses `igraph_vector_t` and its related types (`igraph_vector_int_t`, `igraph_vector_bool_t` and so on) 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). The elements of a vector are of type `igraph_real_t` for `igraph_vector_t`, and of type `igraph_integer_t` for `igraph_vector_int_t`. As you might expect, `igraph_vector_bool_t` holds `igraph_bool_t` values. Vectors can be resized and most `igraph` functions returning the result in a vector automatically resize it to the size they need.

`igraph_square_lattice()` takes an integer vector argument specifying the dimensions of the lattice. In this example we generate a 30x30 two dimensional periodic lattice. See the documentation of `igraph_square_lattice()` in the reference manual for the other arguments.

The vertices in a graph are identified by a vertex ID, an integer between `0` and `n - 1`, where `n` is the number of vertices in the graph. The vertex count can be retrieved using `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 this example program may add loop edges, edges pointing a vertex to itself, or 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, i.e. graphs which contain neither of these. This is because some structural properties are ill-defined for non-simple graphs. Loop and multi-edges can be removed by calling `igraph_simplify()`.

## 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. (Do a 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.

This example demonstrates some new operations. First of all, it shows a way to create a graph a list of edges stored in a plain C array. Function `igraph_vector_view()` creates a view of a C array. It does not copy any data, which means that you must 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`, into which these functions will write their result, must be initialized first, and also that the functions resize it to be able to hold the result.

Notice that in order to print values of type `igraph_integer_t`, we used the `IGRAPH_PRId` format macro constant. This macro is similar to the standard `PRI` constants defined in `stdint.h`, and expands to the correct `printf` format specifier on each platform that `igraph` supports.

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, represented by type `igraph_vs_t`. Vertex selectors help perform operations on a subset of vertices. You can read more about them in one of the following chapters.