使用 JGraphT 1.4.0 的元素作为标签导入边缘列表图
Import a edgelist graph using its elements as labels with JGraphT 1.4.0
我将我的一个项目从 JGraphT 1.3.1 更新到 1.4.0,并注意到为 I/O 引入了一个新的 org.jgrapht.nio
包;我想改用它,因为基本上 org.jgrapht.io
已被弃用,我希望我的工作能够在未来几年内保持不变。
我的问题是,在替换已弃用的 类 后,边缘列表如
a b
b c
b d
a d
(其中空白字符设置为分隔符)不再与标签一起作为字母字符导入,而是作为索引出现,即上面的边缘列表变为
0 1
1 2
1 3
0 3
您可以通过 CSVImporterTest.java
test class and replacing its nodes in one of its test methods with alphabetic characters: the test will fail because then the graph is created by the builder, the vertex supplier is given by SupplierUtil.createStringSupplier(1)
调用来重现此行为,该调用基本上将数字生成为字符串,而不是从边列表中选取顶点。
因为 user guide 关于序列化还没有更新到 1.4.0 并且不包括任何使用 org.jgrapht.nio
包的例子,而且很明显我没有得到关于如何恢复 org.jgrapht.io.CSVImporter
的行为的事情,我应该如何实际从边列表中读取节点而不是对它们进行计数?我是否必须添加更多处理才能将这些索引转换回字母?
我什至尝试自己构建一个 lambda 函数,因为构建器 vertexSupplier(Supplier<T>)
将 Supplier<T>
作为输入,但我卡在了 () -> T t
,其中 t
显然是未定义的,应该从文件中的某个地方获取。
新的 I/O 包是从头开始重新设计的,实际上它改变了图创建过程中的语义。这主要是将包名称从 org.jgrapht.io
更改为 org.jgrapht.nio
的原因。
在过去的几年中 vertex/edge 使用图形顶点和边供应商改进了图形的创建。新的 I/O 导入器切换行为并在需要新顶点时调用 Graph#addVertex()
,这反过来使用提供的图形顶点供应商来创建顶点。
不幸的是,这会导致您观察到的行为。输入文件中的实际顶点标识符仍然可以访问,因为它们被视为顶点属性,并且在导入期间使用 "ID".
键进行报告
另请参阅 ,这是一个非常相似的案例,它使用此功能创建了具有完全相同标识符的第二个图表。
另一方面,旧的行为是有道理的。很自然地期望导入保留您的顶点标识符(至少对于大多数导入器而言)。通过提供一种方法 #setVertexFactory(Function)
,已经可以解决这个问题。此方法允许用户通过提供自定义顶点工厂方法来绕过顶点创建。工厂方法负责根据从输入文件读取的顶点标识符创建一个新的图顶点。
该修复程序将在下一个版本(可能是 1.4.1)中可用,并且已经在快照版本 (1.4.1-SNAPSHOT) 中可用。请参阅 https://github.com/jgrapht/jgrapht#using-via-maven 了解如何使用快照构建。
为了保留旧的行为,您应该像这样构建导入器:
CSVImporter<String, DefaultEdge> importer = new CSVImporter<>();
importer.setVertexFactory(id->id);
importer.importGraph(g, new StringReader(input));
我将我的一个项目从 JGraphT 1.3.1 更新到 1.4.0,并注意到为 I/O 引入了一个新的 org.jgrapht.nio
包;我想改用它,因为基本上 org.jgrapht.io
已被弃用,我希望我的工作能够在未来几年内保持不变。
我的问题是,在替换已弃用的 类 后,边缘列表如
a b
b c
b d
a d
(其中空白字符设置为分隔符)不再与标签一起作为字母字符导入,而是作为索引出现,即上面的边缘列表变为
0 1
1 2
1 3
0 3
您可以通过 CSVImporterTest.java
test class and replacing its nodes in one of its test methods with alphabetic characters: the test will fail because then the graph is created by the builder, the vertex supplier is given by SupplierUtil.createStringSupplier(1)
调用来重现此行为,该调用基本上将数字生成为字符串,而不是从边列表中选取顶点。
因为 user guide 关于序列化还没有更新到 1.4.0 并且不包括任何使用 org.jgrapht.nio
包的例子,而且很明显我没有得到关于如何恢复 org.jgrapht.io.CSVImporter
的行为的事情,我应该如何实际从边列表中读取节点而不是对它们进行计数?我是否必须添加更多处理才能将这些索引转换回字母?
我什至尝试自己构建一个 lambda 函数,因为构建器 vertexSupplier(Supplier<T>)
将 Supplier<T>
作为输入,但我卡在了 () -> T t
,其中 t
显然是未定义的,应该从文件中的某个地方获取。
新的 I/O 包是从头开始重新设计的,实际上它改变了图创建过程中的语义。这主要是将包名称从 org.jgrapht.io
更改为 org.jgrapht.nio
的原因。
在过去的几年中 vertex/edge 使用图形顶点和边供应商改进了图形的创建。新的 I/O 导入器切换行为并在需要新顶点时调用 Graph#addVertex()
,这反过来使用提供的图形顶点供应商来创建顶点。
不幸的是,这会导致您观察到的行为。输入文件中的实际顶点标识符仍然可以访问,因为它们被视为顶点属性,并且在导入期间使用 "ID".
键进行报告另请参阅
另一方面,旧的行为是有道理的。很自然地期望导入保留您的顶点标识符(至少对于大多数导入器而言)。通过提供一种方法 #setVertexFactory(Function)
,已经可以解决这个问题。此方法允许用户通过提供自定义顶点工厂方法来绕过顶点创建。工厂方法负责根据从输入文件读取的顶点标识符创建一个新的图顶点。
该修复程序将在下一个版本(可能是 1.4.1)中可用,并且已经在快照版本 (1.4.1-SNAPSHOT) 中可用。请参阅 https://github.com/jgrapht/jgrapht#using-via-maven 了解如何使用快照构建。
为了保留旧的行为,您应该像这样构建导入器:
CSVImporter<String, DefaultEdge> importer = new CSVImporter<>();
importer.setVertexFactory(id->id);
importer.importGraph(g, new StringReader(input));