Простой неориентированный немаркированный граф в JGraphT не работает? Что такое параметр edgeClass?

Я хочу сделать простой неориентированный немаркированный (ребра не помечены) граф A<->B в JGraphT 0.8.3:

import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.SimpleGraph;

class A {
    public static void main(String[] args) {
        SimpleGraph<String, String> sg =
            new SimpleGraph<String, String>(String.class);
        sg.addVertex("A");
        sg.addVertex("B");
        sg.addEdge("A", "B");
        System.out.println("edges of A: " + sg.edgesOf("A"));
        System.out.println("edges of B: " + sg.edgesOf("B"));
    }
}

Я получаю этот вывод:

$ java -cp 'jgrapht-jdk1.6.jar:.' A
edges of A: []
edges of B: []

Почему множества ребер вершин A и B пусты? Также для чего нужен параметр класса SimpleGraph? Вроде бы тип ребер, но так как мои ребра здесь не помечены, то неужели это не имеет значения? Кажется, что все классы графов принимают класс ребра (edgeClass) в качестве параметра. Не могу найти где в документации описано edgeClass.


Я обнаружил, что если пометить ребро (изменить строку addEdge на sg.addEdge("A", "B", "an_edge");), то это сработает... но я не хочу помечать ребра...

$ java -cp 'jgrapht-jdk1.6.jar:.' A
edges of A: [an_edge]
edges of B: [an_edge]

person Dog    schedule 25.04.2013    source источник


Ответы (1)


Вам не нужно маркировать края. проблема в вашем подходе заключается в том, что вы указываете графику использовать String в качестве типа ребра. Правильный станд. способ сделать что-то будет:

    SimpleGraph<String, DefaultEdge> sg = new SimpleGraph<String, DefaultEdge>(DefaultEdge.class);
    sg.addVertex("A");
    sg.addVertex("B");
    sg.addVertex("C");
    sg.addEdge("A", "B");
    sg.addEdge("B", "C");
    System.out.println("graph: " + sg.toString());
    System.out.println("edges of A: " + sg.edgesOf("A"));
    System.out.println("edges of B: " + sg.edgesOf("B"));

это даст вам следующий вывод:

graph: ([A, B, C], [{A,B}, {B,C}])
edges of A: [(A : B)]
edges of B: [(A : B), (B : C)]

Поэтому, чтобы решить эту проблему, необходимо переключить класс ребер на DefaultEdge, как показано в коде.

person Matthias Kricke    schedule 26.04.2013
comment
Но для чего нужен граничный класс? Почему это не работает с String? Я также заметил, что могу сделать граничный класс равным Object, и он тоже будет работать. Я довольно много искал в Интернете и документации и нашел удивительным, что не могу найти никого, кто бы объяснил, для чего это нужно. - person Dog; 26.04.2013
comment
а) Класс Edge полезен, когда вы хотите установить веса для ваших ребер (например, в контексте путешествия) или когда вы хотите дать ребро тип (например, онтологии). Если вам не нужны эти подвиги, DefaultEdge является правильным ответом . б) Он не порвался со String, без метки он просто не может его идентифицировать. graph.toString() показывает ребро даже с ребрами String, это выглядит так: graph: ([A, B, C], [={A,B}]). Таким образом, пустая строка является идентификатором ребра. Если вы вставите другое ребро без метки, это не будет установлено, потому что пустая строка уже существует, а вставка работает с методом equals и hashcode. - person Matthias Kricke; 26.04.2013
comment
ой. так что он использует отражение для вызова конструктора по умолчанию String? - person Dog; 26.04.2013
comment
Да, именно так. При создании нового ребра базовая функция вызывает: edgeClass.newInstance(); - person Matthias Kricke; 26.04.2013