Reading and writing files
Reading and writing graphs as edge lists and in the NCOL, LGL, GraphML, GML, Pajek, DIMACS, graph database, DL, DOT and LEDA formats.
20 entries: 20 functions. Part of the Open Graph reference; All functions lists every entry on one page, with a filter. The badges say how each entry is checked.
Edge lists, NCOL and LGL
read_graph_edgelist#
Exact
Builds a graph from a text stream of whitespace-separated vertex id pairs.
og_error_t og_read_graph_edgelist(
og_t *graph,
FILE *instream,
og_int_t n,
og_bool_t directed
);
The stream is read as a sequence of decimal integers separated by any whitespace; line breaks have no special meaning. Each consecutive pair (from, to) becomes one edge, in file order, so edge ids follow the order of the pairs. Vertex ids are 0-based.
The graph gets max(n, largest id + 1) vertices: n only adds isolated vertices at the end, and an id at or above n is not an error. Self-loops and repeated pairs are kept as they are. No attributes are created.
- Parameters
graphAn uninitialised graph. On success it holds the result; destroy it withdestroy.instreamAn open stream; it is read to its end. NULL isOG_EINVAL.nThe smallest number of vertices the graph gets; 0 lets the largest id decide. Must not be negative.directedOG_DIRECTEDorOG_UNDIRECTED: the direction of the new graph (the file does not record it).
- Returns
OG_SUCCESS, or one of the error codes below. On error no graph is left initialised.- Errors
OG_EINVALn is negative, or instream is NULL.OG_PARSEERRORAn odd number of ids (the last edge is incomplete), or a token that is not a decimal integer (hex, letters, a decimal point).OG_EINVVIDA vertex id is negative.OG_EOVERFLOWA number is too large to represent.OG_EUNDERFLOWA number is too small (too negative, or a real that rounds to zero or minus infinity).OG_EFILEReading the input stream fails.OG_ENOMEMNot enough memory.
- Complexity
- O(|V| + |E|), linear in the size of the stream.
- Checked
- Same graphs and the same error codes as python-igraph 1.0 on 282 reads (hand-written texts with signs, hex, overflow and NUL bytes; files python-igraph wrote, half of them mutated) and 220 round trips of graphs with 0 to 300 vertices.
- C name
og_read_graph_edgelist- In notebooks
Og.ReadGraphEdgelist- igraph 1.0
igraph_read_graph_edgelist- See also
write_graph_edgelist,read_graph_ncol,read_graph_graphdb
FILE *f = fopen("edges.txt", "r");
og_t g;
if (f != NULL && og_read_graph_edgelist(&g, f, 0, OG_UNDIRECTED) == OG_SUCCESS) {
printf("%" OG_PRId " vertices, %" OG_PRId " edges\n", og_vcount(&g), og_ecount(&g));
og_destroy(&g);
}
if (f != NULL) {
fclose(f);
}
write_graph_edgelist#
Exact
Writes every edge as one line holding the two vertex ids.
og_error_t og_write_graph_edgelist(const og_t *graph, FILE *outstream);
Each edge becomes a line "from to" with 0-based vertex ids. Lines are grouped by the first vertex in increasing order and, for each vertex, sorted by the other end; an undirected edge is written smaller id first. Attributes are not written.
The format carries no vertex count, so isolated vertices with the largest ids are lost when the file is read back with read_graph_edgelist, unless the reader is given n.
- Parameters
graphThe graph to write.outstreamAn open stream to write to.
- Returns
OG_SUCCESS, or one of the error codes below.- Errors
OG_EFILEThe output stream refuses data (a write fails).
- Complexity
- O(|V| + |E|).
- Checked
- Byte-identical to python-igraph 1.0's output on 200 random graphs and 220 graphs of 0 to 300 vertices.
- C name
og_write_graph_edgelist- In notebooks
Og.WriteGraphEdgelist- igraph 1.0
igraph_write_graph_edgelist- See also
read_graph_edgelist,write_graph_ncol
read_graph_ncol#
Exact
Reads a named edge list in the NCOL format of the LGL package: one "name name [weight]" line per edge.
og_error_t og_read_graph_ncol(
og_t *graph,
FILE *instream,
const og_strvector_t *predefnames,
og_bool_t names,
og_add_weights_t weights,
og_bool_t directed
);
Each non-empty line holds two vertex names and an optional weight, separated by spaces or tabs. A name is any run of printable bytes without blanks, compared case-sensitively. Vertices get ids in the order their names first appear, after the names in predefnames, which take ids 0, 1, ... in their given order (so known vertices can be given fixed ids). Edges follow the line order. CR, LF, CR LF and LF CR all end a line; other control characters are an error.
With names true the names are stored as the string vertex attribute "name". weights decides about the numeric edge attribute "weight": OG_ADD_WEIGHTS_NO never makes it, OG_ADD_WEIGHTS_YES always, OG_ADD_WEIGHTS_IF_PRESENT only when at least one line has a weight; edges without a weight get 1. Attributes are stored only when an attribute handler is installed (set_attribute_table(&og_cattribute_table)); without one the structure is read and attribute data is dropped.
Weights are parsed with the C library (strtod), which follows the numeric locale: see enter_safelocale.
- Parameters
graphAn uninitialised graph. On success it holds the result; destroy it withdestroy.instreamAn open stream; it is read to its end. NULL isOG_EINVAL.predefnamesNames that take the first vertex ids, in order, or NULL. A name met in the file reuses its predefined id.namesWhether to store the vertex names as the "name" attribute.weightsOG_ADD_WEIGHTS_NO,OG_ADD_WEIGHTS_YESorOG_ADD_WEIGHTS_IF_PRESENT(enumog_add_weights_t).directedOG_DIRECTEDorOG_UNDIRECTED: the direction of the new graph (the file does not record it).
- Returns
OG_SUCCESS, or one of the error codes below. On error no graph is left initialised.- Errors
OG_EINVALweights is not one of the threeog_add_weights_tvalues, or instream is NULL.OG_PARSEERRORA line with only one name, text after the weight, a weight that is not a number, or a control character.OG_EOVERFLOWA number is too large to represent.OG_EUNDERFLOWA number is too small (too negative, or a real that rounds to zero or minus infinity).OG_EFILEReading the input stream fails.OG_ENOMEMNot enough memory.
- Complexity
- O(|V| + |E|) expected (names are looked up in a hash table), linear in the size of the stream.
- Checked
- Same graphs, names, weights and error codes as python-igraph 1.0 on 396 reads under every names/weights/directed combination. python-igraph cannot pass predefnames, so that argument is covered by unit tests only.
- C name
og_read_graph_ncol- In notebooks
Og.ReadGraphNcol- igraph 1.0
igraph_read_graph_ncol- See also
write_graph_ncol,read_graph_lgl,read_graph_edgelist,enter_safelocale
write_graph_ncol#
Exact
Writes the edges as "name name [weight]" lines in the NCOL format.
og_error_t og_write_graph_ncol(
const og_t *graph,
FILE *outstream,
const char *names,
const char *weights
);
One line per edge, in edge id order; an undirected edge is written smaller id first. When names gives a string vertex attribute, both ends are written by that attribute, otherwise by vertex id. When weights gives a numeric edge attribute, its value follows (15 significant digits; Inf, -Inf and NaN spelled out). An attribute that is missing or of the wrong type gives a warning and is left out.
NCOL has no place for vertices without edges, so they are not written. A written name must be non-empty printable ASCII without blanks; any other name makes the call fail, because the file could not be read back.
- Parameters
graphThe graph to write.outstreamAn open stream to write to.namesName of the string vertex attribute to write instead of ids, or NULL for ids.weightsName of the numeric edge attribute to write as weights, or NULL for none.
- Returns
OG_SUCCESS, or one of the error codes below.- Errors
OG_EINVALA vertex with edges has an empty name, or one with a blank, a control byte or a non-ASCII byte.OG_EFILEThe output stream refuses data (a write fails).OG_ENOMEMNot enough memory.
- Complexity
- O(|V| + |E|).
- Checked
- Byte-identical to python-igraph 1.0 on 167 writes (names and weights present, missing or of the wrong type, names it refuses) and 220 graphs of 0 to 300 vertices.
- C name
og_write_graph_ncol- In notebooks
Og.WriteGraphNcol- igraph 1.0
igraph_write_graph_ncol- See also
read_graph_ncol,write_graph_lgl,write_graph_edgelist
read_graph_lgl#
Exact
Reads the LGL format, where a "# name" line opens a block that lists that vertex's neighbours.
og_error_t og_read_graph_lgl(
og_t *graph,
FILE *instream,
og_bool_t names,
og_add_weights_t weights,
og_bool_t directed
);
A line "# name" makes name the current vertex; every following line "name [weight]" adds an edge from the current vertex to that neighbour, in file order. An empty line ends the block, and an edge line outside a block is an error. A "#" line with nothing after it still creates its vertex, which is how LGL files keep isolated vertices.
Names, vertex ids in order of first appearance, line endings and the names and weights switches work as in read_graph_ncol, producing the same "name" and "weight" attributes. Attributes are stored only when an attribute handler is installed (set_attribute_table(&og_cattribute_table)); without one the structure is read and attribute data is dropped.
- Parameters
graphAn uninitialised graph. On success it holds the result; destroy it withdestroy.instreamAn open stream; it is read to its end. NULL isOG_EINVAL.namesWhether to store the vertex names as the "name" attribute.weightsOG_ADD_WEIGHTS_NO,OG_ADD_WEIGHTS_YESorOG_ADD_WEIGHTS_IF_PRESENT(enumog_add_weights_t).directedOG_DIRECTEDorOG_UNDIRECTED: the direction of the new graph (the file does not record it).
- Returns
OG_SUCCESS, or one of the error codes below. On error no graph is left initialised.- Errors
OG_EINVALweights is not one of the threeog_add_weights_tvalues, or instream is NULL.OG_PARSEERRORAn edge line outside a block, '#' without a name, text after the name or the weight, a weight that is not a number, or a control character.OG_EOVERFLOWA number is too large to represent.OG_EUNDERFLOWA number is too small (too negative, or a real that rounds to zero or minus infinity).OG_EFILEReading the input stream fails.OG_ENOMEMNot enough memory.
- Complexity
- O(|V| + |E|) expected, linear in the size of the stream.
- Checked
- Same results and error codes as python-igraph 1.0 on 372 reads (hand-written files and files it wrote, half of them mutated) and 220 graphs of 0 to 300 vertices.
- C name
og_read_graph_lgl- In notebooks
Og.ReadGraphLgl- igraph 1.0
igraph_read_graph_lgl- See also
write_graph_lgl,read_graph_ncol
write_graph_lgl#
Exact
Writes the graph in the LGL format, one "# vertex" block per vertex that has edges starting at it.
og_error_t og_write_graph_lgl(
const og_t *graph,
FILE *outstream,
const char *names,
const char *weights,
og_bool_t isolates
);
Vertices are taken in id order. A vertex with at least one edge starting at it (in an undirected graph: being the smaller end) gets a "# vertex" line followed by one line per such edge, naming the other end in increasing id order and, optionally, the weight. With isolates true, every vertex without any edge is then written as a bare "# vertex" line, so it survives a round trip.
names and weights work as in write_graph_ncol; an LGL name also must not contain '#'.
- Parameters
graphThe graph to write.outstreamAn open stream to write to.namesName of the string vertex attribute to write instead of ids, or NULL for ids.weightsName of the numeric edge attribute to write as weights, or NULL for none.isolatesWhether to list the vertices without edges at the end.
- Returns
OG_SUCCESS, or one of the error codes below.- Errors
OG_EINVALA written vertex has an empty name, or one with a blank, '#', a control byte or a non-ASCII byte.OG_EFILEThe output stream refuses data (a write fails).OG_ENOMEMNot enough memory.
- Complexity
- O(|V| + |E|).
- Checked
- Byte-identical to python-igraph 1.0 on 167 writes (isolates on and off, names it refuses) and 220 graphs of 0 to 300 vertices.
- C name
og_write_graph_lgl- In notebooks
Og.WriteGraphLgl- igraph 1.0
igraph_write_graph_lgl- See also
read_graph_lgl,write_graph_ncol
GraphML
read_graph_graphml#
Exact
Reads one graph of a GraphML document, with its graph, vertex and edge attributes.
og_error_t og_read_graph_graphml(
og_t *graph,
FILE *instream,
og_int_t index
);
The document is parsed by Open Graph's own XML 1.0 parser with namespaces; no XML library is used. It reads UTF-8, UTF-16 in either byte order, ISO-8859-1, ISO-8859-15, windows-1252 and US-ASCII, character and entity references, CDATA sections, comments and default attribute values from an internal DTD; external entities and DTDs are never loaded. index selects the graph when the document holds several (0 is the first).
Each <key> declares an attribute of the graph, the nodes or the edges, named by attr.name (by its id when attr.name is missing): attr.type boolean gives a Boolean attribute, int, long, float and double a numeric one, string a string one; keys without a type are not stored. A key's <default> fills elements that have no <data> for it. Vertices get ids in the order their node ids first appear (in <node> elements or as edge ends); the file's node ids are kept as the string vertex attribute "id", and edge ids, when the file has any, as the edge attribute "id", unless a key already uses that name. The graph is directed when edgedefault is "directed". Nested graphs and hyperedges are not read. Attributes are stored only when an attribute handler is installed (set_attribute_table(&og_cattribute_table)); without one the structure is read and attribute data is dropped.
In three places Open Graph follows the GraphML format where python-igraph 1.0's answer differs: '&' inside XML attribute values, the edges' own ids, and graphs with index above 0.
- Parameters
graphAn uninitialised graph. On success it holds the result; destroy it withdestroy.instreamAn open stream; it is read to its end. NULL isOG_EINVAL.index0-based position of the graph to read among the document's <graph> elements.
- Returns
OG_SUCCESS, or one of the error codes below. On error no graph is left initialised.- Errors
OG_EINVALindex is negative or there is no graph with that index, a node id is empty, or instream is NULL.OG_PARSEERRORThe document is not well-formed XML, uses an unsupported encoding, has an invalid <key> (unknown attr.type or for, missing or repeated id or name), an edge without source or target, or a Boolean value that cannot be read.OG_EFILEReading the input stream fails.OG_ENOMEMNot enough memory.
- Complexity
- Linear in the size of the document, plus O(|V| + |E|) per attribute.
- Checked
- 958 reads against python-igraph 1.0 (keys, defaults, types, empty data, namespaces, encodings, errors, random documents, multi-graph files), with its error codes. In 301 of them ('&' in attribute values, edge ids, index above 0) the expected answer is what the GraphML format gives, where python-igraph 1.0's differs.
- C name
og_read_graph_graphml- In notebooks
Og.ReadGraphGraphml- igraph 1.0
igraph_read_graph_graphml- See also
write_graph_graphml,read_graph_gml,set_attribute_table
og_t g;
FILE *f = fopen("network.graphml", "rb");
og_set_attribute_table(&og_cattribute_table); /* keep the attributes */
if (f != NULL && og_read_graph_graphml(&g, f, 0) == OG_SUCCESS) {
/* ... use g and its attributes ... */
og_destroy(&g);
}
if (f != NULL) {
fclose(f);
}
write_graph_graphml#
Exact
Writes the graph and all its graph, vertex and edge attributes as a GraphML document.
og_error_t og_write_graph_graphml(
const og_t *graph,
FILE *outstream,
og_bool_t prefixattr
);
The output is UTF-8 GraphML: one <key> per attribute (numeric as double, string as string, Boolean as boolean; other attribute types are skipped with a warning), then one <graph> with edgedefault "directed" or "undirected", nodes named n0, n1, ... in id order and edges in id order, each with its <data>. NaN numeric values are left out. The five XML special characters are escaped.
With prefixattr true the key ids get the prefixes g_, v_ and e_, so a graph, a vertex and an edge attribute of the same name cannot clash; with false the key id is the attribute name. Without an attribute handler only the structure is written.
- Parameters
graphThe graph to write.outstreamAn open stream to write to.prefixattrWhether key ids get the prefixes g_, v_ and e_.
- Returns
OG_SUCCESS, or one of the error codes below.- Errors
OG_EINVALAn attribute name or string value holds a control character other than tab, LF and CR, which XML 1.0 cannot carry.OG_EFILEThe output stream refuses data (a write fails).OG_ENOMEMNot enough memory.
- Complexity
- O((|V| + |E|) x number of attributes).
- Checked
- Byte-identical to python-igraph 1.0 on 174 writes (prefixattr on and off, every attribute type, escaping, UTF-8, control-character errors) and 220 graphs of 0 to 300 vertices, apart from the comment line that names the creator.
- C name
og_write_graph_graphml- In notebooks
Og.WriteGraphGraphml- igraph 1.0
igraph_write_graph_graphml- See also
read_graph_graphml,write_graph_gml
FILE *f = fopen("out.graphml", "wb");
if (f != NULL) {
og_error_t err = og_write_graph_graphml(&g, f, true);
fclose(f);
if (err != OG_SUCCESS) {
/* handle the error */
}
}
GML
read_graph_gml#
Exact
Reads the first graph of a GML file, with its simple-valued attributes.
og_error_t og_read_graph_gml(og_t *graph, FILE *instream);
GML is a nested list of key-value pairs. The reader looks at the top-level Version (anything but 1 gives a warning) and the first graph list. Inside it every node list is a vertex and every edge list an edge whose integer source and target name node ids. Vertices take ids in file order; the file's node ids are kept as the numeric vertex attribute "id". The graph is directed when a directed key holds a non-zero whole number.
Every other key becomes an attribute of the graph, the vertex or the edge, named exactly as the key is written (a prefix a writer put in front, such as write_graph_gml's og, stays part of the name): numbers as numeric attributes, strings as string attributes. Where a key holds a list instead of a value, the element gets NaN or the empty string, and a key that only ever holds lists is dropped with a warning; when a key repeats in one record the last value counts. Strings may use the entities ", &, ', < and >; unknown entities are kept as written. Lists are parsed without recursion, so deep nesting cannot overflow the stack. Attributes are stored only when an attribute handler is installed (set_attribute_table(&og_cattribute_table)); without one the structure is read and attribute data is dropped.
- Parameters
graphAn uninitialised graph. On success it holds the result; destroy it withdestroy.instreamAn open stream; it is read to its end. NULL isOG_EINVAL.
- Returns
OG_SUCCESS, or one of the error codes below. On error no graph is left initialised.- Errors
OG_PARSEERRORA syntax error, no graph list, graph, node or edge that is not a list, a node with several or non-integer ids, two nodes with the same id, or an edge with a missing, repeated or non-integer source or target, or one that names an id no node has.OG_EINVALinstream is NULL.OG_EFILEReading the input stream fails.OG_ENOMEMNot enough memory.
- Complexity
- Linear in the size of the file, plus O(|V| log |V|) to match node ids.
- Checked
- Same graphs, attributes and error codes as python-igraph 1.0 on 458 reads (138 hand-written texts, 320 files it wrote, half of them mutated) and 220 graphs of 0 to 300 vertices; warnings are not compared.
- C name
og_read_graph_gml- In notebooks
Og.ReadGraphGml- igraph 1.0
igraph_read_graph_gml- See also
write_graph_gml,read_graph_graphml
write_graph_gml#
Exact
Writes the graph and its attributes in the GML format.
og_error_t og_write_graph_gml(
const og_t *graph,
FILE *outstream,
og_write_gml_sw_t options,
const og_vector_t *id,
const char *creator
);
The file holds a Creator line, "Version 1" and a graph list with directed 0 or 1, the graph attributes, a node list per vertex (with its id) and an edge list per edge (source, target); an undirected edge is written larger end first. Numbers are written with 15 significant digits, NaN values left out and infinities kept with a warning; Booleans as 0 and 1 (with a warning); strings in double quotes with '"' as " and '&' as & (options OG_WRITE_GML_ENCODE_ONLY_QUOT_SW leaves '&' alone).
GML keys are alphanumeric and start with a letter: other characters are dropped from attribute names, and a name that does not start with a letter gets Open Graph's own prefix "og" ("_weight" is written as ogweight, "2024" as og2024). read_graph_gml gives the prefix no meaning: such a key reads back as the attribute it names, ogweight. An attribute whose GML name would collide with the structure (graph attributes directed, node and edge; edge attributes source and target) is skipped with a warning.
Node ids come from id when it is given, else from a numeric vertex attribute "id", else they are the vertex ids; ids that are not all distinct whole numbers are ignored with a warning. creator NULL writes "Open Graph version <version> <date>"; an empty string writes no Creator line.
- Parameters
graphThe graph to write.outstreamAn open stream to write to.optionsBit flags (og_write_gml_sw_t):OG_WRITE_GML_DEFAULT_SW, orOG_WRITE_GML_ENCODE_ONLY_QUOT_SWto escape only '"'.idNode ids to write, one per vertex, or NULL.creatorText of the Creator line; NULL for Open Graph's name, version and the date; "" for none.
- Returns
OG_SUCCESS, or one of the error codes below.- Errors
OG_EINVALid does not have one value per vertex.OG_EFILEThe output stream refuses data (a write fails).OG_ENOMEMNot enough memory.
- Complexity
- O((|V| + |E|) x number of attributes + |V| log |V|).
- Checked
- Byte-identical to python-igraph 1.0 on 210 writes and 220 graphs of 0 to 300 vertices, apart from the prefix of names that do not start with a letter (python-igraph writes its own name there, Open Graph "og").
OG_WRITE_GML_ENCODE_ONLY_QUOT_SWand a NULL creator are unit-tested only; non-integer ids are not compared (python-igraph rounds them before the call, Open Graph ignores them as the reference manual says). - C name
og_write_graph_gml- In notebooks
Og.WriteGraphGml- igraph 1.0
igraph_write_graph_gml- See also
read_graph_gml,write_graph_graphml
Pajek
read_graph_pajek#
Exact
Reads a Pajek .net file, including two-mode networks, vertex coordinates and drawing parameters.
og_error_t og_read_graph_pajek(og_t *graph, FILE *instream);
Reading starts at the "*Vertices n" line ("*Vertices n n1" for a two-mode network); lines before it, among them one *Network line, are skipped. Vertex lines "id [label [x y [z]] [shape] parameters]" give the string attribute "name", the numeric attributes x, y and z, and the string attribute "shape". Edges come from *Arcs and *Edges sections, their list forms *Arcslist and *Edgeslist, and *Matrix sections (every non-zero entry an edge, weighted by it). Vertex numbers are 1-based; the graph has n vertices. The last edge section decides the direction: *Arcs, *Arcslist and a one-mode *Matrix make it directed. Sections that are not read are skipped up to the next line that starts with '*'.
Pajek's short parameter codes become attributes with readable names, each with Pajek's default for elements that do not set it (vertices: ic color, bc framecolor, x_fact xfact, r radius, ...; edges: w edgewidth, c color, p linepattern, l label, ...); the edge value becomes "weight". An unknown parameter becomes a string attribute of its own name, with '_' appended when the name is taken. In a two-mode network the Boolean vertex attribute "type" is true for the second mode. Attributes are stored only when an attribute handler is installed (set_attribute_table(&og_cattribute_table)); without one the structure is read and attribute data is dropped.
- Parameters
graphAn uninitialised graph. On success it holds the result; destroy it withdestroy.instreamAn open stream; it is read to its end. NULL isOG_EINVAL.
- Returns
OG_SUCCESS, or one of the error codes below. On error no graph is left initialised.- Errors
OG_PARSEERRORNo *Vertices line, a malformed line or section header, a control character, or a first-mode count above the vertex count.OG_EINVALA negative vertex count, a vertex number outside 1..n, or instream is NULL.OG_EINVVIDA *Matrix section has more rows or columns than the network has vertices.OG_EOVERFLOWA number is too large to represent.OG_EFILEReading the input stream fails.OG_ENOMEMNot enough memory.
- Complexity
- Linear in the size of the file (a *Matrix section has n^2 entries).
- Checked
- Same graphs, attributes and error codes as python-igraph 1.0 on 758 reads (318 hand-written texts covering every section, parameter and quoting rule; 440 files it wrote, half of them mutated) and 220 graphs of 0 to 300 vertices. Not compared: *Arcslist/*Edgeslist edges when edge attributes exist, where python-igraph 1.0 leaves the values uninitialised and Open Graph uses the defaults.
- C name
og_read_graph_pajek- In notebooks
Og.ReadGraphPajek- igraph 1.0
igraph_read_graph_pajek- See also
write_graph_pajek
write_graph_pajek#
Exact
Writes the graph as a Pajek .net file, with names, coordinates, weights and the drawing parameters Pajek knows.
og_error_t og_write_graph_pajek(const og_t *graph, FILE *outstream);
The file has a *Vertices line; vertex lines when the graph has any vertex attribute Pajek can carry (name, x, y, z, shape, color, framecolor, labelcolor, fontsize and the other drawing parameters); then *Arcs (directed) or *Edges with one line per edge in edge id order, using 1-based numbers, followed by the "weight" attribute and the edge drawing parameters (edgewidth, color, label, ...). Attribute names are turned back into Pajek's codes; other attributes are not written. Strings are quoted, with '"' written as " and a line break as the two characters \n.
A Boolean vertex attribute "type" makes a two-mode network: the vertices with type false come first, *Vertices gets their count as a second number and the edges are renumbered to match. Lines end in LF only and no byte-order mark is written.
- Parameters
graphThe graph to write.outstreamAn open stream to write to.
- Returns
OG_SUCCESS, or one of the error codes below.- Errors
OG_EFILEThe output stream refuses data (a write fails).OG_ENOMEMNot enough memory.
- Complexity
- O((|V| + |E|) x number of attributes).
- Checked
- Byte-identical to python-igraph 1.0 on 236 writes (random attribute sets of right and wrong types, two-mode graphs, quoting and escaping) and 220 graphs of 0 to 300 vertices.
- C name
og_write_graph_pajek- In notebooks
Og.WriteGraphPajek- igraph 1.0
igraph_write_graph_pajek- See also
read_graph_pajek
DIMACS, graph database, DL, DOT and LEDA
read_graph_dimacs_flow#
Exact
Reads a DIMACS network-flow file: a maximum-flow problem with source, target and capacities, or an edge problem with vertex labels.
og_error_t og_read_graph_dimacs_flow(
og_t *graph,
FILE *instream,
og_strvector_t *problem,
og_vector_int_t *label,
og_int_t *source,
og_int_t *target,
og_vector_t *capacity,
og_bool_t directed
);
Each line starts with a type letter and one separator: c (comment), p (the problem line, "p max nodes arcs" or "p edge nodes edges"), n (node lines), a (arcs "a from to capacity", max problems) and e (edges "e from to", edge problems). Ids in the file are 1-based. The graph has the node count of the problem line, or more when an arc names a larger id; edges follow the file order.
For a max problem the node lines "n id s" and "n id t" give the source and the target, returned as 0-based ids (-2 when the file names none), and capacity receives one value per arc. For an edge problem the node lines "n id label" give integer labels: label receives one entry per vertex, the vertex's 0-based index when the file gives none, and capacity is emptied. problem receives "max" or "edge".
- Parameters
graphAn uninitialised graph. On success it holds the result; destroy it withdestroy.instreamAn open stream; it is read to its end. NULL isOG_EINVAL.problemReceives one string, "max" or "edge"; may be NULL.labelEdge problems: receives the label of every vertex; may be NULL.sourceMax problems: receives the 0-based source (-2 when there is none); may be NULL.targetMax problems: receives the 0-based target (-2 when there is none); may be NULL.capacityMax problems: receives the capacity of each edge in edge order; emptied for edge problems; may be NULL.directedOG_DIRECTEDorOG_UNDIRECTED: the direction of the new graph (the file does not record it).
- Returns
OG_SUCCESS, or one of the error codes below. On error no graph is left initialised.- Errors
OG_EINVALThe file has no problem line, or instream is NULL.OG_PARSEERRORAn unknown line type, a second problem line, a line that cannot be read, a negative count, an arc in an edge problem or an edge line in a max problem, or a repeated source or target line.OG_EINVVIDAn arc or edge names an id below 1, or a label line names a vertex the graph does not have.OG_EFILEReading the input stream fails.OG_ENOMEMNot enough memory.
- Complexity
- O(|V| + |E|).
- Checked
- Max-flow files: same graph, source, target, capacities and error codes as python-igraph 1.0 on 293 reads and 220 graphs of 0 to 300 vertices. Edge problems are unit-tested only: python-igraph 1.0 does not read them as the reference manual describes, and Open Graph follows the manual.
- C name
og_read_graph_dimacs_flow- In notebooks
Og.ReadGraphDimacsFlow- igraph 1.0
igraph_read_graph_dimacs_flow- See also
write_graph_dimacs_flow,maxflow
write_graph_dimacs_flow#
Exact
Writes a maximum-flow problem in the DIMACS format.
og_error_t og_write_graph_dimacs_flow(
const og_t *graph,
FILE *outstream,
og_int_t source,
og_int_t target,
const og_vector_t *capacity
);
The output is a comment line, the problem line "p max |V| |E|", the source and target node lines and one "a from to capacity" line per edge in edge id order, all ids 1-based. An undirected edge is written as one arc from its smaller to its larger end. A NULL capacity writes 1 for every edge. source and target are written as given and not checked.
- Parameters
graphThe graph to write.outstreamAn open stream to write to.sourceThe 0-based source vertex.targetThe 0-based target vertex.capacityOne capacity per edge, or NULL for 1 everywhere.
- Returns
OG_SUCCESS, or one of the error codes below.- Errors
OG_EINVALcapacity does not have one value per edge.OG_EFILEThe output stream refuses data (a write fails).
- Complexity
- O(|E|).
- Checked
- Byte-identical to python-igraph 1.0 on 116 writes and 220 graphs of 0 to 300 vertices, apart from the first comment line, which names Open Graph.
- C name
og_write_graph_dimacs_flow- In notebooks
Og.WriteGraphDimacsFlow- igraph 1.0
igraph_write_graph_dimacs_flow- See also
read_graph_dimacs_flow
read_graph_graphdb#
Exact
Reads a graph in the binary format of the graph database of De Santo, Foggia, Sansone and Vento (2003).
og_error_t og_read_graph_graphdb(
og_t *graph,
FILE *instream,
og_bool_t directed
);
The file is a sequence of 16-bit little-endian words: the vertex count, then for every vertex its number of outgoing edges followed by their 0-based targets. Edges are added in that order. A target at or beyond the vertex count enlarges the graph. The file does not record the direction; directed chooses it.
A file that ends inside a record, or has bytes left over after the last vertex, is refused. There is no writer for this format.
- Parameters
graphAn uninitialised graph. On success it holds the result; destroy it withdestroy.instreamAn open stream; it is read to its end. NULL isOG_EINVAL.directedOG_DIRECTEDorOG_UNDIRECTED: the direction of the new graph (the file does not record it).
- Returns
OG_SUCCESS, or one of the error codes below. On error no graph is left initialised.- Errors
OG_PARSEERRORThe file ends too early, or has extra bytes after the graph.OG_EINVALinstream is NULL.OG_EFILEReading the input stream fails.OG_ENOMEMNot enough memory.
- Complexity
- O(|V| + |E|).
- Checked
- Same graphs and errors as python-igraph 1.0 on 148 files (truncated ones and out-of-range targets included) and 200 files of 0 to 300 vertices.
- C name
og_read_graph_graphdb- In notebooks
Og.ReadGraphGraphdb- igraph 1.0
igraph_read_graph_graphdb- See also
read_graph_edgelist
read_graph_dl#
Exact
Reads a UCINET DL file in full-matrix, edge-list or node-list form.
og_error_t og_read_graph_dl(
og_t *graph,
FILE *instream,
og_bool_t directed
);
The file starts with "DL n=<count>", then an optional "FORMAT = FULLMATRIX | EDGELIST1 | NODELIST1" (full matrix by default), an optional "LABELS:" list or "LABELS EMBEDDED", and "DATA:". Keywords are case-insensitive, labels case-sensitive. A full matrix holds 0/1 entries row by row, each 1 an edge; an edge list holds "from to [weight]" lines; a node list holds "from to1 to2 ..." lines. Vertex numbers are 1-based; with embedded labels the vertices are named by labels instead (for a matrix: a header line of column labels and a label at the start of each row).
Labels, from the list or embedded, become the string vertex attribute "name" (missing labels are empty, extra ones dropped); edge-list weights become the edge attribute "weight" (NaN for edges without one). After DATA: a comma or a NUL byte ends the data. Attributes are stored only when an attribute handler is installed (set_attribute_table(&og_cattribute_table)); without one the structure is read and attribute data is dropped.
- Parameters
graphAn uninitialised graph. On success it holds the result; destroy it withdestroy.instreamAn open stream; it is read to its end. NULL isOG_EINVAL.directedOG_DIRECTEDorOG_UNDIRECTED: the direction of the new graph (the file does not record it).
- Returns
OG_SUCCESS, or one of the error codes below. On error no graph is left initialised.- Errors
OG_PARSEERRORA malformed header or statement, a wrong kind of token (a number where a label belongs or the reverse, a matrix entry that is not a digit), a missing final line break, or a file that ends inside the label list.OG_EINVALA vertex number below 1, a matrix digit other than 0 or 1, or instream is NULL.OG_EINVVIDA vertex number above n.OG_EOVERFLOWA number is too large to represent.OG_EUNDERFLOWA number is too small (too negative, or a real that rounds to zero or minus infinity).OG_EFILEReading the input stream fails.OG_ENOMEMNot enough memory.
- Complexity
- Linear in the size of the file (a full matrix has n^2 entries).
- Checked
- Same graphs, names, weights and error codes as python-igraph 1.0 on 719 reads and 200 files of 1 to 300 vertices. One deliberate difference: a LABELS list shorter than n gives the remaining vertices empty names, where python-igraph reads past its list.
- C name
og_read_graph_dl- In notebooks
Og.ReadGraphDl- igraph 1.0
igraph_read_graph_dl- See also
read_graph_pajek,read_graph_edgelist
write_graph_dot#
Exact
Writes the graph and its attributes in the Graphviz DOT language.
og_error_t og_write_graph_dot(const og_t *graph, FILE *outstream);
The output is a "graph" (undirected) or "digraph" (directed) block: a "graph [...]" line with the graph attributes, one line per vertex by id with its attributes, then one line per edge in edge id order with "--" or "->" and its attributes; an undirected edge is written larger end first. A value is written bare when DOT reads it as a plain name or numeral, and quoted otherwise (DOT keywords such as node or edge, blanks, other characters), with backslash, '"' and line breaks escaped. Whole numbers are written in full, other reals with 15 significant digits, Inf, -Inf and NaN bare.
DOT is an output format here; there is no DOT reader. Without an attribute handler only the structure is written.
- Parameters
graphThe graph to write.outstreamAn open stream to write to.
- Returns
OG_SUCCESS, or one of the error codes below.- Errors
OG_EFILEThe output stream refuses data (a write fails).OG_ENOMEMNot enough memory.
- Complexity
- O((|V| + |E|) x number of attributes).
- Checked
- Byte-identical to python-igraph 1.0 on 151 writes (every attribute type, keywords, numerals, strings that need quotes) and 220 graphs of 0 to 300 vertices, apart from the first comment line, which names Open Graph and its version.
- C name
og_write_graph_dot- In notebooks
Og.WriteGraphDot- igraph 1.0
igraph_write_graph_dot- See also
write_graph_graphml,write_graph_gml
write_graph_leda#
Exact
Writes the graph in LEDA's native graph format, with at most one vertex and one edge attribute as data.
og_error_t og_write_graph_leda(
const og_t *graph,
FILE *outstream,
const char *vertex_attr_name,
const char *edge_attr_name
);
The file starts with LEDA.GRAPH, the data types of the vertices and edges (string, double, bool, or void for none), and -1 for a directed or -2 for an undirected graph. Then come the vertex section, one |{value}| line per vertex, and the edge section: "from to reverse |{value}|" per edge with 1-based numbers, grouped by the first vertex in id order, where reverse is the 1-based id of an edge going the opposite way (0 when there is none).
vertex_attr_name and edge_attr_name choose the attributes written as data; NULL writes none, and a missing attribute or one of a type LEDA cannot hold gives a warning and is left out. Booleans are written |{true}| and |{false}|.
- Parameters
graphThe graph to write.outstreamAn open stream to write to.vertex_attr_nameName of the vertex attribute to write as vertex data, or NULL.edge_attr_nameName of the edge attribute to write as edge data, or NULL.
- Returns
OG_SUCCESS, or one of the error codes below.- Errors
OG_EINVALA string value contains a line break, which the format cannot hold.OG_EFILEThe output stream refuses data (a write fails).OG_ENOMEMNot enough memory.
- Complexity
- O(|V| + |E| log d), d the largest degree (the reverse-edge lookup).
- Checked
- Byte-identical to python-igraph 1.0 on 156 writes with numeric and string attributes and 220 graphs of 0 to 300 vertices. Boolean values (written as |{true}| and |{false}|) are unit-tested only, as python-igraph 1.0's output for them differs.
- C name
og_write_graph_leda- In notebooks
Og.WriteGraphLeda- igraph 1.0
igraph_write_graph_leda- See also
write_graph_graphml
The number format
enter_safelocale#
Unit tests
Switches the calling thread to the C numeric locale, so that numbers are read and written with a decimal point.
og_error_t og_enter_safelocale(og_safelocale_t *loc);
The readers and writers parse and print reals with the C library, which follows the current numeric locale; under a locale with a decimal comma 1.5 would be written "1,5". This function makes LC_NUMERIC "C" for the calling thread alone where the platform allows it (Windows: a per-thread locale; POSIX: newlocale and uselocale), and for the whole process otherwise (setlocale), which is not safe while other threads use the locale.
Every successful call must be paired with exit_safelocale on the same thread and with the same og_safelocale_t; pairs may nest. og_safelocale_t is a small struct the caller declares and treats as opaque (in igraph it is an opaque pointer; the calls are used the same way).
- Parameters
locStorage for what must be restored; pass the same object toexit_safelocale.
- Returns
OG_SUCCESS, or one of the error codes below.- Errors
OG_FAILUREThe locale could not be switched.OG_ENOMEMNot enough memory.
- Complexity
- O(1).
- Checked
- Not reachable from python-igraph. Tested under a decimal-comma locale on Windows and macOS: printf and Open Graph's readers and writers use '.', nested pairs work and nothing leaks.
- C name
og_enter_safelocale- In notebooks
Og.Native.og_enter_safelocale- igraph 1.0
igraph_enter_safelocale- See also
exit_safelocale,write_graph_gml,read_graph_ncol
og_safelocale_t loc;
if (og_enter_safelocale(&loc) == OG_SUCCESS) {
og_write_graph_gml(&g, f, OG_WRITE_GML_DEFAULT_SW, NULL, ""); /* writes 1.5, never 1,5 */
og_exit_safelocale(&loc);
}
exit_safelocale#
Unit tests
Restores the numeric locale that enter_safelocale replaced.
void og_exit_safelocale(og_safelocale_t *loc);
Puts back the locale saved in loc, per thread or for the process, whichever enter_safelocale used, and frees what loc held. Call it once for every successful enter_safelocale, on the same thread. On a loc whose enter_safelocale failed it does nothing harmful.
- Parameters
locThe object filled byenter_safelocale.
- Returns
- Nothing.
- Complexity
- O(1).
- Checked
- After it a decimal-comma locale formats "1,5" again (Windows and macOS).
- C name
og_exit_safelocale- In notebooks
Og.Native.og_exit_safelocale- igraph 1.0
igraph_exit_safelocale- See also
enter_safelocale