All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.jfschaefer.layeredgraphlayout.gengraph.GenGraph Maven / Gradle / Ivy

package de.jfschaefer.layeredgraphlayout.gengraph;

import de.jfschaefer.layeredgraphlayout.Edge;
import de.jfschaefer.layeredgraphlayout.Node;
import de.jfschaefer.layeredgraphlayout.pgraph.PGraph;

import java.util.*;

/**
 * Created by user on 7/30/15.
 */

public class GenGraph {
    protected Map> nodeMap;
    protected Map> edgeMap;
    protected boolean locked = false;
    protected boolean cyclesRemoved = false;

    public GenGraph() {
        nodeMap = new HashMap>();
        edgeMap = new HashMap>();
    }

    public void addNode(V node, double width, double height) {
        assert !locked;
        nodeMap.put(node, new Node(node, width, height));
    }

    public void addEdge(E edge, V from, V to) {
        assert !locked;
        Node nfrom = nodeMap.get(from);
        Node nto = nodeMap.get(to);
        edgeMap.put(edge, new Edge(edge, nfrom, nto));
    }

    public final Collection> getNodes() {
        return nodeMap.values();
    }

    public final Collection> getEdges() {
        return edgeMap.values();
    }

    public final Set getOriginalNodes() {
        return nodeMap.keySet();
    }

    public final Set getOriginalEdges() {
        return edgeMap.keySet();
    }

    public void removeCyclesGreedy() {
        if (cyclesRemoved) return;
        assert !locked;
        Set> remainingNodes = new HashSet>();
        for (Node n : getNodes()) {
            remainingNodes.add(n);
        }

        while (!remainingNodes.isEmpty()) {
            //remove remaining sources and sinks
            int size;
            do {
                size = remainingNodes.size();
                Set> done = new HashSet>();
                for (Node node : remainingNodes) {
                    if (node.isSinkIn(remainingNodes) || node.isSourceIn(remainingNodes)) {
                        done.add(node);
                    }
                }
                remainingNodes.removeAll(done);
            } while (size != remainingNodes.size());

            //reverse a few edges to make one more node a source/sink.
            if (remainingNodes.isEmpty()) break;
            double bestRatio = 1d;     // worse than worst case
            Node chosenNode = null;
            boolean indegreeGToutdegree = false;        // in degree greater than out degree
            for (Node node : remainingNodes) {
                int indegree = node.inDegreeIn(remainingNodes);
                int outdegree = node.outDegreeIn(remainingNodes);
                assert indegree != 0;    //otherwise it would have been a source in the previous step
                assert outdegree != 0;   //otherwise it would have been a sink in the previous step
                double thisRatio = ((double) Math.min(indegree, outdegree)) / (indegree + outdegree);
                if (thisRatio < bestRatio) {
                    bestRatio = thisRatio;
                    chosenNode = node;
                    indegreeGToutdegree = (indegree > outdegree);
                }
            }
            assert chosenNode != null;
            Set> edgesToBeFlipped = new HashSet>();
            if (indegreeGToutdegree) {   //flip outgoing edges
                for (Edge edge : chosenNode.getOutgoingEdges()) {
                    if (remainingNodes.contains(edge.getTo())) {
                        edgesToBeFlipped.add(edge);
                    }
                }
            } else {    //flip ingoing edges
                for (Edge edge : chosenNode.getIngoingEdges()) {
                    if (remainingNodes.contains(edge.getFrom())) {
                        edgesToBeFlipped.add(edge);
                    }
                }
            }
            for (Edge e : edgesToBeFlipped) {
                e.flip();
            }
        }

        locked = true;
        cyclesRemoved = true;
    }

    public PGraph generatePGraph() {
        removeCyclesGreedy();
        PGraph result = new PGraph();
        for (Node node : getNodes()) {
            result.addNode(node);
        }
        for (Edge edge : getEdges()) {
            result.addEdge(edge);
        }
        return result;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy