使用 graphml 和 jung 加载自定义节点和边

Posted

技术标签:

【中文标题】使用 graphml 和 jung 加载自定义节点和边【英文标题】:loading custom nodes and edges with graphml and jung 【发布时间】:2017-11-17 20:03:28 【问题描述】:

我在尝试使用 JUNG 在文本文件中读取和写入图形时遇到问题。情况如下: Given 是一个文件,其中包含一个多重图的坐标及其权重。

一个例子是:

6346    6728    5911    156 5
6346    6728    6599    156 10
6346    6728    8555    156 5

我用 JUNG 编写了一个转换器,它读取一个包含数百万行的文件并构造一个

DirectedSparseMultigraph<Node, Edge>

Nodes 和 Edges 是下面列出的自定义类

class Node 
    int id; // good coding practice would have this as private

    public Node(int id) 
        this.id = id;
    
    public String toString()  // Always a good idea for debuging
        return "V"+id;
   // JUNG2 makes good use of these.
            


class Edge  
    Context context;  
    Time time;
    Value value;
    int id;
    public Edge(int id, Context context, Time time, Value value) 
        this.id = id; // This is defined in the outer class.
        this.context = context;
        this.time = time;
        this.value = value;
     
    public String toString()  // Always good for debugging
        return "E"+id;
    

根据这些数据在内存中构建一个图表可以正常工作。我们离问题更近了。需要注意的是,将构建的图形保存到磁盘可以正常工作,方法是使用 DirectedSparseMultigraph 对象。在下一步中,构造的 DirectedSparseMultigraph 通过以下代码行从磁盘加载

    GraphMLReader<DirectedSparseMultigraph<Node, Edge>, Node, Edge> gmlr = null;

    try
    
        gmlr = new GraphMLReader<DirectedSparseMultigraph<Node, Edge>, Node, Edge>();
     catch (ParserConfigurationException e1)
    
        e1.printStackTrace();
     catch (SAXException e1)
    
        e1.printStackTrace();
    

    DirectedSparseMultigraph<Node, Edge> g_new = null;
    try
    
        gmlr.load("bla.sh", g_new);
     catch (IOException e)
    
        e.printStackTrace();
    

这就是问题的开始。错误信息如下:

Exception in thread "main" java.lang.IllegalArgumentException: If no edge factory is supplied, edge id may not be null: source=V6818, target=V2472
at edu.uci.ics.jung.io.GraphMLReader.createEdge(GraphMLReader.java:693)
at edu.uci.ics.jung.io.GraphMLReader.startElement(GraphMLReader.java:299)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:182)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1343)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2786)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:510)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:649)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(SAXParserImpl.java:333)
at edu.uci.ics.jung.io.GraphMLReader.parse(GraphMLReader.java:241)
at edu.uci.ics.jung.io.GraphMLReader.load(GraphMLReader.java:192)
at edu.uci.ics.jung.io.GraphMLReader.load(GraphMLReader.java:201)
at main.Graph.main(Graph.java:99)

如果您对如何解决此问题有任何想法或提示,我非常期待您的留言。 问候 J 错误

【问题讨论】:

快速戳一下:您必须使用GraphMLReader 构造函数,该构造函数接收一个Factory&lt;V&gt; 顶点和一个Factory&lt;E&gt; 边,并且这些工厂应该创建您的@ 实例分别为 987654329@- 和 Edge 类。 【参考方案1】:

GraphMLReader 可以通过两种方式解析您的文件:

(1) 您提供节点和边缘工厂;在这种情况下,您的节点和边类型可以是您想要的任何东西。 (constructor with factories)

(2) 你不提供节点和边缘工厂;在这种情况下,您的节点和边类型必须是 Strings。 (constructor without factories)

您的代码不提供节点和边缘工厂,并且您的 Edge 类型与 String 的赋值不兼容,因此它会崩溃。诚然,这在错误消息中并不是很明显,但在the code 中却相当清楚。

在这种情况下,您无法真正提供 NodeEdge 工厂(无需重新设计它们),因为您没有无参数构造函数。因此,您要么需要重新设计这些类,要么使用一个两阶段的过程,即:使用简单的字符串键解析图形 + 填充元数据,然后基于数据结构构建一个新图形GraphMLReader 提供。

【讨论】:

感谢您帮助我,让我为迟到接受答案而道歉,但我还想提供一个具体的解决方案,可以帮助其他类似情况的人。因此,我遇到了***.com/questions/11063810/…,其中提供了一个与您的建议相一致的示例。它有点笨拙,但是在习惯了它之后,它就可以完美地工作并且可以轻松扩展。再次感谢您。 据此也可以查看eyeshalfclosed.com/blog/2010/12/04/…

以上是关于使用 graphml 和 jung 加载自定义节点和边的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JUNG 图形可视化中添加自定义顶点标签?

如何使用 JUNG 的 Edmonds Karp 获得每个可能的源/汇节点对的最大流量?

如何使用 JUNG 对二部图进行投影

比较用于绘制网络拓扑的开源 Java 图形绘制框架(JUNG 和 Prefuse)

JUNG 计算图属性,相关度

PrimeFaces p:tree使用自定义图标