0

I was looking at jgraphT but I am not very experienced and it lacks a bit in documentation.

I have some nodes and I'd like to create a connected topology giving some redundancy. Example:

I start with n1,n2,n3,n4

I would like to be able to communicate with each node but still have more than one possible path so that if one node falls other nodes can still communicate.

Can jgraphT create a good topology for me?Maybe giving some weights so that it values some node more than others?

Or you know some other library to get the same achievement? Moreover it could be nice if I could generate some kind of webpage documenting the topology I created...

Phate
  • 6,066
  • 15
  • 73
  • 138

1 Answers1

2

Slightly too long for a comment:

I think the formal characteristics of what you are looking for are not specified clearly enough. You are obviously looking for a graph with a certain connectivity ( http://en.wikipedia.org/wiki/Connectivity_%28graph_theory%29 ), but based on the current question, one could just recommend to use a CompleteGraphGenerator.

The crucial points are probably those where you are mentioning "some redundancy" and "some weights" (and "some webpage" documenting the topology).

Presumably, you want a minimal redundancy. That is, you probably want to insert the minimum number of additional edges so that the graph is still connected after removing k arbitrary vertices.

I'm not aware of a library that can do this out-of-the-box.

Two rough ideas based on what JGraphT offers:


EDIT:


Added an implementation based on the first idea mentioned above. The ensureConnectivity method will make sure that a given graph has a certain connectivity as follows: It computes the minimum cut using the StoerWagnerMinimumCut class. The output of this class is a list of vertices that are one of the components that will be created by the cut. The computeCutVertices method will compute the vertices that actually have to be removed in order to divide the graph into several components. For each of these vertices, the set of neighbors will be computed. Any two of these neighbors (that had not already been connected) will be connected with a new edge. This whole process will be repeated until the number of "cut vertices" is greater than the desired connectivity.

Note that this has not been tested extensively, and there might be more elegant or efficient solutions, but ... it should work, in general

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.jgrapht.Graph;
import org.jgrapht.UndirectedGraph;
import org.jgrapht.alg.StoerWagnerMinimumCut;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.SimpleGraph;

public class GraphConnectivityTest
{
    public static void main(String[] args)
    {
        UndirectedGraph<String, DefaultEdge> graph =
            new SimpleGraph<String, DefaultEdge>(DefaultEdge.class);

        String v0 = "0";
        String v1 = "1";
        String v2 = "2";
        String v3 = "3";
        String v4 = "4";
        String v5 = "5";
        String v6 = "6";
        String v7 = "7";
        graph.addVertex(v0);
        graph.addVertex(v1);
        graph.addVertex(v2);
        graph.addVertex(v3);
        graph.addVertex(v4);
        graph.addVertex(v5);
        graph.addVertex(v6);
        graph.addVertex(v7);

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

        graph.addEdge(v4, v5);
        graph.addEdge(v4, v6);
        graph.addEdge(v4, v7);
        graph.addEdge(v5, v6);
        graph.addEdge(v5, v7);
        graph.addEdge(v6, v7);

        graph.addEdge(v1, v4);
        //graph.addEdge(v3, v6);

        ensureConnectivity(graph, 2);
    }

    /**
     * Make sure that the given graph has the specified connectivity.
     * That is: Make sure that more than the given number of vertices
     * have to be removed in order to split the graph into two
     * components.
     * 
     * @param graph The graph
     * @param connectivity The desired connectivity
     */
    private static <V, E> void ensureConnectivity(
        UndirectedGraph<V, E> graph, int connectivity)
    {
        System.out.println("Desired connectivity is "+connectivity);
        while (true)
        {
            StoerWagnerMinimumCut<V, E> m = 
                new StoerWagnerMinimumCut<V, E>(graph);
            Set<V> minCut = m.minCut();

            Set<V> cutVertices = 
                computeCutVertices(graph, minCut);
            System.out.println("Removing "+cutVertices+" will create two components");
            if (cutVertices.size() > connectivity)
            {
                System.out.println("Reached desired connectivity");
                return;
            }
            for (V cutVertex : cutVertices)
            {
                E edge = addBridgeEdge(graph, cutVertex);
                System.out.println("Added edge "+edge);
            }
        }
    }


    /**
     * Creates an edge between two arbitrary neighbors of the
     * given vertex in the given graph that have not yet
     * been connected.
     * 
     * @param graph The graph
     * @param v The vertex
     */
    private static <V, E> E addBridgeEdge(Graph<V, E> graph, V v)
    {
        Set<E> edges = graph.edgesOf(v);
        Set<V> neighbors = new LinkedHashSet<V>();
        for (E edge : edges)
        {
            V v0 = graph.getEdgeSource(edge);
            V v1 = graph.getEdgeTarget(edge);
            neighbors.add(v0);
            neighbors.add(v1);
        }
        neighbors.remove(v);

        List<V> neighborsList = new ArrayList<V>(neighbors);
        for (int i=0; i<neighborsList.size(); i++)
        {
            for (int j=i+1; j<neighborsList.size(); j++)
            {
                V n0 = neighborsList.get(i);
                V n1 = neighborsList.get(j);
                E present = graph.getEdge(n0, n1);
                if (present == null)
                {
                    return graph.addEdge(n0, n1);
                }
            }
        }
        return null;
    }


    /**
     * Compute the vertices in the given graph that have to be 
     * removed from the graph in order to split it into two 
     * components (of which one only contains the given 
     * "minCut" vertices)
     * 
     * @param graph The graph
     * @param minCut The set of vertices on one side of the cut
     * @return The vertices that have to be removed 
     */
    private static <V, E> Set<V> computeCutVertices(
        Graph<V, E> graph, Set<V> minCut)
    {
        Set<V> cutVertices = new LinkedHashSet<V>();
        for (V v : minCut)
        {
            Set<E> edges = graph.edgesOf(v);
            for (E edge : edges)
            {
                V v0 = graph.getEdgeSource(edge);
                V v1 = graph.getEdgeTarget(edge);
                if (minCut.contains(v0) && !minCut.contains(v1))
                {
                    cutVertices.add(v1);
                }
                if (!minCut.contains(v0) && minCut.contains(v1))
                {
                    cutVertices.add(v0);
                }
            }
        }
        return cutVertices;
    }
}
Marco13
  • 53,703
  • 9
  • 80
  • 159
  • Hi, about your second method...is there a way to decide HOW to add additional edges? I mean...finding a criteria in order to decide that node1 should have an additional edge on node2 and not node3. Isn't there any densification alghoritm jgraphT implements? – Phate Mar 27 '14 at 11:29
  • Again: I think that a more formal description might be beneficial here (what does "some redundancy" mean exactly? Why don't you create a complete graph?). The connected components approach was just a first idea: When you computed the set of strongly connected components, your could insert one edge between any vertex of one component and any vertex of the other component. (But note that this is still some brainstorming: You did not even mention whether you are talking about a *directed* or an *undirected* graph!) – Marco13 Mar 27 '14 at 13:05
  • I don't create a complete graph because node number is pretty high and this solution is not scalable. Also, sorry for not having mentioned it, we are talking about an undirected graph. My ideal solution would be to start with a tree so to get a connected graph with the least number of arcs. Then as you said, I'd like to densificate it so that if a arbitrary node number, up to a k, are removed the graph is still connected. I was looking at some automate process which would do that for me and I hoped jgraphT had some mechanism.. – Phate Mar 27 '14 at 15:18
  • @Phate Added an EDIT with an attempt to implement the first approach that I sketched. Maybe you find it useful. – Marco13 Mar 27 '14 at 19:13