使用 JGraphT 库的 EdgeProvider class

Using the JGraphT library's EdgeProvider class

我四处寻找解决方案,但由于我对 Java 的通用编程风格没有太多经验,我什至对使用什么词进行搜索有点困惑这个。我正在尝试使用 DOTImporter (http://jgrapht.org/javadoc/org/jgrapht/ext/DOTImporter.html) from the JGraphT library, which in turn requires me to use the EdgeProvider interface (http://jgrapht.org/javadoc/org/jgrapht/ext/EdgeProvider.html). I have tried myriad ways of implementing this, but the fact that buildEdge uses a generic return type has me quite confused. I'm trying to use their DefaultEdge as well (http://jgrapht.org/javadoc/org/jgrapht/graph/DefaultEdge.html),这并没有好多少,因为他们的 API 指定了两种获取几个字段(源和目标)的方法,但没有办法设置这些字段,并且由于它们不是 public,并且构造函数没有参数,所以我不太确定应该如何设置它们。

为了将其置于上下文中,我正在尝试加载一个 .dot 文件,而我真正关心的只是标签,因此我的图形实际上将由字符串顶点组成,因此边将是(字符串, String) 结构也是如此。这真的很简单,因此我不介意实现我自己的图形结构来使用它,但我真的很想利用 DOTImporter。

如果有人能为我提供一些关于如何为 EdgeProvider 正确实施具体 class 以及如何使用 DefaultEdge class 的帮助,我将不胜感激。

简短回答:这是 DOTImporter 的完整示例(非常简单...):

1 之前 JGraphT 版本的示例代码。4.x:

public class DOTTest {

    public static void main(String[] args) throws ImportException {
        //Example graph
        String input =
                "digraph graphname {\r\n" + "     a -> b -> c;\r\n" + "     b -> d;\r\n" + " }";

        GraphImporter<String, DefaultEdge> importer = new DOTImporter<>(
                (label, attributes) -> label, 
                (from, to, label, attributes) -> new DefaultEdge()
        );

        Graph<String, DefaultEdge> result = new SimpleDirectedGraph<>(DefaultEdge.class);
        importer.importGraph(result, new StringReader(input));

        System.out.println(result);
    }
}

JGraphT 1.5.0 及更高版本的新示例代码:

public class DOTTest {

    public static void main(String[] args) throws ImportException {
        //Example graph
        String input =
                "digraph graphname {\r\n" + "     a -> b -> c;\r\n" + "     b -> d;\r\n" + " }";

    Graph<String, DefaultEdge> result = new SimpleDirectedGraph<>(DefaultEdge.class);

    DOTImporter<String, DefaultEdge> dotImporter = new DOTImporter<>();
    dotImporter.setVertexFactory(label -> label);
    dotImporter.importGraph(result, new StringReader(input);

    System.out.println(result);
}

}

请注意,在 JGraphT 中,每个 class 都带有相应的测试 class,其中包含许多示例。

更长的答案: 在 JGraphT 中,每个顶点和每条边都是一个对象。这允许非常灵活的图形。缺点是需要提供工厂方法。例如,如果您调用 graph.addEdge(u,v),则必须创建一个新对象来表示 u 和 v 之间的边。为此,需要一个边工厂。在许多实际情况下,用户不需要自定义边缘对象。对于这些情况,JGraphT 提供了 DefaultEdge class。一个您希望拥有自定义边的实际示例,例如,当您构建表示道路网络的图形时。一个顶点就是一个交叉点,一条边就是一条街道。例如,街道对象将存储车道数、行驶速度、行驶方向等。

那么 IntrusiveEdge 的目的是什么?除非您打算为 JGraphT 贡献代码,否则这并不重要。你不应该直接使用 IntrusiveEdge。 IntrusiveEdge 是大多数边缘的基本类型。在引擎盖下,它存储边的源、目标和权重。但是,这些字段是隐藏的,即不能直接访问它们!相反,图 class 提供了访问这些字段的方法,例如graph.getEdgeSource(myEdge).