igraph Reference Manual

For using the igraph C library

Search the manual:

Chapter 21. 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.

1. Simple edge list and similar formats

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 an even number of non-negative integers separated by whitespace. The integers represent vertex IDs. Placing each edge (i.e. pair of integers) on a separate line is not required, but it is 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.

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.

1.3. igraph_read_graph_ncol — Reads a .ncol file used by LGL.

int igraph_read_graph_ncol(igraph_t *graph, FILE *instream,
                           const igraph_strvector_t *predefnames,
                           igraph_bool_t names,
                           igraph_add_weights_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://lgl.sourceforge.net), 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 appearance 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:

Whether to add the weights of the edges to the graph as an edge attribute called weight. IGRAPH_ADD_WEIGHTS_YES adds the weights (even if they are not present in the file, in this case they are assumed to be zero). IGRAPH_ADD_WEIGHTS_NO does not add any edge attribute. IGRAPH_ADD_WEIGHTS_IF_PRESENT adds the attribute if and only if there is at least one explicit edge weight in the input file.

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: 

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() 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: 

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_add_weights_t weights,
                          igraph_bool_t directed);

The .lgl format is used by the Large Graph Layout visualization software (http://lgl.sourceforge.net), 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:

Whether to add the weights of the edges to the graph as an edge attribute called weight. IGRAPH_ADD_WEIGHTS_YES adds the weights (even if they are not present in the file, in this case they are assumed to be zero). IGRAPH_ADD_WEIGHTS_NO does not add any edge attribute. IGRAPH_ADD_WEIGHTS_IF_PRESENT adds the attribute if and only if there is at least one explicit edge weight in the input file.

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: 

Example 21.1.  File examples/simple/igraph_read_graph_lgl.c

/* -*- mode: C -*-  */
/*
   IGraph R package.
   Copyright (C) 2005-2012  Gabor Csardi <csardi.gabor@gmail.com>
   334 Harvard st, Cambridge MA, 02139 USA

   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., 51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301 USA

*/

#include <igraph.h>

int main() {

    igraph_t g;
    FILE *input;

    /* Without names and weights */
    input = fopen("igraph_read_graph_lgl-1.lgl", "r");
    if (!input) {
        return 1;
    }
    igraph_read_graph_lgl(&g, input, 0, IGRAPH_ADD_WEIGHTS_NO, 1);
    fclose(input);
    if (!igraph_is_directed(&g)) {
        return 2;
    }
    igraph_write_graph_edgelist(&g, stdout);
    igraph_destroy(&g);

    /* With names and weights */
    input = fopen("igraph_read_graph_lgl-2.lgl", "r");
    if (!input) {
        return 3;
    }
    igraph_read_graph_lgl(&g, input, 0, IGRAPH_ADD_WEIGHTS_NO, 1);
    fclose(input);
    if (!igraph_is_directed(&g)) {
        return 4;
    }
    igraph_write_graph_ncol(&g, stdout, 0, 0);
    igraph_destroy(&g);

    /* Same graph, but forcing undirected mode */
    input = fopen("igraph_read_graph_lgl-2.lgl", "r");
    igraph_read_graph_lgl(&g, input, 0, IGRAPH_ADD_WEIGHTS_NO, 0);
    fclose(input);
    if (igraph_is_directed(&g)) {
        return 5;
    }
    igraph_write_graph_ncol(&g, stdout, 0, 0);
    igraph_destroy(&g);

    /* Erroneous LGL file (empty vertex name) */
    input = fopen("igraph_read_graph_lgl-3.lgl", "r");
    if (!input) {
        return 6;
    }
    igraph_set_error_handler(igraph_error_handler_ignore);
    if (igraph_read_graph_lgl(&g, input, 0, IGRAPH_ADD_WEIGHTS_NO, 1) !=
        IGRAPH_PARSEERROR) {
        return 7;
    }
    fclose(input);

    return 0;
}


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() 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: 

Example 21.2.  File examples/simple/igraph_write_graph_lgl.c

#include <igraph.h>

int main() {

    igraph_t g;
    igraph_strvector_t names, weights;
    int i;
    char str[2] = " ";
    igraph_set_attribute_table(&igraph_cattribute_table);
    igraph_small(&g, 7, IGRAPH_UNDIRECTED, 0, 1, 0, 2, 1, 2, 1, 3, 2, 4, 3, 4, -1);


    printf("Output without isolates:\n");
    igraph_write_graph_lgl(&g, stdout, /*names*/ NULL, /*weights*/ NULL, /*isolates*/ 0);


    printf("\nOutput with isolates:\n");
    igraph_write_graph_lgl(&g, stdout, /*names*/ NULL, /*weights*/ NULL, /*isolates*/ 1);


    printf("\nOutput vertex and edge labels:\n");
    igraph_strvector_init(&names, 7);
    for (i = 0; i < 7; i++) {
        str[0] = 'A' + i;
        igraph_strvector_set(&names, i, str);
    }
    SETVASV(&g, "names", &names);

    igraph_strvector_init(&weights, 6);
    for (i = 0; i < 6; i++) {
        str[0] = '3' + i;
        igraph_strvector_set(&weights, i, str);
    }
    SETEASV(&g, "weights", &weights);

    igraph_write_graph_lgl(&g, stdout, "names", "weights", /*isolates*/ 0);

    igraph_strvector_destroy(&names);
    igraph_strvector_destroy(&weights);
    igraph_destroy(&g);

    return 0;
}


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: 

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 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()

2. Binary formats

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. From the (now defunct) graph database homepage:

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.

Example 21.3.  File examples/simple/igraph_read_graph_graphdb.c

/* -*- mode: C -*-  */
/*
   IGraph library.
   Copyright (C) 2007-2012  Gabor Csardi <csardi.gabor@gmail.com>
   334 Harvard st, Cambridge MA, 02139 USA

   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.,  51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301 USA

*/

#include <igraph.h>

int main() {

    igraph_t g;
    FILE *input;

    input = fopen("iso_b03_m1000.A00", "rb");
    if (!input) {
        return 1;
    }
    igraph_read_graph_graphdb(&g, input, IGRAPH_DIRECTED);
    fclose(input);
    igraph_write_graph_edgelist(&g, stdout);
    igraph_destroy(&g);

    return 0;
}


3. GraphML format

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, i.e. if you use igraph from R or Python.

Graph attribute names are taken from the attr.name attributes of the key tags in the GraphML file. Since attr.name is not mandatory, igraph will fall back to the id attribute of the key tag if attr.name is missing.

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

Example 21.4.  File examples/simple/graphml.c

/* -*- mode: C -*-  */
/*
   IGraph library.
   Copyright (C) 2006-2012  Gabor Csardi <csardi.gabor@gmail.com>
   334 Harvard street, Cambridge, MA 02139 USA

   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.,  51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301 USA

*/
#include <igraph.h>
#include <stdio.h>
#include <unistd.h>     /* unlink */

void custom_warning_handler (const char *reason, const char *file,
                             int line, int igraph_errno) {
    printf("Warning: %s\n", reason);
}

void dump_graph(const char* header, const igraph_t* g) {
    fputs(header, stdout);
    printf("Vertices: %li\n", (long int) igraph_vcount(g));
    printf("Edges: %li\n", (long int) igraph_ecount(g));
    printf("Directed: %i\n", (int) igraph_is_directed(g));
    igraph_write_graph_edgelist(g, stdout);
}

void dump_vertex_attribute_bool(const char* name, const igraph_t* g) {
    long int i, n = igraph_vcount(g);

    printf("Vertex attribute '%s':", name);
    for (i = 0; i < n; i++) {
        printf(" %s", VAB(g, name, i) ? "true" : "false");
    }
    printf("\n");
}

void dump_vertex_attribute_numeric(const char* name, const igraph_t* g) {
    long int i, n = igraph_vcount(g);

    printf("Vertex attribute '%s':", name);
    for (i = 0; i < n; i++) {
        printf(" %g", (float)VAN(g, name, i));
    }
    printf("\n");
}

void dump_vertex_attribute_string(const char* name, const igraph_t* g) {
    long int i, n = igraph_vcount(g);

    printf("Vertex attribute '%s':", name);
    for (i = 0; i < n; i++) {
        printf(" %s", VAS(g, name, i));
    }
    printf("\n");
}

int main() {
    igraph_t g;
    igraph_error_handler_t* oldhandler;
    igraph_warning_handler_t* oldwarnhandler;
    int result;
    FILE *ifile, *ofile;

    igraph_set_attribute_table(&igraph_cattribute_table);

    /* GraphML */
    ifile = fopen("test.gxl", "r");
    if (ifile == 0) {
        return 10;
    }

    oldhandler = igraph_set_error_handler(igraph_error_handler_ignore);
    oldwarnhandler = igraph_set_warning_handler(custom_warning_handler);
    if ((result = igraph_read_graph_graphml(&g, ifile, 0))) {
        /* maybe it is simply disabled at compile-time */
        if (result == IGRAPH_UNIMPLEMENTED) {
            return 77;
        }
        return 1;
    }
    igraph_set_error_handler(oldhandler);

    fclose(ifile);

    /* Write it back */
    ofile = fopen("test2.gxl", "w");
    /* If we can't create the test file, just skip the test */
    if (ofile) {
        if ((result = igraph_write_graph_graphml(&g, ofile, /*prefixattr=*/ 1))) {
            return 1;
        }
        fclose(ofile);
        unlink("test2.gxl");
    }
    dump_graph("The directed graph:\n", &g);
    igraph_destroy(&g);

    /* The same with undirected graph */
    ifile = fopen("test.gxl", "r");
    if ((result = igraph_read_graph_graphml(&g, ifile, 0))) {
        return 1;
    }
    fclose(ifile);
    dump_graph("The undirected graph:\n", &g);
    igraph_destroy(&g);

    /* Test a GraphML file with default attributes */
    ifile = fopen("graphml-default-attrs.xml", "r");
    if ((result = igraph_read_graph_graphml(&g, ifile, 0))) {
        return 1;
    }
    fclose(ifile);
    dump_graph("The directed graph:\n", &g);
    dump_vertex_attribute_bool("type", &g);
    dump_vertex_attribute_string("gender", &g);
    dump_vertex_attribute_numeric("age", &g);
    dump_vertex_attribute_bool("retired", &g);
    igraph_destroy(&g);

    /* Test a GraphML file with namespaces */
    ifile = fopen("graphml-namespace.xml", "r");
    if ((result = igraph_read_graph_graphml(&g, ifile, 0))) {
        return 1;
    }
    fclose(ifile);
    dump_graph("The undirected graph:\n", &g);
    igraph_destroy(&g);

    /* Test a not-really-valid GraphML file as it has no namespace information */
    ifile = fopen("graphml-lenient.xml", "r");
    if ((result = igraph_read_graph_graphml(&g, ifile, 0))) {
        return 1;
    }
    fclose(ifile);
    dump_graph("The undirected graph:\n", &g);
    igraph_destroy(&g);

    /* Test a completely malformed GraphML file */
    ifile = fopen("graphml-malformed.xml", "r");
    igraph_set_error_handler(igraph_error_handler_ignore);
    igraph_set_warning_handler(igraph_warning_handler_ignore);
    result = igraph_read_graph_graphml(&g, ifile, 0);
    if (result != IGRAPH_PARSEERROR) {
        return 1;
    }
    fclose(ifile);
    igraph_destroy(&g);

    /* Restore the old error handler */
    igraph_set_error_handler(igraph_error_handler_abort);

    /* Restore the old warning handler */
    igraph_set_warning_handler(oldwarnhandler);

    /* There were sometimes problems with this file */
    /* Only if called from R though, and only on random occasions, once in every
       ten reads. Do testing here doesn't make much sense, but if we have the file
       then let's do it anyway. */
    ifile = fopen("graphml-hsa05010.xml", "r");
    igraph_read_graph_graphml(&g, ifile, 0);
    fclose(ifile);
    igraph_destroy(&g);

    return 0;
}


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,
                               igraph_bool_t prefixattr);

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) for detailed format description.

Arguments: 

graph:

The graph to write.

outstream:

The stream object to write to, it should be writable.

prefixattr:

Logical value, whether to put a prefix in front of the attribute names to ensure uniqueness if the graph has vertex and edge (or graph) attributes with the same name.

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).

Example 21.5.  File examples/simple/graphml.c

/* -*- mode: C -*-  */
/*
   IGraph library.
   Copyright (C) 2006-2012  Gabor Csardi <csardi.gabor@gmail.com>
   334 Harvard street, Cambridge, MA 02139 USA

   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.,  51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301 USA

*/
#include <igraph.h>
#include <stdio.h>
#include <unistd.h>     /* unlink */

void custom_warning_handler (const char *reason, const char *file,
                             int line, int igraph_errno) {
    printf("Warning: %s\n", reason);
}

void dump_graph(const char* header, const igraph_t* g) {
    fputs(header, stdout);
    printf("Vertices: %li\n", (long int) igraph_vcount(g));
    printf("Edges: %li\n", (long int) igraph_ecount(g));
    printf("Directed: %i\n", (int) igraph_is_directed(g));
    igraph_write_graph_edgelist(g, stdout);
}

void dump_vertex_attribute_bool(const char* name, const igraph_t* g) {
    long int i, n = igraph_vcount(g);

    printf("Vertex attribute '%s':", name);
    for (i = 0; i < n; i++) {
        printf(" %s", VAB(g, name, i) ? "true" : "false");
    }
    printf("\n");
}

void dump_vertex_attribute_numeric(const char* name, const igraph_t* g) {
    long int i, n = igraph_vcount(g);

    printf("Vertex attribute '%s':", name);
    for (i = 0; i < n; i++) {
        printf(" %g", (float)VAN(g, name, i));
    }
    printf("\n");
}

void dump_vertex_attribute_string(const char* name, const igraph_t* g) {
    long int i, n = igraph_vcount(g);

    printf("Vertex attribute '%s':", name);
    for (i = 0; i < n; i++) {
        printf(" %s", VAS(g, name, i));
    }
    printf("\n");
}

int main() {
    igraph_t g;
    igraph_error_handler_t* oldhandler;
    igraph_warning_handler_t* oldwarnhandler;
    int result;
    FILE *ifile, *ofile;

    igraph_set_attribute_table(&igraph_cattribute_table);

    /* GraphML */
    ifile = fopen("test.gxl", "r");
    if (ifile == 0) {
        return 10;
    }

    oldhandler = igraph_set_error_handler(igraph_error_handler_ignore);
    oldwarnhandler = igraph_set_warning_handler(custom_warning_handler);
    if ((result = igraph_read_graph_graphml(&g, ifile, 0))) {
        /* maybe it is simply disabled at compile-time */
        if (result == IGRAPH_UNIMPLEMENTED) {
            return 77;
        }
        return 1;
    }
    igraph_set_error_handler(oldhandler);

    fclose(ifile);

    /* Write it back */
    ofile = fopen("test2.gxl", "w");
    /* If we can't create the test file, just skip the test */
    if (ofile) {
        if ((result = igraph_write_graph_graphml(&g, ofile, /*prefixattr=*/ 1))) {
            return 1;
        }
        fclose(ofile);
        unlink("test2.gxl");
    }
    dump_graph("The directed graph:\n", &g);
    igraph_destroy(&g);

    /* The same with undirected graph */
    ifile = fopen("test.gxl", "r");
    if ((result = igraph_read_graph_graphml(&g, ifile, 0))) {
        return 1;
    }
    fclose(ifile);
    dump_graph("The undirected graph:\n", &g);
    igraph_destroy(&g);

    /* Test a GraphML file with default attributes */
    ifile = fopen("graphml-default-attrs.xml", "r");
    if ((result = igraph_read_graph_graphml(&g, ifile, 0))) {
        return 1;
    }
    fclose(ifile);
    dump_graph("The directed graph:\n", &g);
    dump_vertex_attribute_bool("type", &g);
    dump_vertex_attribute_string("gender", &g);
    dump_vertex_attribute_numeric("age", &g);
    dump_vertex_attribute_bool("retired", &g);
    igraph_destroy(&g);

    /* Test a GraphML file with namespaces */
    ifile = fopen("graphml-namespace.xml", "r");
    if ((result = igraph_read_graph_graphml(&g, ifile, 0))) {
        return 1;
    }
    fclose(ifile);
    dump_graph("The undirected graph:\n", &g);
    igraph_destroy(&g);

    /* Test a not-really-valid GraphML file as it has no namespace information */
    ifile = fopen("graphml-lenient.xml", "r");
    if ((result = igraph_read_graph_graphml(&g, ifile, 0))) {
        return 1;
    }
    fclose(ifile);
    dump_graph("The undirected graph:\n", &g);
    igraph_destroy(&g);

    /* Test a completely malformed GraphML file */
    ifile = fopen("graphml-malformed.xml", "r");
    igraph_set_error_handler(igraph_error_handler_ignore);
    igraph_set_warning_handler(igraph_warning_handler_ignore);
    result = igraph_read_graph_graphml(&g, ifile, 0);
    if (result != IGRAPH_PARSEERROR) {
        return 1;
    }
    fclose(ifile);
    igraph_destroy(&g);

    /* Restore the old error handler */
    igraph_set_error_handler(igraph_error_handler_abort);

    /* Restore the old warning handler */
    igraph_set_warning_handler(oldwarnhandler);

    /* There were sometimes problems with this file */
    /* Only if called from R though, and only on random occasions, once in every
       ten reads. Do testing here doesn't make much sense, but if we have the file
       then let's do it anyway. */
    ifile = fopen("graphml-hsa05010.xml", "r");
    igraph_read_graph_graphml(&g, ifile, 0);
    fclose(ifile);
    igraph_destroy(&g);

    return 0;
}


4. GML format

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.fim.uni-passau.de/en/fim/faculty/chairs/theoretische-informatik/projects.html 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() for a more modern format, igraph_write_graph_gml() for writing GML files.

Example 21.6.  File examples/simple/gml.c

/* -*- mode: C -*-  */
/*
   IGraph library.
   Copyright (C) 2007-2012  Gabor Csardi <csardi.gabor@gmail.com>
   334 Harvard street, Cambridge, MA 02139 USA

   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.,  51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301 USA

*/

#include <igraph.h>
#include <stdio.h>

int main() {
    igraph_t g;
    FILE *ifile;

    ifile = fopen("karate.gml", "r");
    if (ifile == 0) {
        return 10;
    }

    igraph_read_graph_gml(&g, ifile);
    fclose(ifile);

    if (igraph_is_directed(&g)) {
        printf("directed\n");
    } else {
        printf("undirected\n");
    }

    igraph_write_graph_edgelist(&g, stdout);
    printf("-----------------\n");
    igraph_write_graph_gml(&g, stdout, 0, "test suite");
    igraph_destroy(&g);

    return 0;
}


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.fim.uni-passau.de/en/fim/faculty/chairs/theoretische-informatik/projects.html for details.

The graph, vertex and edges attributes are written to the file as well, if they are numeric or string.

As igraph is more forgiving about attribute names, it might be necessary 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() for reading GML files, igraph_read_graph_graphml() for a more modern format.

Example 21.7.  File examples/simple/gml.c

/* -*- mode: C -*-  */
/*
   IGraph library.
   Copyright (C) 2007-2012  Gabor Csardi <csardi.gabor@gmail.com>
   334 Harvard street, Cambridge, MA 02139 USA

   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.,  51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301 USA

*/

#include <igraph.h>
#include <stdio.h>

int main() {
    igraph_t g;
    FILE *ifile;

    ifile = fopen("karate.gml", "r");
    if (ifile == 0) {
        return 10;
    }

    igraph_read_graph_gml(&g, ifile);
    fclose(ifile);

    if (igraph_is_directed(&g)) {
        printf("directed\n");
    } else {
        printf("undirected\n");
    }

    igraph_write_graph_edgelist(&g, stdout);
    printf("-----------------\n");
    igraph_write_graph_gml(&g, stdout, 0, "test suite");
    igraph_destroy(&g);

    return 0;
}


5. Pajek format

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.

Starting from version 0.6.1 igraph reads bipartite (two-mode) graphs from Pajek files and add the type vertex attribute for them. Warnings are given for invalid edges, i.e. edges connecting vertices of the same type.

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 (i.e. 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. Only Pajek networks are supported, permutations, hierarchies, clusters and vectors are not.

  6. 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.

The weight edge attribute might be added if there are edge weights present.

See the pajek homepage: 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 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() for writing Pajek files, igraph_read_graph_graphml() for reading GraphML files.

Example 21.8.  File examples/simple/foreign.c

/* -*- mode: C -*-  */
/*
   IGraph library.
   Copyright (C) 2006-2012  Gabor Csardi <csardi.gabor@gmail.com>
   334 Harvard street, Cambridge, MA 02139 USA

   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.,  51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301 USA

*/

#include <igraph.h>
#include <stdio.h>

int main() {
    igraph_t g;
    FILE *ifile;

    /* PAJEK */
    ifile = fopen("links.net", "r");
    if (ifile == 0) {
        return 10;
    }
    igraph_read_graph_pajek(&g, ifile);
    fclose(ifile);
    printf("The graph:\n");
    printf("Vertices: %li\n", (long int) igraph_vcount(&g));
    printf("Edges: %li\n", (long int) igraph_ecount(&g));
    printf("Directed: %i\n", (int) igraph_is_directed(&g));
    igraph_write_graph_edgelist(&g, stdout);
    igraph_destroy(&g);

    return 0;
}


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(), e.g. the color vertex attributes determines the color (c in Pajek) parameter.

As of version 0.6.1 igraph writes bipartite graphs into Pajek files correctly, i.e. they will be also bipartite when read into Pajek. As Pajek is less flexible for bipartite graphs (the numeric IDs of the vertices must be sorted according to vertex type), igraph might need to reorder the vertices when writing a bipartite Pajek file. This effectively means that numeric vertex IDs usually change when a bipartite graph is written to a Pajek file, and then read back into igraph.

Early versions of Pajek supported only Windows-style line endings in Pajek files, but recent versions support both Windows and Unix line endings. igraph therefore uses the platform-native line endings when the input file is opened in text mode, and uses Unix-style line endings when the input file is opened in binary mode. If you are using an old version of Pajek, you are on Unix and you are having problems reading files written by igraph on a Windows machine, convert the line endings manually with a text editor or with unix2dos or iconv from the command line).

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() for reading Pajek graphs, igraph_write_graph_graphml() for writing a graph in GraphML format, this suites igraph graphs better.

Example 21.9.  File examples/simple/igraph_write_graph_pajek.c

/* -*- mode: C -*-  */
/*
   IGraph library.
   Copyright (C) 2006-2012  Gabor Csardi <csardi.gabor@gmail.com>
   334 Harvard st, Cambridge MA, 02139 USA

   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.,  51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301 USA

*/

#include <igraph.h>

int main() {

    igraph_t g;
    igraph_strvector_t names;

    igraph_set_attribute_table(&igraph_cattribute_table);

    /* save a simple ring graph */
    igraph_ring(&g, 10, IGRAPH_DIRECTED, 0 /* mutual */, 1 /* circular */);
    igraph_write_graph_pajek(&g, stdout);

    /* add some vertex attributes */
    igraph_strvector_init(&names, 0);
    igraph_strvector_add(&names, "A");
    igraph_strvector_add(&names, "B");
    igraph_strvector_add(&names, "C");
    igraph_strvector_add(&names, "D");
    igraph_strvector_add(&names, "E");
    igraph_strvector_add(&names, "F");
    igraph_strvector_add(&names, "G");
    igraph_strvector_add(&names, "H");
    igraph_strvector_add(&names, "I");
    igraph_strvector_add(&names, "J");
    SETVASV(&g, "id", &names);
    igraph_strvector_destroy(&names);

    /* save the graph with vertex names */
    igraph_write_graph_pajek(&g, stdout);

    igraph_strvector_init(&names, 0);
    igraph_strvector_add(&names, "square");
    igraph_strvector_add(&names, "square");
    igraph_strvector_add(&names, "square");
    igraph_strvector_add(&names, "square");
    igraph_strvector_add(&names, "escaping spaces");
    igraph_strvector_add(&names, "square");
    igraph_strvector_add(&names, "square");
    igraph_strvector_add(&names, "escaping \\backslashes\\");
    igraph_strvector_add(&names, "square");
    igraph_strvector_add(&names, "escaping \"quotes\"");
    SETVASV(&g, "shape", &names);
    igraph_strvector_destroy(&names);

    /* save the graph with escaped shapes */
    igraph_write_graph_pajek(&g, stdout);

    /* destroy the graph */
    igraph_destroy(&g);
    return 0;
}


6. UCINET's DL file format

6.1. igraph_read_graph_dl — Read a file in the DL format of UCINET

int igraph_read_graph_dl(igraph_t *graph, FILE *instream,
                         igraph_bool_t directed);

This is a simple textual file format used by UCINET. See http://www.analytictech.com/networks/dataentry.htm for examples. All the forms described here are supported by igraph. Vertex names and edge weights are also supported and they are added as attributes. (If an attribute handler is attached.)

Note the specification does not mention whether the format is case sensitive or not. For igraph DL files are case sensitive, i.e. Larry and larry are not the same.

Arguments: 

graph:

Pointer to an uninitialized graph object.

instream:

The stream to read the DL file from.

directed:

Logical scalar, whether to create a directed file.

Returns: 

Error code.

Time complexity: linear in terms of the number of edges and vertices, except for the matrix format, which is quadratic in the number of vertices.

Example 21.10.  File examples/simple/igraph_read_graph_dl.c

/* -*- mode: C -*-  */
/*
   IGraph library.
   Copyright (C) 2009-2012  Gabor Csardi <csardi.gabor@gmail.com>
   334 Harvard st, Cambridge MA, 02139 USA

   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.,  51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301 USA

*/

#include <igraph.h>
#include <stdio.h>
#include <stdlib.h>

int main() {

    const char *files[] = { "fullmatrix1.dl", "fullmatrix2.dl",
                            "fullmatrix3.dl", "fullmatrix4.dl",
                            "edgelist1.dl", "edgelist2.dl", "edgelist3.dl",
                            "edgelist4.dl", "edgelist5.dl", "edgelist6.dl",
                            "edgelist7.dl", "nodelist1.dl", "nodelist2.dl"
                          };
    int no_files = sizeof(files) / sizeof(const char*);
    int i, ret;
    igraph_t g;
    FILE *infile;

    for (i = 0; i < no_files; i++) {
        printf("Doing %s\n", files[i]);
        infile = fopen(files[i], "r");
        if (!infile) {
            printf("Cannot open file: %s\n", files[i]);
            exit(1 + i);
        }
        igraph_read_graph_dl(&g, infile, /*directed=*/ 1);
        ret = fclose(infile);
        if (ret) {
            printf("Cannot close file: %s\n", files[i]);
            exit(101 + i);
        }
        igraph_write_graph_edgelist(&g, stdout);
        igraph_destroy(&g);
    }

    if (IGRAPH_FINALLY_STACK_SIZE() != 0) {
        return 1;
    }

    return 0;
}


7. Graphviz format

7.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 for details. The grammar of the DOT format can be found here: 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() for a more modern format.

Example 21.11.  File examples/simple/dot.c

/* -*- mode: C -*-  */
/*
   IGraph library.
   Copyright (C) 2007-2012  Gabor Csardi <csardi.gabor@gmail.com>
   334 Harvard street, Cambridge, MA 02139 USA

   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.,  51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301 USA

*/

#include <igraph.h>
#include <stdio.h>

int main() {

    igraph_t g;
    FILE *ifile;

    ifile = fopen("karate.gml", "r");
    if (ifile == 0) {
        return 10;
    }

    igraph_read_graph_gml(&g, ifile);
    fclose(ifile);

    if (igraph_is_directed(&g)) {
        printf("directed\n");
    } else {
        printf("undirected\n");
    }

    igraph_write_graph_edgelist(&g, stdout);
    printf("-----------------\n");
    igraph_write_graph_dot(&g, stdout);
    igraph_destroy(&g);

    return 0;
}