Обновление графика JGraphT работает неправильно

Я пытаюсь реализовать своего рода технику суммирования графов, где я проверяю, есть ли у узла дочерние элементы или нет, если нет, то узел свернут в своего родителя. У меня есть 2 фрагмента кода, чтобы сделать это, но один из них не работает из-за ошибки в getEdgeSource, или, по крайней мере, я так думаю. При использовании 1-й реализации я могу пометить узлы, которые должны быть свернуты, после этого я снова зациклю все узлы в графе и добавлю их к их соответствующим родителям, а затем удалю их. Это работает отлично. Другой фрагмент кода должен сделать то же самое, но узлы не добавляются к родителю, они только удаляются. Вот фрагменты ниже: Сначала вот мой класс Node:

public class Node implements Serializable{
    private static final long serialVersionUID = 1L;
    public String nodeID;
    public String timestamp;
    public ArrayList<Node> children = new ArrayList<Node>();
    public boolean tagged;
    public boolean isRoot;

    public Node(String a) {
        nodeID = a;
    }

    public void addChild(Node a){
        children.add(a);
    }

    public int getSize(){
        return children.size();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof Node)) {
            return false;
        }
        Node other = (Node) obj;
        return this.nodeID.equals(other.nodeID);
    }
    @Override
    public int hashCode() {
        return nodeID.hashCode();
    }
}

(Рабочий код, но больше временной сложности):

    public void oneLevelCollapse(DirectedGraph<Node, Edge> graph) {
    graphCopy = (DirectedGraph<Node, Edge>) ((AbstractBaseGraph<Node, Edge>)graph).clone();

    // iterate over every node and tag nodes to collapse
    for (Node node : graphCopy.vertexSet()) {
        // remove node if it has no children and only one parent
        if (graphCopy.outDegreeOf(node) == 0 && graphCopy.inDegreeOf(node) == 1) {
            node.tagged = true;
        }
    }
    // iterate over every node again and collapse/delete
    for (Node node : graphCopy.vertexSet()) {
        for (Edge edge : graphCopy.outgoingEdgesOf(node)) {
            Node child = graph.getEdgeTarget(edge);
            if (child.tagged) {
                node.addChild(child);
                graph.removeVertex(child);
            }
        }
    }
}

(Код, который должен работать, но не работает):

public void oneLevelCollapse(DirectedGraph<Node, Edge> graph) {
    graphCopy = (DirectedGraph<Node, Edge>) ((AbstractBaseGraph<Node, Edge>)graph).clone();

    // iterate over every node and tag nodes to collapse
    for (Node node : graphCopy.vertexSet()) {
        // remove node if it has no children and only one parent
        if (graphCopy.outDegreeOf(node) == 0 && graphCopy.inDegreeOf(node) == 1) {
            for (Edge edge : graphCopy.incomingEdgesOf(node)) {
                graph.getEdgeSource(edge).addChild(node);
                graph.removeVertex(node);
            }
        }
    }

}

Граф не имеет самоконтроля, граф - это граф, который я изменяю, сохраняя при этом копию исходного графа, который представляет собой graphCopy.

1 ответ

Вы не предоставили код для своего класса Edge, но с DefaultEdge для класса edge, обе ваши реализации oneLevelCollapse(...) работают и пройдут этот модульный тест:

public void testJgraph() {
    DirectedGraph<Node, DefaultEdge> graph = new SimpleDirectedGraph<>(DefaultEdge.class);
    Node v1 = new Node("a");
    Node v2 = new Node("b");
    Node v3 = new Node("c");
    graph.addVertex(v1);
    graph.addVertex(v2);
    graph.addVertex(v3);

    graph.addEdge(v1, v2);
    graph.addEdge(v2, v3);

    oneLevelCollapse(graph);

    assertEquals(2, graph.vertexSet().size());
    assertTrue(graph.vertexSet().contains(v1));
    assertTrue(graph.vertexSet().contains(v2));
    assertEquals(v3, v2.children.get(0));

}
Другие вопросы по тегам