用于使用 igraph C 库
这些函数可以将图写入文件,或从文件读取图。
它们假设当前区域设置使用小数点而不是十进制逗号。 有关更多信息,请参见 igraph_enter_safelocale()
和 igraph_exit_safelocale()
。
请注意,由于 igraph 使用传统的 C 流,因此可以从内存读取/写入文件,至少在支持 “非标准” 流的 GNU 操作系统上是这样。
igraph_read_graph_edgelist
— 从文件读取边列表并创建图。igraph_write_graph_edgelist
— 将图的边列表写入文件。igraph_read_graph_ncol
— 读取 LGL 使用的 .ncol
文件。igraph_write_graph_ncol
— 以 .ncol
格式将图写入文件。igraph_read_graph_lgl
— 从 .lgl
文件读取图。igraph_write_graph_lgl
— 以 .lgl
格式将图写入文件。igraph_read_graph_dimacs_flow
— 以 DIMACS 格式读取图。igraph_write_graph_dimacs_flow
— 以 DIMACS 格式写入图。
igraph_error_t igraph_read_graph_edgelist(igraph_t *graph, FILE *instream, igraph_integer_t n, igraph_bool_t directed);
此格式只是一系列由空格分隔的偶数个非负整数。 这些整数表示顶点 ID。 不要求将每条边(即整数对)放在单独的一行上,但建议这样做以提高可读性。 有向图的边假定为“从,到”顺序。
最大顶点 ID 加一,或者参数 n
确定顶点计数,以较大者为准。 有关读取顶点通过名称而不是数字顶点 ID 指定的文件,请参见 igraph_read_graph_ncol()
。
参数:
|
指向未初始化的图对象的指针。 |
|
指向流的指针,它应该是可读的。 |
|
图中的顶点数。 如果小于文件中的最大整数,则将被忽略。 因此,在此处提供零是安全的。 |
|
如果为 true,则图是有向的,如果为 false,则将是无向的。 |
返回值:
错误代码: |
时间复杂度: O(|V|+|E|),顶点数加边数。 假设读取一个整数需要 O(1) 时间。
igraph_error_t igraph_write_graph_edgelist(const igraph_t *graph, FILE *outstream);
边表示为基于 0 的顶点索引对。 每行写入一条边,用单个空格分隔。 对于有向图,边以“从,到”顺序写入。
参数:
|
要写入的图对象。 |
|
指向流的指针,它应该是可写的。 |
返回值:
错误代码: 如果写入文件时出现错误,则为 |
时间复杂度: O(|E|),图中的边数。 假设将整数写入文件需要 O(1) 时间。
igraph_error_t 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);
对于从 “命名”(以及可选的加权)边列表创建图也很有用。
此格式由大型图布局程序使用(https://lgl.sourceforge.net),它只是一个符号加权边列表。 它是一个简单的文本文件,每行一条边。 边由两个由空格分隔的符号顶点名称定义。 顶点名称本身不能包含空格。 它们后面可以跟一个可选数字,即边的权重; 该数字可以为负数,也可以采用科学计数法。 如果没有为边指定权重,则假定为零。
生成的图始终是无向的。 LGL 无法处理包含多个或环边的文件,但此处不进行检查,因为 igraph 对此很满意。
参数:
|
指向未初始化的图对象的指针。 |
|
指向流的指针,它应该是可读的。 |
|
指向文件中顶点的符号名称的指针。 如果此处给出了 |
|
布尔值。 如果 |
|
是否将边的权重作为名为 “权重” 的边属性添加到图中。 |
|
是否创建有向图。 由于此格式最初仅用于无向图,因此文件中没有关于图的方向性的信息。 将此参数设置为 |
返回值:
错误代码: |
时间复杂度: 如果我们忽略解析所需的时间,则为 O(|V|+|E|log(|V|))。 像往常一样,|V| 是顶点数,而 |E| 是边数。
另请参阅:
igraph_error_t igraph_write_graph_ncol(const igraph_t *graph, FILE *outstream, const char *names, const char *weights);
.ncol
是 LGL 使用的格式,有关详细信息,请参见 igraph_read_graph_ncol()
。
请注意,在 .ncol
文件中具有多个或环边会破坏 LGL 软件,但 igraph 不会检查此条件。
此格式无法表示零度顶点。
参数:
|
要写入的图。 |
|
要写入的流对象,它应该是可写的。 |
|
字符串顶点属性的名称,如果要将符号名称写入文件。 提供 |
|
数值边属性的名称,它将作为权重写入文件。 提供 |
返回值:
错误代码: 如果写入文件时出现错误,则为 |
时间复杂度: O(|E|),边数。 预计所有文件操作的时间复杂度为 O(1)。
另请参阅:
igraph_error_t igraph_read_graph_lgl(igraph_t *graph, FILE *instream, igraph_bool_t names, igraph_add_weights_t weights, igraph_bool_t directed);
.lgl
格式由大型图布局可视化软件使用(https://lgl.sourceforge.net),它可以描述可选加权无向图。 来自 LGL 手册
第二种格式是 LGL 文件格式(
.lgl
文件后缀)。 这是另一种图文件格式,它试图尽可能吝啬空间,同时保持边文件采用人类可读(非二进制)格式。 格式本身如下# vertex1name vertex2name [optionalWeight] vertex3name [optionalWeight]在此,边的第一个顶点以井号 '#' 开头。 然后,与该顶点共享边的每个顶点都将在后续行中逐行列出。
LGL 无法处理环和多条边或有向图,但在 igraph 中,具有多条边和环边不是错误。
参数:
|
指向未初始化的图对象的指针。 |
|
一个流,它应该是可读的。 |
|
布尔值,如果 |
|
是否将边的权重作为名为 “权重” 的边属性添加到图中。 |
|
是否创建有向图。 由于此格式最初仅用于无向图,因此文件中没有关于图的方向性的信息。 将此参数设置为 |
返回值:
错误代码: |
时间复杂度: 如果我们忽略解析所需的时间,则为 O(|V|+|E|log(|V|))。 像往常一样,|V| 是顶点数,而 |E| 是边数。
另请参阅:
示例 21.1. 文件 examples/simple/igraph_read_graph_lgl.c
#include <igraph.h> int main(void) { igraph_t g; FILE *input; /* Turn on attribute handling. */ igraph_set_attribute_table(&igraph_cattribute_table); /* 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; }
igraph_error_t igraph_write_graph_lgl(const igraph_t *graph, FILE *outstream, const char *names, const char *weights, igraph_bool_t isolates);
.lgl
是 LGL 使用的格式,有关详细信息,请参见 igraph_read_graph_lgl()
。
请注意,在 .lgl
文件中具有多个或环边会破坏 LGL 软件,但 igraph 不会检查此条件。
参数:
|
要写入的图。 |
|
要写入的流对象,它应该是可写的。 |
|
字符串顶点属性的名称,如果要将符号名称写入文件。 提供 |
|
数值边属性的名称,它将作为权重写入文件。 提供 |
|
如果 |
返回值:
错误代码: 如果写入文件时出现错误,则为 |
时间复杂度: 如果 isolates
为 false
,则为 O(|E|),否则为 O(|V|+|E|)。 预计所有文件操作的时间复杂度为 O(1)。
另请参阅:
示例 21.2. 文件 examples/simple/igraph_write_graph_lgl.c
#include <igraph.h> int main(void) { igraph_t graph; igraph_strvector_t names; igraph_vector_t weights; igraph_integer_t i; igraph_integer_t vcount, ecount; igraph_set_attribute_table(&igraph_cattribute_table); igraph_small(&graph, 7, IGRAPH_UNDIRECTED, 0,1, 1,3, 1,2, 2,0, 4,2, 3,4, -1); vcount = igraph_vcount(&graph); ecount = igraph_ecount(&graph); printf("Output without isolates:\n"); igraph_write_graph_lgl(&graph, stdout, /*names*/ NULL, /*weights*/ NULL, /*isolates*/ 0); printf("\nOutput with isolates:\n"); igraph_write_graph_lgl(&graph, stdout, /*names*/ NULL, /*weights*/ NULL, /*isolates*/ 1); printf("\nOutput vertex and edge labels:\n"); igraph_strvector_init(&names, vcount); for (i = 0; i < vcount; i++) { char str[2] = " "; /* initialize to ensure presence of null terminator */ str[0] = 'A' + i; igraph_strvector_set(&names, i, str); } SETVASV(&graph, "names", &names); igraph_vector_init_range(&weights, 1, ecount + 1); SETEANV(&graph, "weights", &weights); igraph_write_graph_lgl(&graph, stdout, "names", "weights", /*isolates*/ 0); igraph_strvector_destroy(&names); igraph_vector_destroy(&weights); igraph_destroy(&graph); return 0; }
igraph_error_t igraph_read_graph_dimacs_flow( igraph_t *graph, FILE *instream, igraph_strvector_t *problem, igraph_vector_int_t *label, igraph_integer_t *source, igraph_integer_t *target, igraph_vector_t *capacity, igraph_bool_t directed);
此函数读取 DIMACS 文件格式,更具体地说是用于网络流问题的版本,请参见 http://archive.dimacs.rutgers.edu/pub/netflow/general-info/ 中的文件
这是一个面向行的文本文件 (ASCII) 格式。 每行的第一个字符定义行的类型。 如果第一个字符是 c
,则该行是注释行,将被忽略。 文件中有一个问题行(p
),它必须出现在任何节点和弧描述符行之前。 问题行有三个字段,用空格分隔:问题类型(max
或 edge
)、图中的顶点数和边数。 在 MAX 问题中,预计正好有两个节点标识行(n
),一个用于源,一个用于目标顶点。 这些行有两个字段:顶点的 ID 和顶点的类型,可以是 s
(= 源)或 t
(= 目标)。 弧线以 a
开头,并有三个字段:源顶点、目标顶点和边容量。 在 EDGE 问题中,每个节点可能有一条节点线(n
)。 它指定节点索引和整数节点标签。 没有明确指定标签的节点将使用其索引作为标签。 在 EDGE 问题中,每条边都指定为边线(e
)。
在 DIMACS 文件中,顶点 ID 从 1 开始编号。
参数:
|
指向未初始化的图对象的指针。 |
|
要从中读取的文件。 |
|
如果不为 |
|
如果不为 |
|
指向整数的指针,源节点的 ID 将存储在此处。 (igraph 顶点 ID,比文件中的实际数字小一。) 如果 |
|
指向整数的指针,目标节点的(igraph)ID 将存储在此处。 如果 |
|
指向已初始化向量的指针,边的容量将存储在此处(如果不为 \ NULL)。 |
|
布尔值,是否创建有向图。 |
返回值:
错误代码。 |
时间复杂度: O(|V|+|E|+c),顶点数加边数,再加上文件中字符的大小。
另请参阅:
igraph_error_t igraph_write_graph_dimacs_flow(const igraph_t *graph, FILE *outstream, igraph_integer_t source, igraph_integer_t target, const igraph_vector_t *capacity);
此函数以 DIMACS 格式将图写入输出流,描述最大流问题。 请参见 ftp://dimacs.rutgers.edu/pub/netflow/general-info/
此文件格式在 igraph_read_graph_dimacs_flow()
的文档中讨论,有关更多信息,请参见该文档。
参数:
|
要写入流的图。 |
|
流。 |
|
整数,最大流的源顶点 ID。 |
|
整数,目标顶点的 ID。 |
|
指向包含边容量值的已初始化向量的指针。 |
返回值:
错误代码。 |
时间复杂度: O(|E|),图中的边数。
另请参阅:
igraph_error_t igraph_read_graph_graphdb(igraph_t *graph, FILE *instream, igraph_bool_t directed);
这是一种二进制格式,用于 ARG 图数据库进行同构测试。 有关更多信息,请参见 https://mivia.unisa.it/datasets/graph-database/arg-database/
来自图数据库主页
图以紧凑的二进制格式存储,每个文件一张图。 该文件由 16 位字组成,这些字使用所谓的“小端”约定表示,即,字的最低有效字节首先存储。
然后,对于每个节点,文件包含从节点本身发出的边的列表。 该列表由一个对其长度进行编码的字表示,后跟每个边的字,表示边的目标节点。 节点编号是基于 0 的,因此图的第一个节点的索引为 0。
截至 igraph 0.10,仅实现了未标记的图。
参考
M. De Santo、P. Foggia、C. Sansone 和 M. Vento: 用于基准测试图同构算法的大型图数据库及其使用。 Pattern Recognition Letters,24(8),1067-1079 (2003)。 https://doi.org/10.1016/S0167-8655(02)00253-2
MIVIA ARG 数据集,https://zenodo.org/records/11204020, https://mivia.unisa.it/datasets/graph-database/arg-database/
参数:
|
指向未初始化的图对象的指针。 |
|
要从中读取的流。 它应该以二进制模式打开。 |
|
是否创建有向图。 |
返回值:
错误代码。 |
时间复杂度:O(|V|+|E|),顶点数加上边数。
示例 21.3. 文件 examples/simple/igraph_read_graph_graphdb.c
#include <igraph.h> int main(void) { 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; }
igraph_error_t igraph_read_graph_graphml(igraph_t *graph, FILE *instream, igraph_integer_t index);
GraphML 是一种基于 XML 的文件格式,用于表示各种类型的图。 目前,igraph 中仅实现了最基本的导入功能:它可以读取没有嵌套图和超边的 GraphML 文件。 仅当附加了属性接口时才会加载图的属性,请参见 igraph_set_attribute_table()
。 字符串属性值以 UTF-8 编码返回。
图属性名称取自 GraphML 文件中 key
标记的 attr.name
属性。 由于 attr.name
不是强制性的,因此如果缺少 attr.name
,igraph 将回退到 key
标记的 id
属性。
参数:
|
指向未初始化的图对象的指针。 |
|
一个流,它应该是可读的。 |
|
如果 GraphML 文件包含多个图,则将加载此索引指定的图。 索引从零开始,因此如果您的 GraphML 文件仅包含单个图,请在此处提供零。 |
返回值:
错误代码: |
示例 21.4. 文件 examples/simple/graphml.c
#include <igraph.h> #include <stdio.h> #include <unistd.h> /* unlink */ int main(void) { igraph_t graph; const char *infilename = "test.graphml"; const char *outfilename = "test2.graphml"; /* Set up attribute handling, so graph attributes can be imported * from the GraphML file. */ igraph_set_attribute_table(&igraph_cattribute_table); /* Problems in the GraphML file may cause igraph to print warnings. * If this is not desired, set a silent warning handler: */ igraph_set_warning_handler(&igraph_warning_handler_ignore); /* Read the contents of a GraphML file. */ /* GraphML */ FILE *infile = fopen("test.graphml", "r"); if (! infile) { fprintf(stderr, "Could not open input file '%s'.", infilename); exit(1); } /* GraphML support is an optional feature in igraph. If igraph was compiled * without GraphML support, igraph_read_graph_graphml() returns IGRAPH_UNIMPLEMENTED. * We temporarily disable the default error handler so we can test for this condition. */ igraph_error_handler_t *oldhandler = igraph_set_error_handler(igraph_error_handler_ignore); igraph_error_t ret = igraph_read_graph_graphml(&graph, infile, 0); if (ret == IGRAPH_UNIMPLEMENTED) { fprintf(stderr, "igraph was compiled without GraphML support."); exit(77); } if (ret != IGRAPH_SUCCESS) { fprintf(stderr, "Unexpected error while reading GraphML."); exit(1); } igraph_set_error_handler(oldhandler); fclose(infile); /* Write it back into another file. */ FILE *outfile = fopen(outfilename, "w"); if (outfile) { igraph_write_graph_graphml(&graph, outfile, true); fclose(outfile); /* Clean up after ourselves */ unlink(outfilename); } else { fprintf(stderr, "Could not write output file '%s'.", outfilename); } /* Destroy the graph */ igraph_destroy(&graph); return 0; }
igraph_error_t igraph_write_graph_graphml(const igraph_t *graph, FILE *outstream, igraph_bool_t prefixattr);
GraphML 是一种基于 XML 的文件格式,用于表示各种类型的图。 有关详细的格式说明,请参见 GraphML 入门 (http://graphml.graphdrawing.org/primer/graphml-primer.html)。
当数值属性值为 NaN 时,将从文件中省略它。
此函数假定属性名称和字符串属性值中的非 ASCII 字符采用 UTF-8 编码。 如果不是这种情况,则生成的 XML 文件将无效。 不允许使用控制字符,即字符代码高达并包括 31(制表符、回车符和换行符除外)。
参数:
|
要写入的图。 |
|
要写入的流对象,它应该是可写的。 |
|
布尔值。 是否在属性名称前放置前缀,以确保如果图具有具有相同名称的顶点和边(或图)属性,则名称的唯一性。 |
返回值:
错误代码: 如果写入文件时出现错误,则为 |
时间复杂度: 否则为 O(|V|+|E|)。 预计所有文件操作的时间复杂度为 O(1)。
示例 21.5. 文件 examples/simple/graphml.c
#include <igraph.h> #include <stdio.h> #include <unistd.h> /* unlink */ int main(void) { igraph_t graph; const char *infilename = "test.graphml"; const char *outfilename = "test2.graphml"; /* Set up attribute handling, so graph attributes can be imported * from the GraphML file. */ igraph_set_attribute_table(&igraph_cattribute_table); /* Problems in the GraphML file may cause igraph to print warnings. * If this is not desired, set a silent warning handler: */ igraph_set_warning_handler(&igraph_warning_handler_ignore); /* Read the contents of a GraphML file. */ /* GraphML */ FILE *infile = fopen("test.graphml", "r"); if (! infile) { fprintf(stderr, "Could not open input file '%s'.", infilename); exit(1); } /* GraphML support is an optional feature in igraph. If igraph was compiled * without GraphML support, igraph_read_graph_graphml() returns IGRAPH_UNIMPLEMENTED. * We temporarily disable the default error handler so we can test for this condition. */ igraph_error_handler_t *oldhandler = igraph_set_error_handler(igraph_error_handler_ignore); igraph_error_t ret = igraph_read_graph_graphml(&graph, infile, 0); if (ret == IGRAPH_UNIMPLEMENTED) { fprintf(stderr, "igraph was compiled without GraphML support."); exit(77); } if (ret != IGRAPH_SUCCESS) { fprintf(stderr, "Unexpected error while reading GraphML."); exit(1); } igraph_set_error_handler(oldhandler); fclose(infile); /* Write it back into another file. */ FILE *outfile = fopen(outfilename, "w"); if (outfile) { igraph_write_graph_graphml(&graph, outfile, true); fclose(outfile); /* Clean up after ourselves */ unlink(outfilename); } else { fprintf(stderr, "Could not write output file '%s'.", outfilename); } /* Destroy the graph */ igraph_destroy(&graph); return 0; }
igraph_error_t igraph_read_graph_gml(igraph_t *graph, FILE *instream);
GML 是一种简单的文本格式,有关详细信息,请参见 https://web.archive.org/web/20190207140002/http://www.fim.uni-passau.de/index.php?id=17297%26L=1。
尽管可以解析所有在语法上正确的 GML,但我们仅实现了此格式的子集。 一些属性可能会被忽略。 这是所有差异的列表
仅使用具有简单类型的属性:整数、实数或字符串。 如果属性是复合的,即数组或记录,则将忽略它。 当属性的一些值为简单类型,而另一些为复合类型时,复合值将替换为默认值(数值为 NaN,字符串为 ""
)。
comment
字段不会被忽略。 它们被视为任何其他字段并转换为属性。
除了 Version
和第一个 graph
属性之外,顶层属性将被完全忽略。
没有最大行长度或最大关键字长度。
仅支持 quot
、amp
、apos
、lt
和 gt
字符实体。 在发出警告后,任何其他实体都将由读取器不变地传递,并有望由用户解码。
我们允许 inf
、-inf
和 nan
(非数字)作为实数。 这不区分大小写,因此 nan
、NaN
和 NAN
是等效的。
如果您无法忍受 GML 解析器的这些限制,请与我们联系。
参数:
|
指向未初始化的图对象的指针。 |
|
用于从中读取 GML 文件的流。 |
返回值:
错误代码。 |
时间复杂度: 应与文件的长度成正比。
另请参阅:
有关更现代的格式,请参见 |
示例 21.6. 文件 examples/simple/gml.c
#include <igraph.h> #include <stdio.h> int main(void) { igraph_t graph; FILE *ifile; ifile = fopen("karate.gml", "r"); if (ifile == 0) { return 1; } igraph_read_graph_gml(&graph, ifile); fclose(ifile); printf("The graph is %s.\n", igraph_is_directed(&graph) ? "directed" : "undirected"); /* Output as edge list */ printf("\n-----------------\n"); igraph_write_graph_edgelist(&graph, stdout); /* Output as GML */ printf("\n-----------------\n"); igraph_write_graph_gml(&graph, stdout,IGRAPH_WRITE_GML_DEFAULT_SW, 0, ""); igraph_destroy(&graph); return 0; }
igraph_error_t igraph_write_graph_gml(const igraph_t *graph, FILE *outstream, igraph_write_gml_sw_t options, const igraph_vector_t *id, const char *creator);
GML 是一种非常通用的文本格式,有关详细信息,请参见 https://web.archive.org/web/20190207140002/http://www.fim.uni-passau.de/index.php?id=17297%26L=1。
图、顶点和边属性也会写入文件,如果它们是数字或字符串。 布尔属性将转换为数字,其中 0 和 1 分别用于假和真。 数值属性的 NaN 值将被跳过,因为 NaN 不是 GML 规范的一部分,并且其他软件可能无法读取包含它们的文件。 这与 igraph_read_graph_gml()
一致,后者在缺少属性值时生成 NaN。 与 NaN 相比,无限值会被保留。 确保没有数值属性值为无限值以生成其他软件可以读取的符合 GML 的文件。
由于 igraph 对属性名称更加宽容,因此可能需要在写入 GML 文件之前简化它们。 这样,我们将有一个语法上正确的 GML 文件。 对每个属性名称执行以下简单过程:首先提取字母数字字符,其他字符将被忽略。 然后,如果第一个字符不是字母,则属性名称将带有前缀 “igraph”。 请注意,这可能会导致两个属性具有相同的名称,igraph 不会检查这一点。
“id” 顶点属性被特殊处理。 如果 id
参数不是 NULL
,那么它应该是一个具有顶点 ID 的数值向量,并且 “id” 顶点属性将被忽略(如果存在)。 如果 id
是 NULL
并且存在数值 “id” 顶点属性,则将改用它。 如果未以任何方式指定 ID,则使用常规 igraph 顶点 ID。 如果提供的某些 ID 值无效(非整数或 NaN),则所有提供的 ID 将被忽略,并改用 igraph 顶点 ID。
请注意,无论以何种方式指定顶点 ID,都不会检查其唯一性。
如果图具有在编码后变为 “source” 或 “target” 的边属性,或者图具有变为 “directed” 的属性,则它们将被忽略并显示警告。 GML 使用这些属性来指定边端点和图的方向性,因此我们无法将它们写入文件。 如果要保留它们,请在调用此函数之前重命名它们。
参数:
|
要写入流的图。 |
||||||
|
用于将文件写入到的流。 |
||||||
|
用于写入 GML 文件的
|
||||||
|
可以是 |
||||||
|
一个可选字符串,用于写入到创建者行中的流。 如果 |
返回值:
错误代码。 |
时间复杂度: 应与写入文件的字符数成正比。
另请参阅:
有关读取 GML 文件,请参见 |
示例 21.7. 文件 examples/simple/gml.c
#include <igraph.h> #include <stdio.h> int main(void) { igraph_t graph; FILE *ifile; ifile = fopen("karate.gml", "r"); if (ifile == 0) { return 1; } igraph_read_graph_gml(&graph, ifile); fclose(ifile); printf("The graph is %s.\n", igraph_is_directed(&graph) ? "directed" : "undirected"); /* Output as edge list */ printf("\n-----------------\n"); igraph_write_graph_edgelist(&graph, stdout); /* Output as GML */ printf("\n-----------------\n"); igraph_write_graph_gml(&graph, stdout,IGRAPH_WRITE_GML_DEFAULT_SW, 0, ""); igraph_destroy(&graph); return 0; }
igraph_error_t igraph_read_graph_pajek(igraph_t *graph, FILE *instream);
仅实现了 Pajek 格式的一个子集。 这部分是因为此格式没有正式规范,但也因为 igraph 不支持某些 Pajek 功能,例如混合图。
从 0.6.1 版本开始,igraph 从 Pajek 文件中读取二分(双模)图,并为其添加 type
布尔顶点属性。 对于无效边,即连接相同类型的顶点的边,会发出警告。
当前限制列表
仅支持 .net
文件,不支持 Pajek 项目文件 (.paj
)。
不支持时间网络(即具有时间事件的网络)。
不支持同时具有有向边和非有向边的图,因为它们无法在 igraph 中表示。
仅支持 Pajek 网络; 不支持排列、层次结构、集群和向量。
不支持多关系网络(即具有多个边类型的网络)。
不会解码编码为 &#dddd;
的 Unicode 字符或编码为 \n
的换行符。
如果安装了属性处理程序,则 igraph 还会从文件中读取顶点和边属性。 大多数属性都已重命名,以使其更具信息性:color
而不是 c
、xfact
而不是 x_fact
、yfact
而不是 y_fact、labeldist
而不是 lr
、labeldegree2
而不是 lphi
、framewidth
而不是 bw
、fontsize
而不是 fos
、rotation
而不是 phi
、radius
而不是 r
、diamondratio
而不是 q
、labeldegree
而不是 la
、color
而不是 ic
、framecolor
而不是 bc
、labelcolor
而不是 lc
; 这些属于顶点。
边的属性也被重命名,s
改为 arrowsize
,w
改为 edgewidth
,h1
改为 hook1
,h2
改为 hook2
,a1
改为 angle1
,a2
改为 angle2
,k1
改为 velocity1
,k2
改为 velocity2
,ap
改为 arrowpos
,lp
改为 labelpos
,lr
改为 labelangle
,lphi
改为 labelangle2
,la
改为 labeldegree
,fos
改为 fontsize
,a
改为 arrowtype
,p
改为 linepattern
,l
改为 label
,lc
改为 labelcolor
,c
改为 color
。
未知的顶点或边的参数会被读取为字符串类型的顶点或边属性。如果参数名称与上述标准属性名称冲突,则会在其后附加一个 _
字符以避免冲突。
此外,可能会添加以下顶点属性:如果文件中存在顶点 ID,则会添加 id
和 name
(具有相同的值)。id
已被弃用,推荐使用 name
,未来版本的 igraph 将不再使用 id
。如果文件中存在顶点坐标,则还会添加 x
和 y
,以及可能的 z
。
如果存在边的权重,则会添加 weight
边属性。
有关 Pajek 的更多信息,请参见 Pajek 主页:http://vlado.fmf.uni-lj.si/pub/networks/pajek/。Pajek 手册,http://vlado.fmf.uni-lj.si/pub/networks/pajek/doc/pajekman.pdf,以及 http://mrvar.fdv.uni-lj.si/pajek/DrawEPS.htm 包含有关 Pajek 文件格式的信息。在 http://mrvar.fdv.uni-lj.si/pajek/history.htm 上有更多有用的信息和示例文件
参数:
|
指向未初始化的图对象的指针。 |
|
一个已经打开的文件句柄。 |
返回值:
错误代码。 |
时间复杂度:O(|V|+|E|+|A|),|V| 是顶点数,|E| 是边数,|A| 是图中的属性数(顶点 + 边)(如果安装了属性处理程序)。
另请参阅:
用于写入 Pajek 文件的 |
示例 21.8. 文件 examples/simple/foreign.c
#include <igraph.h> #include <stdio.h> int main(void) { igraph_t g; FILE *ifile; /* Turn on attribute handling. */ igraph_set_attribute_table(&igraph_cattribute_table); /* Read a Pajek file. */ ifile = fopen("links.net", "r"); if (ifile == 0) { return 10; } igraph_read_graph_pajek(&g, ifile); fclose(ifile); /* Write it in edgelist format. */ printf("The graph:\n"); printf("Vertices: %" IGRAPH_PRId "\n", igraph_vcount(&g)); printf("Edges: %" IGRAPH_PRId "\n", igraph_ecount(&g)); printf("Directed: %i\n", igraph_is_directed(&g) ? 1 : 0); igraph_write_graph_edgelist(&g, stdout); igraph_destroy(&g); return 0; }
igraph_error_t igraph_write_graph_pajek(const igraph_t *graph, FILE *outstream);
以 Pajek 软件的本机格式写入文件。不建议将此格式用于数据交换或存档。它仅用于与 Pajek 的互操作性。
Pajek 顶点和边的参数(如颜色)由顶点和边的属性决定。当然,这需要安装属性处理程序。相应的顶点和边属性的名称在 igraph_read_graph_pajek()
中列出,例如,color
顶点属性决定颜色(Pajek 中的 c
)参数。
与任何已记录的 Pajek 参数不对应的顶点和边属性将被丢弃。
从 0.6.1 版本开始,igraph 正确地将二分图写入 Pajek 文件,即,当读入 Pajek 时,它们也将是二分图。由于 Pajek 对于二分图的灵活性较低(顶点的数字 ID 必须按顶点类型排序),因此在写入二分 Pajek 文件时,igraph 可能需要重新排序顶点。这实际上意味着当二分图写入 Pajek 文件,然后读回 igraph 时,数字顶点 ID 通常会更改。
早期版本的 Pajek 仅支持 Pajek 文件中的 Windows 样式的行尾符,但最近的版本同时支持 Windows 和 Unix 行尾符。因此,当输入文件以文本模式打开时,igraph 使用平台本地行尾符,当输入文件以二进制模式打开时,使用 Unix 样式的行尾符。如果您使用的是旧版本的 Pajek,并且您在 Unix 上,并且在读取 igraph 在 Windows 机器上写入的文件时遇到问题,请使用文本编辑器或命令行中的 unix2dos
或 iconv
手动转换行尾符)。
Pajek 仅会在 UTF-8 编码的文件开头包含字节顺序标记 (BOM) 时才解释它们。igraph 不知道字符串属性编码,因此永远不会写入 BOM。如果/当需要时,您需要手动添加它。
参数:
|
要写入的图对象。 |
|
要写入的文件。它应该被打开并且可写。 |
返回值:
错误代码。 |
时间复杂度:O(|V|+|E|+|A|),|V| 是顶点数,|E| 是边数,|A| 是图中的属性数(顶点 + 边)(如果安装了属性处理程序)。
另请参阅:
用于读取 Pajek 图的 |
示例 21.9. 文件 examples/simple/igraph_write_graph_pajek.c
#include <igraph.h> int main(void) { 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, false /* mutual */, true /* circular */); igraph_write_graph_pajek(&g, stdout); /* add some vertex attributes */ igraph_strvector_init(&names, 0); igraph_strvector_push_back(&names, "A"); igraph_strvector_push_back(&names, "B"); igraph_strvector_push_back(&names, "C"); igraph_strvector_push_back(&names, "D"); igraph_strvector_push_back(&names, "E"); igraph_strvector_push_back(&names, "F"); igraph_strvector_push_back(&names, "G"); igraph_strvector_push_back(&names, "H"); igraph_strvector_push_back(&names, "I"); igraph_strvector_push_back(&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_push_back(&names, "square"); igraph_strvector_push_back(&names, "square"); igraph_strvector_push_back(&names, "square"); igraph_strvector_push_back(&names, "square"); igraph_strvector_push_back(&names, "escaping spaces"); igraph_strvector_push_back(&names, "square"); igraph_strvector_push_back(&names, "square"); igraph_strvector_push_back(&names, "escaping\nnewline"); igraph_strvector_push_back(&names, "square"); igraph_strvector_push_back(&names, "encoding \"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; }
igraph_error_t igraph_read_graph_dl(igraph_t *graph, FILE *instream, igraph_bool_t directed);
这是 UCINET 使用的一种简单的文本文件格式。有关示例,请参见 http://www.analytictech.com/networks/dataentry.htm。igraph 支持此处描述的所有形式。还支持顶点名称和边权重,并将它们添加为属性。(如果附加了属性处理程序。)
请注意,规范没有提及该格式是否区分大小写。对于 igraph,DL 文件区分大小写,即 Larry
和 larry
不是同一个。
参数:
|
指向未初始化的图对象的指针。 |
|
从中读取 DL 文件的流。 |
|
布尔值,是否创建有向文件。 |
返回值:
错误代码。 |
时间复杂度:在边和顶点的数量方面是线性的,除了矩阵格式,它在顶点数量方面是二次的。
示例 21.10. 文件 examples/simple/igraph_read_graph_dl.c
#include <igraph.h> #include <stdio.h> #include <stdlib.h> int main(void) { 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" }; igraph_t graph; FILE *infile; /* Turn on attribute handling. */ igraph_set_attribute_table(&igraph_cattribute_table); for (size_t i = 0; i < sizeof(files) / sizeof(files[0]); i++) { printf("Doing %s\n", files[i]); infile = fopen(files[i], "r"); if (!infile) { printf("Cannot open file: %s\n", files[i]); abort(); } igraph_read_graph_dl(&graph, infile, IGRAPH_DIRECTED); fclose(infile); igraph_write_graph_edgelist(&graph, stdout); igraph_destroy(&graph); } if (IGRAPH_FINALLY_STACK_SIZE() != 0) { return 1; } return 0; }
igraph_error_t igraph_write_graph_dot(const igraph_t *graph, FILE* outstream);
DOT 是广泛使用的 GraphViz 软件使用的格式,有关详细信息,请参见 https://graphviz.cn。DOT 格式的语法可以在这里找到:https://graphviz.cn/doc/info/lang.html
这只是一个初步实现,不会写入任何可视化信息。
此格式仅用于与 Graphviz 的互操作性。不建议将此格式用于数据交换或存档。
参数:
|
要写入流的图。 |
|
用于将文件写入到的流。 |
时间复杂度: 应与写入文件的字符数成正比。
另请参阅:
对于更现代的格式,请使用 |
示例 21.11. 文件 examples/simple/dot.c
#include <igraph.h> #include <stdio.h> int main(void) { 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; }
igraph_error_t igraph_write_graph_leda(const igraph_t *graph, FILE *outstream, const char *vertex_attr_name, const char *edge_attr_name);
此函数以 LEDA 格式将图写入输出流。参见 http://www.algorithmic-solutions.info/leda_guide/graphs/leda_native_graph_fileformat.html
目前对 LEDA 格式的支持非常基本;igraph 仅写入 LEDA 图部分,该部分支持一个选定的顶点和边属性,并且没有布局信息或视觉属性。
参数:
|
要写入流的图。 |
|
流。 |
|
要将值存储在输出中的顶点属性的名称,如果没有顶点属性应该存储,则为 |
|
要将值存储在输出中的边属性的名称,如果没有边属性应该存储,则为 |
返回值:
错误代码。 |
时间复杂度:O(|V|+|E|),图中的顶点数和边数。
igraph_error_t igraph_enter_safelocale(igraph_safelocale_t *loc);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
igraph 的外部格式读取器和写入器需要使用小数点而不是逗号的区域设置。这是一个便利函数,用于临时设置 C 区域设置,以便读取器和写入器可以正常工作。它必须与对 igraph_exit_safelocale()
的调用配对,否则将发生内存泄漏。
此函数尝试仅在尽力而为的基础上为当前线程设置区域设置。并非所有平台都支持将区域设置更改限制为单个线程。在这些情况下,此函数会回退到使用标准的 setlocale()
函数,该函数会影响整个进程,并且从并发线程使用是不安全的。
通常建议在已使用特定于系统的方法永久设置为 C 区域设置的线程中运行 igraph。当由于程序员无法控制进程(例如,在开发插件/扩展时)而无法轻松实现时,这是一个便利函数。请注意,进程默认以 C 区域设置启动,因此除非区域设置已更改为非默认设置,否则无需执行任何操作。
参数:
|
指向类型为 |
返回值:
错误代码。 |
示例 21.12. 文件 examples/simple/safelocale.c
#include <igraph.h> #include <locale.h> #include <stdio.h> #include <string.h> int main(void) { const char *filename = "weighted.gml"; igraph_t graph; igraph_safelocale_t loc; /* Attempt to set a locale that uses a decimal comma. Locale names * differ between platforms, and not all locales are available, * so the locale change may not be successful. */ const char *locname = setlocale(LC_ALL, "de_DE"); struct lconv *lc = localeconv(); if (strcmp(lc->decimal_point, ",")) { /* If decimal point is not a comma, presumably because the requested * locale was not available, report locale information. */ fprintf(stderr, "setlocale() returned '%s', decimal point is '%s'\n", locname ? locname : "NULL", lc->decimal_point); } FILE *file = fopen(filename, "r"); if (! file) { fprintf(stderr, "Cannot open %s file.\n", filename); exit(1); } /* An attribute table is needed to read graph attributes. */ igraph_set_attribute_table(&igraph_cattribute_table); /* At this point, the current locale may use decimal commas. * We temporarily set a C locale using enter_safelocale() to * allow the GML reader and writer to work correctly.*/ igraph_enter_safelocale(&loc); if (igraph_read_graph_gml(&graph, file) != IGRAPH_SUCCESS) { fprintf(stderr, "Reading %s failed.\n", filename); abort(); } igraph_write_graph_gml(&graph, stdout, IGRAPH_WRITE_GML_DEFAULT_SW, NULL, ""); igraph_exit_safelocale(&loc); igraph_destroy(&graph); return 0; }
void igraph_exit_safelocale(igraph_safelocale_t *loc);
此函数是实验性的,其签名尚未被视为最终签名。我们保留更改函数签名的权利,而无需更改 igraph 的主要版本。使用它需要您自担风险。
恢复由 igraph_enter_safelocale()
保存的区域设置,并释放所有关联的数据。此函数必须与对 igraph_enter_safelocale()
的调用配对。
参数:
|
类型为 |
igraph_error_t igraph_read_graph_dimacs(igraph_t *graph, FILE *instream, igraph_strvector_t *problem, igraph_vector_int_t *label, igraph_integer_t *source, igraph_integer_t *target, igraph_vector_t *capacity, igraph_bool_t directed);
自 0.10.0 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_read_graph_dimacs_flow()
。
igraph_error_t igraph_write_graph_dimacs(const igraph_t *graph, FILE *outstream, igraph_integer_t source, igraph_integer_t target, const igraph_vector_t *capacity);
自 0.10.0 版本起已弃用。请不要在新代码中使用此函数;请改用 igraph_write_graph_dimacs_flow()
。
← 第 20. 章 图绘制的生成布局 | 第 22. 章 最大流、最小割及相关度量 → |